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