mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-05 15:15:42 +00:00
Add a new gdbarch method which can read the execution context from a core file. An execution context, for this commit, means the filename of the executable used to generate the core file and the arguments passed to the executable. In later commits this will be extended further to include the environment in which the executable was run, but this commit is already pretty big, so I've split that part out into a later commit. Initially this new gdbarch method is only implemented for Linux targets, but a later commit will add FreeBSD support too. Currently when GDB opens a core file, GDB reports the command and arguments used to generate the core file. For example: (gdb) core-file ./core.521524 [New LWP 521524] Core was generated by `./gen-core abc def'. However, this information comes from the psinfo structure in the core file, and this struct only allows 80 characters for the command and arguments combined. If the command and arguments exceed this then they are truncated. Additionally, neither the executable nor the arguments are quoted in the psinfo structure, so if, for example, the executable was named 'aaa bbb' (i.e. contains white space) and was run with the arguments 'ccc' and 'ddd', then when this core file was opened by GDB we'd see: (gdb) core-file ./core.521524 [New LWP 521524] Core was generated by `./aaa bbb ccc ddd'. It is impossible to know if 'bbb' is part of the executable filename, or another argument. However, the kernel places the executable command onto the user stack, this is pointed to by the AT_EXECFN entry in the auxv vector. Additionally, the inferior arguments are all available on the user stack. The new gdbarch method added in this commit extracts this information from the user stack and allows GDB to access it. The information on the stack is writable by the user, so a user application can start up, edit the arguments, override the AT_EXECFN string, and then dump core. In this case GDB will report incorrect information, however, it is worth noting that the psinfo structure is also filled (by the kernel) by just copying information from the user stack, so, if the user edits the on stack arguments, the values reported in psinfo will change, so the new approach is no worse than what we currently have. The benefit of this approach is that GDB gets to report the full executable name and all the arguments without the 80 character limit, and GDB is aware which parts are the executable name, and which parts are arguments, so we can, for example, style the executable name. Another benefit is that, now we know all the arguments, we can poke these into the inferior object. This means that after loading a core file a user can 'show args' to see the arguments used. A user could even transition from core file debugging to live inferior debugging using, e.g. 'run', and GDB would restart the inferior with the correct arguments. Now the downside: finding the AT_EXECFN string is easy, the auxv entry points directly too it. However, finding the arguments is a little trickier. There's currently no easy way to get a direct pointer to the arguments. Instead, I've got a heuristic which I believe should find the arguments in most cases. The algorithm is laid out in linux-tdep.c, I'll not repeat it here, but it's basically a search of the user stack, starting from AT_EXECFN. If the new heuristic fails then GDB just falls back to the old approach, asking bfd to read the psinfo structure for us, which gives the old 80 character limited answer. For testing, I've run this series on (all GNU/Linux) x86-64. s390, ppc64le, and the new test passes in each case. I've done some very basic testing on ARM which does things a little different than the other architectures mentioned, see ARM specific notes in linux_corefile_parse_exec_context_1 for details.
382 lines
12 KiB
C++
382 lines
12 KiB
C++
/* Dynamic architecture support for GDB, the GNU debugger.
|
|
|
|
Copyright (C) 1998-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 GDB_GDBARCH_H
|
|
#define GDB_GDBARCH_H
|
|
|
|
#include <vector>
|
|
#include "frame.h"
|
|
#include "dis-asm.h"
|
|
#include "gdbsupport/gdb_obstack.h"
|
|
#include "infrun.h"
|
|
#include "osabi.h"
|
|
#include "displaced-stepping.h"
|
|
#include "gdbsupport/gdb-checked-static-cast.h"
|
|
#include "registry.h"
|
|
|
|
struct floatformat;
|
|
struct ui_file;
|
|
struct value;
|
|
struct objfile;
|
|
struct obj_section;
|
|
struct minimal_symbol;
|
|
struct regcache;
|
|
struct reggroup;
|
|
struct regset;
|
|
struct disassemble_info;
|
|
struct target_ops;
|
|
struct obstack;
|
|
struct bp_target_info;
|
|
struct target_desc;
|
|
struct symbol;
|
|
struct syscall;
|
|
struct agent_expr;
|
|
struct axs_value;
|
|
struct stap_parse_info;
|
|
struct expr_builder;
|
|
struct ravenscar_arch_ops;
|
|
struct mem_range;
|
|
struct syscalls_info;
|
|
struct thread_info;
|
|
struct ui_out;
|
|
struct inferior;
|
|
struct x86_xsave_layout;
|
|
struct solib_ops;
|
|
struct core_file_exec_context;
|
|
|
|
#include "regcache.h"
|
|
|
|
/* The base class for every architecture's tdep sub-class. The virtual
|
|
destructor ensures the class has RTTI information, which allows
|
|
gdb::checked_static_cast to be used in the gdbarch_tdep function. */
|
|
|
|
struct gdbarch_tdep_base
|
|
{
|
|
virtual ~gdbarch_tdep_base() = default;
|
|
};
|
|
|
|
using gdbarch_tdep_up = std::unique_ptr<gdbarch_tdep_base>;
|
|
|
|
/* Callback type for the 'iterate_over_objfiles_in_search_order'
|
|
gdbarch method. */
|
|
|
|
using iterate_over_objfiles_in_search_order_cb_ftype
|
|
= gdb::function_view<bool(objfile *)>;
|
|
|
|
/* Callback type for regset section iterators. The callback usually
|
|
invokes the REGSET's supply or collect method, to which it must
|
|
pass a buffer - for collects this buffer will need to be created using
|
|
COLLECT_SIZE, for supply the existing buffer being read from should
|
|
be at least SUPPLY_SIZE. SECT_NAME is a BFD section name, and HUMAN_NAME
|
|
is used for diagnostic messages. CB_DATA should have been passed
|
|
unchanged through the iterator. */
|
|
|
|
typedef void (iterate_over_regset_sections_cb)
|
|
(const char *sect_name, int supply_size, int collect_size,
|
|
const struct regset *regset, const char *human_name, void *cb_data);
|
|
|
|
/* For a function call, does the function return a value using a
|
|
normal value return or a structure return - passing a hidden
|
|
argument pointing to storage. For the latter, there are two
|
|
cases: language-mandated structure return and target ABI
|
|
structure return. */
|
|
|
|
enum function_call_return_method
|
|
{
|
|
/* Standard value return. */
|
|
return_method_normal = 0,
|
|
|
|
/* Language ABI structure return. This is handled
|
|
by passing the return location as the first parameter to
|
|
the function, even preceding "this". */
|
|
return_method_hidden_param,
|
|
|
|
/* Target ABI struct return. This is target-specific; for instance,
|
|
on ia64 the first argument is passed in out0 but the hidden
|
|
structure return pointer would normally be passed in r8. */
|
|
return_method_struct,
|
|
};
|
|
|
|
enum class memtag_type
|
|
{
|
|
/* Logical tag, the tag that is stored in unused bits of a pointer to a
|
|
virtual address. */
|
|
logical = 0,
|
|
|
|
/* Allocation tag, the tag that is associated with every granule of memory in
|
|
the physical address space. Allocation tags are used to validate memory
|
|
accesses via pointers containing logical tags. */
|
|
allocation,
|
|
};
|
|
|
|
/* Callback types for 'read_core_file_mappings' gdbarch method. */
|
|
|
|
using read_core_file_mappings_pre_loop_ftype =
|
|
gdb::function_view<void (ULONGEST count)>;
|
|
|
|
using read_core_file_mappings_loop_ftype =
|
|
gdb::function_view<void (int num,
|
|
ULONGEST start,
|
|
ULONGEST end,
|
|
ULONGEST file_ofs,
|
|
const char *filename,
|
|
const bfd_build_id *build_id)>;
|
|
|
|
/* Possible values for gdbarch_call_dummy_location. */
|
|
enum call_dummy_location_type
|
|
{
|
|
ON_STACK,
|
|
AT_ENTRY_POINT,
|
|
};
|
|
|
|
#include "gdbarch-gen.h"
|
|
|
|
/* An internal function that should _only_ be called from gdbarch_tdep.
|
|
Returns the gdbarch_tdep_base field held within GDBARCH. */
|
|
|
|
extern struct gdbarch_tdep_base *gdbarch_tdep_1 (struct gdbarch *gdbarch);
|
|
|
|
/* Return the gdbarch_tdep_base object held within GDBARCH cast to the type
|
|
TDepType, which should be a sub-class of gdbarch_tdep_base.
|
|
|
|
When GDB is compiled in maintainer mode a run-time check is performed
|
|
that the gdbarch_tdep_base within GDBARCH really is of type TDepType.
|
|
When GDB is compiled in release mode the run-time check is not
|
|
performed, and we assume the caller knows what they are doing. */
|
|
|
|
template<typename TDepType>
|
|
static inline TDepType *
|
|
gdbarch_tdep (struct gdbarch *gdbarch)
|
|
{
|
|
struct gdbarch_tdep_base *tdep = gdbarch_tdep_1 (gdbarch);
|
|
return gdb::checked_static_cast<TDepType *> (tdep);
|
|
}
|
|
|
|
/* Mechanism for co-ordinating the selection of a specific
|
|
architecture.
|
|
|
|
GDB targets (*-tdep.c) can register an interest in a specific
|
|
architecture. Other GDB components can register a need to maintain
|
|
per-architecture data.
|
|
|
|
The mechanisms below ensures that there is only a loose connection
|
|
between the set-architecture command and the various GDB
|
|
components. Each component can independently register their need
|
|
to maintain architecture specific data with gdbarch.
|
|
|
|
Pragmatics:
|
|
|
|
Previously, a single TARGET_ARCHITECTURE_HOOK was provided. It
|
|
didn't scale.
|
|
|
|
The more traditional mega-struct containing architecture specific
|
|
data for all the various GDB components was also considered. Since
|
|
GDB is built from a variable number of (fairly independent)
|
|
components it was determined that the global approach was not
|
|
applicable. */
|
|
|
|
|
|
/* Register a new architectural family with GDB.
|
|
|
|
Register support for the specified ARCHITECTURE with GDB. When
|
|
gdbarch determines that the specified architecture has been
|
|
selected, the corresponding INIT function is called.
|
|
|
|
--
|
|
|
|
The INIT function takes two parameters: INFO which contains the
|
|
information available to gdbarch about the (possibly new)
|
|
architecture; ARCHES which is a list of the previously created
|
|
``struct gdbarch'' for this architecture.
|
|
|
|
The INFO parameter is, as far as possible, be pre-initialized with
|
|
information obtained from INFO.ABFD or the global defaults.
|
|
|
|
The ARCHES parameter is a linked list (sorted most recently used)
|
|
of all the previously created architures for this architecture
|
|
family. The (possibly NULL) ARCHES->gdbarch can used to access
|
|
values from the previously selected architecture for this
|
|
architecture family.
|
|
|
|
The INIT function shall return any of: NULL - indicating that it
|
|
doesn't recognize the selected architecture; an existing ``struct
|
|
gdbarch'' from the ARCHES list - indicating that the new
|
|
architecture is just a synonym for an earlier architecture (see
|
|
gdbarch_list_lookup_by_info()); a newly created ``struct gdbarch''
|
|
- that describes the selected architecture (see gdbarch_alloc()).
|
|
|
|
The DUMP_TDEP function shall print out all target specific values.
|
|
Care should be taken to ensure that the function works in both the
|
|
multi-arch and non- multi-arch cases. */
|
|
|
|
struct gdbarch_list
|
|
{
|
|
struct gdbarch *gdbarch;
|
|
struct gdbarch_list *next;
|
|
};
|
|
|
|
struct gdbarch_info
|
|
{
|
|
const struct bfd_arch_info *bfd_arch_info = nullptr;
|
|
|
|
enum bfd_endian byte_order = BFD_ENDIAN_UNKNOWN;
|
|
|
|
enum bfd_endian byte_order_for_code = BFD_ENDIAN_UNKNOWN;
|
|
|
|
bfd *abfd = nullptr;
|
|
|
|
/* Architecture-specific target description data. */
|
|
struct tdesc_arch_data *tdesc_data = nullptr;
|
|
|
|
enum gdb_osabi osabi = GDB_OSABI_UNKNOWN;
|
|
|
|
const struct target_desc *target_desc = nullptr;
|
|
};
|
|
|
|
typedef struct gdbarch *(gdbarch_init_ftype) (struct gdbarch_info info, struct gdbarch_list *arches);
|
|
typedef void (gdbarch_dump_tdep_ftype) (struct gdbarch *gdbarch, struct ui_file *file);
|
|
typedef bool (gdbarch_supports_arch_info_ftype) (const struct bfd_arch_info *);
|
|
|
|
extern void gdbarch_register (enum bfd_architecture architecture,
|
|
gdbarch_init_ftype *init,
|
|
gdbarch_dump_tdep_ftype *dump_tdep = nullptr,
|
|
gdbarch_supports_arch_info_ftype *supports_arch_info = nullptr);
|
|
|
|
/* Return true if ARCH is initialized. */
|
|
|
|
bool gdbarch_initialized_p (gdbarch *arch);
|
|
|
|
/* Return a vector of the valid architecture names. Since architectures are
|
|
registered during the _initialize phase this function only returns useful
|
|
information once initialization has been completed. */
|
|
|
|
extern std::vector<const char *> gdbarch_printable_names ();
|
|
|
|
|
|
/* Helper function. Search the list of ARCHES for a GDBARCH that
|
|
matches the information provided by INFO. */
|
|
|
|
extern struct gdbarch_list *gdbarch_list_lookup_by_info (struct gdbarch_list *arches, const struct gdbarch_info *info);
|
|
|
|
|
|
/* Helper function. Create a preliminary ``struct gdbarch''. Perform
|
|
basic initialization using values obtained from the INFO and TDEP
|
|
parameters. set_gdbarch_*() functions are called to complete the
|
|
initialization of the object. */
|
|
|
|
extern struct gdbarch *gdbarch_alloc (const struct gdbarch_info *info,
|
|
gdbarch_tdep_up tdep);
|
|
|
|
|
|
/* Helper function. Free a partially-constructed ``struct gdbarch''.
|
|
It is assumed that the caller frees the ``struct
|
|
gdbarch_tdep''. */
|
|
|
|
extern void gdbarch_free (struct gdbarch *);
|
|
|
|
struct gdbarch_deleter
|
|
{
|
|
void operator() (gdbarch *arch) const
|
|
{ gdbarch_free (arch); }
|
|
};
|
|
|
|
using gdbarch_up = std::unique_ptr<gdbarch, gdbarch_deleter>;
|
|
|
|
/* Get the obstack owned by ARCH. */
|
|
|
|
extern obstack *gdbarch_obstack (gdbarch *arch);
|
|
|
|
/* Helper function. Allocate memory from the ``struct gdbarch''
|
|
obstack. The memory is freed when the corresponding architecture
|
|
is also freed. */
|
|
|
|
#define GDBARCH_OBSTACK_CALLOC(GDBARCH, NR, TYPE) obstack_calloc<TYPE> (gdbarch_obstack ((GDBARCH)), (NR))
|
|
|
|
#define GDBARCH_OBSTACK_ZALLOC(GDBARCH, TYPE) obstack_zalloc<TYPE> (gdbarch_obstack ((GDBARCH)))
|
|
|
|
/* Duplicate STRING, returning an equivalent string that's allocated on the
|
|
obstack associated with GDBARCH. The string is freed when the corresponding
|
|
architecture is also freed. */
|
|
|
|
extern char *gdbarch_obstack_strdup (struct gdbarch *arch, const char *string);
|
|
|
|
/* Helper function. Force an update of INF's architecture.
|
|
|
|
The actual architecture selected is determined by INFO, ``(gdb) set
|
|
architecture'' et.al., the existing architecture and BFD's default
|
|
architecture. INFO should be initialized to zero and then selected
|
|
fields should be updated.
|
|
|
|
Returns non-zero if the update succeeds. */
|
|
|
|
extern int gdbarch_update_p (inferior *inf, gdbarch_info info);
|
|
|
|
/* Helper function. Find an architecture matching info.
|
|
|
|
INFO should have relevant fields set, and then finished using
|
|
gdbarch_info_fill.
|
|
|
|
Returns the corresponding architecture, or NULL if no matching
|
|
architecture was found. */
|
|
|
|
extern struct gdbarch *gdbarch_find_by_info (struct gdbarch_info info);
|
|
|
|
/* A registry adaptor for gdbarch. This arranges to store the
|
|
registry in the gdbarch. */
|
|
template<>
|
|
struct registry_accessor<gdbarch>
|
|
{
|
|
static registry<gdbarch> *get (gdbarch *arch);
|
|
};
|
|
|
|
/* Set the dynamic target-system-dependent parameters (architecture,
|
|
byte-order, ...) using information found in the BFD. */
|
|
|
|
extern void set_gdbarch_from_file (bfd *);
|
|
|
|
|
|
/* Initialize the current architecture to the "first" one we find on
|
|
our list. */
|
|
|
|
extern void initialize_current_architecture (void);
|
|
|
|
/* gdbarch trace variable */
|
|
extern unsigned int gdbarch_debug;
|
|
|
|
extern void gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file);
|
|
|
|
/* Return the number of cooked registers (raw + pseudo) for ARCH. */
|
|
|
|
static inline int
|
|
gdbarch_num_cooked_regs (gdbarch *arch)
|
|
{
|
|
return gdbarch_num_regs (arch) + gdbarch_num_pseudo_regs (arch);
|
|
}
|
|
|
|
/* Return true if stacks for ARCH grow down, otherwise return false. */
|
|
|
|
static inline bool
|
|
gdbarch_stack_grows_down (gdbarch *arch)
|
|
{
|
|
return gdbarch_inner_than (arch, 1, 2);
|
|
}
|
|
|
|
#endif /* GDB_GDBARCH_H */
|