1 //===-- OptionArgParser.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/OptionArgParser.h" 10 #include "lldb/DataFormatters/FormatManager.h" 11 #include "lldb/Target/ABI.h" 12 #include "lldb/Target/RegisterContext.h" 13 #include "lldb/Target/Target.h" 14 #include "lldb/Utility/RegisterValue.h" 15 #include "lldb/Utility/Status.h" 16 #include "lldb/Utility/StreamString.h" 17 18 using namespace lldb_private; 19 using namespace lldb; 20 21 bool OptionArgParser::ToBoolean(llvm::StringRef ref, bool fail_value, 22 bool *success_ptr) { 23 if (success_ptr) 24 *success_ptr = true; 25 ref = ref.trim(); 26 if (ref.equals_insensitive("false") || ref.equals_insensitive("off") || 27 ref.equals_insensitive("no") || ref.equals_insensitive("0")) { 28 return false; 29 } else if (ref.equals_insensitive("true") || ref.equals_insensitive("on") || 30 ref.equals_insensitive("yes") || ref.equals_insensitive("1")) { 31 return true; 32 } 33 if (success_ptr) 34 *success_ptr = false; 35 return fail_value; 36 } 37 38 llvm::Expected<bool> OptionArgParser::ToBoolean(llvm::StringRef option_name, 39 llvm::StringRef option_arg) { 40 bool parse_success; 41 const bool option_value = 42 ToBoolean(option_arg, false /* doesn't matter */, &parse_success); 43 if (parse_success) 44 return option_value; 45 else 46 return llvm::createStringError( 47 "Invalid boolean value for option '%s': '%s'", 48 option_name.str().c_str(), 49 option_arg.empty() ? "<null>" : option_arg.str().c_str()); 50 } 51 52 char OptionArgParser::ToChar(llvm::StringRef s, char fail_value, 53 bool *success_ptr) { 54 if (success_ptr) 55 *success_ptr = false; 56 if (s.size() != 1) 57 return fail_value; 58 59 if (success_ptr) 60 *success_ptr = true; 61 return s[0]; 62 } 63 64 int64_t OptionArgParser::ToOptionEnum(llvm::StringRef s, 65 const OptionEnumValues &enum_values, 66 int32_t fail_value, Status &error) { 67 error.Clear(); 68 if (enum_values.empty()) { 69 error.SetErrorString("invalid enumeration argument"); 70 return fail_value; 71 } 72 73 if (s.empty()) { 74 error.SetErrorString("empty enumeration string"); 75 return fail_value; 76 } 77 78 for (const auto &enum_value : enum_values) { 79 llvm::StringRef this_enum(enum_value.string_value); 80 if (this_enum.starts_with(s)) 81 return enum_value.value; 82 } 83 84 StreamString strm; 85 strm.PutCString("invalid enumeration value, valid values are: "); 86 bool is_first = true; 87 for (const auto &enum_value : enum_values) { 88 strm.Printf("%s\"%s\"", 89 is_first ? is_first = false,"" : ", ", enum_value.string_value); 90 } 91 error.SetErrorString(strm.GetString()); 92 return fail_value; 93 } 94 95 Status OptionArgParser::ToFormat(const char *s, lldb::Format &format, 96 size_t *byte_size_ptr) { 97 format = eFormatInvalid; 98 Status error; 99 100 if (s && s[0]) { 101 if (byte_size_ptr) { 102 if (isdigit(s[0])) { 103 char *format_char = nullptr; 104 unsigned long byte_size = ::strtoul(s, &format_char, 0); 105 if (byte_size != ULONG_MAX) 106 *byte_size_ptr = byte_size; 107 s = format_char; 108 } else 109 *byte_size_ptr = 0; 110 } 111 112 if (!FormatManager::GetFormatFromCString(s, format)) { 113 StreamString error_strm; 114 error_strm.Printf( 115 "Invalid format character or name '%s'. Valid values are:\n", s); 116 for (Format f = eFormatDefault; f < kNumFormats; f = Format(f + 1)) { 117 char format_char = FormatManager::GetFormatAsFormatChar(f); 118 if (format_char) 119 error_strm.Printf("'%c' or ", format_char); 120 121 error_strm.Printf("\"%s\"", FormatManager::GetFormatAsCString(f)); 122 error_strm.EOL(); 123 } 124 125 if (byte_size_ptr) 126 error_strm.PutCString( 127 "An optional byte size can precede the format character.\n"); 128 error.SetErrorString(error_strm.GetString()); 129 } 130 131 if (error.Fail()) 132 return error; 133 } else { 134 error.SetErrorStringWithFormat("%s option string", s ? "empty" : "invalid"); 135 } 136 return error; 137 } 138 139 lldb::ScriptLanguage OptionArgParser::ToScriptLanguage( 140 llvm::StringRef s, lldb::ScriptLanguage fail_value, bool *success_ptr) { 141 if (success_ptr) 142 *success_ptr = true; 143 144 if (s.equals_insensitive("python")) 145 return eScriptLanguagePython; 146 if (s.equals_insensitive("lua")) 147 return eScriptLanguageLua; 148 if (s.equals_insensitive("default")) 149 return eScriptLanguageDefault; 150 if (s.equals_insensitive("none")) 151 return eScriptLanguageNone; 152 153 if (success_ptr) 154 *success_ptr = false; 155 return fail_value; 156 } 157 158 lldb::addr_t OptionArgParser::ToRawAddress(const ExecutionContext *exe_ctx, 159 llvm::StringRef s, 160 lldb::addr_t fail_value, 161 Status *error_ptr) { 162 std::optional<lldb::addr_t> maybe_addr = DoToAddress(exe_ctx, s, error_ptr); 163 return maybe_addr ? *maybe_addr : fail_value; 164 } 165 166 lldb::addr_t OptionArgParser::ToAddress(const ExecutionContext *exe_ctx, 167 llvm::StringRef s, 168 lldb::addr_t fail_value, 169 Status *error_ptr) { 170 std::optional<lldb::addr_t> maybe_addr = DoToAddress(exe_ctx, s, error_ptr); 171 if (!maybe_addr) 172 return fail_value; 173 174 lldb::addr_t addr = *maybe_addr; 175 176 if (Process *process = exe_ctx->GetProcessPtr()) 177 if (ABISP abi_sp = process->GetABI()) 178 addr = abi_sp->FixCodeAddress(addr); 179 180 return addr; 181 } 182 183 std::optional<lldb::addr_t> 184 OptionArgParser::DoToAddress(const ExecutionContext *exe_ctx, llvm::StringRef s, 185 Status *error_ptr) { 186 if (s.empty()) { 187 if (error_ptr) 188 error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"", 189 s.str().c_str()); 190 return {}; 191 } 192 193 llvm::StringRef sref = s; 194 195 lldb::addr_t addr = LLDB_INVALID_ADDRESS; 196 if (!s.getAsInteger(0, addr)) { 197 if (error_ptr) 198 error_ptr->Clear(); 199 200 return addr; 201 } 202 203 // Try base 16 with no prefix... 204 if (!s.getAsInteger(16, addr)) { 205 if (error_ptr) 206 error_ptr->Clear(); 207 return addr; 208 } 209 210 Target *target = nullptr; 211 if (!exe_ctx || !(target = exe_ctx->GetTargetPtr())) { 212 if (error_ptr) 213 error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"", 214 s.str().c_str()); 215 return {}; 216 } 217 218 lldb::ValueObjectSP valobj_sp; 219 EvaluateExpressionOptions options; 220 options.SetCoerceToId(false); 221 options.SetUnwindOnError(true); 222 options.SetKeepInMemory(false); 223 options.SetTryAllThreads(true); 224 225 ExpressionResults expr_result = 226 target->EvaluateExpression(s, exe_ctx->GetFramePtr(), valobj_sp, options); 227 228 bool success = false; 229 if (expr_result == eExpressionCompleted) { 230 if (valobj_sp) 231 valobj_sp = valobj_sp->GetQualifiedRepresentationIfAvailable( 232 valobj_sp->GetDynamicValueType(), true); 233 // Get the address to watch. 234 if (valobj_sp) 235 addr = valobj_sp->GetValueAsUnsigned(0, &success); 236 if (success) { 237 if (error_ptr) 238 error_ptr->Clear(); 239 return addr; 240 } 241 if (error_ptr) 242 error_ptr->SetErrorStringWithFormat( 243 "address expression \"%s\" resulted in a value whose type " 244 "can't be converted to an address: %s", 245 s.str().c_str(), valobj_sp->GetTypeName().GetCString()); 246 return {}; 247 } 248 249 // Since the compiler can't handle things like "main + 12" we should try to 250 // do this for now. The compiler doesn't like adding offsets to function 251 // pointer types. 252 // Some languages also don't have a natural representation for register 253 // values (e.g. swift) so handle simple uses of them here as well. 254 // We use a regex to parse these forms, the regex handles: 255 // $reg_name 256 // $reg_name+offset 257 // symbol_name+offset 258 // 259 // The important matching elements in the regex below are: 260 // 1: The reg name if there's no +offset 261 // 3: The symbol/reg name if there is an offset 262 // 4: +/- 263 // 5: The offset value. 264 static RegularExpression g_symbol_plus_offset_regex( 265 "^(\\$[^ +-]+)|(([^ +-]+)([-\\+])[[:space:]]*(0x[0-9A-Fa-f]+|[0-9]+)[[:space:]]*)$"); 266 267 llvm::SmallVector<llvm::StringRef, 4> matches; 268 if (g_symbol_plus_offset_regex.Execute(sref, &matches)) { 269 uint64_t offset = 0; 270 llvm::StringRef name; 271 if (!matches[1].empty()) 272 name = matches[1]; 273 else 274 name = matches[3]; 275 276 llvm::StringRef sign = matches[4]; 277 llvm::StringRef str_offset = matches[5]; 278 279 // Some languages don't have a natural type for register values, but it 280 // is still useful to look them up here: 281 std::optional<lldb::addr_t> register_value; 282 StackFrame *frame = exe_ctx->GetFramePtr(); 283 llvm::StringRef reg_name = name; 284 if (frame && reg_name.consume_front("$")) { 285 RegisterContextSP reg_ctx_sp = frame->GetRegisterContext(); 286 if (reg_ctx_sp) { 287 const RegisterInfo *reg_info = reg_ctx_sp->GetRegisterInfoByName(reg_name); 288 if (reg_info) { 289 RegisterValue reg_val; 290 bool success = reg_ctx_sp->ReadRegister(reg_info, reg_val); 291 if (success && reg_val.GetType() != RegisterValue::eTypeInvalid) { 292 register_value = reg_val.GetAsUInt64(0, &success); 293 if (!success) 294 register_value.reset(); 295 } 296 } 297 } 298 } 299 if (!str_offset.empty() && !str_offset.getAsInteger(0, offset)) { 300 Status error; 301 if (register_value) 302 addr = register_value.value(); 303 else 304 addr = ToAddress(exe_ctx, name, LLDB_INVALID_ADDRESS, &error); 305 if (addr != LLDB_INVALID_ADDRESS) { 306 if (sign[0] == '+') 307 return addr + offset; 308 return addr - offset; 309 } 310 } else if (register_value) 311 // In the case of register values, someone might just want to get the 312 // value in a language whose expression parser doesn't support registers. 313 return register_value.value(); 314 } 315 316 if (error_ptr) 317 error_ptr->SetErrorStringWithFormat( 318 "address expression \"%s\" evaluation failed", s.str().c_str()); 319 return {}; 320 } 321