| // Copyright 2019 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "src/developer/debug/zxdb/expr/permissive_input_location.h" |
| |
| #include "src/developer/debug/zxdb/expr/found_name.h" |
| #include "src/developer/debug/zxdb/expr/parsed_identifier.h" |
| #include "src/developer/debug/zxdb/symbols/process_symbols.h" |
| |
| namespace zxdb { |
| |
| namespace { |
| |
| // Returns true if the identifier is a special name that's understood by the symbol system but |
| // which won't be in the index. |
| // |
| // Currently these are PLT breakpoints (called "$plt(foo)" for the function "foo"), and the |
| // entrypoint (called "$main"). |
| bool IsSpecialSymbolName(const Identifier& ident) { |
| return ident.components().size() == 1u && |
| ident.components()[0].special() != SpecialIdentifier::kNone; |
| } |
| |
| } // namespace |
| |
| std::vector<InputLocation> ExpandPermissiveInputLocationNames( |
| const FindNameContext& context, const std::vector<InputLocation>& input) { |
| // Currently all users of this API need the same set of options. This can be moved to a parameter |
| // of this function if needed. |
| FindNameOptions opts(FindNameOptions::kNoKinds); |
| opts.max_results = FindNameOptions::kAllResults; |
| opts.search_mode = FindNameOptions::kAllNamespaces; |
| opts.find_functions = true; |
| opts.find_vars = true; |
| |
| std::vector<InputLocation> result; |
| |
| std::vector<FoundName> found; // Keep outside to avoid reallocation. |
| for (const auto& in : input) { |
| if (in.type == InputLocation::Type::kName) { |
| // Needs expansion. |
| found.clear(); |
| |
| if (IsSpecialSymbolName(in.name)) { |
| // Pass special names through, don't look in the index because they won't be there. |
| result.push_back(in); |
| } else { |
| FindName(context, opts, ToParsedIdentifier(in.name), &found); |
| for (const auto& f : found) |
| result.emplace_back(ToIdentifier(f.GetName())); |
| } |
| } else { |
| // Not a symbolic name, the output is the same as the input. |
| result.push_back(in); |
| } |
| } |
| return result; |
| } |
| |
| // An alternate implementation of this function could get the actual symbol objects from the |
| // FindName results (function, variable), and then do a symbol lookup on that to get the full |
| // InputLocation. Basically InputLocation would have another "symbol object" mode that would take |
| // a RefPtr<Symbol> to look up. |
| // |
| // The advantage of that implementation is that it saves the symbol name lookup when we go to the |
| // ResolveInputLocation() call. Not round-tripping through names also helps remove some potential |
| // ambiguity about what we're referring to if there are multiple matches. |
| // |
| // The disadvantage is that the implementation is more complicated, especially since symbol objects |
| // don't currently have any ModuleSymbol information associated with them. |
| // |
| // TODO(bug 37608) Revisit this design when symbols know their modules. This might make the above |
| // design more desirable. |
| std::vector<Location> ResolvePermissiveInputLocations(const ProcessSymbols* process_symbols, |
| const ResolveOptions& resolve_options, |
| const FindNameContext& context, |
| const std::vector<InputLocation>& input) { |
| std::vector<Location> result; |
| for (const auto& in : ExpandPermissiveInputLocationNames(context, input)) { |
| std::vector<Location> inner_result = process_symbols->ResolveInputLocation(in, resolve_options); |
| result.insert(result.end(), inner_result.begin(), inner_result.end()); |
| } |
| return result; |
| } |
| |
| } // namespace zxdb |