binutils-gdb/gdb/extension-priv.h
Andrew Burgess ef1a41f20b gdb: add extension hook ext_lang_find_objfile_from_buildid
Add a new ext_lang_find_objfile_from_buildid function which is called
from find_objfile_by_build_id and gives extension languages a chance
to find missing objfiles.

This commit adds the ext_lang_find_objfile_from_buildid function and
the extension_language_ops::find_objfile_from_buildid() hook, but does
not implement the hook for any extension languages, that will come in
the next commit.

This commit does rewrite find_objfile_by_build_id (build-id.c) to call
the new hook though.  The basic steps of find_objfile_by_build_id are
now this:

  1. Try to find the missing objfile using the build-id by looking in
  the debug-file-directory's .build-id/ sub-directory.  If we find the
  file then we're done.

  2. Ask debuginfod to download the missing file for us.  If we
  download the file successfully then we're done.

  3. Ask the extension language hook to find the file for us.  If the
  extension language asks us to try again then we repeat step (1) only
  and if we still don't have the file, we move to step (4).  If the
  extension language told us where the file is then we use that file
  and we're done.

  4. We didn't find the file.  Carry on without it.

Only step (3) is new in this logic, everything else was already done.

There are no tests added here as we can't currently write an extension
language callback.  The next commit will add the tests.

Approved-By: Tom Tromey <tom@tromey.com>
2024-11-10 10:18:22 +00:00

342 lines
14 KiB
C++

/* Private implementation details of interface between gdb and its
extension languages.
Copyright (C) 2014-2024 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#ifndef EXTENSION_PRIV_H
#define EXTENSION_PRIV_H
#include "extension.h"
#include <signal.h>
#include "cli/cli-script.h"
/* High level description of an extension/scripting language.
An entry for each is compiled into GDB regardless of whether the support
is present. This is done so that we can issue meaningful errors if the
support is not compiled in. */
struct extension_language_defn
{
/* Enum of the extension language. */
enum extension_language language;
/* The name of the extension language, lowercase. E.g., python. */
const char *name;
/* The capitalized name of the extension language.
For python this is "Python". For gdb this is "GDB". */
const char *capitalized_name;
/* The file suffix of this extension language. E.g., ".py". */
const char *suffix;
/* The suffix of per-objfile scripts to auto-load.
E.g., When the program loads libfoo.so, look for libfoo.so-gdb.py. */
const char *auto_load_suffix;
/* We support embedding external extension language code in GDB's own
scripting language. We do this by having a special command that begins
the extension language snippet, and terminate it with "end".
This specifies the control type used to implement this. */
enum command_control_type cli_control_type;
/* A pointer to the "methods" to load scripts in this language,
or NULL if the support is not compiled into GDB. */
const struct extension_language_script_ops *script_ops;
/* Either a pointer to the "methods" of the extension language interface
or NULL if the support is not compiled into GDB.
This is also NULL for GDB's own scripting language which is relatively
primitive, and doesn't provide these features. */
const struct extension_language_ops *ops;
};
/* The interface for loading scripts from external extension languages,
as well as GDB's own scripting language.
All of these methods are required to be implemented.
By convention all of these functions take a pseudo-this parameter
as the first argument. */
struct extension_language_script_ops
{
/* Load a script. This is called, e.g., via the "source" command.
If there's an error while processing the script this function may,
but is not required to, throw an error. */
script_sourcer_func *script_sourcer;
/* Load a script attached to an objfile.
If there's an error while processing the script this function may,
but is not required to, throw an error. */
objfile_script_sourcer_func *objfile_script_sourcer;
/* Execute a script attached to an objfile.
If there's an error while processing the script this function may,
but is not required to, throw an error. */
objfile_script_executor_func *objfile_script_executor;
/* Return non-zero if auto-loading scripts in this extension language
is enabled. */
bool (*auto_load_enabled) (const struct extension_language_defn *);
};
/* The interface for making calls from GDB to an external extension
language. This is for non-script-loading related functionality, like
pretty-printing, etc. The reason these are separated out is GDB's own
scripting language makes use of extension_language_script_opts, but it
makes no use of these. There is no (current) intention to split
extension_language_ops up any further.
All of these methods are optional and may be NULL, except where
otherwise indicated.
By convention all of these functions take a pseudo-this parameter
as the first argument. */
struct extension_language_ops
{
/* Called after GDB has processed the early initialization settings
files. This is when the extension language should be initialized. By
the time this is called all of the earlier initialization functions
have already been called. */
void (*initialize) (const struct extension_language_defn *);
/* Return non-zero if the extension language successfully initialized.
This method is required. */
int (*initialized) (const struct extension_language_defn *);
/* Called just before GDB exits. This shuts down the extension
language. This can be NULL. */
void (*shutdown) (const struct extension_language_defn *);
/* Process a sequence of commands embedded in GDB's own scripting language.
E.g.,
python
print 42
end */
void (*eval_from_control_command) (const struct extension_language_defn *,
struct command_line *);
/* Type-printing support:
start_type_printers, apply_type_printers, free_type_printers.
These methods are optional and may be NULL, but if one of them is
implemented then they all must be. */
/* Called before printing a type. */
void (*start_type_printers) (const struct extension_language_defn *,
struct ext_lang_type_printers *);
/* Try to pretty-print TYPE. If successful the pretty-printed type is
stored in *PRETTIED_TYPE.
Returns EXT_LANG_RC_OK upon success, EXT_LANG_RC_NOP if the type
is not recognized, and EXT_LANG_RC_ERROR if an error was encountered.
This function has a bit of a funny name, since it actually applies
recognizers, but this seemed clearer given the start_type_printers
and free_type_printers functions. */
enum ext_lang_rc (*apply_type_printers)
(const struct extension_language_defn *,
const struct ext_lang_type_printers *,
struct type *,
gdb::unique_xmalloc_ptr<char> *prettied_type);
/* Called after a type has been printed to give the type pretty-printer
mechanism an opportunity to clean up. */
void (*free_type_printers) (const struct extension_language_defn *,
struct ext_lang_type_printers *);
/* Try to pretty-print a value, onto stdio stream STREAM according
to OPTIONS. VAL is the object to print. Returns EXT_LANG_RC_OK
upon success, EXT_LANG_RC_NOP if the value is not recognized, and
EXT_LANG_RC_ERROR if an error was encountered. */
enum ext_lang_rc (*apply_val_pretty_printer)
(const struct extension_language_defn *,
struct value *val, struct ui_file *stream, int recurse,
const struct value_print_options *options,
const struct language_defn *language);
/* GDB access to the "frame filter" feature.
FRAME is the source frame to start frame-filter invocation. FLAGS is an
integer holding the flags for printing. The following elements of
the FRAME_FILTER_FLAGS enum denotes the make-up of FLAGS:
PRINT_LEVEL is a flag indicating whether to print the frame's
relative level in the output. PRINT_FRAME_INFO is a flag that
indicates whether this function should print the frame
information, PRINT_ARGS is a flag that indicates whether to print
frame arguments, and PRINT_LOCALS, likewise, with frame local
variables. ARGS_TYPE is an enumerator describing the argument
format, OUT is the output stream to print. FRAME_LOW is the
beginning of the slice of frames to print, and FRAME_HIGH is the
upper limit of the frames to count. Returns SCR_BT_ERROR on error,
or SCR_BT_COMPLETED on success. */
enum ext_lang_bt_status (*apply_frame_filter)
(const struct extension_language_defn *,
const frame_info_ptr &frame, frame_filter_flags flags,
enum ext_lang_frame_args args_type,
struct ui_out *out, int frame_low, int frame_high);
/* Used for registering the ptwrite filter to the current thread. */
void (*apply_ptwrite_filter)
(const struct extension_language_defn *extlang,
struct btrace_thread_info *btinfo);
/* Update values held by the extension language when OBJFILE is discarded.
New global types must be created for every such value, which must then be
updated to use the new types.
This function typically just iterates over all appropriate values and
calls preserve_one_value for each one.
COPIED_TYPES is used to prevent cycles / duplicates and is passed to
preserve_one_value. */
void (*preserve_values) (const struct extension_language_defn *,
struct objfile *objfile, htab_t copied_types);
/* Return non-zero if there is a stop condition for the breakpoint.
This is used to implement the restriction that a breakpoint may have
at most one condition. */
int (*breakpoint_has_cond) (const struct extension_language_defn *,
struct breakpoint *);
/* Return a value of enum ext_lang_bp_stop indicating if there is a stop
condition for the breakpoint, and if so whether the program should
stop. This is called when the program has stopped at the specified
breakpoint.
While breakpoints can have at most one condition, this is called for
every extension language, even if another extension language has a
"stop" method: other kinds of breakpoints may be implemented using
this method, e.g., "finish breakpoints" in Python. */
enum ext_lang_bp_stop (*breakpoint_cond_says_stop)
(const struct extension_language_defn *, struct breakpoint *);
/* The next two are used to connect GDB's SIGINT handling with the
extension language's.
Terminology: If an extension language can use GDB's SIGINT handling then
we say the extension language has "cooperative SIGINT handling".
Python is an example of this.
These need not be implemented, but if one of them is implemented
then they all must be. */
/* Set the SIGINT indicator.
This is called by GDB's SIGINT handler and must be async-safe. */
void (*set_quit_flag) (const struct extension_language_defn *);
/* Return true if a SIGINT has occurred.
This is expected to also clear the indicator. */
bool (*check_quit_flag) (const struct extension_language_defn *);
/* Called before gdb prints its prompt, giving extension languages an
opportunity to change it with set_prompt.
Returns EXT_LANG_RC_OK if the prompt was changed, EXT_LANG_RC_NOP if
the prompt was not changed, and EXT_LANG_RC_ERROR if an error was
encountered.
Extension languages are called in order, and once the prompt is
changed or an error occurs no further languages are called. */
enum ext_lang_rc (*before_prompt) (const struct extension_language_defn *,
const char *current_gdb_prompt);
/* Return a vector of matching xmethod workers defined in this
extension language. The workers service methods with name
METHOD_NAME on objects of type OBJ_TYPE. The vector is returned
in DM_VEC.
This field may be NULL if the extension language does not support
xmethods. */
enum ext_lang_rc (*get_matching_xmethod_workers)
(const struct extension_language_defn *extlang,
struct type *obj_type,
const char *method_name,
std::vector<xmethod_worker_up> *dm_vec);
/* Colorize a source file. NAME is the source file's name, and
CONTENTS is the contents of the file. This should either return
colorized (using ANSI terminal escapes) version of the contents,
or an empty option. */
std::optional<std::string> (*colorize) (const std::string &name,
const std::string &contents);
/* Colorize a single line of disassembler output, CONTENT. This should
either return colorized (using ANSI terminal escapes) version of the
contents, or an empty optional. */
std::optional<std::string> (*colorize_disasm) (const std::string &content,
gdbarch *gdbarch);
/* Print a single instruction from ADDRESS in architecture GDBARCH. INFO
is the standard libopcodes disassembler_info structure. Bytes for the
instruction being printed should be read using INFO->read_memory_func
as the actual instruction bytes might be in a buffer.
Use INFO->fprintf_func to print the results of the disassembly, and
return the length of the instruction.
If no instruction can be disassembled then return an empty value and
other extension languages will get a chance to perform the
disassembly. */
std::optional<int> (*print_insn) (struct gdbarch *gdbarch,
CORE_ADDR address,
struct disassemble_info *info);
/* Give extension languages a chance to deal with missing debug
information. OBJFILE is the file for which GDB was unable to find
any debug information. */
ext_lang_missing_file_result
(*handle_missing_debuginfo) (const struct extension_language_defn *,
struct objfile *objfile);
/* Give extension languages a chance to deal with missing objfiles.
PSPACE is the program space in which GDB is searching for a missing
objfile, and will not be NULL. BUILD_ID is the build-id of the
objfile we're looking for, and will not be NULL. FILENAME is the name
of the file we're looking for, and will not be NULL. See
ext_lang_find_objfile_from_buildid for some additional information
about the meaning of FILENAME. */
ext_lang_missing_file_result
(*find_objfile_from_buildid) (const struct extension_language_defn *,
program_space *pspace,
const struct bfd_build_id *build_id,
const char *filename);
};
/* State necessary to restore a signal handler to its previous value. */
struct signal_handler
{
/* Non-zero if "handler" has been set. */
int handler_saved;
/* The signal handler. */
sighandler_t handler;
};
/* State necessary to restore the currently active extension language
to its previous value. */
struct active_ext_lang_state
{
/* The previously active extension language. */
const struct extension_language_defn *ext_lang;
/* Its SIGINT handler. */
struct signal_handler sigint_handler;
};
extern struct active_ext_lang_state *set_active_ext_lang
(const struct extension_language_defn *);
extern void restore_active_ext_lang (struct active_ext_lang_state *previous);
#endif /* EXTENSION_PRIV_H */