-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[lldb] [disassembler] chore: enhance VariableAnnotator to return structured data: introduce VariableAnnotator::AnnotateStructured method #169408
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 2 commits
7d03658
7e7ae05
4b601f8
3654a86
110c041
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -286,6 +286,10 @@ bool Disassembler::ElideMixedSourceAndDisassemblyLine( | |
| return false; | ||
| } | ||
|
|
||
| static constexpr const char *UndefLocation = "undef"; | ||
| static const std::string UndefLocationFormatted = | ||
| llvm::formatv("<{0}>", UndefLocation).str(); | ||
|
|
||
| // For each instruction, this block attempts to resolve in-scope variables | ||
| // and determine if the current PC falls within their | ||
| // DWARF location entry. If so, it prints a simplified annotation using the | ||
|
|
@@ -300,16 +304,41 @@ bool Disassembler::ElideMixedSourceAndDisassemblyLine( | |
| // disassembled instruction stream, similar to how debug information | ||
| // enhances source-level debugging. | ||
| std::vector<std::string> VariableAnnotator::Annotate(Instruction &inst) { | ||
| auto structured_annotations = AnnotateStructured(inst); | ||
|
||
|
|
||
| std::vector<std::string> events; | ||
| events.reserve(structured_annotations.size()); | ||
|
|
||
| for (const auto &annotation : structured_annotations) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here, I can't tell what type
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated ✅ Here and in most other places within this pr. |
||
| auto location = (annotation.location_description == UndefLocation | ||
| ? UndefLocationFormatted | ||
| : annotation.location_description); | ||
|
|
||
| auto display_string = | ||
| llvm::formatv("{0} = {1}", annotation.variable_name, location).str(); | ||
|
|
||
| events.push_back(std::move(display_string)); | ||
| } | ||
|
|
||
| return events; | ||
| } | ||
|
|
||
| std::vector<VariableAnnotation> | ||
| VariableAnnotator::AnnotateStructured(Instruction &inst) { | ||
| std::vector<VariableAnnotation> annotations; | ||
|
|
||
| auto module_sp = inst.GetAddress().GetModule(); | ||
|
|
||
| // If we lost module context, everything becomes <undef>. | ||
| // If we lost module context, mark all live variables as UndefLocation. | ||
| if (!module_sp) { | ||
| for (const auto &KV : m_live_vars) | ||
| events.emplace_back(llvm::formatv("{0} = <undef>", KV.second.name).str()); | ||
| for (const auto &KV : m_live_vars) { | ||
| auto annotation_entity = KV.second; | ||
| annotation_entity.is_live = false; | ||
| annotation_entity.location_description = UndefLocation; | ||
| annotations.push_back(annotation_entity); | ||
| } | ||
| m_live_vars.clear(); | ||
| return events; | ||
| return annotations; | ||
| } | ||
|
|
||
| // Resolve function/block at this *file* address. | ||
|
|
@@ -319,10 +348,14 @@ std::vector<std::string> VariableAnnotator::Annotate(Instruction &inst) { | |
| if (!module_sp->ResolveSymbolContextForAddress(iaddr, mask, sc) || | ||
| !sc.function) { | ||
| // No function context: everything dies here. | ||
| for (const auto &KV : m_live_vars) | ||
| events.emplace_back(llvm::formatv("{0} = <undef>", KV.second.name).str()); | ||
| for (const auto &KV : m_live_vars) { | ||
| auto annotation_entity = KV.second; | ||
| annotation_entity.is_live = false; | ||
| annotation_entity.location_description = UndefLocation; | ||
| annotations.push_back(annotation_entity); | ||
| } | ||
| m_live_vars.clear(); | ||
| return events; | ||
| return annotations; | ||
| } | ||
|
|
||
| // Collect in-scope variables for this instruction into current_vars. | ||
|
|
@@ -349,7 +382,7 @@ std::vector<std::string> VariableAnnotator::Annotate(Instruction &inst) { | |
| // Prefer "register-only" output when we have an ABI. | ||
| opts.PrintRegisterOnly = static_cast<bool>(abi_sp); | ||
|
|
||
| llvm::DenseMap<lldb::user_id_t, VarState> current_vars; | ||
| llvm::DenseMap<lldb::user_id_t, VariableAnnotation> current_vars; | ||
|
|
||
| for (size_t i = 0, e = var_list.GetSize(); i != e; ++i) { | ||
| lldb::VariableSP v = var_list.GetVariableAtIndex(i); | ||
|
|
@@ -376,8 +409,26 @@ std::vector<std::string> VariableAnnotator::Annotate(Instruction &inst) { | |
| if (loc.empty()) | ||
| continue; | ||
|
|
||
| current_vars.try_emplace(v->GetID(), | ||
| VarState{std::string(name), std::string(loc)}); | ||
| std::optional<std::string> decl_file; | ||
| std::optional<uint32_t> decl_line; | ||
| std::optional<std::string> type_name; | ||
|
|
||
| const Declaration &decl = v->GetDeclaration(); | ||
| if (decl.GetFile()) { | ||
| decl_file = decl.GetFile().GetFilename().AsCString(); | ||
| if (decl.GetLine() > 0) | ||
| decl_line = decl.GetLine(); | ||
| } | ||
|
|
||
| if (Type *type = v->GetType()) | ||
| if (const char *type_str = type->GetName().AsCString()) | ||
| type_name = type_str; | ||
|
|
||
| current_vars.try_emplace( | ||
| v->GetID(), | ||
| VariableAnnotation{std::string(name), std::string(loc), true, | ||
| entry.expr->GetRegisterKind(), entry.file_range, | ||
| decl_file, decl_line, type_name}); | ||
| } | ||
|
|
||
| // Diff m_live_vars → current_vars. | ||
|
|
@@ -387,24 +438,31 @@ std::vector<std::string> VariableAnnotator::Annotate(Instruction &inst) { | |
| auto it = m_live_vars.find(KV.first); | ||
| if (it == m_live_vars.end()) { | ||
| // Newly live. | ||
| events.emplace_back( | ||
| llvm::formatv("{0} = {1}", KV.second.name, KV.second.last_loc).str()); | ||
| } else if (it->second.last_loc != KV.second.last_loc) { | ||
| auto annotation_entity = KV.second; | ||
| annotation_entity.is_live = true; | ||
| annotations.push_back(annotation_entity); | ||
| } else if (it->second.location_description != | ||
| KV.second.location_description) { | ||
| // Location changed. | ||
| events.emplace_back( | ||
| llvm::formatv("{0} = {1}", KV.second.name, KV.second.last_loc).str()); | ||
| auto annotation_entity = KV.second; | ||
| annotation_entity.is_live = true; | ||
| annotations.push_back(annotation_entity); | ||
| } | ||
| } | ||
|
|
||
| // 2) Ends: anything that was live but is not in current_vars becomes <undef>. | ||
| for (const auto &KV : m_live_vars) { | ||
| if (!current_vars.count(KV.first)) | ||
| events.emplace_back(llvm::formatv("{0} = <undef>", KV.second.name).str()); | ||
| } | ||
| // 2) Ends: anything that was live but is not in current_vars becomes | ||
| // UndefLocation. | ||
| for (const auto &KV : m_live_vars) | ||
| if (!current_vars.count(KV.first)) { | ||
| auto annotation_entity = KV.second; | ||
| annotation_entity.is_live = false; | ||
| annotation_entity.location_description = UndefLocation; | ||
| annotations.push_back(annotation_entity); | ||
| } | ||
|
|
||
| // Commit new state. | ||
| m_live_vars = std::move(current_vars); | ||
| return events; | ||
| return annotations; | ||
| } | ||
|
|
||
| void Disassembler::PrintInstructions(Debugger &debugger, const ArchSpec &arch, | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.