| // 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 |