Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1 | //===-- 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 Bello | bdae378 | 2013-08-28 12:14:27 +0000 | [diff] [blame] | 13 | #include <inttypes.h> |
| 14 | |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 15 | // C++ Includes |
| 16 | // Other libraries and framework includes |
Zachary Turner | a78bd7f | 2015-03-03 23:11:11 +0000 | [diff] [blame] | 17 | #include "clang/AST/Decl.h" |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 18 | // Project includes |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 19 | #include "lldb/Core/DataBufferHeap.h" |
| 20 | #include "lldb/Core/DataExtractor.h" |
Greg Clayton | 6611103 | 2010-06-23 01:19:29 +0000 | [diff] [blame] | 21 | #include "lldb/Core/Debugger.h" |
Greg Clayton | 1f74607 | 2012-08-29 21:13:06 +0000 | [diff] [blame] | 22 | #include "lldb/Core/Module.h" |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 23 | #include "lldb/Core/StreamString.h" |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 24 | #include "lldb/Core/ValueObjectMemory.h" |
Enrico Granata | 4d93b8c | 2013-09-30 19:11:51 +0000 | [diff] [blame] | 25 | #include "lldb/DataFormatters/ValueObjectPrinter.h" |
Sean Callanan | 4dbb271 | 2015-09-25 20:35:58 +0000 | [diff] [blame] | 26 | #include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h" |
Vince Harron | 5275aaa | 2015-01-15 20:08:35 +0000 | [diff] [blame] | 27 | #include "lldb/Host/StringConvert.h" |
Greg Clayton | 6611103 | 2010-06-23 01:19:29 +0000 | [diff] [blame] | 28 | #include "lldb/Interpreter/Args.h" |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 29 | #include "lldb/Interpreter/CommandReturnObject.h" |
Greg Clayton | 6611103 | 2010-06-23 01:19:29 +0000 | [diff] [blame] | 30 | #include "lldb/Interpreter/CommandInterpreter.h" |
| 31 | #include "lldb/Interpreter/Options.h" |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 32 | #include "lldb/Interpreter/OptionGroupFormat.h" |
| 33 | #include "lldb/Interpreter/OptionGroupOutputFile.h" |
Greg Clayton | 68ebae6 | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 34 | #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h" |
Greg Clayton | 67cc063 | 2012-08-22 17:17:09 +0000 | [diff] [blame] | 35 | #include "lldb/Interpreter/OptionValueString.h" |
Greg Clayton | d8d4a57 | 2015-08-11 21:38:15 +0000 | [diff] [blame] | 36 | #include "lldb/Symbol/ClangASTContext.h" |
Greg Clayton | 1f74607 | 2012-08-29 21:13:06 +0000 | [diff] [blame] | 37 | #include "lldb/Symbol/TypeList.h" |
Kuba Brecka | beed821 | 2014-09-04 01:03:18 +0000 | [diff] [blame] | 38 | #include "lldb/Target/MemoryHistory.h" |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 39 | #include "lldb/Target/Process.h" |
Jason Molenda | b57e4a1 | 2013-11-04 09:33:30 +0000 | [diff] [blame] | 40 | #include "lldb/Target/StackFrame.h" |
Kuba Brecka | beed821 | 2014-09-04 01:03:18 +0000 | [diff] [blame] | 41 | #include "lldb/Target/Thread.h" |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 42 | |
| 43 | using namespace lldb; |
| 44 | using namespace lldb_private; |
| 45 | |
Greg Clayton | 68ebae6 | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 46 | static OptionDefinition |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 47 | g_option_table[] = |
| 48 | { |
Zachary Turner | d37221d | 2014-07-09 16:31:49 +0000 | [diff] [blame] | 49 | { 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."}, |
Enrico Granata | 40d3570 | 2015-11-04 02:12:09 +0000 | [diff] [blame] | 52 | { LLDB_OPT_SET_3, false , "offset" ,'E', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCount ,"How many elements of the specified type to skip before starting to display data."}, |
Greg Clayton | 2346fcf | 2012-11-02 21:14:58 +0000 | [diff] [blame] | 53 | { LLDB_OPT_SET_1| |
| 54 | LLDB_OPT_SET_2| |
Zachary Turner | d37221d | 2014-07-09 16:31:49 +0000 | [diff] [blame] | 55 | LLDB_OPT_SET_3, false, "force" ,'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone ,"Necessary if reading over target.max-memory-read-size bytes."}, |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 56 | }; |
| 57 | |
| 58 | |
| 59 | |
| 60 | class OptionGroupReadMemory : public OptionGroup |
| 61 | { |
| 62 | public: |
| 63 | |
| 64 | OptionGroupReadMemory () : |
Greg Clayton | 68ebae6 | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 65 | m_num_per_line (1,1), |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 66 | m_output_as_binary (false), |
Enrico Granata | 7a33621 | 2015-10-29 23:40:24 +0000 | [diff] [blame] | 67 | m_view_as_type(), |
| 68 | m_offset(0,0) |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 69 | { |
| 70 | } |
| 71 | |
Bruce Mitchener | 13d21e9 | 2015-10-07 16:56:17 +0000 | [diff] [blame] | 72 | ~OptionGroupReadMemory () override |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 73 | { |
| 74 | } |
| 75 | |
| 76 | |
Bruce Mitchener | 13d21e9 | 2015-10-07 16:56:17 +0000 | [diff] [blame] | 77 | uint32_t |
| 78 | GetNumDefinitions () override |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 79 | { |
| 80 | return sizeof (g_option_table) / sizeof (OptionDefinition); |
| 81 | } |
| 82 | |
Bruce Mitchener | 13d21e9 | 2015-10-07 16:56:17 +0000 | [diff] [blame] | 83 | const OptionDefinition* |
| 84 | GetDefinitions () override |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 85 | { |
| 86 | return g_option_table; |
| 87 | } |
| 88 | |
Bruce Mitchener | 13d21e9 | 2015-10-07 16:56:17 +0000 | [diff] [blame] | 89 | Error |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 90 | SetOptionValue (CommandInterpreter &interpreter, |
| 91 | uint32_t option_idx, |
Bruce Mitchener | 13d21e9 | 2015-10-07 16:56:17 +0000 | [diff] [blame] | 92 | const char *option_arg) override |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 93 | { |
| 94 | Error error; |
Greg Clayton | 3bcdfc0 | 2012-12-04 00:32:51 +0000 | [diff] [blame] | 95 | const int short_option = g_option_table[option_idx].short_option; |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 96 | |
| 97 | switch (short_option) |
| 98 | { |
| 99 | case 'l': |
Pavel Labath | c95f7e2 | 2015-02-20 11:14:59 +0000 | [diff] [blame] | 100 | error = m_num_per_line.SetValueFromString (option_arg); |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 101 | if (m_num_per_line.GetCurrentValue() == 0) |
Greg Clayton | 86edbf4 | 2011-10-26 00:56:27 +0000 | [diff] [blame] | 102 | error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg); |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 103 | break; |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 104 | |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 105 | case 'b': |
| 106 | m_output_as_binary = true; |
| 107 | break; |
| 108 | |
| 109 | case 't': |
Pavel Labath | c95f7e2 | 2015-02-20 11:14:59 +0000 | [diff] [blame] | 110 | error = m_view_as_type.SetValueFromString (option_arg); |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 111 | break; |
Sean Callanan | 1276c33 | 2012-04-28 01:27:38 +0000 | [diff] [blame] | 112 | |
| 113 | case 'r': |
| 114 | m_force = true; |
| 115 | break; |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 116 | |
Tamas Berghammer | aaaa157 | 2015-11-04 19:32:01 +0000 | [diff] [blame] | 117 | case 'E': |
Enrico Granata | 7a33621 | 2015-10-29 23:40:24 +0000 | [diff] [blame] | 118 | error = m_offset.SetValueFromString(option_arg); |
| 119 | break; |
| 120 | |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 121 | default: |
Greg Clayton | 86edbf4 | 2011-10-26 00:56:27 +0000 | [diff] [blame] | 122 | error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 123 | break; |
| 124 | } |
| 125 | return error; |
| 126 | } |
| 127 | |
Bruce Mitchener | 13d21e9 | 2015-10-07 16:56:17 +0000 | [diff] [blame] | 128 | void |
| 129 | OptionParsingStarting (CommandInterpreter &interpreter) override |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 130 | { |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 131 | m_num_per_line.Clear(); |
| 132 | m_output_as_binary = false; |
| 133 | m_view_as_type.Clear(); |
Enrico Granata | d325bf9 | 2013-06-04 22:54:16 +0000 | [diff] [blame] | 134 | m_force = false; |
Enrico Granata | 7a33621 | 2015-10-29 23:40:24 +0000 | [diff] [blame] | 135 | m_offset.Clear(); |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 136 | } |
| 137 | |
Greg Clayton | 68ebae6 | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 138 | Error |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 139 | FinalizeSettings (Target *target, OptionGroupFormat& format_options) |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 140 | { |
Greg Clayton | 68ebae6 | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 141 | Error error; |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 142 | OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue(); |
| 143 | OptionValueUInt64 &count_value = format_options.GetCountValue(); |
Greg Clayton | 86edbf4 | 2011-10-26 00:56:27 +0000 | [diff] [blame] | 144 | const bool byte_size_option_set = byte_size_value.OptionWasSet(); |
Greg Clayton | 68ebae6 | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 145 | const bool num_per_line_option_set = m_num_per_line.OptionWasSet(); |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 146 | const bool count_option_set = format_options.GetCountValue().OptionWasSet(); |
Greg Clayton | 68ebae6 | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 147 | |
Greg Clayton | 68ebae6 | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 148 | switch (format_options.GetFormat()) |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 149 | { |
| 150 | default: |
| 151 | break; |
| 152 | |
| 153 | case eFormatBoolean: |
Greg Clayton | 68ebae6 | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 154 | if (!byte_size_option_set) |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 155 | byte_size_value = 1; |
Greg Clayton | 68ebae6 | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 156 | if (!num_per_line_option_set) |
| 157 | m_num_per_line = 1; |
| 158 | if (!count_option_set) |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 159 | format_options.GetCountValue() = 8; |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 160 | break; |
| 161 | |
| 162 | case eFormatCString: |
| 163 | break; |
Greg Clayton | 5009f9d | 2011-10-27 17:55:14 +0000 | [diff] [blame] | 164 | |
| 165 | case eFormatInstruction: |
| 166 | if (count_option_set) |
Jim Ingham | d073fe4 | 2012-11-07 01:52:04 +0000 | [diff] [blame] | 167 | byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize(); |
Greg Clayton | 5009f9d | 2011-10-27 17:55:14 +0000 | [diff] [blame] | 168 | m_num_per_line = 1; |
| 169 | break; |
| 170 | |
| 171 | case eFormatAddressInfo: |
| 172 | if (!byte_size_option_set) |
| 173 | byte_size_value = target->GetArchitecture().GetAddressByteSize(); |
| 174 | m_num_per_line = 1; |
| 175 | if (!count_option_set) |
| 176 | format_options.GetCountValue() = 8; |
| 177 | break; |
| 178 | |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 179 | case eFormatPointer: |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 180 | byte_size_value = target->GetArchitecture().GetAddressByteSize(); |
Greg Clayton | 68ebae6 | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 181 | if (!num_per_line_option_set) |
| 182 | m_num_per_line = 4; |
| 183 | if (!count_option_set) |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 184 | format_options.GetCountValue() = 8; |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 185 | break; |
| 186 | |
| 187 | case eFormatBinary: |
| 188 | case eFormatFloat: |
| 189 | case eFormatOctal: |
| 190 | case eFormatDecimal: |
| 191 | case eFormatEnum: |
| 192 | case eFormatUnicode16: |
| 193 | case eFormatUnicode32: |
| 194 | case eFormatUnsigned: |
Greg Clayton | 5009f9d | 2011-10-27 17:55:14 +0000 | [diff] [blame] | 195 | case eFormatHexFloat: |
Greg Clayton | 68ebae6 | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 196 | if (!byte_size_option_set) |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 197 | byte_size_value = 4; |
Greg Clayton | 68ebae6 | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 198 | if (!num_per_line_option_set) |
| 199 | m_num_per_line = 1; |
| 200 | if (!count_option_set) |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 201 | format_options.GetCountValue() = 8; |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 202 | break; |
Greg Clayton | 5009f9d | 2011-10-27 17:55:14 +0000 | [diff] [blame] | 203 | |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 204 | case eFormatBytes: |
| 205 | case eFormatBytesWithASCII: |
Greg Clayton | 86edbf4 | 2011-10-26 00:56:27 +0000 | [diff] [blame] | 206 | if (byte_size_option_set) |
Greg Clayton | 68ebae6 | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 207 | { |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 208 | if (byte_size_value > 1) |
Daniel Malea | d01b295 | 2012-11-29 21:49:15 +0000 | [diff] [blame] | 209 | error.SetErrorStringWithFormat ("display format (bytes/bytes with ascii) conflicts with the specified byte size %" PRIu64 "\n" |
Johnny Chen | da324de | 2012-03-06 01:17:59 +0000 | [diff] [blame] | 210 | "\tconsider using a different display format or don't specify the byte size", |
| 211 | byte_size_value.GetCurrentValue()); |
Greg Clayton | 68ebae6 | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 212 | } |
| 213 | else |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 214 | byte_size_value = 1; |
Greg Clayton | 68ebae6 | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 215 | if (!num_per_line_option_set) |
| 216 | m_num_per_line = 16; |
| 217 | if (!count_option_set) |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 218 | format_options.GetCountValue() = 32; |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 219 | break; |
Greg Clayton | 4e4294b | 2011-06-17 23:50:44 +0000 | [diff] [blame] | 220 | case eFormatCharArray: |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 221 | case eFormatChar: |
| 222 | case eFormatCharPrintable: |
Greg Clayton | 68ebae6 | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 223 | if (!byte_size_option_set) |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 224 | byte_size_value = 1; |
Greg Clayton | 68ebae6 | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 225 | if (!num_per_line_option_set) |
| 226 | m_num_per_line = 32; |
| 227 | if (!count_option_set) |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 228 | format_options.GetCountValue() = 64; |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 229 | break; |
| 230 | case eFormatComplex: |
Greg Clayton | 68ebae6 | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 231 | if (!byte_size_option_set) |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 232 | byte_size_value = 8; |
Greg Clayton | 68ebae6 | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 233 | if (!num_per_line_option_set) |
| 234 | m_num_per_line = 1; |
| 235 | if (!count_option_set) |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 236 | format_options.GetCountValue() = 8; |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 237 | break; |
Jason Molenda | fc306d3 | 2013-03-23 05:16:54 +0000 | [diff] [blame] | 238 | case eFormatComplexInteger: |
| 239 | if (!byte_size_option_set) |
| 240 | byte_size_value = 8; |
| 241 | if (!num_per_line_option_set) |
| 242 | m_num_per_line = 1; |
| 243 | if (!count_option_set) |
| 244 | format_options.GetCountValue() = 8; |
| 245 | break; |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 246 | case eFormatHex: |
Greg Clayton | 68ebae6 | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 247 | if (!byte_size_option_set) |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 248 | byte_size_value = 4; |
Greg Clayton | 68ebae6 | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 249 | if (!num_per_line_option_set) |
| 250 | { |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 251 | switch (byte_size_value) |
Greg Clayton | 68ebae6 | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 252 | { |
| 253 | case 1: |
| 254 | case 2: |
| 255 | m_num_per_line = 8; |
| 256 | break; |
| 257 | case 4: |
| 258 | m_num_per_line = 4; |
| 259 | break; |
| 260 | case 8: |
| 261 | m_num_per_line = 2; |
| 262 | break; |
| 263 | default: |
| 264 | m_num_per_line = 1; |
| 265 | break; |
| 266 | } |
| 267 | } |
| 268 | if (!count_option_set) |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 269 | count_value = 8; |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 270 | break; |
| 271 | |
| 272 | case eFormatVectorOfChar: |
| 273 | case eFormatVectorOfSInt8: |
| 274 | case eFormatVectorOfUInt8: |
| 275 | case eFormatVectorOfSInt16: |
| 276 | case eFormatVectorOfUInt16: |
| 277 | case eFormatVectorOfSInt32: |
| 278 | case eFormatVectorOfUInt32: |
| 279 | case eFormatVectorOfSInt64: |
| 280 | case eFormatVectorOfUInt64: |
Ewan Crawford | a0f0867 | 2015-10-16 08:28:47 +0000 | [diff] [blame] | 281 | case eFormatVectorOfFloat16: |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 282 | case eFormatVectorOfFloat32: |
| 283 | case eFormatVectorOfFloat64: |
| 284 | case eFormatVectorOfUInt128: |
Greg Clayton | 68ebae6 | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 285 | if (!byte_size_option_set) |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 286 | byte_size_value = 128; |
Greg Clayton | 68ebae6 | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 287 | if (!num_per_line_option_set) |
| 288 | m_num_per_line = 1; |
| 289 | if (!count_option_set) |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 290 | count_value = 4; |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 291 | break; |
| 292 | } |
Greg Clayton | 68ebae6 | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 293 | return error; |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 294 | } |
| 295 | |
Greg Clayton | 82f4cf4 | 2011-10-26 04:32:38 +0000 | [diff] [blame] | 296 | bool |
| 297 | AnyOptionWasSet () const |
| 298 | { |
| 299 | return m_num_per_line.OptionWasSet() || |
| 300 | m_output_as_binary || |
Enrico Granata | 7a33621 | 2015-10-29 23:40:24 +0000 | [diff] [blame] | 301 | m_view_as_type.OptionWasSet() || |
| 302 | m_offset.OptionWasSet(); |
Greg Clayton | 82f4cf4 | 2011-10-26 04:32:38 +0000 | [diff] [blame] | 303 | } |
| 304 | |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 305 | OptionValueUInt64 m_num_per_line; |
| 306 | bool m_output_as_binary; |
| 307 | OptionValueString m_view_as_type; |
Sean Callanan | 1276c33 | 2012-04-28 01:27:38 +0000 | [diff] [blame] | 308 | bool m_force; |
Enrico Granata | 7a33621 | 2015-10-29 23:40:24 +0000 | [diff] [blame] | 309 | OptionValueUInt64 m_offset; |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 310 | }; |
| 311 | |
| 312 | |
| 313 | |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 314 | //---------------------------------------------------------------------- |
| 315 | // Read memory from the inferior process |
| 316 | //---------------------------------------------------------------------- |
Jim Ingham | 5a98841 | 2012-06-08 21:56:10 +0000 | [diff] [blame] | 317 | class CommandObjectMemoryRead : public CommandObjectParsed |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 318 | { |
| 319 | public: |
| 320 | |
Greg Clayton | a701509 | 2010-09-18 01:14:36 +0000 | [diff] [blame] | 321 | CommandObjectMemoryRead (CommandInterpreter &interpreter) : |
Jim Ingham | 5a98841 | 2012-06-08 21:56:10 +0000 | [diff] [blame] | 322 | CommandObjectParsed (interpreter, |
| 323 | "memory read", |
| 324 | "Read from the memory of the process being debugged.", |
| 325 | NULL, |
Enrico Granata | e87764f | 2015-05-27 05:04:35 +0000 | [diff] [blame] | 326 | eCommandRequiresTarget | eCommandProcessMustBePaused), |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 327 | m_option_group (interpreter), |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 328 | m_format_options (eFormatBytesWithASCII, 1, 8), |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 329 | m_memory_options (), |
Greg Clayton | 68ebae6 | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 330 | m_outfile_options (), |
Greg Clayton | 82f4cf4 | 2011-10-26 04:32:38 +0000 | [diff] [blame] | 331 | m_varobj_options(), |
| 332 | m_next_addr(LLDB_INVALID_ADDRESS), |
| 333 | m_prev_byte_size(0), |
| 334 | m_prev_format_options (eFormatBytesWithASCII, 1, 8), |
| 335 | m_prev_memory_options (), |
| 336 | m_prev_outfile_options (), |
| 337 | m_prev_varobj_options() |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 338 | { |
Caroline Tice | 405fe67 | 2010-10-04 22:28:36 +0000 | [diff] [blame] | 339 | CommandArgumentEntry arg1; |
| 340 | CommandArgumentEntry arg2; |
| 341 | CommandArgumentData start_addr_arg; |
| 342 | CommandArgumentData end_addr_arg; |
| 343 | |
| 344 | // Define the first (and only) variant of this arg. |
Enrico Granata | b84a9db | 2013-01-29 01:48:30 +0000 | [diff] [blame] | 345 | start_addr_arg.arg_type = eArgTypeAddressOrExpression; |
Caroline Tice | 405fe67 | 2010-10-04 22:28:36 +0000 | [diff] [blame] | 346 | start_addr_arg.arg_repetition = eArgRepeatPlain; |
| 347 | |
| 348 | // There is only one variant this argument could be; put it into the argument entry. |
| 349 | arg1.push_back (start_addr_arg); |
| 350 | |
| 351 | // Define the first (and only) variant of this arg. |
Enrico Granata | b84a9db | 2013-01-29 01:48:30 +0000 | [diff] [blame] | 352 | end_addr_arg.arg_type = eArgTypeAddressOrExpression; |
Caroline Tice | 405fe67 | 2010-10-04 22:28:36 +0000 | [diff] [blame] | 353 | end_addr_arg.arg_repetition = eArgRepeatOptional; |
| 354 | |
| 355 | // There is only one variant this argument could be; put it into the argument entry. |
| 356 | arg2.push_back (end_addr_arg); |
| 357 | |
| 358 | // Push the data for the first argument into the m_arguments vector. |
| 359 | m_arguments.push_back (arg1); |
| 360 | m_arguments.push_back (arg2); |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 361 | |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 362 | // Add the "--format" and "--count" options to group 1 and 3 |
| 363 | m_option_group.Append (&m_format_options, |
| 364 | OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT, |
Greg Clayton | 8388955 | 2011-11-22 18:07:35 +0000 | [diff] [blame] | 365 | LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3); |
Greg Clayton | 5009f9d | 2011-10-27 17:55:14 +0000 | [diff] [blame] | 366 | m_option_group.Append (&m_format_options, |
| 367 | OptionGroupFormat::OPTION_GROUP_GDB_FMT, |
Greg Clayton | 8388955 | 2011-11-22 18:07:35 +0000 | [diff] [blame] | 368 | LLDB_OPT_SET_1 | LLDB_OPT_SET_3); |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 369 | // Add the "--size" option to group 1 and 2 |
| 370 | m_option_group.Append (&m_format_options, |
| 371 | OptionGroupFormat::OPTION_GROUP_SIZE, |
| 372 | LLDB_OPT_SET_1 | LLDB_OPT_SET_2); |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 373 | m_option_group.Append (&m_memory_options); |
| 374 | m_option_group.Append (&m_outfile_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3); |
Greg Clayton | 68ebae6 | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 375 | m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3); |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 376 | m_option_group.Finalize(); |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 377 | } |
| 378 | |
Bruce Mitchener | 13d21e9 | 2015-10-07 16:56:17 +0000 | [diff] [blame] | 379 | ~CommandObjectMemoryRead () override |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 380 | { |
| 381 | } |
| 382 | |
| 383 | Options * |
Bruce Mitchener | 13d21e9 | 2015-10-07 16:56:17 +0000 | [diff] [blame] | 384 | GetOptions () override |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 385 | { |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 386 | return &m_option_group; |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 387 | } |
| 388 | |
Bruce Mitchener | 13d21e9 | 2015-10-07 16:56:17 +0000 | [diff] [blame] | 389 | const char * |
| 390 | GetRepeatCommand (Args ¤t_command_args, uint32_t index) override |
Greg Clayton | 82f4cf4 | 2011-10-26 04:32:38 +0000 | [diff] [blame] | 391 | { |
| 392 | return m_cmd_name.c_str(); |
| 393 | } |
| 394 | |
Jim Ingham | 5a98841 | 2012-06-08 21:56:10 +0000 | [diff] [blame] | 395 | protected: |
Bruce Mitchener | 13d21e9 | 2015-10-07 16:56:17 +0000 | [diff] [blame] | 396 | bool |
| 397 | DoExecute (Args& command, CommandReturnObject &result) override |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 398 | { |
Enrico Granata | e87764f | 2015-05-27 05:04:35 +0000 | [diff] [blame] | 399 | // No need to check "target" for validity as eCommandRequiresTarget ensures it is valid |
Greg Clayton | f9fc609 | 2013-01-09 19:44:40 +0000 | [diff] [blame] | 400 | Target *target = m_exe_ctx.GetTargetPtr(); |
| 401 | |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 402 | const size_t argc = command.GetArgumentCount(); |
| 403 | |
Greg Clayton | 82f4cf4 | 2011-10-26 04:32:38 +0000 | [diff] [blame] | 404 | if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2) |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 405 | { |
Greg Clayton | b9d5df5 | 2012-12-06 22:49:16 +0000 | [diff] [blame] | 406 | result.AppendErrorWithFormat ("%s takes a start address expression with an optional end address expression.\n", m_cmd_name.c_str()); |
Greg Clayton | 2e1f745 | 2012-12-15 02:08:17 +0000 | [diff] [blame] | 407 | result.AppendRawWarning("Expressions should be quoted if they contain spaces or other special characters.\n"); |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 408 | result.SetStatus(eReturnStatusFailed); |
| 409 | return false; |
| 410 | } |
| 411 | |
Greg Clayton | a1e5dc8 | 2015-08-11 22:53:00 +0000 | [diff] [blame] | 412 | CompilerType clang_ast_type; |
Greg Clayton | 68ebae6 | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 413 | Error error; |
| 414 | |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 415 | const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue(); |
| 416 | if (view_as_type_cstr && view_as_type_cstr[0]) |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 417 | { |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 418 | // We are viewing memory as a type |
Greg Clayton | 2e1f745 | 2012-12-15 02:08:17 +0000 | [diff] [blame] | 419 | |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 420 | SymbolContext sc; |
Greg Clayton | 84db910 | 2012-03-26 23:03:23 +0000 | [diff] [blame] | 421 | const bool exact_match = false; |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 422 | TypeList type_list; |
| 423 | uint32_t reference_count = 0; |
| 424 | uint32_t pointer_count = 0; |
| 425 | size_t idx; |
Sean Callanan | 17cf113 | 2012-07-10 21:24:26 +0000 | [diff] [blame] | 426 | |
| 427 | #define ALL_KEYWORDS \ |
| 428 | KEYWORD("const") \ |
| 429 | KEYWORD("volatile") \ |
| 430 | KEYWORD("restrict") \ |
| 431 | KEYWORD("struct") \ |
| 432 | KEYWORD("class") \ |
| 433 | KEYWORD("union") |
| 434 | |
| 435 | #define KEYWORD(s) s, |
| 436 | static const char *g_keywords[] = |
| 437 | { |
| 438 | ALL_KEYWORDS |
| 439 | }; |
| 440 | #undef KEYWORD |
| 441 | |
| 442 | #define KEYWORD(s) (sizeof(s) - 1), |
| 443 | static const int g_keyword_lengths[] = |
| 444 | { |
| 445 | ALL_KEYWORDS |
| 446 | }; |
| 447 | #undef KEYWORD |
| 448 | |
| 449 | #undef ALL_KEYWORDS |
| 450 | |
| 451 | static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *); |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 452 | std::string type_str(view_as_type_cstr); |
| 453 | |
| 454 | // Remove all instances of g_keywords that are followed by spaces |
| 455 | for (size_t i = 0; i < g_num_keywords; ++i) |
| 456 | { |
| 457 | const char *keyword = g_keywords[i]; |
Sean Callanan | 17cf113 | 2012-07-10 21:24:26 +0000 | [diff] [blame] | 458 | int keyword_len = g_keyword_lengths[i]; |
| 459 | |
| 460 | idx = 0; |
| 461 | while ((idx = type_str.find (keyword, idx)) != std::string::npos) |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 462 | { |
| 463 | if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t') |
Sean Callanan | 17cf113 | 2012-07-10 21:24:26 +0000 | [diff] [blame] | 464 | { |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 465 | type_str.erase(idx, keyword_len+1); |
Sean Callanan | 17cf113 | 2012-07-10 21:24:26 +0000 | [diff] [blame] | 466 | idx = 0; |
| 467 | } |
| 468 | else |
| 469 | { |
| 470 | idx += keyword_len; |
| 471 | } |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 472 | } |
| 473 | } |
| 474 | bool done = type_str.empty(); |
| 475 | // |
| 476 | idx = type_str.find_first_not_of (" \t"); |
| 477 | if (idx > 0 && idx != std::string::npos) |
| 478 | type_str.erase (0, idx); |
| 479 | while (!done) |
| 480 | { |
| 481 | // Strip trailing spaces |
| 482 | if (type_str.empty()) |
| 483 | done = true; |
| 484 | else |
| 485 | { |
| 486 | switch (type_str[type_str.size()-1]) |
| 487 | { |
| 488 | case '*': |
| 489 | ++pointer_count; |
| 490 | // fall through... |
| 491 | case ' ': |
| 492 | case '\t': |
| 493 | type_str.erase(type_str.size()-1); |
| 494 | break; |
| 495 | |
| 496 | case '&': |
| 497 | if (reference_count == 0) |
| 498 | { |
| 499 | reference_count = 1; |
| 500 | type_str.erase(type_str.size()-1); |
| 501 | } |
| 502 | else |
| 503 | { |
| 504 | result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr); |
| 505 | result.SetStatus(eReturnStatusFailed); |
| 506 | return false; |
| 507 | } |
| 508 | break; |
| 509 | |
| 510 | default: |
| 511 | done = true; |
| 512 | break; |
| 513 | } |
| 514 | } |
| 515 | } |
| 516 | |
| 517 | ConstString lookup_type_name(type_str.c_str()); |
Jason Molenda | b57e4a1 | 2013-11-04 09:33:30 +0000 | [diff] [blame] | 518 | StackFrame *frame = m_exe_ctx.GetFramePtr(); |
Greg Clayton | c14ee32 | 2011-09-22 04:58:26 +0000 | [diff] [blame] | 519 | if (frame) |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 520 | { |
Greg Clayton | c14ee32 | 2011-09-22 04:58:26 +0000 | [diff] [blame] | 521 | sc = frame->GetSymbolContext (eSymbolContextModule); |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 522 | if (sc.module_sp) |
| 523 | { |
Sean Callanan | b6d70eb | 2011-10-12 02:08:07 +0000 | [diff] [blame] | 524 | sc.module_sp->FindTypes (sc, |
| 525 | lookup_type_name, |
Greg Clayton | 84db910 | 2012-03-26 23:03:23 +0000 | [diff] [blame] | 526 | exact_match, |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 527 | 1, |
| 528 | type_list); |
| 529 | } |
| 530 | } |
| 531 | if (type_list.GetSize() == 0) |
| 532 | { |
Greg Clayton | 29399a2 | 2012-04-06 17:41:13 +0000 | [diff] [blame] | 533 | target->GetImages().FindTypes (sc, |
Greg Clayton | c14ee32 | 2011-09-22 04:58:26 +0000 | [diff] [blame] | 534 | lookup_type_name, |
Greg Clayton | 84db910 | 2012-03-26 23:03:23 +0000 | [diff] [blame] | 535 | exact_match, |
Greg Clayton | c14ee32 | 2011-09-22 04:58:26 +0000 | [diff] [blame] | 536 | 1, |
| 537 | type_list); |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 538 | } |
Saleem Abdulrasool | ba507b0 | 2015-10-18 19:34:38 +0000 | [diff] [blame] | 539 | |
Enrico Granata | 7bd2bbb | 2013-06-11 18:47:55 +0000 | [diff] [blame] | 540 | if (type_list.GetSize() == 0 && lookup_type_name.GetCString() && *lookup_type_name.GetCString() == '$') |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 541 | { |
Sean Callanan | b92bd75 | 2015-10-01 16:28:02 +0000 | [diff] [blame] | 542 | if (ClangPersistentVariables *persistent_vars = llvm::dyn_cast_or_null<ClangPersistentVariables>(target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC))) |
Enrico Granata | 7bd2bbb | 2013-06-11 18:47:55 +0000 | [diff] [blame] | 543 | { |
Sean Callanan | b92bd75 | 2015-10-01 16:28:02 +0000 | [diff] [blame] | 544 | clang::TypeDecl *tdecl = persistent_vars->GetPersistentType(ConstString(lookup_type_name)); |
Saleem Abdulrasool | ba507b0 | 2015-10-18 19:34:38 +0000 | [diff] [blame] | 545 | |
Sean Callanan | b92bd75 | 2015-10-01 16:28:02 +0000 | [diff] [blame] | 546 | if (tdecl) |
| 547 | { |
Saleem Abdulrasool | ba507b0 | 2015-10-18 19:34:38 +0000 | [diff] [blame] | 548 | clang_ast_type.SetCompilerType(ClangASTContext::GetASTContext(&tdecl->getASTContext()), |
| 549 | reinterpret_cast<lldb::opaque_compiler_type_t>(const_cast<clang::Type*>(tdecl->getTypeForDecl()))); |
Sean Callanan | b92bd75 | 2015-10-01 16:28:02 +0000 | [diff] [blame] | 550 | } |
Enrico Granata | 7bd2bbb | 2013-06-11 18:47:55 +0000 | [diff] [blame] | 551 | } |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 552 | } |
Saleem Abdulrasool | ba507b0 | 2015-10-18 19:34:38 +0000 | [diff] [blame] | 553 | |
Enrico Granata | 7bd2bbb | 2013-06-11 18:47:55 +0000 | [diff] [blame] | 554 | if (clang_ast_type.IsValid() == false) |
| 555 | { |
| 556 | if (type_list.GetSize() == 0) |
| 557 | { |
| 558 | result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n", |
| 559 | lookup_type_name.GetCString(), |
| 560 | view_as_type_cstr); |
| 561 | result.SetStatus(eReturnStatusFailed); |
| 562 | return false; |
| 563 | } |
| 564 | else |
| 565 | { |
| 566 | TypeSP type_sp (type_list.GetTypeAtIndex(0)); |
Greg Clayton | 99558cc4 | 2015-08-24 23:46:31 +0000 | [diff] [blame] | 567 | clang_ast_type = type_sp->GetFullCompilerType (); |
Enrico Granata | 7bd2bbb | 2013-06-11 18:47:55 +0000 | [diff] [blame] | 568 | } |
| 569 | } |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 570 | |
| 571 | while (pointer_count > 0) |
| 572 | { |
Greg Clayton | a1e5dc8 | 2015-08-11 22:53:00 +0000 | [diff] [blame] | 573 | CompilerType pointer_type = clang_ast_type.GetPointerType(); |
Greg Clayton | 57ee306 | 2013-07-11 22:46:58 +0000 | [diff] [blame] | 574 | if (pointer_type.IsValid()) |
| 575 | clang_ast_type = pointer_type; |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 576 | else |
| 577 | { |
| 578 | result.AppendError ("unable make a pointer type\n"); |
| 579 | result.SetStatus(eReturnStatusFailed); |
| 580 | return false; |
| 581 | } |
| 582 | --pointer_count; |
| 583 | } |
| 584 | |
Enrico Granata | 1cd5e92 | 2015-01-28 00:07:51 +0000 | [diff] [blame] | 585 | m_format_options.GetByteSizeValue() = clang_ast_type.GetByteSize(nullptr); |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 586 | |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 587 | if (m_format_options.GetByteSizeValue() == 0) |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 588 | { |
| 589 | result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n", |
| 590 | view_as_type_cstr); |
| 591 | result.SetStatus(eReturnStatusFailed); |
| 592 | return false; |
| 593 | } |
Greg Clayton | 68ebae6 | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 594 | |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 595 | if (!m_format_options.GetCountValue().OptionWasSet()) |
| 596 | m_format_options.GetCountValue() = 1; |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 597 | } |
| 598 | else |
| 599 | { |
Greg Clayton | c14ee32 | 2011-09-22 04:58:26 +0000 | [diff] [blame] | 600 | error = m_memory_options.FinalizeSettings (target, m_format_options); |
Greg Clayton | 68ebae6 | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 601 | } |
| 602 | |
| 603 | // Look for invalid combinations of settings |
| 604 | if (error.Fail()) |
| 605 | { |
Greg Clayton | b9d5df5 | 2012-12-06 22:49:16 +0000 | [diff] [blame] | 606 | result.AppendError(error.AsCString()); |
Greg Clayton | 68ebae6 | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 607 | result.SetStatus(eReturnStatusFailed); |
| 608 | return false; |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 609 | } |
| 610 | |
Greg Clayton | 82f4cf4 | 2011-10-26 04:32:38 +0000 | [diff] [blame] | 611 | lldb::addr_t addr; |
| 612 | size_t total_byte_size = 0; |
| 613 | if (argc == 0) |
| 614 | { |
| 615 | // Use the last address and byte size and all options as they were |
| 616 | // if no options have been set |
| 617 | addr = m_next_addr; |
| 618 | total_byte_size = m_prev_byte_size; |
Greg Clayton | 2e1f745 | 2012-12-15 02:08:17 +0000 | [diff] [blame] | 619 | clang_ast_type = m_prev_clang_ast_type; |
| 620 | if (!m_format_options.AnyOptionWasSet() && |
Greg Clayton | 82f4cf4 | 2011-10-26 04:32:38 +0000 | [diff] [blame] | 621 | !m_memory_options.AnyOptionWasSet() && |
| 622 | !m_outfile_options.AnyOptionWasSet() && |
| 623 | !m_varobj_options.AnyOptionWasSet()) |
| 624 | { |
| 625 | m_format_options = m_prev_format_options; |
| 626 | m_memory_options = m_prev_memory_options; |
| 627 | m_outfile_options = m_prev_outfile_options; |
| 628 | m_varobj_options = m_prev_varobj_options; |
| 629 | } |
| 630 | } |
| 631 | |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 632 | size_t item_count = m_format_options.GetCountValue().GetCurrentValue(); |
Matthew Gardiner | f03e6d84 | 2014-09-29 08:02:24 +0000 | [diff] [blame] | 633 | |
| 634 | // TODO For non-8-bit byte addressable architectures this needs to be |
| 635 | // revisited to fully support all lldb's range of formatting options. |
| 636 | // Furthermore code memory reads (for those architectures) will not |
| 637 | // be correctly formatted even w/o formatting options. |
| 638 | size_t item_byte_size = |
| 639 | target->GetArchitecture().GetDataByteSize() > 1 ? |
| 640 | target->GetArchitecture().GetDataByteSize() : |
| 641 | m_format_options.GetByteSizeValue().GetCurrentValue(); |
| 642 | |
Greg Clayton | 68ebae6 | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 643 | const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue(); |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 644 | |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 645 | if (total_byte_size == 0) |
Greg Clayton | 82f4cf4 | 2011-10-26 04:32:38 +0000 | [diff] [blame] | 646 | { |
| 647 | total_byte_size = item_count * item_byte_size; |
| 648 | if (total_byte_size == 0) |
| 649 | total_byte_size = 32; |
| 650 | } |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 651 | |
Greg Clayton | 82f4cf4 | 2011-10-26 04:32:38 +0000 | [diff] [blame] | 652 | if (argc > 0) |
Greg Clayton | f9fc609 | 2013-01-09 19:44:40 +0000 | [diff] [blame] | 653 | addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, &error); |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 654 | |
| 655 | if (addr == LLDB_INVALID_ADDRESS) |
| 656 | { |
Greg Clayton | b9d5df5 | 2012-12-06 22:49:16 +0000 | [diff] [blame] | 657 | result.AppendError("invalid start address expression."); |
| 658 | result.AppendError(error.AsCString()); |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 659 | result.SetStatus(eReturnStatusFailed); |
| 660 | return false; |
| 661 | } |
| 662 | |
| 663 | if (argc == 2) |
| 664 | { |
Greg Clayton | f9fc609 | 2013-01-09 19:44:40 +0000 | [diff] [blame] | 665 | lldb::addr_t end_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0); |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 666 | if (end_addr == LLDB_INVALID_ADDRESS) |
| 667 | { |
Greg Clayton | b9d5df5 | 2012-12-06 22:49:16 +0000 | [diff] [blame] | 668 | result.AppendError("invalid end address expression."); |
| 669 | result.AppendError(error.AsCString()); |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 670 | result.SetStatus(eReturnStatusFailed); |
| 671 | return false; |
| 672 | } |
| 673 | else if (end_addr <= addr) |
| 674 | { |
Daniel Malea | d01b295 | 2012-11-29 21:49:15 +0000 | [diff] [blame] | 675 | result.AppendErrorWithFormat("end address (0x%" PRIx64 ") must be greater that the start address (0x%" PRIx64 ").\n", end_addr, addr); |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 676 | result.SetStatus(eReturnStatusFailed); |
| 677 | return false; |
| 678 | } |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 679 | else if (m_format_options.GetCountValue().OptionWasSet()) |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 680 | { |
Greg Clayton | 6fea17e | 2014-03-03 19:15:20 +0000 | [diff] [blame] | 681 | result.AppendErrorWithFormat("specify either the end address (0x%" PRIx64 ") or the count (--count %" PRIu64 "), not both.\n", end_addr, (uint64_t)item_count); |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 682 | result.SetStatus(eReturnStatusFailed); |
| 683 | return false; |
| 684 | } |
| 685 | |
| 686 | total_byte_size = end_addr - addr; |
| 687 | item_count = total_byte_size / item_byte_size; |
| 688 | } |
Matthew Gardiner | f03e6d84 | 2014-09-29 08:02:24 +0000 | [diff] [blame] | 689 | |
Enrico Granata | d325bf9 | 2013-06-04 22:54:16 +0000 | [diff] [blame] | 690 | uint32_t max_unforced_size = target->GetMaximumMemReadSize(); |
| 691 | |
| 692 | if (total_byte_size > max_unforced_size && !m_memory_options.m_force) |
Sean Callanan | 1276c33 | 2012-04-28 01:27:38 +0000 | [diff] [blame] | 693 | { |
Enrico Granata | d325bf9 | 2013-06-04 22:54:16 +0000 | [diff] [blame] | 694 | result.AppendErrorWithFormat("Normally, \'memory read\' will not read over %" PRIu32 " bytes of data.\n",max_unforced_size); |
| 695 | result.AppendErrorWithFormat("Please use --force to override this restriction just once.\n"); |
| 696 | result.AppendErrorWithFormat("or set target.max-memory-read-size if you will often need a larger limit.\n"); |
Sean Callanan | 1276c33 | 2012-04-28 01:27:38 +0000 | [diff] [blame] | 697 | return false; |
| 698 | } |
| 699 | |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 700 | DataBufferSP data_sp; |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 701 | size_t bytes_read = 0; |
Greg Clayton | 2e1f745 | 2012-12-15 02:08:17 +0000 | [diff] [blame] | 702 | if (clang_ast_type.GetOpaqueQualType()) |
| 703 | { |
| 704 | // Make sure we don't display our type as ASCII bytes like the default memory read |
| 705 | if (m_format_options.GetFormatValue().OptionWasSet() == false) |
| 706 | m_format_options.GetFormatValue().SetCurrentValue(eFormatDefault); |
| 707 | |
Enrico Granata | 1cd5e92 | 2015-01-28 00:07:51 +0000 | [diff] [blame] | 708 | bytes_read = clang_ast_type.GetByteSize(nullptr) * m_format_options.GetCountValue().GetCurrentValue(); |
Enrico Granata | 7a33621 | 2015-10-29 23:40:24 +0000 | [diff] [blame] | 709 | |
| 710 | if (argc > 0) |
| 711 | addr = addr + (clang_ast_type.GetByteSize(nullptr) * m_memory_options.m_offset.GetCurrentValue()); |
Greg Clayton | 2e1f745 | 2012-12-15 02:08:17 +0000 | [diff] [blame] | 712 | } |
Enrico Granata | 6b4ddc6 | 2013-01-21 19:20:50 +0000 | [diff] [blame] | 713 | else if (m_format_options.GetFormatValue().GetCurrentValue() != eFormatCString) |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 714 | { |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 715 | data_sp.reset (new DataBufferHeap (total_byte_size, '\0')); |
Greg Clayton | 46a4426 | 2013-07-24 18:17:35 +0000 | [diff] [blame] | 716 | if (data_sp->GetBytes() == NULL) |
| 717 | { |
Virgile Bello | ffeba25 | 2014-03-08 17:15:35 +0000 | [diff] [blame] | 718 | 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 Clayton | 46a4426 | 2013-07-24 18:17:35 +0000 | [diff] [blame] | 719 | result.SetStatus(eReturnStatusFailed); |
| 720 | return false; |
| 721 | } |
| 722 | |
Greg Clayton | e72dfb3 | 2012-02-24 01:59:29 +0000 | [diff] [blame] | 723 | Address address(addr, NULL); |
Greg Clayton | c14ee32 | 2011-09-22 04:58:26 +0000 | [diff] [blame] | 724 | bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error); |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 725 | if (bytes_read == 0) |
| 726 | { |
Greg Clayton | 57f0630 | 2012-05-25 17:05:55 +0000 | [diff] [blame] | 727 | const char *error_cstr = error.AsCString(); |
| 728 | if (error_cstr && error_cstr[0]) |
| 729 | { |
| 730 | result.AppendError(error_cstr); |
| 731 | } |
| 732 | else |
| 733 | { |
Daniel Malea | d01b295 | 2012-11-29 21:49:15 +0000 | [diff] [blame] | 734 | result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr); |
Greg Clayton | 57f0630 | 2012-05-25 17:05:55 +0000 | [diff] [blame] | 735 | } |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 736 | result.SetStatus(eReturnStatusFailed); |
| 737 | return false; |
| 738 | } |
| 739 | |
| 740 | if (bytes_read < total_byte_size) |
Greg Clayton | 6fea17e | 2014-03-03 19:15:20 +0000 | [diff] [blame] | 741 | 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 Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 742 | } |
Enrico Granata | 6b4ddc6 | 2013-01-21 19:20:50 +0000 | [diff] [blame] | 743 | else |
| 744 | { |
| 745 | // we treat c-strings as a special case because they do not have a fixed size |
| 746 | if (m_format_options.GetByteSizeValue().OptionWasSet() && !m_format_options.HasGDBFormat()) |
| 747 | item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue(); |
| 748 | else |
| 749 | item_byte_size = target->GetMaximumSizeOfStringSummary(); |
| 750 | if (!m_format_options.GetCountValue().OptionWasSet()) |
| 751 | item_count = 1; |
| 752 | data_sp.reset (new DataBufferHeap ((item_byte_size+1) * item_count, '\0')); // account for NULLs as necessary |
Greg Clayton | 46a4426 | 2013-07-24 18:17:35 +0000 | [diff] [blame] | 753 | if (data_sp->GetBytes() == NULL) |
| 754 | { |
| 755 | 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)); |
| 756 | result.SetStatus(eReturnStatusFailed); |
| 757 | return false; |
| 758 | } |
Enrico Granata | 6b4ddc6 | 2013-01-21 19:20:50 +0000 | [diff] [blame] | 759 | uint8_t *data_ptr = data_sp->GetBytes(); |
| 760 | auto data_addr = addr; |
| 761 | auto count = item_count; |
| 762 | item_count = 0; |
Enrico Granata | dc3c3ee | 2015-04-06 18:41:17 +0000 | [diff] [blame] | 763 | bool break_on_no_NULL = false; |
Enrico Granata | 6b4ddc6 | 2013-01-21 19:20:50 +0000 | [diff] [blame] | 764 | while (item_count < count) |
| 765 | { |
| 766 | std::string buffer; |
| 767 | buffer.resize(item_byte_size+1,0); |
| 768 | Error error; |
| 769 | size_t read = target->ReadCStringFromMemory(data_addr, &buffer[0], item_byte_size+1, error); |
| 770 | if (error.Fail()) |
| 771 | { |
| 772 | result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr); |
| 773 | result.SetStatus(eReturnStatusFailed); |
| 774 | return false; |
| 775 | } |
Enrico Granata | dc3c3ee | 2015-04-06 18:41:17 +0000 | [diff] [blame] | 776 | |
Enrico Granata | 6b4ddc6 | 2013-01-21 19:20:50 +0000 | [diff] [blame] | 777 | if (item_byte_size == read) |
| 778 | { |
| 779 | result.AppendWarningWithFormat("unable to find a NULL terminated string at 0x%" PRIx64 ".Consider increasing the maximum read length.\n", data_addr); |
Enrico Granata | dc3c3ee | 2015-04-06 18:41:17 +0000 | [diff] [blame] | 780 | --read; |
| 781 | break_on_no_NULL = true; |
Enrico Granata | 6b4ddc6 | 2013-01-21 19:20:50 +0000 | [diff] [blame] | 782 | } |
Enrico Granata | dc3c3ee | 2015-04-06 18:41:17 +0000 | [diff] [blame] | 783 | else |
| 784 | ++read; // account for final NULL byte |
| 785 | |
Enrico Granata | 6b4ddc6 | 2013-01-21 19:20:50 +0000 | [diff] [blame] | 786 | memcpy(data_ptr, &buffer[0], read); |
| 787 | data_ptr += read; |
| 788 | data_addr += read; |
| 789 | bytes_read += read; |
| 790 | item_count++; // if we break early we know we only read item_count strings |
Enrico Granata | dc3c3ee | 2015-04-06 18:41:17 +0000 | [diff] [blame] | 791 | |
| 792 | if (break_on_no_NULL) |
| 793 | break; |
Enrico Granata | 6b4ddc6 | 2013-01-21 19:20:50 +0000 | [diff] [blame] | 794 | } |
| 795 | data_sp.reset(new DataBufferHeap(data_sp->GetBytes(),bytes_read+1)); |
| 796 | } |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 797 | |
Greg Clayton | 2e1f745 | 2012-12-15 02:08:17 +0000 | [diff] [blame] | 798 | m_next_addr = addr + bytes_read; |
| 799 | m_prev_byte_size = bytes_read; |
| 800 | m_prev_format_options = m_format_options; |
| 801 | m_prev_memory_options = m_memory_options; |
| 802 | m_prev_outfile_options = m_outfile_options; |
| 803 | m_prev_varobj_options = m_varobj_options; |
| 804 | m_prev_clang_ast_type = clang_ast_type; |
| 805 | |
Greg Clayton | 6d7e77b | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 806 | StreamFile outfile_stream; |
| 807 | Stream *output_stream = NULL; |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 808 | const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue(); |
| 809 | if (outfile_spec) |
Greg Clayton | 6d7e77b | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 810 | { |
| 811 | char path[PATH_MAX]; |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 812 | outfile_spec.GetPath (path, sizeof(path)); |
| 813 | |
| 814 | uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate; |
| 815 | const bool append = m_outfile_options.GetAppend().GetCurrentValue(); |
| 816 | if (append) |
| 817 | open_options |= File::eOpenOptionAppend; |
| 818 | |
| 819 | if (outfile_stream.GetFile ().Open (path, open_options).Success()) |
Greg Clayton | 6d7e77b | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 820 | { |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 821 | if (m_memory_options.m_output_as_binary) |
Greg Clayton | 6d7e77b | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 822 | { |
Greg Clayton | c7bece56 | 2013-01-25 18:06:21 +0000 | [diff] [blame] | 823 | const size_t bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read); |
Greg Clayton | 6d7e77b | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 824 | if (bytes_written > 0) |
| 825 | { |
Greg Clayton | c7bece56 | 2013-01-25 18:06:21 +0000 | [diff] [blame] | 826 | result.GetOutputStream().Printf ("%zi bytes %s to '%s'\n", |
Greg Clayton | 6d7e77b | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 827 | bytes_written, |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 828 | append ? "appended" : "written", |
Greg Clayton | 6d7e77b | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 829 | path); |
| 830 | return true; |
| 831 | } |
| 832 | else |
| 833 | { |
Daniel Malea | d01b295 | 2012-11-29 21:49:15 +0000 | [diff] [blame] | 834 | result.AppendErrorWithFormat("Failed to write %" PRIu64 " bytes to '%s'.\n", (uint64_t)bytes_read, path); |
Greg Clayton | 6d7e77b | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 835 | result.SetStatus(eReturnStatusFailed); |
| 836 | return false; |
| 837 | } |
| 838 | } |
| 839 | else |
| 840 | { |
| 841 | // We are going to write ASCII to the file just point the |
| 842 | // output_stream to our outfile_stream... |
| 843 | output_stream = &outfile_stream; |
| 844 | } |
| 845 | } |
| 846 | else |
| 847 | { |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 848 | result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write"); |
Greg Clayton | 6d7e77b | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 849 | result.SetStatus(eReturnStatusFailed); |
| 850 | return false; |
| 851 | } |
| 852 | } |
| 853 | else |
| 854 | { |
| 855 | output_stream = &result.GetOutputStream(); |
| 856 | } |
| 857 | |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 858 | |
Greg Clayton | f9fc609 | 2013-01-09 19:44:40 +0000 | [diff] [blame] | 859 | ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope(); |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 860 | if (clang_ast_type.GetOpaqueQualType()) |
| 861 | { |
| 862 | for (uint32_t i = 0; i<item_count; ++i) |
| 863 | { |
| 864 | addr_t item_addr = addr + (i * item_byte_size); |
Greg Clayton | e72dfb3 | 2012-02-24 01:59:29 +0000 | [diff] [blame] | 865 | Address address (item_addr); |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 866 | StreamString name_strm; |
Daniel Malea | d01b295 | 2012-11-29 21:49:15 +0000 | [diff] [blame] | 867 | name_strm.Printf ("0x%" PRIx64, item_addr); |
Greg Clayton | 5009f9d | 2011-10-27 17:55:14 +0000 | [diff] [blame] | 868 | ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope, |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 869 | name_strm.GetString().c_str(), |
| 870 | address, |
| 871 | clang_ast_type)); |
| 872 | if (valobj_sp) |
| 873 | { |
Greg Clayton | 2e1f745 | 2012-12-15 02:08:17 +0000 | [diff] [blame] | 874 | Format format = m_format_options.GetFormat(); |
Greg Clayton | 68ebae6 | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 875 | if (format != eFormatDefault) |
| 876 | valobj_sp->SetFormat (format); |
| 877 | |
Enrico Granata | 4d93b8c | 2013-09-30 19:11:51 +0000 | [diff] [blame] | 878 | DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(eLanguageRuntimeDescriptionDisplayVerbosityFull,format)); |
Enrico Granata | 9fb5ab5 | 2013-03-26 18:04:53 +0000 | [diff] [blame] | 879 | |
Enrico Granata | 4d93b8c | 2013-09-30 19:11:51 +0000 | [diff] [blame] | 880 | valobj_sp->Dump(*output_stream,options); |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 881 | } |
| 882 | else |
| 883 | { |
| 884 | result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n", |
| 885 | view_as_type_cstr, |
| 886 | name_strm.GetString().c_str()); |
| 887 | result.SetStatus(eReturnStatusFailed); |
| 888 | return false; |
| 889 | } |
| 890 | } |
| 891 | return true; |
| 892 | } |
| 893 | |
| 894 | result.SetStatus(eReturnStatusSuccessFinishResult); |
| 895 | DataExtractor data (data_sp, |
Greg Clayton | c14ee32 | 2011-09-22 04:58:26 +0000 | [diff] [blame] | 896 | target->GetArchitecture().GetByteOrder(), |
Matthew Gardiner | f03e6d84 | 2014-09-29 08:02:24 +0000 | [diff] [blame] | 897 | target->GetArchitecture().GetAddressByteSize(), |
| 898 | target->GetArchitecture().GetDataByteSize()); |
Enrico Granata | 3189891 | 2013-05-21 17:39:04 +0000 | [diff] [blame] | 899 | |
| 900 | Format format = m_format_options.GetFormat(); |
| 901 | if ( ( (format == eFormatChar) || (format == eFormatCharPrintable) ) |
Enrico Granata | 0947a6e | 2013-10-29 23:04:29 +0000 | [diff] [blame] | 902 | && (item_byte_size != 1)) |
Enrico Granata | 3189891 | 2013-05-21 17:39:04 +0000 | [diff] [blame] | 903 | { |
Enrico Granata | 0947a6e | 2013-10-29 23:04:29 +0000 | [diff] [blame] | 904 | // if a count was not passed, or it is 1 |
| 905 | if (m_format_options.GetCountValue().OptionWasSet() == false || item_count == 1) |
| 906 | { |
| 907 | // this turns requests such as |
| 908 | // memory read -fc -s10 -c1 *charPtrPtr |
| 909 | // which make no sense (what is a char of size 10?) |
| 910 | // into a request for fetching 10 chars of size 1 from the same memory location |
| 911 | format = eFormatCharArray; |
| 912 | item_count = item_byte_size; |
| 913 | item_byte_size = 1; |
| 914 | } |
| 915 | else |
| 916 | { |
| 917 | // here we passed a count, and it was not 1 |
| 918 | // so we have a byte_size and a count |
| 919 | // we could well multiply those, but instead let's just fail |
Greg Clayton | 6fea17e | 2014-03-03 19:15:20 +0000 | [diff] [blame] | 920 | result.AppendErrorWithFormat("reading memory as characters of size %" PRIu64 " is not supported", (uint64_t)item_byte_size); |
Enrico Granata | 0947a6e | 2013-10-29 23:04:29 +0000 | [diff] [blame] | 921 | result.SetStatus(eReturnStatusFailed); |
| 922 | return false; |
| 923 | } |
Enrico Granata | 3189891 | 2013-05-21 17:39:04 +0000 | [diff] [blame] | 924 | } |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 925 | |
Greg Clayton | 6d7e77b | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 926 | assert (output_stream); |
Greg Clayton | c7bece56 | 2013-01-25 18:06:21 +0000 | [diff] [blame] | 927 | size_t bytes_dumped = data.Dump (output_stream, |
| 928 | 0, |
Enrico Granata | 3189891 | 2013-05-21 17:39:04 +0000 | [diff] [blame] | 929 | format, |
Greg Clayton | c7bece56 | 2013-01-25 18:06:21 +0000 | [diff] [blame] | 930 | item_byte_size, |
| 931 | item_count, |
Matthew Gardiner | f03e6d84 | 2014-09-29 08:02:24 +0000 | [diff] [blame] | 932 | num_per_line / target->GetArchitecture().GetDataByteSize(), |
Greg Clayton | c7bece56 | 2013-01-25 18:06:21 +0000 | [diff] [blame] | 933 | addr, |
| 934 | 0, |
| 935 | 0, |
| 936 | exe_scope); |
Greg Clayton | 1848afb | 2011-10-28 23:44:55 +0000 | [diff] [blame] | 937 | m_next_addr = addr + bytes_dumped; |
Greg Clayton | 6d7e77b | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 938 | output_stream->EOL(); |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 939 | return true; |
| 940 | } |
| 941 | |
Greg Clayton | 84c3966 | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 942 | OptionGroupOptions m_option_group; |
| 943 | OptionGroupFormat m_format_options; |
| 944 | OptionGroupReadMemory m_memory_options; |
| 945 | OptionGroupOutputFile m_outfile_options; |
Greg Clayton | 68ebae6 | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 946 | OptionGroupValueObjectDisplay m_varobj_options; |
Greg Clayton | 82f4cf4 | 2011-10-26 04:32:38 +0000 | [diff] [blame] | 947 | lldb::addr_t m_next_addr; |
| 948 | lldb::addr_t m_prev_byte_size; |
| 949 | OptionGroupFormat m_prev_format_options; |
| 950 | OptionGroupReadMemory m_prev_memory_options; |
| 951 | OptionGroupOutputFile m_prev_outfile_options; |
| 952 | OptionGroupValueObjectDisplay m_prev_varobj_options; |
Greg Clayton | a1e5dc8 | 2015-08-11 22:53:00 +0000 | [diff] [blame] | 953 | CompilerType m_prev_clang_ast_type; |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 954 | }; |
| 955 | |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 956 | OptionDefinition |
| 957 | g_memory_find_option_table[] = |
| 958 | { |
Zachary Turner | d37221d | 2014-07-09 16:31:49 +0000 | [diff] [blame] | 959 | { LLDB_OPT_SET_1, false, "expression", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeExpression, "Evaluate an expression to obtain a byte pattern."}, |
| 960 | { LLDB_OPT_SET_2, false, "string", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Use text to find a byte pattern."}, |
| 961 | { LLDB_OPT_SET_1|LLDB_OPT_SET_2, false, "count", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCount, "How many times to perform the search."}, |
| 962 | { 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 Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 963 | }; |
| 964 | |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 965 | //---------------------------------------------------------------------- |
| 966 | // Find the specified data in memory |
| 967 | //---------------------------------------------------------------------- |
| 968 | class CommandObjectMemoryFind : public CommandObjectParsed |
| 969 | { |
| 970 | public: |
| 971 | |
| 972 | class OptionGroupFindMemory : public OptionGroup |
| 973 | { |
| 974 | public: |
| 975 | OptionGroupFindMemory () : |
| 976 | OptionGroup(), |
| 977 | m_count(1), |
Enrico Granata | 8d81a84 | 2013-11-13 20:08:30 +0000 | [diff] [blame] | 978 | m_offset(0) |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 979 | { |
| 980 | } |
| 981 | |
Bruce Mitchener | 13d21e9 | 2015-10-07 16:56:17 +0000 | [diff] [blame] | 982 | ~OptionGroupFindMemory () override |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 983 | { |
| 984 | } |
| 985 | |
Bruce Mitchener | 13d21e9 | 2015-10-07 16:56:17 +0000 | [diff] [blame] | 986 | uint32_t |
| 987 | GetNumDefinitions () override |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 988 | { |
| 989 | return sizeof (g_memory_find_option_table) / sizeof (OptionDefinition); |
| 990 | } |
| 991 | |
Bruce Mitchener | 13d21e9 | 2015-10-07 16:56:17 +0000 | [diff] [blame] | 992 | const OptionDefinition* |
| 993 | GetDefinitions () override |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 994 | { |
| 995 | return g_memory_find_option_table; |
| 996 | } |
| 997 | |
Bruce Mitchener | 13d21e9 | 2015-10-07 16:56:17 +0000 | [diff] [blame] | 998 | Error |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 999 | SetOptionValue (CommandInterpreter &interpreter, |
| 1000 | uint32_t option_idx, |
Bruce Mitchener | 13d21e9 | 2015-10-07 16:56:17 +0000 | [diff] [blame] | 1001 | const char *option_arg) override |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 1002 | { |
| 1003 | Error error; |
| 1004 | const int short_option = g_memory_find_option_table[option_idx].short_option; |
| 1005 | |
| 1006 | switch (short_option) |
| 1007 | { |
| 1008 | case 'e': |
Pavel Labath | c95f7e2 | 2015-02-20 11:14:59 +0000 | [diff] [blame] | 1009 | m_expr.SetValueFromString(option_arg); |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 1010 | break; |
| 1011 | |
| 1012 | case 's': |
Pavel Labath | c95f7e2 | 2015-02-20 11:14:59 +0000 | [diff] [blame] | 1013 | m_string.SetValueFromString(option_arg); |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 1014 | break; |
| 1015 | |
| 1016 | case 'c': |
Pavel Labath | c95f7e2 | 2015-02-20 11:14:59 +0000 | [diff] [blame] | 1017 | if (m_count.SetValueFromString(option_arg).Fail()) |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 1018 | error.SetErrorString("unrecognized value for count"); |
| 1019 | break; |
| 1020 | |
Enrico Granata | 8d81a84 | 2013-11-13 20:08:30 +0000 | [diff] [blame] | 1021 | case 'o': |
Pavel Labath | c95f7e2 | 2015-02-20 11:14:59 +0000 | [diff] [blame] | 1022 | if (m_offset.SetValueFromString(option_arg).Fail()) |
Enrico Granata | 8d81a84 | 2013-11-13 20:08:30 +0000 | [diff] [blame] | 1023 | error.SetErrorString("unrecognized value for dump-offset"); |
| 1024 | break; |
| 1025 | |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 1026 | default: |
| 1027 | error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); |
| 1028 | break; |
| 1029 | } |
| 1030 | return error; |
| 1031 | } |
| 1032 | |
Bruce Mitchener | 13d21e9 | 2015-10-07 16:56:17 +0000 | [diff] [blame] | 1033 | void |
| 1034 | OptionParsingStarting (CommandInterpreter &interpreter) override |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 1035 | { |
| 1036 | m_expr.Clear(); |
| 1037 | m_string.Clear(); |
| 1038 | m_count.Clear(); |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 1039 | } |
| 1040 | |
| 1041 | OptionValueString m_expr; |
| 1042 | OptionValueString m_string; |
| 1043 | OptionValueUInt64 m_count; |
Enrico Granata | 8d81a84 | 2013-11-13 20:08:30 +0000 | [diff] [blame] | 1044 | OptionValueUInt64 m_offset; |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 1045 | }; |
| 1046 | |
| 1047 | CommandObjectMemoryFind (CommandInterpreter &interpreter) : |
| 1048 | CommandObjectParsed (interpreter, |
| 1049 | "memory find", |
| 1050 | "Find a value in the memory of the process being debugged.", |
| 1051 | NULL, |
Enrico Granata | e87764f | 2015-05-27 05:04:35 +0000 | [diff] [blame] | 1052 | eCommandRequiresProcess | eCommandProcessMustBeLaunched), |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 1053 | m_option_group (interpreter), |
| 1054 | m_memory_options () |
| 1055 | { |
| 1056 | CommandArgumentEntry arg1; |
| 1057 | CommandArgumentEntry arg2; |
| 1058 | CommandArgumentData addr_arg; |
| 1059 | CommandArgumentData value_arg; |
| 1060 | |
| 1061 | // Define the first (and only) variant of this arg. |
Enrico Granata | 760af88 | 2015-08-03 20:47:19 +0000 | [diff] [blame] | 1062 | addr_arg.arg_type = eArgTypeAddressOrExpression; |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 1063 | addr_arg.arg_repetition = eArgRepeatPlain; |
| 1064 | |
| 1065 | // There is only one variant this argument could be; put it into the argument entry. |
| 1066 | arg1.push_back (addr_arg); |
| 1067 | |
| 1068 | // Define the first (and only) variant of this arg. |
Enrico Granata | 760af88 | 2015-08-03 20:47:19 +0000 | [diff] [blame] | 1069 | value_arg.arg_type = eArgTypeAddressOrExpression; |
| 1070 | value_arg.arg_repetition = eArgRepeatPlain; |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 1071 | |
| 1072 | // There is only one variant this argument could be; put it into the argument entry. |
| 1073 | arg2.push_back (value_arg); |
| 1074 | |
| 1075 | // Push the data for the first argument into the m_arguments vector. |
| 1076 | m_arguments.push_back (arg1); |
| 1077 | m_arguments.push_back (arg2); |
| 1078 | |
| 1079 | m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2); |
| 1080 | m_option_group.Finalize(); |
| 1081 | } |
| 1082 | |
Bruce Mitchener | 13d21e9 | 2015-10-07 16:56:17 +0000 | [diff] [blame] | 1083 | ~CommandObjectMemoryFind () override |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 1084 | { |
| 1085 | } |
| 1086 | |
| 1087 | Options * |
Bruce Mitchener | 13d21e9 | 2015-10-07 16:56:17 +0000 | [diff] [blame] | 1088 | GetOptions () override |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 1089 | { |
| 1090 | return &m_option_group; |
| 1091 | } |
| 1092 | |
| 1093 | protected: |
Bruce Mitchener | 13d21e9 | 2015-10-07 16:56:17 +0000 | [diff] [blame] | 1094 | bool |
| 1095 | DoExecute (Args& command, CommandReturnObject &result) override |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 1096 | { |
Enrico Granata | e87764f | 2015-05-27 05:04:35 +0000 | [diff] [blame] | 1097 | // No need to check "process" for validity as eCommandRequiresProcess ensures it is valid |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 1098 | Process *process = m_exe_ctx.GetProcessPtr(); |
| 1099 | |
| 1100 | const size_t argc = command.GetArgumentCount(); |
| 1101 | |
| 1102 | if (argc != 2) |
| 1103 | { |
Enrico Granata | 6e49c48 | 2013-11-13 02:22:24 +0000 | [diff] [blame] | 1104 | result.AppendError("two addresses needed for memory find"); |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 1105 | return false; |
| 1106 | } |
| 1107 | |
| 1108 | Error error; |
| 1109 | lldb::addr_t low_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0),LLDB_INVALID_ADDRESS,&error); |
| 1110 | if (low_addr == LLDB_INVALID_ADDRESS || error.Fail()) |
| 1111 | { |
| 1112 | result.AppendError("invalid low address"); |
| 1113 | return false; |
| 1114 | } |
| 1115 | lldb::addr_t high_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1),LLDB_INVALID_ADDRESS,&error); |
| 1116 | if (high_addr == LLDB_INVALID_ADDRESS || error.Fail()) |
| 1117 | { |
Ed Maste | 47a8a5e | 2014-09-06 11:29:08 +0000 | [diff] [blame] | 1118 | result.AppendError("invalid high address"); |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 1119 | return false; |
| 1120 | } |
| 1121 | |
| 1122 | if (high_addr <= low_addr) |
| 1123 | { |
| 1124 | result.AppendError("starting address must be smaller than ending address"); |
| 1125 | return false; |
| 1126 | } |
| 1127 | |
| 1128 | lldb::addr_t found_location = LLDB_INVALID_ADDRESS; |
| 1129 | |
| 1130 | DataBufferHeap buffer; |
| 1131 | |
| 1132 | if (m_memory_options.m_string.OptionWasSet()) |
| 1133 | buffer.CopyData(m_memory_options.m_string.GetStringValue(), strlen(m_memory_options.m_string.GetStringValue())); |
| 1134 | else if (m_memory_options.m_expr.OptionWasSet()) |
| 1135 | { |
| 1136 | StackFrame* frame = m_exe_ctx.GetFramePtr(); |
| 1137 | ValueObjectSP result_sp; |
Enrico Granata | 0b3b987 | 2015-08-03 18:51:39 +0000 | [diff] [blame] | 1138 | if ((eExpressionCompleted == process->GetTarget().EvaluateExpression(m_memory_options.m_expr.GetStringValue(), frame, result_sp)) && |
| 1139 | result_sp.get()) |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 1140 | { |
| 1141 | uint64_t value = result_sp->GetValueAsUnsigned(0); |
Greg Clayton | 99558cc4 | 2015-08-24 23:46:31 +0000 | [diff] [blame] | 1142 | switch (result_sp->GetCompilerType().GetByteSize(nullptr)) |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 1143 | { |
| 1144 | case 1: { |
| 1145 | uint8_t byte = (uint8_t)value; |
| 1146 | buffer.CopyData(&byte,1); |
| 1147 | } |
| 1148 | break; |
| 1149 | case 2: { |
| 1150 | uint16_t word = (uint16_t)value; |
| 1151 | buffer.CopyData(&word,2); |
| 1152 | } |
| 1153 | break; |
| 1154 | case 4: { |
| 1155 | uint32_t lword = (uint32_t)value; |
| 1156 | buffer.CopyData(&lword,4); |
| 1157 | } |
| 1158 | break; |
| 1159 | case 8: { |
| 1160 | buffer.CopyData(&value, 8); |
| 1161 | } |
| 1162 | break; |
| 1163 | case 3: |
| 1164 | case 5: |
| 1165 | case 6: |
| 1166 | case 7: |
| 1167 | result.AppendError("unknown type. pass a string instead"); |
| 1168 | return false; |
| 1169 | default: |
Enrico Granata | 0b3b987 | 2015-08-03 18:51:39 +0000 | [diff] [blame] | 1170 | result.AppendError("result size larger than 8 bytes. pass a string instead"); |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 1171 | return false; |
| 1172 | } |
| 1173 | } |
| 1174 | else |
| 1175 | { |
Enrico Granata | 0b3b987 | 2015-08-03 18:51:39 +0000 | [diff] [blame] | 1176 | result.AppendError("expression evaluation failed. pass a string instead"); |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 1177 | return false; |
| 1178 | } |
| 1179 | } |
| 1180 | else |
| 1181 | { |
| 1182 | result.AppendError("please pass either a block of text, or an expression to evaluate."); |
| 1183 | return false; |
| 1184 | } |
| 1185 | |
| 1186 | size_t count = m_memory_options.m_count.GetCurrentValue(); |
| 1187 | found_location = low_addr; |
| 1188 | bool ever_found = false; |
| 1189 | while (count) |
| 1190 | { |
| 1191 | found_location = Search(found_location, high_addr, buffer.GetBytes(), buffer.GetByteSize()); |
| 1192 | if (found_location == LLDB_INVALID_ADDRESS) |
| 1193 | { |
| 1194 | if (!ever_found) |
| 1195 | { |
Enrico Granata | 0b3b987 | 2015-08-03 18:51:39 +0000 | [diff] [blame] | 1196 | result.AppendMessage("data not found within the range.\n"); |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 1197 | result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult); |
| 1198 | } |
| 1199 | else |
Enrico Granata | 0b3b987 | 2015-08-03 18:51:39 +0000 | [diff] [blame] | 1200 | result.AppendMessage("no more matches within the range.\n"); |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 1201 | break; |
| 1202 | } |
Enrico Granata | 0b3b987 | 2015-08-03 18:51:39 +0000 | [diff] [blame] | 1203 | result.AppendMessageWithFormat("data found at location: 0x%" PRIx64 "\n", found_location); |
Enrico Granata | 8d81a84 | 2013-11-13 20:08:30 +0000 | [diff] [blame] | 1204 | |
| 1205 | DataBufferHeap dumpbuffer(32,0); |
| 1206 | process->ReadMemory(found_location+m_memory_options.m_offset.GetCurrentValue(), dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), error); |
| 1207 | if (!error.Fail()) |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 1208 | { |
Enrico Granata | 8d81a84 | 2013-11-13 20:08:30 +0000 | [diff] [blame] | 1209 | DataExtractor data(dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), process->GetByteOrder(), process->GetAddressByteSize()); |
| 1210 | data.Dump(&result.GetOutputStream(), 0, lldb::eFormatBytesWithASCII, 1, dumpbuffer.GetByteSize(), 16, found_location+m_memory_options.m_offset.GetCurrentValue(), 0, 0); |
| 1211 | result.GetOutputStream().EOL(); |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 1212 | } |
Enrico Granata | 8d81a84 | 2013-11-13 20:08:30 +0000 | [diff] [blame] | 1213 | |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 1214 | --count; |
| 1215 | found_location++; |
| 1216 | ever_found = true; |
| 1217 | } |
| 1218 | |
| 1219 | result.SetStatus(lldb::eReturnStatusSuccessFinishResult); |
| 1220 | return true; |
| 1221 | } |
| 1222 | |
| 1223 | lldb::addr_t |
| 1224 | Search (lldb::addr_t low, |
| 1225 | lldb::addr_t high, |
| 1226 | uint8_t* buffer, |
| 1227 | size_t buffer_size) |
| 1228 | { |
| 1229 | Process *process = m_exe_ctx.GetProcessPtr(); |
| 1230 | DataBufferHeap heap(buffer_size, 0); |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 1231 | for (auto ptr = low; |
Enrico Granata | 0b3b987 | 2015-08-03 18:51:39 +0000 | [diff] [blame] | 1232 | ptr < high; |
| 1233 | ptr++) |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 1234 | { |
| 1235 | Error error; |
Enrico Granata | 0b3b987 | 2015-08-03 18:51:39 +0000 | [diff] [blame] | 1236 | process->ReadMemory(ptr, heap.GetBytes(), buffer_size, error); |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 1237 | if (error.Fail()) |
| 1238 | return LLDB_INVALID_ADDRESS; |
| 1239 | if (memcmp(heap.GetBytes(), buffer, buffer_size) == 0) |
Enrico Granata | 0b3b987 | 2015-08-03 18:51:39 +0000 | [diff] [blame] | 1240 | return ptr; |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 1241 | } |
| 1242 | return LLDB_INVALID_ADDRESS; |
| 1243 | } |
| 1244 | |
| 1245 | OptionGroupOptions m_option_group; |
| 1246 | OptionGroupFindMemory m_memory_options; |
| 1247 | }; |
| 1248 | |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 1249 | |
| 1250 | OptionDefinition |
| 1251 | g_memory_write_option_table[] = |
| 1252 | { |
Zachary Turner | d37221d | 2014-07-09 16:31:49 +0000 | [diff] [blame] | 1253 | { LLDB_OPT_SET_1, true, "infile", 'i', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."}, |
Bruce Mitchener | 350b78e | 2014-07-10 14:45:57 +0000 | [diff] [blame] | 1254 | { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOffset, "Start writing bytes from an offset within the input file."}, |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 1255 | }; |
| 1256 | |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1257 | //---------------------------------------------------------------------- |
| 1258 | // Write memory to the inferior process |
| 1259 | //---------------------------------------------------------------------- |
Jim Ingham | 5a98841 | 2012-06-08 21:56:10 +0000 | [diff] [blame] | 1260 | class CommandObjectMemoryWrite : public CommandObjectParsed |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1261 | { |
| 1262 | public: |
| 1263 | |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 1264 | class OptionGroupWriteMemory : public OptionGroup |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1265 | { |
| 1266 | public: |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 1267 | OptionGroupWriteMemory () : |
| 1268 | OptionGroup() |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1269 | { |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1270 | } |
| 1271 | |
Bruce Mitchener | 13d21e9 | 2015-10-07 16:56:17 +0000 | [diff] [blame] | 1272 | ~OptionGroupWriteMemory () override |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1273 | { |
| 1274 | } |
| 1275 | |
Bruce Mitchener | 13d21e9 | 2015-10-07 16:56:17 +0000 | [diff] [blame] | 1276 | uint32_t |
| 1277 | GetNumDefinitions () override |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 1278 | { |
| 1279 | return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition); |
| 1280 | } |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 1281 | |
Bruce Mitchener | 13d21e9 | 2015-10-07 16:56:17 +0000 | [diff] [blame] | 1282 | const OptionDefinition* |
| 1283 | GetDefinitions () override |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 1284 | { |
| 1285 | return g_memory_write_option_table; |
| 1286 | } |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 1287 | |
Bruce Mitchener | 13d21e9 | 2015-10-07 16:56:17 +0000 | [diff] [blame] | 1288 | Error |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 1289 | SetOptionValue (CommandInterpreter &interpreter, |
| 1290 | uint32_t option_idx, |
Bruce Mitchener | 13d21e9 | 2015-10-07 16:56:17 +0000 | [diff] [blame] | 1291 | const char *option_arg) override |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1292 | { |
| 1293 | Error error; |
Greg Clayton | 3bcdfc0 | 2012-12-04 00:32:51 +0000 | [diff] [blame] | 1294 | const int short_option = g_memory_write_option_table[option_idx].short_option; |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 1295 | |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1296 | switch (short_option) |
| 1297 | { |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 1298 | case 'i': |
| 1299 | m_infile.SetFile (option_arg, true); |
| 1300 | if (!m_infile.Exists()) |
Greg Clayton | 6d7e77b | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 1301 | { |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 1302 | m_infile.Clear(); |
Greg Clayton | 86edbf4 | 2011-10-26 00:56:27 +0000 | [diff] [blame] | 1303 | error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg); |
Greg Clayton | 6d7e77b | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 1304 | } |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 1305 | break; |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 1306 | |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 1307 | case 'o': |
| 1308 | { |
| 1309 | bool success; |
Vince Harron | 5275aaa | 2015-01-15 20:08:35 +0000 | [diff] [blame] | 1310 | m_infile_offset = StringConvert::ToUInt64(option_arg, 0, 0, &success); |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 1311 | if (!success) |
| 1312 | { |
Greg Clayton | 86edbf4 | 2011-10-26 00:56:27 +0000 | [diff] [blame] | 1313 | error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg); |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 1314 | } |
| 1315 | } |
| 1316 | break; |
| 1317 | |
| 1318 | default: |
Greg Clayton | 86edbf4 | 2011-10-26 00:56:27 +0000 | [diff] [blame] | 1319 | error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 1320 | break; |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1321 | } |
| 1322 | return error; |
| 1323 | } |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 1324 | |
Bruce Mitchener | 13d21e9 | 2015-10-07 16:56:17 +0000 | [diff] [blame] | 1325 | void |
| 1326 | OptionParsingStarting (CommandInterpreter &interpreter) override |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1327 | { |
Greg Clayton | 6d7e77b | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 1328 | m_infile.Clear(); |
| 1329 | m_infile_offset = 0; |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1330 | } |
| 1331 | |
Greg Clayton | 6d7e77b | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 1332 | FileSpec m_infile; |
| 1333 | off_t m_infile_offset; |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1334 | }; |
| 1335 | |
Greg Clayton | a701509 | 2010-09-18 01:14:36 +0000 | [diff] [blame] | 1336 | CommandObjectMemoryWrite (CommandInterpreter &interpreter) : |
Jim Ingham | 5a98841 | 2012-06-08 21:56:10 +0000 | [diff] [blame] | 1337 | CommandObjectParsed (interpreter, |
| 1338 | "memory write", |
| 1339 | "Write to the memory of the process being debugged.", |
| 1340 | NULL, |
Enrico Granata | e87764f | 2015-05-27 05:04:35 +0000 | [diff] [blame] | 1341 | eCommandRequiresProcess | eCommandProcessMustBeLaunched), |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 1342 | m_option_group (interpreter), |
| 1343 | m_format_options (eFormatBytes, 1, UINT64_MAX), |
| 1344 | m_memory_options () |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1345 | { |
Caroline Tice | 405fe67 | 2010-10-04 22:28:36 +0000 | [diff] [blame] | 1346 | CommandArgumentEntry arg1; |
| 1347 | CommandArgumentEntry arg2; |
| 1348 | CommandArgumentData addr_arg; |
| 1349 | CommandArgumentData value_arg; |
| 1350 | |
| 1351 | // Define the first (and only) variant of this arg. |
| 1352 | addr_arg.arg_type = eArgTypeAddress; |
| 1353 | addr_arg.arg_repetition = eArgRepeatPlain; |
| 1354 | |
| 1355 | // There is only one variant this argument could be; put it into the argument entry. |
| 1356 | arg1.push_back (addr_arg); |
| 1357 | |
| 1358 | // Define the first (and only) variant of this arg. |
| 1359 | value_arg.arg_type = eArgTypeValue; |
| 1360 | value_arg.arg_repetition = eArgRepeatPlus; |
| 1361 | |
| 1362 | // There is only one variant this argument could be; put it into the argument entry. |
| 1363 | arg2.push_back (value_arg); |
| 1364 | |
| 1365 | // Push the data for the first argument into the m_arguments vector. |
| 1366 | m_arguments.push_back (arg1); |
| 1367 | m_arguments.push_back (arg2); |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 1368 | |
| 1369 | m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1); |
| 1370 | m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2); |
| 1371 | m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2); |
| 1372 | m_option_group.Finalize(); |
| 1373 | |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1374 | } |
| 1375 | |
Bruce Mitchener | 13d21e9 | 2015-10-07 16:56:17 +0000 | [diff] [blame] | 1376 | ~CommandObjectMemoryWrite () override |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1377 | { |
| 1378 | } |
| 1379 | |
| 1380 | Options * |
Bruce Mitchener | 13d21e9 | 2015-10-07 16:56:17 +0000 | [diff] [blame] | 1381 | GetOptions () override |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1382 | { |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 1383 | return &m_option_group; |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1384 | } |
| 1385 | |
| 1386 | bool |
| 1387 | UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size) |
| 1388 | { |
| 1389 | if (total_byte_size > 8) |
| 1390 | return false; |
| 1391 | |
| 1392 | if (total_byte_size == 8) |
| 1393 | return true; |
| 1394 | |
| 1395 | const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1; |
| 1396 | return uval64 <= max; |
| 1397 | } |
| 1398 | |
| 1399 | bool |
| 1400 | SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size) |
| 1401 | { |
| 1402 | if (total_byte_size > 8) |
| 1403 | return false; |
| 1404 | |
| 1405 | if (total_byte_size == 8) |
| 1406 | return true; |
| 1407 | |
| 1408 | const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1; |
| 1409 | const int64_t min = ~(max); |
| 1410 | return min <= sval64 && sval64 <= max; |
| 1411 | } |
| 1412 | |
Jim Ingham | 5a98841 | 2012-06-08 21:56:10 +0000 | [diff] [blame] | 1413 | protected: |
Bruce Mitchener | 13d21e9 | 2015-10-07 16:56:17 +0000 | [diff] [blame] | 1414 | bool |
| 1415 | DoExecute (Args& command, CommandReturnObject &result) override |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1416 | { |
Enrico Granata | e87764f | 2015-05-27 05:04:35 +0000 | [diff] [blame] | 1417 | // No need to check "process" for validity as eCommandRequiresProcess ensures it is valid |
Greg Clayton | f9fc609 | 2013-01-09 19:44:40 +0000 | [diff] [blame] | 1418 | Process *process = m_exe_ctx.GetProcessPtr(); |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1419 | |
| 1420 | const size_t argc = command.GetArgumentCount(); |
| 1421 | |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 1422 | if (m_memory_options.m_infile) |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1423 | { |
Greg Clayton | 6d7e77b | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 1424 | if (argc < 1) |
| 1425 | { |
| 1426 | result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str()); |
| 1427 | result.SetStatus(eReturnStatusFailed); |
| 1428 | return false; |
| 1429 | } |
| 1430 | } |
| 1431 | else if (argc < 2) |
| 1432 | { |
| 1433 | result.AppendErrorWithFormat ("%s takes a destination address and at least one value.\n", m_cmd_name.c_str()); |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1434 | result.SetStatus(eReturnStatusFailed); |
| 1435 | return false; |
| 1436 | } |
| 1437 | |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1438 | StreamString buffer (Stream::eBinary, |
Greg Clayton | 514487e | 2011-02-15 21:59:32 +0000 | [diff] [blame] | 1439 | process->GetTarget().GetArchitecture().GetAddressByteSize(), |
| 1440 | process->GetTarget().GetArchitecture().GetByteOrder()); |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1441 | |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 1442 | OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue(); |
| 1443 | size_t item_byte_size = byte_size_value.GetCurrentValue(); |
Greg Clayton | c982c76 | 2010-07-09 20:39:50 +0000 | [diff] [blame] | 1444 | |
Greg Clayton | b9d5df5 | 2012-12-06 22:49:16 +0000 | [diff] [blame] | 1445 | Error error; |
Greg Clayton | f9fc609 | 2013-01-09 19:44:40 +0000 | [diff] [blame] | 1446 | lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx, |
Greg Clayton | b9d5df5 | 2012-12-06 22:49:16 +0000 | [diff] [blame] | 1447 | command.GetArgumentAtIndex(0), |
| 1448 | LLDB_INVALID_ADDRESS, |
| 1449 | &error); |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1450 | |
| 1451 | if (addr == LLDB_INVALID_ADDRESS) |
| 1452 | { |
Greg Clayton | b9d5df5 | 2012-12-06 22:49:16 +0000 | [diff] [blame] | 1453 | result.AppendError("invalid address expression\n"); |
| 1454 | result.AppendError(error.AsCString()); |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1455 | result.SetStatus(eReturnStatusFailed); |
| 1456 | return false; |
| 1457 | } |
Greg Clayton | 6d7e77b | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 1458 | |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 1459 | if (m_memory_options.m_infile) |
Greg Clayton | 6d7e77b | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 1460 | { |
| 1461 | size_t length = SIZE_MAX; |
Jason Molenda | 250b1b89 | 2015-02-03 23:39:47 +0000 | [diff] [blame] | 1462 | if (item_byte_size > 1) |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 1463 | length = item_byte_size; |
| 1464 | lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length)); |
Greg Clayton | 6d7e77b | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 1465 | if (data_sp) |
| 1466 | { |
| 1467 | length = data_sp->GetByteSize(); |
| 1468 | if (length > 0) |
| 1469 | { |
| 1470 | Error error; |
| 1471 | size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error); |
| 1472 | |
| 1473 | if (bytes_written == length) |
| 1474 | { |
| 1475 | // All bytes written |
Daniel Malea | d01b295 | 2012-11-29 21:49:15 +0000 | [diff] [blame] | 1476 | result.GetOutputStream().Printf("%" PRIu64 " bytes were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, addr); |
Greg Clayton | 6d7e77b | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 1477 | result.SetStatus(eReturnStatusSuccessFinishResult); |
| 1478 | } |
| 1479 | else if (bytes_written > 0) |
| 1480 | { |
| 1481 | // Some byte written |
Daniel Malea | d01b295 | 2012-11-29 21:49:15 +0000 | [diff] [blame] | 1482 | result.GetOutputStream().Printf("%" PRIu64 " bytes of %" PRIu64 " requested were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, (uint64_t)length, addr); |
Greg Clayton | 6d7e77b | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 1483 | result.SetStatus(eReturnStatusSuccessFinishResult); |
| 1484 | } |
| 1485 | else |
| 1486 | { |
Daniel Malea | d01b295 | 2012-11-29 21:49:15 +0000 | [diff] [blame] | 1487 | result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString()); |
Greg Clayton | 6d7e77b | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 1488 | result.SetStatus(eReturnStatusFailed); |
| 1489 | } |
| 1490 | } |
| 1491 | } |
| 1492 | else |
| 1493 | { |
| 1494 | result.AppendErrorWithFormat ("Unable to read contents of file.\n"); |
| 1495 | result.SetStatus(eReturnStatusFailed); |
| 1496 | } |
| 1497 | return result.Succeeded(); |
| 1498 | } |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 1499 | else if (item_byte_size == 0) |
Greg Clayton | 6d7e77b | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 1500 | { |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 1501 | if (m_format_options.GetFormat() == eFormatPointer) |
Greg Clayton | 6d7e77b | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 1502 | item_byte_size = buffer.GetAddressByteSize(); |
| 1503 | else |
| 1504 | item_byte_size = 1; |
| 1505 | } |
| 1506 | |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1507 | command.Shift(); // shift off the address argument |
| 1508 | uint64_t uval64; |
| 1509 | int64_t sval64; |
| 1510 | bool success = false; |
Greg Clayton | c7bece56 | 2013-01-25 18:06:21 +0000 | [diff] [blame] | 1511 | const size_t num_value_args = command.GetArgumentCount(); |
| 1512 | for (size_t i=0; i<num_value_args; ++i) |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1513 | { |
| 1514 | const char *value_str = command.GetArgumentAtIndex(i); |
| 1515 | |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 1516 | switch (m_format_options.GetFormat()) |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1517 | { |
Greg Clayton | bb7f31f | 2011-06-23 21:22:24 +0000 | [diff] [blame] | 1518 | case kNumFormats: |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1519 | case eFormatFloat: // TODO: add support for floats soon |
| 1520 | case eFormatCharPrintable: |
| 1521 | case eFormatBytesWithASCII: |
| 1522 | case eFormatComplex: |
| 1523 | case eFormatEnum: |
| 1524 | case eFormatUnicode16: |
| 1525 | case eFormatUnicode32: |
| 1526 | case eFormatVectorOfChar: |
| 1527 | case eFormatVectorOfSInt8: |
| 1528 | case eFormatVectorOfUInt8: |
| 1529 | case eFormatVectorOfSInt16: |
| 1530 | case eFormatVectorOfUInt16: |
| 1531 | case eFormatVectorOfSInt32: |
| 1532 | case eFormatVectorOfUInt32: |
| 1533 | case eFormatVectorOfSInt64: |
| 1534 | case eFormatVectorOfUInt64: |
Enrico Granata | 1556077 | 2015-10-16 23:42:04 +0000 | [diff] [blame] | 1535 | case eFormatVectorOfFloat16: |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1536 | case eFormatVectorOfFloat32: |
| 1537 | case eFormatVectorOfFloat64: |
| 1538 | case eFormatVectorOfUInt128: |
Greg Clayton | 7a5388b | 2011-03-20 04:57:14 +0000 | [diff] [blame] | 1539 | case eFormatOSType: |
| 1540 | case eFormatComplexInteger: |
Greg Clayton | 5009f9d | 2011-10-27 17:55:14 +0000 | [diff] [blame] | 1541 | case eFormatAddressInfo: |
| 1542 | case eFormatHexFloat: |
| 1543 | case eFormatInstruction: |
Sean Callanan | bf154da | 2012-08-08 17:35:10 +0000 | [diff] [blame] | 1544 | case eFormatVoid: |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1545 | result.AppendError("unsupported format for writing memory"); |
| 1546 | result.SetStatus(eReturnStatusFailed); |
| 1547 | return false; |
| 1548 | |
| 1549 | case eFormatDefault: |
| 1550 | case eFormatBytes: |
| 1551 | case eFormatHex: |
Enrico Granata | 7ec18e3 | 2012-08-09 19:33:34 +0000 | [diff] [blame] | 1552 | case eFormatHexUppercase: |
Greg Clayton | c982c76 | 2010-07-09 20:39:50 +0000 | [diff] [blame] | 1553 | case eFormatPointer: |
| 1554 | |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1555 | // Decode hex bytes |
Vince Harron | 5275aaa | 2015-01-15 20:08:35 +0000 | [diff] [blame] | 1556 | uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 16, &success); |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1557 | if (!success) |
| 1558 | { |
| 1559 | result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str); |
| 1560 | result.SetStatus(eReturnStatusFailed); |
| 1561 | return false; |
| 1562 | } |
| 1563 | else if (!UIntValueIsValidForSize (uval64, item_byte_size)) |
| 1564 | { |
Greg Clayton | 6fea17e | 2014-03-03 19:15:20 +0000 | [diff] [blame] | 1565 | 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 Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1566 | result.SetStatus(eReturnStatusFailed); |
| 1567 | return false; |
| 1568 | } |
| 1569 | buffer.PutMaxHex64 (uval64, item_byte_size); |
| 1570 | break; |
| 1571 | |
| 1572 | case eFormatBoolean: |
| 1573 | uval64 = Args::StringToBoolean(value_str, false, &success); |
| 1574 | if (!success) |
| 1575 | { |
| 1576 | result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str); |
| 1577 | result.SetStatus(eReturnStatusFailed); |
| 1578 | return false; |
| 1579 | } |
| 1580 | buffer.PutMaxHex64 (uval64, item_byte_size); |
| 1581 | break; |
| 1582 | |
| 1583 | case eFormatBinary: |
Vince Harron | 5275aaa | 2015-01-15 20:08:35 +0000 | [diff] [blame] | 1584 | uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 2, &success); |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1585 | if (!success) |
| 1586 | { |
| 1587 | result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str); |
| 1588 | result.SetStatus(eReturnStatusFailed); |
| 1589 | return false; |
| 1590 | } |
| 1591 | else if (!UIntValueIsValidForSize (uval64, item_byte_size)) |
| 1592 | { |
Greg Clayton | 6fea17e | 2014-03-03 19:15:20 +0000 | [diff] [blame] | 1593 | 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 Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1594 | result.SetStatus(eReturnStatusFailed); |
| 1595 | return false; |
| 1596 | } |
| 1597 | buffer.PutMaxHex64 (uval64, item_byte_size); |
| 1598 | break; |
| 1599 | |
Greg Clayton | 4e4294b | 2011-06-17 23:50:44 +0000 | [diff] [blame] | 1600 | case eFormatCharArray: |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1601 | case eFormatChar: |
| 1602 | case eFormatCString: |
| 1603 | if (value_str[0]) |
| 1604 | { |
| 1605 | size_t len = strlen (value_str); |
| 1606 | // Include the NULL for C strings... |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 1607 | if (m_format_options.GetFormat() == eFormatCString) |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1608 | ++len; |
| 1609 | Error error; |
| 1610 | if (process->WriteMemory (addr, value_str, len, error) == len) |
| 1611 | { |
| 1612 | addr += len; |
| 1613 | } |
| 1614 | else |
| 1615 | { |
Daniel Malea | d01b295 | 2012-11-29 21:49:15 +0000 | [diff] [blame] | 1616 | result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString()); |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1617 | result.SetStatus(eReturnStatusFailed); |
| 1618 | return false; |
| 1619 | } |
| 1620 | } |
| 1621 | break; |
| 1622 | |
| 1623 | case eFormatDecimal: |
Vince Harron | 5275aaa | 2015-01-15 20:08:35 +0000 | [diff] [blame] | 1624 | sval64 = StringConvert::ToSInt64(value_str, INT64_MAX, 0, &success); |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1625 | if (!success) |
| 1626 | { |
| 1627 | result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str); |
| 1628 | result.SetStatus(eReturnStatusFailed); |
| 1629 | return false; |
| 1630 | } |
| 1631 | else if (!SIntValueIsValidForSize (sval64, item_byte_size)) |
| 1632 | { |
Greg Clayton | 6fea17e | 2014-03-03 19:15:20 +0000 | [diff] [blame] | 1633 | 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 Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1634 | result.SetStatus(eReturnStatusFailed); |
| 1635 | return false; |
| 1636 | } |
| 1637 | buffer.PutMaxHex64 (sval64, item_byte_size); |
| 1638 | break; |
| 1639 | |
| 1640 | case eFormatUnsigned: |
Vince Harron | 5275aaa | 2015-01-15 20:08:35 +0000 | [diff] [blame] | 1641 | uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 0, &success); |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1642 | if (!success) |
| 1643 | { |
| 1644 | result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str); |
| 1645 | result.SetStatus(eReturnStatusFailed); |
| 1646 | return false; |
| 1647 | } |
| 1648 | else if (!UIntValueIsValidForSize (uval64, item_byte_size)) |
| 1649 | { |
Greg Clayton | 6fea17e | 2014-03-03 19:15:20 +0000 | [diff] [blame] | 1650 | result.AppendErrorWithFormat ("Value %" PRIu64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size); |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1651 | result.SetStatus(eReturnStatusFailed); |
| 1652 | return false; |
| 1653 | } |
| 1654 | buffer.PutMaxHex64 (uval64, item_byte_size); |
| 1655 | break; |
| 1656 | |
| 1657 | case eFormatOctal: |
Vince Harron | 5275aaa | 2015-01-15 20:08:35 +0000 | [diff] [blame] | 1658 | uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 8, &success); |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1659 | if (!success) |
| 1660 | { |
| 1661 | result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str); |
| 1662 | result.SetStatus(eReturnStatusFailed); |
| 1663 | return false; |
| 1664 | } |
| 1665 | else if (!UIntValueIsValidForSize (uval64, item_byte_size)) |
| 1666 | { |
Greg Clayton | 6fea17e | 2014-03-03 19:15:20 +0000 | [diff] [blame] | 1667 | result.AppendErrorWithFormat ("Value %" PRIo64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size); |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1668 | result.SetStatus(eReturnStatusFailed); |
| 1669 | return false; |
| 1670 | } |
| 1671 | buffer.PutMaxHex64 (uval64, item_byte_size); |
| 1672 | break; |
| 1673 | } |
| 1674 | } |
| 1675 | |
| 1676 | if (!buffer.GetString().empty()) |
| 1677 | { |
| 1678 | Error error; |
Greg Clayton | 471b31c | 2010-07-20 22:52:08 +0000 | [diff] [blame] | 1679 | if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size()) |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1680 | return true; |
| 1681 | else |
| 1682 | { |
Daniel Malea | d01b295 | 2012-11-29 21:49:15 +0000 | [diff] [blame] | 1683 | result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString()); |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1684 | result.SetStatus(eReturnStatusFailed); |
| 1685 | return false; |
| 1686 | } |
| 1687 | } |
| 1688 | return true; |
| 1689 | } |
| 1690 | |
Greg Clayton | 1deb796 | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 1691 | OptionGroupOptions m_option_group; |
| 1692 | OptionGroupFormat m_format_options; |
| 1693 | OptionGroupWriteMemory m_memory_options; |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1694 | }; |
| 1695 | |
Kuba Brecka | beed821 | 2014-09-04 01:03:18 +0000 | [diff] [blame] | 1696 | //---------------------------------------------------------------------- |
| 1697 | // Get malloc/free history of a memory address. |
| 1698 | //---------------------------------------------------------------------- |
| 1699 | class CommandObjectMemoryHistory : public CommandObjectParsed |
| 1700 | { |
| 1701 | public: |
| 1702 | |
| 1703 | CommandObjectMemoryHistory (CommandInterpreter &interpreter) : |
| 1704 | CommandObjectParsed (interpreter, |
| 1705 | "memory history", |
| 1706 | "Prints out the recorded stack traces for allocation/deallocation of a memory address.", |
| 1707 | NULL, |
Enrico Granata | e87764f | 2015-05-27 05:04:35 +0000 | [diff] [blame] | 1708 | eCommandRequiresTarget | eCommandRequiresProcess | eCommandProcessMustBePaused | eCommandProcessMustBeLaunched) |
Kuba Brecka | beed821 | 2014-09-04 01:03:18 +0000 | [diff] [blame] | 1709 | { |
| 1710 | CommandArgumentEntry arg1; |
| 1711 | CommandArgumentData addr_arg; |
| 1712 | |
| 1713 | // Define the first (and only) variant of this arg. |
| 1714 | addr_arg.arg_type = eArgTypeAddress; |
| 1715 | addr_arg.arg_repetition = eArgRepeatPlain; |
| 1716 | |
| 1717 | // There is only one variant this argument could be; put it into the argument entry. |
| 1718 | arg1.push_back (addr_arg); |
| 1719 | |
| 1720 | // Push the data for the first argument into the m_arguments vector. |
| 1721 | m_arguments.push_back (arg1); |
| 1722 | } |
| 1723 | |
Bruce Mitchener | 13d21e9 | 2015-10-07 16:56:17 +0000 | [diff] [blame] | 1724 | ~CommandObjectMemoryHistory () override |
Kuba Brecka | beed821 | 2014-09-04 01:03:18 +0000 | [diff] [blame] | 1725 | { |
| 1726 | } |
| 1727 | |
Bruce Mitchener | 13d21e9 | 2015-10-07 16:56:17 +0000 | [diff] [blame] | 1728 | const char * |
| 1729 | GetRepeatCommand (Args ¤t_command_args, uint32_t index) override |
Kuba Brecka | beed821 | 2014-09-04 01:03:18 +0000 | [diff] [blame] | 1730 | { |
| 1731 | return m_cmd_name.c_str(); |
| 1732 | } |
| 1733 | |
| 1734 | protected: |
Bruce Mitchener | 13d21e9 | 2015-10-07 16:56:17 +0000 | [diff] [blame] | 1735 | bool |
| 1736 | DoExecute (Args& command, CommandReturnObject &result) override |
Kuba Brecka | beed821 | 2014-09-04 01:03:18 +0000 | [diff] [blame] | 1737 | { |
| 1738 | const size_t argc = command.GetArgumentCount(); |
| 1739 | |
| 1740 | if (argc == 0 || argc > 1) |
| 1741 | { |
| 1742 | result.AppendErrorWithFormat ("%s takes an address expression", m_cmd_name.c_str()); |
| 1743 | result.SetStatus(eReturnStatusFailed); |
| 1744 | return false; |
| 1745 | } |
| 1746 | |
| 1747 | Error error; |
| 1748 | lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx, |
| 1749 | command.GetArgumentAtIndex(0), |
| 1750 | LLDB_INVALID_ADDRESS, |
| 1751 | &error); |
| 1752 | |
| 1753 | if (addr == LLDB_INVALID_ADDRESS) |
| 1754 | { |
| 1755 | result.AppendError("invalid address expression"); |
| 1756 | result.AppendError(error.AsCString()); |
| 1757 | result.SetStatus(eReturnStatusFailed); |
| 1758 | return false; |
| 1759 | } |
| 1760 | |
| 1761 | Stream *output_stream = &result.GetOutputStream(); |
| 1762 | |
| 1763 | const ProcessSP &process_sp = m_exe_ctx.GetProcessSP(); |
| 1764 | const MemoryHistorySP &memory_history = MemoryHistory::FindPlugin(process_sp); |
| 1765 | |
| 1766 | if (! memory_history.get()) |
| 1767 | { |
| 1768 | result.AppendError("no available memory history provider"); |
| 1769 | result.SetStatus(eReturnStatusFailed); |
| 1770 | return false; |
| 1771 | } |
| 1772 | |
| 1773 | HistoryThreads thread_list = memory_history->GetHistoryThreads(addr); |
| 1774 | |
| 1775 | for (auto thread : thread_list) { |
| 1776 | thread->GetStatus(*output_stream, 0, UINT32_MAX, 0); |
| 1777 | } |
| 1778 | |
| 1779 | result.SetStatus(eReturnStatusSuccessFinishResult); |
| 1780 | |
| 1781 | return true; |
| 1782 | } |
| 1783 | |
| 1784 | }; |
| 1785 | |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1786 | |
| 1787 | //------------------------------------------------------------------------- |
| 1788 | // CommandObjectMemory |
| 1789 | //------------------------------------------------------------------------- |
| 1790 | |
Greg Clayton | 6611103 | 2010-06-23 01:19:29 +0000 | [diff] [blame] | 1791 | CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) : |
Greg Clayton | a701509 | 2010-09-18 01:14:36 +0000 | [diff] [blame] | 1792 | CommandObjectMultiword (interpreter, |
| 1793 | "memory", |
Caroline Tice | 3f4c09c | 2010-09-07 22:38:08 +0000 | [diff] [blame] | 1794 | "A set of commands for operating on memory.", |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1795 | "memory <subcommand> [<subcommand-options>]") |
| 1796 | { |
Enrico Granata | 5346843 | 2013-11-13 02:18:44 +0000 | [diff] [blame] | 1797 | LoadSubCommand ("find", CommandObjectSP (new CommandObjectMemoryFind (interpreter))); |
Greg Clayton | a701509 | 2010-09-18 01:14:36 +0000 | [diff] [blame] | 1798 | LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter))); |
| 1799 | LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter))); |
Kuba Brecka | beed821 | 2014-09-04 01:03:18 +0000 | [diff] [blame] | 1800 | LoadSubCommand ("history", CommandObjectSP (new CommandObjectMemoryHistory (interpreter))); |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1801 | } |
| 1802 | |
| 1803 | CommandObjectMemory::~CommandObjectMemory () |
| 1804 | { |
| 1805 | } |