1 //===-- OptionGroupFormat.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 "lldb/Interpreter/OptionGroupFormat.h" 11 12 #include "lldb/Host/OptionParser.h" 13 #include "lldb/Interpreter/CommandInterpreter.h" 14 #include "lldb/Target/ExecutionContext.h" 15 #include "lldb/Target/Target.h" 16 17 using namespace lldb; 18 using namespace lldb_private; 19 20 OptionGroupFormat::OptionGroupFormat(lldb::Format default_format, 21 uint64_t default_byte_size, 22 uint64_t default_count) 23 : m_format(default_format, default_format), 24 m_byte_size(default_byte_size, default_byte_size), 25 m_count(default_count, default_count), m_prev_gdb_format('x'), 26 m_prev_gdb_size('w') {} 27 28 OptionGroupFormat::~OptionGroupFormat() {} 29 30 static OptionDefinition g_option_table[] = { 31 {LLDB_OPT_SET_1, false, "format", 'f', OptionParser::eRequiredArgument, 32 nullptr, nullptr, 0, eArgTypeFormat, 33 "Specify a format to be used for display."}, 34 {LLDB_OPT_SET_2, false, "gdb-format", 'G', OptionParser::eRequiredArgument, 35 nullptr, nullptr, 0, eArgTypeGDBFormat, 36 "Specify a format using a GDB format specifier string."}, 37 {LLDB_OPT_SET_3, false, "size", 's', OptionParser::eRequiredArgument, 38 nullptr, nullptr, 0, eArgTypeByteSize, 39 "The size in bytes to use when displaying with the selected format."}, 40 {LLDB_OPT_SET_4, false, "count", 'c', OptionParser::eRequiredArgument, 41 nullptr, nullptr, 0, eArgTypeCount, 42 "The number of total items to display."}, 43 }; 44 45 llvm::ArrayRef<OptionDefinition> OptionGroupFormat::GetDefinitions() { 46 auto result = llvm::makeArrayRef(g_option_table); 47 if (m_byte_size.GetDefaultValue() < UINT64_MAX) { 48 if (m_count.GetDefaultValue() < UINT64_MAX) 49 return result; 50 else 51 return result.take_front(3); 52 } 53 return result.take_front(2); 54 } 55 56 Status OptionGroupFormat::SetOptionValue(uint32_t option_idx, 57 llvm::StringRef option_arg, 58 ExecutionContext *execution_context) { 59 Status error; 60 const int short_option = g_option_table[option_idx].short_option; 61 62 switch (short_option) { 63 case 'f': 64 error = m_format.SetValueFromString(option_arg); 65 break; 66 67 case 'c': 68 if (m_count.GetDefaultValue() == 0) { 69 error.SetErrorString("--count option is disabled"); 70 } else { 71 error = m_count.SetValueFromString(option_arg); 72 if (m_count.GetCurrentValue() == 0) 73 error.SetErrorStringWithFormat("invalid --count option value '%s'", 74 option_arg.str().c_str()); 75 } 76 break; 77 78 case 's': 79 if (m_byte_size.GetDefaultValue() == 0) { 80 error.SetErrorString("--size option is disabled"); 81 } else { 82 error = m_byte_size.SetValueFromString(option_arg); 83 if (m_byte_size.GetCurrentValue() == 0) 84 error.SetErrorStringWithFormat("invalid --size option value '%s'", 85 option_arg.str().c_str()); 86 } 87 break; 88 89 case 'G': { 90 uint64_t count = 0; 91 llvm::StringRef gdb_format_str = option_arg; 92 gdb_format_str.consumeInteger(0, count); 93 94 Format format = eFormatDefault; 95 uint32_t byte_size = 0; 96 97 while (!gdb_format_str.empty() && 98 ParserGDBFormatLetter(execution_context, gdb_format_str[0], format, 99 byte_size)) { 100 gdb_format_str = gdb_format_str.drop_front(); 101 } 102 103 // We the first character of the "gdb_format_str" is not the 104 // NULL terminator, we didn't consume the entire string and 105 // something is wrong. Also, if none of the format, size or count 106 // was specified correctly, then abort. 107 if (!gdb_format_str.empty() || 108 (format == eFormatInvalid && byte_size == 0 && count == 0)) { 109 // Nothing got set correctly 110 error.SetErrorStringWithFormat("invalid gdb format string '%s'", 111 option_arg.str().c_str()); 112 return error; 113 } 114 115 // At least one of the format, size or count was set correctly. 116 // Anything that wasn't set correctly should be set to the 117 // previous default 118 if (format == eFormatInvalid) 119 ParserGDBFormatLetter(execution_context, m_prev_gdb_format, format, 120 byte_size); 121 122 const bool byte_size_enabled = m_byte_size.GetDefaultValue() < UINT64_MAX; 123 const bool count_enabled = m_count.GetDefaultValue() < UINT64_MAX; 124 if (byte_size_enabled) { 125 // Byte size is enabled 126 if (byte_size == 0) 127 ParserGDBFormatLetter(execution_context, m_prev_gdb_size, format, 128 byte_size); 129 } else { 130 // Byte size is disabled, make sure it wasn't specified 131 // but if this is an address, it's actually necessary to 132 // specify one so don't error out 133 if (byte_size > 0 && format != lldb::eFormatAddressInfo) { 134 error.SetErrorString( 135 "this command doesn't support specifying a byte size"); 136 return error; 137 } 138 } 139 140 if (count_enabled) { 141 // Count is enabled and was not set, set it to the default for gdb format 142 // statements (which is 1). 143 if (count == 0) 144 count = 1; 145 } else { 146 // Count is disabled, make sure it wasn't specified 147 if (count > 0) { 148 error.SetErrorString("this command doesn't support specifying a count"); 149 return error; 150 } 151 } 152 153 m_format.SetCurrentValue(format); 154 m_format.SetOptionWasSet(); 155 if (byte_size_enabled) { 156 m_byte_size.SetCurrentValue(byte_size); 157 m_byte_size.SetOptionWasSet(); 158 } 159 if (count_enabled) { 160 m_count.SetCurrentValue(count); 161 m_count.SetOptionWasSet(); 162 } 163 } break; 164 165 default: 166 error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); 167 break; 168 } 169 170 return error; 171 } 172 173 bool OptionGroupFormat::ParserGDBFormatLetter( 174 ExecutionContext *execution_context, char format_letter, Format &format, 175 uint32_t &byte_size) { 176 m_has_gdb_format = true; 177 switch (format_letter) { 178 case 'o': 179 format = eFormatOctal; 180 m_prev_gdb_format = format_letter; 181 return true; 182 case 'x': 183 format = eFormatHex; 184 m_prev_gdb_format = format_letter; 185 return true; 186 case 'd': 187 format = eFormatDecimal; 188 m_prev_gdb_format = format_letter; 189 return true; 190 case 'u': 191 format = eFormatUnsigned; 192 m_prev_gdb_format = format_letter; 193 return true; 194 case 't': 195 format = eFormatBinary; 196 m_prev_gdb_format = format_letter; 197 return true; 198 case 'f': 199 format = eFormatFloat; 200 m_prev_gdb_format = format_letter; 201 return true; 202 case 'a': 203 format = eFormatAddressInfo; 204 { 205 TargetSP target_sp = 206 execution_context ? execution_context->GetTargetSP() : TargetSP(); 207 if (target_sp) 208 byte_size = target_sp->GetArchitecture().GetAddressByteSize(); 209 m_prev_gdb_format = format_letter; 210 return true; 211 } 212 case 'i': 213 format = eFormatInstruction; 214 m_prev_gdb_format = format_letter; 215 return true; 216 case 'c': 217 format = eFormatChar; 218 m_prev_gdb_format = format_letter; 219 return true; 220 case 's': 221 format = eFormatCString; 222 m_prev_gdb_format = format_letter; 223 return true; 224 case 'T': 225 format = eFormatOSType; 226 m_prev_gdb_format = format_letter; 227 return true; 228 case 'A': 229 format = eFormatHexFloat; 230 m_prev_gdb_format = format_letter; 231 return true; 232 233 case 'b': 234 case 'h': 235 case 'w': 236 case 'g': 237 { 238 // Size isn't used for printing instructions, so if a size is specified, and 239 // the previous format was 240 // 'i', then we should reset it to the default ('x'). Otherwise we'll 241 // continue to print as instructions, 242 // which isn't expected. 243 if (format_letter == 'b') 244 byte_size = 1; 245 else if (format_letter == 'h') 246 byte_size = 2; 247 else if (format_letter == 'w') 248 byte_size = 4; 249 else if (format_letter == 'g') 250 byte_size = 8; 251 252 m_prev_gdb_size = format_letter; 253 if (m_prev_gdb_format == 'i') 254 m_prev_gdb_format = 'x'; 255 return true; 256 } 257 break; 258 default: 259 break; 260 } 261 262 263 return false; 264 } 265 266 void OptionGroupFormat::OptionParsingStarting( 267 ExecutionContext *execution_context) { 268 m_format.Clear(); 269 m_byte_size.Clear(); 270 m_count.Clear(); 271 m_has_gdb_format = false; 272 } 273