| // Copyright 2018 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. | |
| #ifndef SRC_DEVELOPER_DEBUG_ZXDB_CONSOLE_INPUT_LOCATION_PARSER_H_ | |
| #define SRC_DEVELOPER_DEBUG_ZXDB_CONSOLE_INPUT_LOCATION_PARSER_H_ | |
| #include <vector> | |
| #include "lib/fit/function.h" | |
| #include "src/developer/debug/zxdb/common/err.h" | |
| #include "src/developer/debug/zxdb/common/err_or.h" | |
| #include "src/developer/debug/zxdb/symbols/input_location.h" | |
| #include "src/developer/debug/zxdb/symbols/location.h" | |
| #include "src/lib/fxl/memory/ref_counted.h" | |
| namespace zxdb { | |
| class Command; | |
| class EvalContext; | |
| class Frame; | |
| class ProcessSymbols; | |
| // Parses a given input from the user to an InputLocation. Symbolic names ("MyFunction") are treated | |
| // as global names and there is no processing done on these. For context-aware handling of function | |
| // names, see ParseLocalInputLocation. | |
| // | |
| // The Location is used to resolve line numbers in the current file. The location need not have a | |
| // current file (it can be an empty location or an unsymbolized one) in which case numeric input | |
| // will fail. | |
| // | |
| // This does not handle the case where no location is specified (some commands, like "break", might | |
| // use this to indicate the current location, but many other commands don't support this format). | |
| // | |
| // This does not handle expressions, see EvalGlobalInputLocation() below. | |
| Err ParseGlobalInputLocation(const Location& location, const std::string& input, | |
| InputLocation* output); | |
| // Like ParseGlobalInputLocation() but also accepts expressions preceeded with a "*". Because | |
| // evaluating expressions may be asynchronous, this function is too. | |
| // | |
| // If the input location is an expression and the thing it points to has an intrinsic size, that | |
| // size will be passed as the second parameter of the callback. | |
| // | |
| // The callback follows "expression" rules in that it will be evaluted from within the stack of this | |
| // function if the result is synchronously available. | |
| void EvalGlobalInputLocation( | |
| const fxl::RefPtr<EvalContext> eval_context, const Location& location, const std::string& input, | |
| fit::callback<void(ErrOr<InputLocation>, std::optional<uint32_t> size)> cb); | |
| // The same as ParseGlobalInputLocation() but this will additionally find unqualified functions on | |
| // the current class if there is one. For file/line and address based inputs, this will be identical | |
| // to ParseGlobalInputLocation(). | |
| // | |
| // The Frame* variant will extract the process symbols and current location from the frame if | |
| // possible. | |
| // | |
| // In the symbolic name case, it can produce more than one location by qualifying the matched class | |
| // member function name so it can be resolved in a global context. It will ALSO return an | |
| // InputLocation that corresponds to the global symbol name. | |
| // | |
| // For example, if the input is "Func" this might return two things: | |
| // - "::some_namespace::MyClass::Func" (match from current frame). | |
| // - "Func" (so all global functions will still be matched when the symbols are queried). | |
| // If there's no "local" match or the optional_frame is null, this will return only the second | |
| // unmodified "Func" version. | |
| // | |
| // This is designed to return the maximal number of matches given the current context that can | |
| // be resolved later without ambiguity (breakpoints will need to match shared libraries loaded | |
| // later when the current context won't be known). | |
| // | |
| // The ProcessSymbols pointer can be null in which case this will have the same behavior as | |
| // ParseGlobalInputLocation() (this simplifies some callers which need to handle both cases). | |
| Err ParseLocalInputLocation(const ProcessSymbols* optional_process_symbols, | |
| const Location& location, const std::string& input, | |
| std::vector<InputLocation>* output); | |
| Err ParseLocalInputLocation(const Frame* optional_frame, const std::string& input, | |
| std::vector<InputLocation>* output); | |
| // Like ParseLocalInputLocation() but also accepts expressions preceeded with a "*". Because | |
| // evaluating expressions may be asynchronous, this function is too. | |
| // | |
| // If the input location is an expression and the thing it points to has an intrinsic size, that | |
| // size will be passed as the second parameter of the callback. | |
| // | |
| // The callback follows "expression" rules in that it will be evaluted from within the stack of this | |
| // function if the result is synchronously available. | |
| void EvalLocalInputLocation( | |
| const fxl::RefPtr<EvalContext>& eval_context, const Frame* optional_frame, | |
| const std::string& input, | |
| fit::callback<void(ErrOr<std::vector<InputLocation>>, std::optional<uint32_t> size)> cb); | |
| void EvalLocalInputLocation( | |
| const fxl::RefPtr<EvalContext>& eval_context, const Location& location, | |
| const std::string& input, | |
| fit::callback<void(ErrOr<std::vector<InputLocation>>, std::optional<uint32_t> size)> cb); | |
| // Parses the input and generates a list of matches. No matches will generate an error. This can | |
| // take either a pre-parsed InputLocation, or can parse the input itself. | |
| // | |
| // The Frame* variant will extract the process symbols and current location from the frame if | |
| // possible. | |
| // | |
| // Set |symbolize| to make the output locations symbolized. This will be slightly slower. If you | |
| // just need the addresses, pass false. | |
| // | |
| // The |optional_frame| will be passed for context to ParseLocalInputLocation() above to handle | |
| // finding names based on the current scope. See that for the behavior of local functions | |
| // definitions. | |
| // | |
| // Underneath final resolution is done by ResolvePermissiveInputLocations() so will match functions | |
| // in any namespace unless globally qualified. | |
| Err ResolveInputLocations(const ProcessSymbols* process_symbols, const Location& location, | |
| const std::string& input, bool symbolize, std::vector<Location>* output); | |
| Err ResolveInputLocations(const Frame* optional_frame, const std::string& input, bool symbolize, | |
| std::vector<Location>* output); | |
| // Variant of the above that takes a pre-parsed list of input locations. | |
| Err ResolveInputLocations(const ProcessSymbols* process_symbols, | |
| const std::vector<InputLocation>& input_locations, bool symbolize, | |
| std::vector<Location>* locations); | |
| // Resolves the given input string to a Location object. Returns an error parsing or if the location | |
| // can not be resolved or resolves to more than one address. | |
| // | |
| // Set |symbolize| to make the output |*location| symbolized. This will be slightly slower. If you | |
| // just need the address, pass false. | |
| // | |
| // These first two variants take pre-parsed InputLocation(s): | |
| Err ResolveUniqueInputLocation(const ProcessSymbols* process_symbols, | |
| const InputLocation& input_location, bool symbolize, | |
| Location* output); | |
| Err ResolveUniqueInputLocation(const ProcessSymbols* process_symbols, | |
| const std::vector<InputLocation>& input_location, bool symbolize, | |
| Location* output); | |
| // These variants parse the input. The Frame* variant will extract the process symbols and current | |
| // location from the frame if possible. | |
| Err ResolveUniqueInputLocation(const ProcessSymbols* process_symbols, const Location& location, | |
| const std::string& input, bool symbolize, Location* output); | |
| Err ResolveUniqueInputLocation(const Frame* optional_frame, const std::string& input, | |
| bool symbolize, Location* output); | |
| // Autocomplete for input locations. | |
| void CompleteInputLocation(const Command& command, const std::string& prefix, | |
| std::vector<std::string>* completions); | |
| // Generates help for a command describing the parsing of locations. The parameter is a string | |
| // containing the name of the command. | |
| // clang-format off | |
| #define LOCATION_ARG_HELP(cmd) \ | |
| " <symbol>\n" \ | |
| " " cmd " main\n" \ | |
| " " cmd " Foo::Bar\n" \ | |
| "\n" \ | |
| " ▷ This will match functions in the current class if there is one.\n" \ | |
| " To override, prefix with \"::\" as in \"" cmd " ::Foo::Bar\".\n" \ | |
| "\n" \ | |
| " <file>:<line>\n" \ | |
| " " cmd " foo.cc:123\n" \ | |
| "\n" \ | |
| " ▷ To disambiguate different files with the same name, include\n" \ | |
| " directory names preceding the name (from the right).\n" \ | |
| "\n" \ | |
| " <line number> (within the frame's file)\n" \ | |
| " " cmd " 123\n" \ | |
| "\n" \ | |
| " ▷ All decimal integers are considered line numbers.\n" \ | |
| "\n" \ | |
| " 0x<address>\n" \ | |
| " " cmd " 0x7d12362f0\n" \ | |
| "\n" \ | |
| " ▷ All hexadecimal numbers are considered addresses. Precede\n" \ | |
| " decimal numbers with * to force interpretation as an address.\n" \ | |
| "\n" | |
| // Append this to LOCATION_ARG_HELP(cmd) if the command supports expressions via | |
| // Eval*InputLocation(). | |
| #define LOCATION_EXPRESSION_HELP(cmd) \ | |
| " \"*<expression>\"\n" \ | |
| " " cmd " *0x7d12362f0\n" \ | |
| " " cmd " *&my_thing\n" \ | |
| " " cmd " *my_array[0]->some_pointer\n" \ | |
| "\n" \ | |
| " ▷ An arbitrary expression can be evaluated and the result will be\n" \ | |
| " interpreted as an address. If the result is a pointer, that\n" \ | |
| " pointer's value will be used. If the result is an integer or a\n" \ | |
| " reference to an integer, the referenced integer will be interpreted\n" \ | |
| " as a memory address.\n" \ | |
| "\n" \ | |
| " The * denotes a expression follows but is not part of the expression.\n" \ | |
| "\n" | |
| // clang-format on | |
| } // namespace zxdb | |
| #endif // SRC_DEVELOPER_DEBUG_ZXDB_CONSOLE_INPUT_LOCATION_PARSER_H_ |