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 = Status::FromErrorString("invalid enumeration argument"); 70 return fail_value; 71 } 72 73 if (s.empty()) { 74 error = Status::FromErrorString("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 = Status(strm.GetString().str()); 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 = Status(error_strm.GetString().str()); 129 } 130 131 if (error.Fail()) 132 return error; 133 } else { 134 error = Status::FromErrorStringWithFormat("%s option string", 135 s ? "empty" : "invalid"); 136 } 137 return error; 138 } 139 140 lldb::ScriptLanguage OptionArgParser::ToScriptLanguage( 141 llvm::StringRef s, lldb::ScriptLanguage fail_value, bool *success_ptr) { 142 if (success_ptr) 143 *success_ptr = true; 144 145 if (s.equals_insensitive("python")) 146 return eScriptLanguagePython; 147 if (s.equals_insensitive("lua")) 148 return eScriptLanguageLua; 149 if (s.equals_insensitive("default")) 150 return eScriptLanguageDefault; 151 if (s.equals_insensitive("none")) 152 return eScriptLanguageNone; 153 154 if (success_ptr) 155 *success_ptr = false; 156 return fail_value; 157 } 158 159 lldb::addr_t OptionArgParser::ToRawAddress(const ExecutionContext *exe_ctx, 160 llvm::StringRef s, 161 lldb::addr_t fail_value, 162 Status *error_ptr) { 163 std::optional<lldb::addr_t> maybe_addr = DoToAddress(exe_ctx, s, error_ptr); 164 return maybe_addr ? *maybe_addr : fail_value; 165 } 166 167 lldb::addr_t OptionArgParser::ToAddress(const ExecutionContext *exe_ctx, 168 llvm::StringRef s, 169 lldb::addr_t fail_value, 170 Status *error_ptr) { 171 std::optional<lldb::addr_t> maybe_addr = DoToAddress(exe_ctx, s, error_ptr); 172 if (!maybe_addr) 173 return fail_value; 174 175 lldb::addr_t addr = *maybe_addr; 176 177 if (Process *process = exe_ctx->GetProcessPtr()) 178 if (ABISP abi_sp = process->GetABI()) 179 addr = abi_sp->FixCodeAddress(addr); 180 181 return addr; 182 } 183 184 std::optional<lldb::addr_t> 185 OptionArgParser::DoToAddress(const ExecutionContext *exe_ctx, llvm::StringRef s, 186 Status *error_ptr) { 187 if (s.empty()) { 188 if (error_ptr) 189 *error_ptr = Status::FromErrorStringWithFormat( 190 "invalid address expression \"%s\"", s.str().c_str()); 191 return {}; 192 } 193 194 llvm::StringRef sref = s; 195 196 lldb::addr_t addr = LLDB_INVALID_ADDRESS; 197 if (!s.getAsInteger(0, addr)) { 198 if (error_ptr) 199 error_ptr->Clear(); 200 201 return addr; 202 } 203 204 // Try base 16 with no prefix... 205 if (!s.getAsInteger(16, addr)) { 206 if (error_ptr) 207 error_ptr->Clear(); 208 return addr; 209 } 210 211 Target *target = nullptr; 212 if (!exe_ctx || !(target = exe_ctx->GetTargetPtr())) { 213 if (error_ptr) 214 *error_ptr = Status::FromErrorStringWithFormat( 215 "invalid address expression \"%s\"", s.str().c_str()); 216 return {}; 217 } 218 219 lldb::ValueObjectSP valobj_sp; 220 EvaluateExpressionOptions options; 221 options.SetCoerceToId(false); 222 options.SetUnwindOnError(true); 223 options.SetKeepInMemory(false); 224 options.SetTryAllThreads(true); 225 226 ExpressionResults expr_result = 227 target->EvaluateExpression(s, exe_ctx->GetFramePtr(), valobj_sp, options); 228 229 bool success = false; 230 if (expr_result == eExpressionCompleted) { 231 if (valobj_sp) 232 valobj_sp = valobj_sp->GetQualifiedRepresentationIfAvailable( 233 valobj_sp->GetDynamicValueType(), true); 234 // Get the address to watch. 235 if (valobj_sp) 236 addr = valobj_sp->GetValueAsUnsigned(0, &success); 237 if (success) { 238 if (error_ptr) 239 error_ptr->Clear(); 240 return addr; 241 } 242 if (error_ptr) 243 *error_ptr = Status::FromErrorStringWithFormat( 244 "address expression \"%s\" resulted in a value whose type " 245 "can't be converted to an address: %s", 246 s.str().c_str(), valobj_sp->GetTypeName().GetCString()); 247 return {}; 248 } 249 250 // Since the compiler can't handle things like "main + 12" we should try to 251 // do this for now. The compiler doesn't like adding offsets to function 252 // pointer types. 253 // Some languages also don't have a natural representation for register 254 // values (e.g. swift) so handle simple uses of them here as well. 255 // We use a regex to parse these forms, the regex handles: 256 // $reg_name 257 // $reg_name+offset 258 // symbol_name+offset 259 // 260 // The important matching elements in the regex below are: 261 // 1: The reg name if there's no +offset 262 // 3: The symbol/reg name if there is an offset 263 // 4: +/- 264 // 5: The offset value. 265 static RegularExpression g_symbol_plus_offset_regex( 266 "^(\\$[^ +-]+)|(([^ +-]+)([-\\+])[[:space:]]*(0x[0-9A-Fa-f]+|[0-9]+)[[:space:]]*)$"); 267 268 llvm::SmallVector<llvm::StringRef, 4> matches; 269 if (g_symbol_plus_offset_regex.Execute(sref, &matches)) { 270 uint64_t offset = 0; 271 llvm::StringRef name; 272 if (!matches[1].empty()) 273 name = matches[1]; 274 else 275 name = matches[3]; 276 277 llvm::StringRef sign = matches[4]; 278 llvm::StringRef str_offset = matches[5]; 279 280 // Some languages don't have a natural type for register values, but it 281 // is still useful to look them up here: 282 std::optional<lldb::addr_t> register_value; 283 StackFrame *frame = exe_ctx->GetFramePtr(); 284 llvm::StringRef reg_name = name; 285 if (frame && reg_name.consume_front("$")) { 286 RegisterContextSP reg_ctx_sp = frame->GetRegisterContext(); 287 if (reg_ctx_sp) { 288 const RegisterInfo *reg_info = reg_ctx_sp->GetRegisterInfoByName(reg_name); 289 if (reg_info) { 290 RegisterValue reg_val; 291 bool success = reg_ctx_sp->ReadRegister(reg_info, reg_val); 292 if (success && reg_val.GetType() != RegisterValue::eTypeInvalid) { 293 register_value = reg_val.GetAsUInt64(0, &success); 294 if (!success) 295 register_value.reset(); 296 } 297 } 298 } 299 } 300 if (!str_offset.empty() && !str_offset.getAsInteger(0, offset)) { 301 Status error; 302 if (register_value) 303 addr = register_value.value(); 304 else 305 addr = ToAddress(exe_ctx, name, LLDB_INVALID_ADDRESS, &error); 306 if (addr != LLDB_INVALID_ADDRESS) { 307 if (sign[0] == '+') 308 return addr + offset; 309 return addr - offset; 310 } 311 } else if (register_value) 312 // In the case of register values, someone might just want to get the 313 // value in a language whose expression parser doesn't support registers. 314 return register_value.value(); 315 } 316 317 if (error_ptr) 318 *error_ptr = Status::FromErrorStringWithFormat( 319 "address expression \"%s\" evaluation failed", s.str().c_str()); 320 return {}; 321 } 322