1 //===-- OptionArgParser.cpp -------------------------------------*- C++ -*-===// 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/Target.h" 12 #include "lldb/Utility/Status.h" 13 #include "lldb/Utility/StreamString.h" 14 15 using namespace lldb_private; 16 using namespace lldb; 17 18 bool OptionArgParser::ToBoolean(llvm::StringRef ref, bool fail_value, 19 bool *success_ptr) { 20 if (success_ptr) 21 *success_ptr = true; 22 ref = ref.trim(); 23 if (ref.equals_lower("false") || ref.equals_lower("off") || 24 ref.equals_lower("no") || ref.equals_lower("0")) { 25 return false; 26 } else if (ref.equals_lower("true") || ref.equals_lower("on") || 27 ref.equals_lower("yes") || ref.equals_lower("1")) { 28 return true; 29 } 30 if (success_ptr) 31 *success_ptr = false; 32 return fail_value; 33 } 34 35 char OptionArgParser::ToChar(llvm::StringRef s, char fail_value, 36 bool *success_ptr) { 37 if (success_ptr) 38 *success_ptr = false; 39 if (s.size() != 1) 40 return fail_value; 41 42 if (success_ptr) 43 *success_ptr = true; 44 return s[0]; 45 } 46 47 int64_t OptionArgParser::ToOptionEnum(llvm::StringRef s, 48 const OptionEnumValues &enum_values, 49 int32_t fail_value, Status &error) { 50 error.Clear(); 51 if (enum_values.empty()) { 52 error.SetErrorString("invalid enumeration argument"); 53 return fail_value; 54 } 55 56 if (s.empty()) { 57 error.SetErrorString("empty enumeration string"); 58 return fail_value; 59 } 60 61 for (const auto &enum_value : enum_values) { 62 llvm::StringRef this_enum(enum_value.string_value); 63 if (this_enum.startswith(s)) 64 return enum_value.value; 65 } 66 67 StreamString strm; 68 strm.PutCString("invalid enumeration value, valid values are: "); 69 bool is_first = true; 70 for (const auto &enum_value : enum_values) { 71 strm.Printf("%s\"%s\"", 72 is_first ? is_first = false,"" : ", ", enum_value.string_value); 73 } 74 error.SetErrorString(strm.GetString()); 75 return fail_value; 76 } 77 78 Status OptionArgParser::ToFormat(const char *s, lldb::Format &format, 79 size_t *byte_size_ptr) { 80 format = eFormatInvalid; 81 Status error; 82 83 if (s && s[0]) { 84 if (byte_size_ptr) { 85 if (isdigit(s[0])) { 86 char *format_char = nullptr; 87 unsigned long byte_size = ::strtoul(s, &format_char, 0); 88 if (byte_size != ULONG_MAX) 89 *byte_size_ptr = byte_size; 90 s = format_char; 91 } else 92 *byte_size_ptr = 0; 93 } 94 95 const bool partial_match_ok = true; 96 if (!FormatManager::GetFormatFromCString(s, partial_match_ok, format)) { 97 StreamString error_strm; 98 error_strm.Printf( 99 "Invalid format character or name '%s'. Valid values are:\n", s); 100 for (Format f = eFormatDefault; f < kNumFormats; f = Format(f + 1)) { 101 char format_char = FormatManager::GetFormatAsFormatChar(f); 102 if (format_char) 103 error_strm.Printf("'%c' or ", format_char); 104 105 error_strm.Printf("\"%s\"", FormatManager::GetFormatAsCString(f)); 106 error_strm.EOL(); 107 } 108 109 if (byte_size_ptr) 110 error_strm.PutCString( 111 "An optional byte size can precede the format character.\n"); 112 error.SetErrorString(error_strm.GetString()); 113 } 114 115 if (error.Fail()) 116 return error; 117 } else { 118 error.SetErrorStringWithFormat("%s option string", s ? "empty" : "invalid"); 119 } 120 return error; 121 } 122 123 lldb::ScriptLanguage OptionArgParser::ToScriptLanguage( 124 llvm::StringRef s, lldb::ScriptLanguage fail_value, bool *success_ptr) { 125 if (success_ptr) 126 *success_ptr = true; 127 128 if (s.equals_lower("python")) 129 return eScriptLanguagePython; 130 if (s.equals_lower("default")) 131 return eScriptLanguageDefault; 132 if (s.equals_lower("none")) 133 return eScriptLanguageNone; 134 135 if (success_ptr) 136 *success_ptr = false; 137 return fail_value; 138 } 139 140 lldb::addr_t OptionArgParser::ToAddress(const ExecutionContext *exe_ctx, 141 llvm::StringRef s, 142 lldb::addr_t fail_value, 143 Status *error_ptr) { 144 bool error_set = false; 145 if (s.empty()) { 146 if (error_ptr) 147 error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"", 148 s.str().c_str()); 149 return fail_value; 150 } 151 152 llvm::StringRef sref = s; 153 154 lldb::addr_t addr = LLDB_INVALID_ADDRESS; 155 if (!s.getAsInteger(0, addr)) { 156 if (error_ptr) 157 error_ptr->Clear(); 158 return addr; 159 } 160 161 // Try base 16 with no prefix... 162 if (!s.getAsInteger(16, addr)) { 163 if (error_ptr) 164 error_ptr->Clear(); 165 return addr; 166 } 167 168 Target *target = nullptr; 169 if (!exe_ctx || !(target = exe_ctx->GetTargetPtr())) { 170 if (error_ptr) 171 error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"", 172 s.str().c_str()); 173 return fail_value; 174 } 175 176 lldb::ValueObjectSP valobj_sp; 177 EvaluateExpressionOptions options; 178 options.SetCoerceToId(false); 179 options.SetUnwindOnError(true); 180 options.SetKeepInMemory(false); 181 options.SetTryAllThreads(true); 182 183 ExpressionResults expr_result = 184 target->EvaluateExpression(s, exe_ctx->GetFramePtr(), valobj_sp, options); 185 186 bool success = false; 187 if (expr_result == eExpressionCompleted) { 188 if (valobj_sp) 189 valobj_sp = valobj_sp->GetQualifiedRepresentationIfAvailable( 190 valobj_sp->GetDynamicValueType(), true); 191 // Get the address to watch. 192 if (valobj_sp) 193 addr = valobj_sp->GetValueAsUnsigned(fail_value, &success); 194 if (success) { 195 if (error_ptr) 196 error_ptr->Clear(); 197 return addr; 198 } else { 199 if (error_ptr) { 200 error_set = true; 201 error_ptr->SetErrorStringWithFormat( 202 "address expression \"%s\" resulted in a value whose type " 203 "can't be converted to an address: %s", 204 s.str().c_str(), valobj_sp->GetTypeName().GetCString()); 205 } 206 } 207 208 } else { 209 // Since the compiler can't handle things like "main + 12" we should try to 210 // do this for now. The compiler doesn't like adding offsets to function 211 // pointer types. 212 static RegularExpression g_symbol_plus_offset_regex( 213 "^(.*)([-\\+])[[:space:]]*(0x[0-9A-Fa-f]+|[0-9]+)[[:space:]]*$"); 214 RegularExpression::Match regex_match(3); 215 if (g_symbol_plus_offset_regex.Execute(sref, ®ex_match)) { 216 uint64_t offset = 0; 217 bool add = true; 218 std::string name; 219 std::string str; 220 if (regex_match.GetMatchAtIndex(s, 1, name)) { 221 if (regex_match.GetMatchAtIndex(s, 2, str)) { 222 add = str[0] == '+'; 223 224 if (regex_match.GetMatchAtIndex(s, 3, str)) { 225 if (!llvm::StringRef(str).getAsInteger(0, offset)) { 226 Status error; 227 addr = ToAddress(exe_ctx, name.c_str(), LLDB_INVALID_ADDRESS, 228 &error); 229 if (addr != LLDB_INVALID_ADDRESS) { 230 if (add) 231 return addr + offset; 232 else 233 return addr - offset; 234 } 235 } 236 } 237 } 238 } 239 } 240 241 if (error_ptr) { 242 error_set = true; 243 error_ptr->SetErrorStringWithFormat( 244 "address expression \"%s\" evaluation failed", s.str().c_str()); 245 } 246 } 247 248 if (error_ptr) { 249 if (!error_set) 250 error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"", 251 s.str().c_str()); 252 } 253 return fail_value; 254 } 255