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