ValueObjectSP GoUserExpression::GoInterpreter::VisitStarExpr(const GoASTStarExpr *e) { ValueObjectSP target = EvaluateExpr(e->GetX()); if (!target) return nullptr; return target->Dereference(m_error); }
void ValueObjectPrinter::PrintChild( ValueObjectSP child_sp, const DumpValueObjectOptions::PointerDepth &curr_ptr_depth) { const uint32_t consumed_depth = (!m_options.m_pointer_as_array) ? 1 : 0; const bool does_consume_ptr_depth = ((IsPtr() && !m_options.m_pointer_as_array) || IsRef()); DumpValueObjectOptions child_options(m_options); child_options.SetFormat(m_options.m_format) .SetSummary() .SetRootValueObjectName(); child_options.SetScopeChecked(true) .SetHideName(m_options.m_hide_name) .SetHideValue(m_options.m_hide_value) .SetOmitSummaryDepth(child_options.m_omit_summary_depth > 1 ? child_options.m_omit_summary_depth - consumed_depth : 0) .SetElementCount(0); if (child_sp.get()) { ValueObjectPrinter child_printer( child_sp.get(), m_stream, child_options, does_consume_ptr_depth ? --curr_ptr_depth : curr_ptr_depth, m_curr_depth + consumed_depth, m_printed_instance_pointers); child_printer.PrintValueObject(); } }
ValueObjectSP GoUserExpression::GoInterpreter::VisitSelectorExpr(const lldb_private::GoASTSelectorExpr *e) { ValueObjectSP target = EvaluateExpr(e->GetX()); if (target) { if (target->GetCompilerType().IsPointerType()) { target = target->Dereference(m_error); if (m_error.Fail()) return nullptr; } ConstString field(e->GetSel()->GetName().m_value); ValueObjectSP result = target->GetChildMemberWithName(field, true); if (!result) m_error.SetErrorStringWithFormat("Unknown child %s", field.AsCString()); return result; } if (const GoASTIdent *package = llvm::dyn_cast<GoASTIdent>(e->GetX())) { if (VariableSP global = FindGlobalVariable(m_exe_ctx.GetTargetSP(), package->GetName().m_value + "." + e->GetSel()->GetName().m_value)) { if (m_frame) { m_error.Clear(); return m_frame->GetValueObjectForFrameVariable(global, m_use_dynamic); } } } if (const GoASTBasicLit *packageLit = llvm::dyn_cast<GoASTBasicLit>(e->GetX())) { if (packageLit->GetValue().m_type == GoLexer::LIT_STRING) { std::string value = packageLit->GetValue().m_value.str(); value = value.substr(1, value.size() - 2); if (VariableSP global = FindGlobalVariable(m_exe_ctx.GetTargetSP(), value + "." + e->GetSel()->GetName().m_value)) { if (m_frame) { m_error.Clear(); return m_frame->TrackGlobalVariable(global, m_use_dynamic); } } } } // EvaluateExpr should have already set m_error. return target; }
// this function abstracts away the layout and mode details of a libc++ string // and returns the address of the data and the size ready for callers to consume static bool ExtractLibcxxStringInfo (ValueObject& valobj, ValueObjectSP &location_sp, uint64_t& size) { ValueObjectSP D(valobj.GetChildAtIndexPath({0,0,0,0})); if (!D) return false; ValueObjectSP layout_decider(D->GetChildAtIndexPath({0,0})); // this child should exist if (!layout_decider) return false; ConstString g_data_name("__data_"); ConstString g_size_name("__size_"); bool short_mode = false; // this means the string is in short-mode and the data is stored inline LibcxxStringLayoutMode layout = (layout_decider->GetName() == g_data_name) ? eLibcxxStringLayoutModeDSC : eLibcxxStringLayoutModeCSD; uint64_t size_mode_value = 0; if (layout == eLibcxxStringLayoutModeDSC) { ValueObjectSP size_mode(D->GetChildAtIndexPath({1,1,0})); if (!size_mode) return false; if (size_mode->GetName() != g_size_name) { // we are hitting the padding structure, move along size_mode = D->GetChildAtIndexPath({1,1,1}); if (!size_mode) return false; } size_mode_value = (size_mode->GetValueAsUnsigned(0)); short_mode = ((size_mode_value & 0x80) == 0); } else { ValueObjectSP size_mode(D->GetChildAtIndexPath({1,0,0})); if (!size_mode) return false; size_mode_value = (size_mode->GetValueAsUnsigned(0)); short_mode = ((size_mode_value & 1) == 0); } if (short_mode) { ValueObjectSP s(D->GetChildAtIndex(1, true)); if (!s) return false; location_sp = s->GetChildAtIndex((layout == eLibcxxStringLayoutModeDSC) ? 0 : 1, true); size = (layout == eLibcxxStringLayoutModeDSC) ? size_mode_value : ((size_mode_value >> 1) % 256); return (location_sp.get() != nullptr); } else {
bool lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetDataType() { if (m_element_type.GetOpaqueQualType() && m_element_type.GetTypeSystem()) return true; m_element_type.Clear(); ValueObjectSP deref; Error error; deref = m_root_node->Dereference(error); if (!deref || error.Fail()) return false; deref = deref->GetChildMemberWithName(ConstString("__value_"), true); if (!deref) return false; m_element_type = deref->GetCompilerType(); return true; }
void ValueObjectPrinter::PrintChild (ValueObjectSP child_sp, const DumpValueObjectOptions::PointerDepth& curr_ptr_depth) { DumpValueObjectOptions child_options(m_options); child_options.SetFormat(m_options.m_format).SetSummary().SetRootValueObjectName(); child_options.SetScopeChecked(true).SetHideName(m_options.m_hide_name).SetHideValue(m_options.m_hide_value) .SetOmitSummaryDepth(child_options.m_omit_summary_depth > 1 ? child_options.m_omit_summary_depth - 1 : 0); if (child_sp.get()) { ValueObjectPrinter child_printer(child_sp.get(), m_stream, child_options, (IsPtr() || IsRef()) ? --curr_ptr_depth : curr_ptr_depth, m_curr_depth + 1); child_printer.PrintValueObject(); } }
ValueObjectSP GoUserExpression::GoInterpreter::VisitCallExpr( const lldb_private::GoASTCallExpr *e) { ValueObjectSP x = EvaluateExpr(e->GetFun()); if (x || e->NumArgs() != 1) { m_error.SetErrorStringWithFormat("Code execution not supported"); return nullptr; } m_error.Clear(); CompilerType type = EvaluateType(e->GetFun()); if (!type) { return nullptr; } ValueObjectSP value = EvaluateExpr(e->GetArgs(0)); if (!value) return nullptr; // TODO: Handle special conversions return value->Cast(type); }
ValueObjectSP GoUserExpression::GoInterpreter::VisitUnaryExpr(const GoASTUnaryExpr *e) { ValueObjectSP x = EvaluateExpr(e->GetX()); if (!x) return nullptr; switch (e->GetOp()) { case GoLexer::OP_AMP: { CompilerType type = x->GetCompilerType().GetPointerType(); uint64_t address = x->GetAddressOf(); return ValueObject::CreateValueObjectFromAddress(nullptr, address, m_exe_ctx, type); } case GoLexer::OP_PLUS: return x; default: m_error.SetErrorStringWithFormat( "Operator %s not supported", GoLexer::LookupToken(e->GetOp()).str().c_str()); return nullptr; } }
bool lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetDataType() { static ConstString g___value_("__value_"); static ConstString g_tree_("__tree_"); static ConstString g_pair3("__pair3_"); if (m_element_type.GetOpaqueQualType() && m_element_type.GetTypeSystem()) return true; m_element_type.Clear(); ValueObjectSP deref; Status error; deref = m_root_node->Dereference(error); if (!deref || error.Fail()) return false; deref = deref->GetChildMemberWithName(g___value_, true); if (deref) { m_element_type = deref->GetCompilerType(); return true; } deref = m_backend.GetChildAtNamePath({g_tree_, g_pair3}); if (!deref) return false; m_element_type = deref->GetCompilerType() .GetTypeTemplateArgument(1) .GetTypeTemplateArgument(1); if (m_element_type) { std::string name; uint64_t bit_offset_ptr; uint32_t bitfield_bit_size_ptr; bool is_bitfield_ptr; m_element_type = m_element_type.GetFieldAtIndex( 0, name, &bit_offset_ptr, &bitfield_bit_size_ptr, &is_bitfield_ptr); m_element_type = m_element_type.GetTypedefedType(); return m_element_type.IsValid(); } else { m_element_type = m_backend.GetCompilerType().GetTypeTemplateArgument(0); return m_element_type.IsValid(); } }
ValueObjectSP BitsetFrontEnd::GetChildAtIndex(size_t idx) { if (idx >= m_elements.size() || !m_first) return ValueObjectSP(); if (m_elements[idx]) return m_elements[idx]; ExecutionContext ctx = m_backend.GetExecutionContextRef().Lock(false); CompilerType type; ValueObjectSP chunk; // For small bitsets __first_ is not an array, but a plain size_t. if (m_first->GetCompilerType().IsArrayType(&type, nullptr, nullptr)) { llvm::Optional<uint64_t> bit_size = type.GetBitSize(ctx.GetBestExecutionContextScope()); if (!bit_size || *bit_size == 0) return {}; chunk = m_first->GetChildAtIndex(idx / *bit_size, true); } else { type = m_first->GetCompilerType(); chunk = m_first; } if (!type || !chunk) return {}; llvm::Optional<uint64_t> bit_size = type.GetBitSize(ctx.GetBestExecutionContextScope()); if (!bit_size || *bit_size == 0) return {}; size_t chunk_idx = idx % *bit_size; uint8_t value = !!(chunk->GetValueAsUnsigned(0) & (uint64_t(1) << chunk_idx)); DataExtractor data(&value, sizeof(value), m_byte_order, m_byte_size); m_elements[idx] = CreateValueObjectFromData(llvm::formatv("[{0}]", idx).str(), data, ctx, m_bool_type); return m_elements[idx]; }
bool isThrownError(ValueObjectSP valobj_sp) { ConstString name = valobj_sp->GetName(); size_t length = name.GetLength(); if (length < 3) return false; const char *name_cstr = name.AsCString(); if (name_cstr[0] != '$') return false; if (name_cstr[1] != 'E') return false; for (int index = 2; index < length; index++) { char digit = name_cstr[index]; if (digit < '0' || digit > '9') return false; } return true; }
bool SwiftREPL::PrintOneVariable (Debugger &debugger, StreamFileSP &output_sp, ValueObjectSP &valobj_sp, ExpressionVariable *var) { bool is_computed = false; if (var) { if (lldb::ValueObjectSP valobj_sp = var->GetValueObject()) { Flags valobj_type_flags(valobj_sp->GetCompilerType().GetTypeInfo()); const bool is_swift(valobj_type_flags.AllSet(eTypeIsSwift)); if ((var->GetName().AsCString("anonymous")[0] != '$') && is_swift) { is_computed = llvm::cast<SwiftExpressionVariable>(var)->GetIsComputed(); } else { return false; } } else { return false; } } const bool colorize_out = output_sp->GetFile().GetIsTerminalWithColors(); bool handled = false; Format format = m_format_options.GetFormat(); bool treat_as_void = (format == eFormatVoid); // if we are asked to suppress void, check if this is the empty tuple type, and if so suppress it if (!treat_as_void && !debugger.GetNotifyVoid()) { const CompilerType &expr_type(valobj_sp->GetCompilerType()); Flags expr_type_flags(expr_type.GetTypeInfo()); if (expr_type_flags.AllSet(eTypeIsSwift | eTypeIsTuple)) { treat_as_void = (expr_type.GetNumFields() == 0); } } if (!treat_as_void) { if (format != eFormatDefault) valobj_sp->SetFormat (format); DumpValueObjectOptions options; options.SetUseDynamicType(lldb::eDynamicCanRunTarget); options.SetMaximumPointerDepth( {DumpValueObjectOptions::PointerDepth::Mode::Formatters,1} ); options.SetUseSyntheticValue(true); options.SetRevealEmptyAggregates(false); options.SetHidePointerValue(true); options.SetVariableFormatDisplayLanguage(lldb::eLanguageTypeSwift); options.SetDeclPrintingHelper ([] (ConstString type_name, ConstString var_name, const DumpValueObjectOptions &options, Stream &stream) -> bool { if (!type_name || !var_name) return false; std::string type_name_str(type_name ? type_name.GetCString() : ""); for(auto iter = type_name_str.find(" *"); iter != std::string::npos; iter = type_name_str.find(" *")) { type_name_str.erase(iter, 2); } if (!type_name_str.empty()) { stream.Printf("%s: %s =", var_name.GetCString(), type_name_str.c_str()); return true; } return false; }); if (is_computed) { StringSummaryFormat::Flags flags; flags.SetDontShowChildren(true); flags.SetDontShowValue(true); flags.SetHideItemNames(true); flags.SetShowMembersOneLiner(false); flags.SetSkipPointers(false); flags.SetSkipReferences(false); options.SetHideValue(true); options.SetShowSummary(true); options.SetSummary(lldb::TypeSummaryImplSP(new StringSummaryFormat(flags,"<computed property>"))); } if (colorize_out) { const char *color = isThrownError(valobj_sp) ? ANSI_ESCAPE1(ANSI_FG_COLOR_RED) : ANSI_ESCAPE1(ANSI_FG_COLOR_CYAN); fprintf(output_sp->GetFile().GetStream(), "%s", color); } valobj_sp->Dump(*output_sp, options); if (colorize_out) fprintf(output_sp->GetFile().GetStream(), ANSI_ESCAPE1(ANSI_CTRL_NORMAL)); handled = true; } return handled; }
OperatingSystemGo::Goroutine OperatingSystemGo::CreateGoroutineAtIndex(uint64_t idx, Error &err) { err.Clear(); Goroutine result; ValueObjectSP g = m_allg_sp->GetSyntheticArrayMember(idx, true)->Dereference(err); if (err.Fail()) { return result; } ConstString name("goid"); ValueObjectSP val = g->GetChildMemberWithName(name, true); bool success = false; result.m_goid = val->GetValueAsUnsigned(0, &success); if (!success) { err.SetErrorToGenericError(); err.SetErrorString("unable to read goid"); return result; } name.SetCString("atomicstatus"); val = g->GetChildMemberWithName(name, true); result.m_status = (uint32_t)val->GetValueAsUnsigned(0, &success); if (!success) { err.SetErrorToGenericError(); err.SetErrorString("unable to read atomicstatus"); return result; } name.SetCString("sched"); val = g->GetChildMemberWithName(name, true); result.m_gobuf = val->GetAddressOf(false); name.SetCString("stack"); val = g->GetChildMemberWithName(name, true); name.SetCString("lo"); ValueObjectSP child = val->GetChildMemberWithName(name, true); result.m_lostack = child->GetValueAsUnsigned(0, &success); if (!success) { err.SetErrorToGenericError(); err.SetErrorString("unable to read stack.lo"); return result; } name.SetCString("hi"); child = val->GetChildMemberWithName(name, true); result.m_histack = child->GetValueAsUnsigned(0, &success); if (!success) { err.SetErrorToGenericError(); err.SetErrorString("unable to read stack.hi"); return result; } return result; }
ValueObjectSP GoUserExpression::GoInterpreter::VisitIndexExpr(const lldb_private::GoASTIndexExpr *e) { ValueObjectSP target = EvaluateExpr(e->GetX()); if (!target) return nullptr; ValueObjectSP index = EvaluateExpr(e->GetIndex()); if (!index) return nullptr; bool is_signed; if (!index->GetCompilerType().IsIntegerType(is_signed)) { m_error.SetErrorString("Unsupported index"); return nullptr; } size_t idx; if (is_signed) idx = index->GetValueAsSigned(0); else idx = index->GetValueAsUnsigned(0); if (GoASTContext::IsGoSlice(target->GetCompilerType())) { target = target->GetStaticValue(); ValueObjectSP cap = target->GetChildMemberWithName(ConstString("cap"), true); if (cap) { uint64_t capval = cap->GetValueAsUnsigned(0); if (idx >= capval) { m_error.SetErrorStringWithFormat("Invalid index %" PRIu64 " , cap = %" PRIu64, uint64_t(idx), capval); return nullptr; } } target = target->GetChildMemberWithName(ConstString("array"), true); if (target && m_use_dynamic != eNoDynamicValues) { ValueObjectSP dynamic = target->GetDynamicValue(m_use_dynamic); if (dynamic) target = dynamic; } if (!target) return nullptr; return target->GetSyntheticArrayMember(idx, true); } return target->GetChildAtIndex(idx, true); }
ValueObjectSP GoUserExpression::GoInterpreter::VisitIdent(const GoASTIdent *e) { ValueObjectSP val; if (m_frame) { VariableSP var_sp; std::string varname = e->GetName().m_value.str(); if (varname.size() > 1 && varname[0] == '$') { RegisterContextSP reg_ctx_sp = m_frame->GetRegisterContext(); const RegisterInfo *reg = reg_ctx_sp->GetRegisterInfoByName(varname.c_str() + 1); if (reg) { std::string type; switch (reg->encoding) { case lldb::eEncodingSint: type.append("int"); break; case lldb::eEncodingUint: type.append("uint"); break; case lldb::eEncodingIEEE754: type.append("float"); break; default: m_error.SetErrorString("Invaild register encoding"); return nullptr; } switch (reg->byte_size) { case 8: type.append("64"); break; case 4: type.append("32"); break; case 2: type.append("16"); break; case 1: type.append("8"); break; default: m_error.SetErrorString("Invaild register size"); return nullptr; } ValueObjectSP regVal = ValueObjectRegister::Create(m_frame.get(), reg_ctx_sp, reg->kinds[eRegisterKindLLDB]); CompilerType goType = LookupType(m_frame->CalculateTarget(), ConstString(type)); if (regVal) { regVal = regVal->Cast(goType); return regVal; } } m_error.SetErrorString("Invaild register name"); return nullptr; } VariableListSP var_list_sp(m_frame->GetInScopeVariableList(false)); if (var_list_sp) { var_sp = var_list_sp->FindVariable(ConstString(varname)); if (var_sp) val = m_frame->GetValueObjectForFrameVariable(var_sp, m_use_dynamic); else { // When a variable is on the heap instead of the stack, go records a variable // '&x' instead of 'x'. var_sp = var_list_sp->FindVariable(ConstString("&" + varname)); if (var_sp) { val = m_frame->GetValueObjectForFrameVariable(var_sp, m_use_dynamic); if (val) val = val->Dereference(m_error); if (m_error.Fail()) return nullptr; } } } if (!val) { m_error.Clear(); TargetSP target = m_frame->CalculateTarget(); if (!target) { m_error.SetErrorString("No target"); return nullptr; } var_sp = FindGlobalVariable(target, m_package + "." + e->GetName().m_value); if (var_sp) return m_frame->TrackGlobalVariable(var_sp, m_use_dynamic); } } if (!val) m_error.SetErrorStringWithFormat("Unknown variable %s", e->GetName().m_value.str().c_str()); return val; }