Signed-off-by: Tao Liu <ltao(a)redhat.com>
---
Makefile | 3 +
configure.c | 21 +-
crash_target.c | 6 +-
defs.h | 8 +-
gdb-10.2.patch | 2439 -----------------------------------------------
gdb-16.2.patch | 2254 +++++++++++++++++++++++++++++++++++++++++++
gdb_interface.c | 14 +-
kernel.c | 6 +-
symbols.c | 4 +-
9 files changed, 2295 insertions(+), 2460 deletions(-)
delete mode 100644 gdb-10.2.patch
create mode 100644 gdb-16.2.patch
diff --git a/Makefile b/Makefile
index 3f8f6b2..f6c4da6 100644
--- a/Makefile
+++ b/Makefile
@@ -191,6 +191,9 @@ GDB_7.6_OFILES=${GDB}/gdb/symtab.o
GDB_10.2_FILES=
GDB_10.2_OFILES=${GDB}/gdb/symtab.o crash_target.o
+GDB_16.2_FILES=
+GDB_16.2_OFILES=${GDB}/gdb/symtab.o crash_target.o
+
#
# GDB_FLAGS is passed up from the gdb Makefile.
#
diff --git a/configure.c b/configure.c
index 08b52be..1a4c4f8 100644
--- a/configure.c
+++ b/configure.c
@@ -189,9 +189,10 @@ void add_extra_lib(char *);
#define GDB_7_3_1 (4)
#define GDB_7_6 (5)
#define GDB_10_2 (6)
-#define SUPPORTED_GDB_VERSIONS (GDB_10_2 + 1)
+#define GDB_16_2 (7)
+#define SUPPORTED_GDB_VERSIONS (GDB_16_2 + 1)
-int default_gdb = GDB_10_2;
+int default_gdb = GDB_16_2;
struct supported_gdb_version {
char *GDB;
@@ -265,6 +266,15 @@ struct supported_gdb_version {
"GDB_FLAGS=-DGDB_10_2",
"GPLv3"
},
+ {
+ "GDB=gdb-16.2",
+ "16.2",
+ "GDB_FILES=${GDB_16.2_FILES}",
+ "GDB_OFILES=${GDB_16.2_OFILES}",
+ "GDB_PATCH_FILES=gdb-16.2.patch",
+ "GDB_FLAGS=-DGDB_16_2",
+ "GPLv3"
+ },
};
#define DAEMON 0x1
@@ -1564,7 +1574,12 @@ setup_gdb_defaults(void)
fprintf(stderr, ".gdb configuration: %s\n",
sp->GDB_VERSION_IN);
return store_gdb_defaults(sp);
}
-
+ if (strcmp(buf, "16.2") == 0) {
+ fclose(fp);
+ sp = &supported_gdb_versions[GDB_16_2];
+ fprintf(stderr, ".gdb configuration: %s\n",
sp->GDB_VERSION_IN);
+ return store_gdb_defaults(sp);
+ }
}
fclose(fp);
diff --git a/crash_target.c b/crash_target.c
index 1080976..5966b7b 100644
--- a/crash_target.c
+++ b/crash_target.c
@@ -125,7 +125,7 @@ crash_target_init (void)
/* Own the target until it is successfully pushed. */
target_ops_up target_holder (target);
- push_target (std::move (target_holder));
+ current_inferior ()->push_target (std::move (target_holder));
inferior_appeared (current_inferior (), CRASH_INFERIOR_PID);
@@ -135,7 +135,7 @@ crash_target_init (void)
switch_to_thread (thread);
/* Fetch all registers from core file. */
- target_fetch_registers (get_current_regcache (), -1);
+ target_fetch_registers (get_thread_regcache(thread), -1);
/* Now, set up the frame cache. */
reinit_frame_cache ();
@@ -144,7 +144,7 @@ crash_target_init (void)
extern "C" int
gdb_change_thread_context (void)
{
- target_fetch_registers(get_current_regcache(), -1);
+ target_fetch_registers(get_thread_regcache(inferior_thread()), -1);
reinit_frame_cache();
return TRUE;
}
diff --git a/defs.h b/defs.h
index bc22bb6..2ffa44e 100644
--- a/defs.h
+++ b/defs.h
@@ -5262,8 +5262,8 @@ enum type_code {
TYPE_CODE_STRUCT, /* C struct or Pascal record */
TYPE_CODE_UNION, /* C union or Pascal variant part */
TYPE_CODE_ENUM, /* Enumeration type */
-#if defined(GDB_5_3) || defined(GDB_6_0) || defined(GDB_6_1) || defined(GDB_7_0) ||
defined(GDB_7_3_1) || defined(GDB_7_6) || defined(GDB_10_2)
-#if defined(GDB_7_0) || defined(GDB_7_3_1) || defined(GDB_7_6) || defined(GDB_10_2)
+#if defined(GDB_5_3) || defined(GDB_6_0) || defined(GDB_6_1) || defined(GDB_7_0) ||
defined(GDB_7_3_1) || defined(GDB_7_6) || defined(GDB_10_2) || defined(GDB_16_2)
+#if defined(GDB_7_0) || defined(GDB_7_3_1) || defined(GDB_7_6) || defined(GDB_10_2) ||
defined(GDB_16_2)
TYPE_CODE_FLAGS, /* Bit flags type */
#endif
TYPE_CODE_FUNC, /* Function type */
@@ -7939,8 +7939,8 @@ extern unsigned long calc_crc32(unsigned long, unsigned char *,
size_t);
#else
extern unsigned long gnu_debuglink_crc32 (unsigned long, unsigned char *, size_t);
#endif
-extern int have_partial_symbols(void);
-extern int have_full_symbols(void);
+extern int have_partial_symbols(void *);
+extern int have_full_symbols(void *);
#if defined(X86) || defined(X86_64) || defined(IA64)
#define XEN_HYPERVISOR_ARCH
diff --git a/gdb-10.2.patch b/gdb-10.2.patch
deleted file mode 100644
index a7fc6c2..0000000
--- a/gdb-10.2.patch
+++ /dev/null
@@ -1,2439 +0,0 @@
-
-# When this file is updated in an existing source tree, it gets re-applied
-# during the next build using "patch -N --fuzz=0", which ignores patches
-# that have already been applied. However, if a gdb file has been modified
-# multiple times, the subsequent patching may fail to recognize that a
-# given patch has been previously applied, and will attempt to re-apply it.
-# To prevent any unintended consequences, this file also acts as a
-# shell script that can restore any gdb file to its original state prior
-# to all subsequent patch applications.
-
-tar xvzmf gdb-10.2.tar.gz \
- gdb-10.2/gdb/symtab.c \
- gdb-10.2/gdb/printcmd.c \
- gdb-10.2/gdb/symfile.c \
- gdb-10.2/gdb/Makefile.in \
- gdb-10.2/gdb/dwarf2/read.c \
- gdb-10.2/gdb/ada-lang.c \
- gdb-10.2/gdb/stack.c \
- gdb-10.2/gdb/ui-file.h
-
-exit 0
-
---- gdb-10.2/Makefile.in.orig
-+++ gdb-10.2/Makefile.in
-@@ -340,6 +340,9 @@ AR_FOR_BUILD = @AR_FOR_BUILD@
- AS_FOR_BUILD = @AS_FOR_BUILD@
- CC_FOR_BUILD = @CC_FOR_BUILD@
- CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@
-+ifeq (${CRASH_TARGET}, PPC64)
-+CFLAGS_FOR_BUILD += -m64 -fPIC
-+endif
- CXXFLAGS_FOR_BUILD = @CXXFLAGS_FOR_BUILD@
- CXX_FOR_BUILD = @CXX_FOR_BUILD@
- DLLTOOL_FOR_BUILD = @DLLTOOL_FOR_BUILD@
-@@ -406,6 +409,9 @@ GNATBIND = @GNATBIND@
- GNATMAKE = @GNATMAKE@
-
- CFLAGS = @CFLAGS@
-+ifeq (${CRASH_TARGET}, PPC64)
-+CFLAGS += -m64 -fPIC
-+endif
- LDFLAGS = @LDFLAGS@
- LIBCFLAGS = $(CFLAGS)
- CXXFLAGS = @CXXFLAGS@
---- gdb-10.2/gdb/Makefile.in.orig
-+++ gdb-10.2/gdb/Makefile.in
-@@ -571,7 +571,7 @@ CONFIG_DEP_SUBDIR = $(addsuffix /$(DEPDIR),$(CONFIG_SRC_SUBDIR))
- # It is also possible that you will need to add -I/usr/include/sys if
- # your system doesn't have fcntl.h in /usr/include (which is where it
- # should be according to Posix).
--DEFS = @DEFS@
-+DEFS = -DCRASH_MERGE -D${CRASH_TARGET} @DEFS@
- GDB_CFLAGS = -I. -I$(srcdir) -I$(srcdir)/config \
- -DLOCALEDIR="\"$(localedir)\"" $(DEFS)
-
-@@ -1135,6 +1135,7 @@ COMMON_SFILES = \
- symmisc.c \
- symtab.c \
- target.c \
-+ ../../crash_target.c \
- target-connection.c \
- target-dcache.c \
- target-descriptions.c \
-@@ -1564,7 +1565,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
- $(SUBDIR_TARGET_OBS) \
- $(SUBDIR_GCC_COMPILE_OBS)
-
--SUBDIRS = doc @subdirs@ data-directory
-+SUBDIRS = build_no_subdirs
- CLEANDIRS = $(SUBDIRS)
-
- # List of subdirectories in the build tree that must exist.
-@@ -1606,8 +1607,8 @@ generated_files = \
- # Flags needed to compile Python code
- PYTHON_CFLAGS = @PYTHON_CFLAGS@
-
--all: gdb$(EXEEXT) $(CONFIG_ALL) gdb-gdb.py gdb-gdb.gdb
-- @$(MAKE) $(FLAGS_TO_PASS) DO=all "DODIRS=`echo $(SUBDIRS) | sed
's/testsuite//'`" subdir_do
-+all: gdb$(EXEEXT) gdb-gdb.py gdb-gdb.gdb
-+ @$(MAKE) -s $(FLAGS_TO_PASS) DO=all "DODIRS=`echo $(SUBDIRS) | sed
's/testsuite//'`" subdir_do
-
- # Rule for compiling .c files in the top-level gdb directory.
- # The order-only dependencies ensure that we create the build subdirectories.
-@@ -1864,9 +1865,10 @@ libgdb.a: $(LIBGDB_OBS)
- # Removing the old gdb first works better if it is running, at least on SunOS.
- gdb$(EXEEXT): gdb.o $(LIBGDB_OBS) $(CDEPS) $(TDEPLIBS)
- $(SILENCE) rm -f gdb$(EXEEXT)
-+ @(cd ../..; make --no-print-directory GDB_FLAGS=-DGDB_10_2 library)
- $(ECHO_CXXLD) $(CC_LD) $(INTERNAL_LDFLAGS) $(WIN32LDAPP) \
-- -o gdb$(EXEEXT) gdb.o $(LIBGDB_OBS) \
-- $(TDEPLIBS) $(TUI_LIBRARY) $(CLIBS) $(LOADLIBES)
-+ -o $(shell /bin/cat mergeobj) $(LIBGDB_OBS) \
-+ $(TDEPLIBS) $(TUI_LIBRARY) $(CLIBS) $(LOADLIBES) $(shell /bin/cat
mergelibs)
- ifneq ($(CODESIGN_CERT),)
- $(ECHO_SIGN) $(CODESIGN) -s $(CODESIGN_CERT) gdb$(EXEEXT)
- endif
-@@ -2530,9 +2532,9 @@ ifeq ($(DEPMODE),depmode=gcc3)
- # into place if the compile succeeds. We need this because gcc does
- # not atomically write the dependency output file.
- override COMPILE.post = -c -o $@ -MT $@ -MMD -MP \
-- -MF $(@D)/$(DEPDIR)/$(basename $((a)F)).Tpo
--override POSTCOMPILE = @mv $(@D)/$(DEPDIR)/$(basename $((a)F)).Tpo \
-- $(@D)/$(DEPDIR)/$(basename $((a)F)).Po
-+ -MF $(subst ../..,.,$(@D))/$(DEPDIR)/$(basename $((a)F)).Tpo
-+override POSTCOMPILE = @mv $(subst ../..,.,$(@D))/$(DEPDIR)/$(basename $((a)F)).Tpo \
-+ $(subst ../..,.,$(@D))/$(DEPDIR)/$(basename $((a)F)).Po
- else
- override COMPILE.pre = source='$<' object='$@' libtool=no \
- DEPDIR=$(DEPDIR) $(DEPMODE) $(depcomp) \
---- gdb-10.2/gdb/cli/cli-cmds.c.orig
-+++ gdb-10.2/gdb/cli/cli-cmds.c
-@@ -435,6 +435,11 @@ complete_command (const char *arg, int from_tty)
- }
- }
-
-+#ifdef CRASH_MERGE
-+static int crash_from_tty = 0;
-+extern "C" void untrusted_file(FILE *, char *);
-+#endif
-+
- int
- is_complete_command (struct cmd_list_element *c)
- {
-@@ -654,8 +659,32 @@ find_and_open_script (const char *script_file, int search_path)
- close (fd);
- errno = save_errno;
- }
-- else
-- opened.emplace (gdb_file_up (result), std::move (full_path));
-+#ifdef CRASH_MERGE
-+ /*
-+ * Only allow trusted versions of .gdbinit files to be
-+ * sourced during session initialization.
-+ */
-+ if (crash_from_tty == -1)
-+ {
-+ struct stat statbuf;
-+ FILE *stream = result;
-+ int _fd = fileno (stream);
-+ if (fstat (_fd, &statbuf) < 0)
-+ {
-+ perror_with_name (full_path.get());
-+ fclose (stream);
-+ return opened;
-+ }
-+ if (statbuf.st_uid != getuid () || (statbuf.st_mode & S_IWOTH))
-+ {
-+ untrusted_file(NULL, full_path.get());
-+ fclose (stream);
-+ return opened;
-+ }
-+ }
-+#endif
-+ opened.emplace (gdb_file_up (result), std::move (full_path));
-+
-
- return opened;
- }
-@@ -719,7 +748,11 @@ source_script_with_search (const char *file, int from_tty, int
search_path)
- If the source command was invoked interactively, throw an
- error. Otherwise (e.g. if it was invoked by a script),
- just emit a warning, rather than cause an error. */
-+#ifdef CRASH_MERGE
-+ if (from_tty > 0)
-+#else
- if (from_tty)
-+#endif
- perror_with_name (file);
- else
- {
-@@ -743,7 +776,14 @@ source_script_with_search (const char *file, int from_tty, int
search_path)
- void
- source_script (const char *file, int from_tty)
- {
-+#ifdef CRASH_MERGE
-+ crash_from_tty = from_tty;
-+#endif
- source_script_with_search (file, from_tty, 0);
-+#ifdef CRASH_MERGE
-+ crash_from_tty = 0;
-+#endif
-+
- }
-
- static void
---- gdb-10.2/gdb/defs.h.orig
-+++ gdb-10.2/gdb/defs.h
-@@ -629,4 +629,7 @@ DEF_ENUM_FLAGS_TYPE (enum user_selected_what_flag,
user_selected_what);
-
- #include "utils.h"
-
-+#ifdef CRASH_MERGE
-+extern "C" int gdb_main_entry(int, char **);
-+#endif
- #endif /* #ifndef DEFS_H */
---- gdb-10.2/gdb/dwarf2/read.c.orig
-+++ gdb-10.2/gdb/dwarf2/read.c
-@@ -3015,7 +3015,11 @@ read_gdb_index_from_buffer (const char *filename,
- indices. */
- if (version < 4)
- {
-+#ifdef CRASH_MERGE
-+ static int warning_printed = 1;
-+#else
- static int warning_printed = 0;
-+#endif
- if (!warning_printed)
- {
- warning (_("Skipping obsolete .gdb_index section in %s."),
-@@ -3034,7 +3038,11 @@ read_gdb_index_from_buffer (const char *filename,
- "set use-deprecated-index-sections on". */
- if (version < 6 && !deprecated_ok)
- {
-+#ifdef CRASH_MERGE
-+ static int warning_printed = 1;
-+#else
- static int warning_printed = 0;
-+#endif
- if (!warning_printed)
- {
- warning (_("\
---- gdb-10.2/gdb/main.c.orig
-+++ gdb-10.2/gdb/main.c
-@@ -392,6 +392,14 @@ start_event_loop ()
- return;
- }
-
-+#ifdef CRASH_MERGE
-+extern "C" void update_gdb_hooks(void);
-+extern "C" void main_loop(void);
-+extern "C" unsigned long crash_get_kaslr_offset(void);
-+extern "C" int console(const char *, ...);
-+void crash_target_init (void);
-+#endif
-+
- /* Call command_loop. */
-
- /* Prevent inlining this function for the benefit of GDB's selftests
-@@ -925,7 +933,11 @@ captured_main_1 (struct captured_main_args *context)
- }
- }
-
-+#ifdef CRASH_MERGE
-+ save_original_signals_state (1);
-+#else
- save_original_signals_state (quiet);
-+#endif
-
- /* Try to set up an alternate signal stack for SIGSEGV handlers. */
- gdb::alternate_signal_stack signal_stack;
-@@ -999,7 +1011,7 @@ captured_main_1 (struct captured_main_args *context)
- {
- print_gdb_version (gdb_stdout, false);
- wrap_here ("");
-- printf_filtered ("\n");
-+ printf_filtered ("\n\n");
- exit (0);
- }
-
-@@ -1038,6 +1050,10 @@ captured_main_1 (struct captured_main_args *context)
- look at things by now. Initialize the default interpreter. */
- set_top_level_interpreter (interpreter_p);
-
-+#ifdef CRASH_MERGE
-+ update_gdb_hooks();
-+#endif
-+
- /* FIXME: cagney/2003-02-03: The big hack (part 2 of 2) that lets
- GDB retain the old MI1 interpreter startup behavior. Output the
- copyright message after the interpreter is installed when it is
-@@ -1066,7 +1082,11 @@ captured_main_1 (struct captured_main_args *context)
- if (!system_gdbinit.empty () && !inhibit_gdbinit)
- {
- for (const std::string &file : system_gdbinit)
-+#ifdef CRASH_MERGE
-+ ret = catch_command_errors (source_script, file.c_str (), -1);
-+#else
- ret = catch_command_errors (source_script, file.c_str (), 0);
-+#endif
- }
-
- /* Read and execute $HOME/.gdbinit file, if it exists. This is done
-@@ -1075,7 +1095,11 @@ captured_main_1 (struct captured_main_args *context)
- debugging or what directory you are in. */
-
- if (!home_gdbinit.empty () && !inhibit_gdbinit &&
!inhibit_home_gdbinit)
-+#ifdef CRASH_MERGE
-+ ret = catch_command_errors (source_script, home_gdbinit.c_str (), -1);
-+#else
- ret = catch_command_errors (source_script, home_gdbinit.c_str (), 0);
-+#endif
-
- /* Process '-ix' and '-iex' options early. */
- for (i = 0; i < cmdarg_vec.size (); i++)
-@@ -1121,7 +1145,11 @@ captured_main_1 (struct captured_main_args *context)
- !batch_flag);
- if (ret != 0)
- ret = catch_command_errors (symbol_file_add_main_adapter,
-+#ifdef CRASH_MERGE
-+ symarg, 0);
-+#else
- symarg, !batch_flag);
-+#endif
- }
- else
- {
-@@ -1191,7 +1219,11 @@ captured_main_1 (struct captured_main_args *context)
- {
- auto_load_local_gdbinit_loaded = 1;
-
-+#ifdef CRASH_MERGE
-+ ret = catch_command_errors (source_script, local_gdbinit.c_str (), -1);
-+#else
- ret = catch_command_errors (source_script, local_gdbinit.c_str (), 0);
-+#endif
- }
- }
-
-@@ -1242,6 +1274,16 @@ captured_main (void *data)
-
- captured_main_1 (context);
-
-+#ifdef CRASH_MERGE
-+ /* Relocate the vmlinux. */
-+ objfile_rebase (symfile_objfile, crash_get_kaslr_offset());
-+
-+ crash_target_init();
-+
-+ /* Back to crash. */
-+ main_loop();
-+#endif
-+
- /* NOTE: cagney/1999-11-07: There is probably no reason for not
- moving this loop and the code found in captured_command_loop()
- into the command_loop() proper. The main thing holding back that
-@@ -1256,6 +1298,9 @@ captured_main (void *data)
- {
- exception_print (gdb_stderr, ex);
- }
-+#ifdef CRASH_MERGE
-+ console("<CAPTURED_MAIN WHILE LOOP>\n");
-+#endif
- }
- /* No exit -- exit is through quit_command. */
- }
-@@ -1277,6 +1322,22 @@ gdb_main (struct captured_main_args *args)
- return 1;
- }
-
-+#ifdef CRASH_MERGE
-+/*
-+ * NOTE: adapted from gdb.c, which is no longer built in; changed name of
-+ * original main() to gdb_main_entry() for use as crash entry point
-+ */
-+int
-+gdb_main_entry (int argc, char **argv)
-+{
-+ struct captured_main_args args;
-+ memset (&args, 0, sizeof args);
-+ args.argc = argc;
-+ args.argv = argv;
-+ args.interpreter_p = INTERP_CONSOLE;
-+ return gdb_main (&args);
-+}
-+#endif
-
- /* Don't use *_filtered for printing help. We don't want to prompt
- for continue no matter how small the screen or how much we're going
---- gdb-10.2/gdb/objfiles.h.orig
-+++ gdb-10.2/gdb/objfiles.h
-@@ -747,9 +747,9 @@ extern int objfile_has_full_symbols (struct objfile *objfile);
-
- extern int objfile_has_symbols (struct objfile *objfile);
-
--extern int have_partial_symbols (void);
-+extern "C" int have_partial_symbols (void);
-
--extern int have_full_symbols (void);
-+extern "C" int have_full_symbols (void);
-
- extern void objfile_set_sym_fns (struct objfile *objfile,
- const struct sym_fns *sf);
---- gdb-10.2/gdb/printcmd.c.orig
-+++ gdb-10.2/gdb/printcmd.c
-@@ -524,6 +524,9 @@ set_next_address (struct gdbarch *gdbarch, CORE_ADDR addr)
- form. However note that DO_DEMANGLE can be overridden by the specific
- settings of the demangle and asm_demangle variables. Returns
- non-zero if anything was printed; zero otherwise. */
-+#ifdef CRASH_MERGE
-+extern "C" int gdb_print_callback(unsigned long);
-+#endif
-
- int
- print_address_symbolic (struct gdbarch *gdbarch, CORE_ADDR addr,
-@@ -535,6 +538,12 @@ print_address_symbolic (struct gdbarch *gdbarch, CORE_ADDR addr,
- int offset = 0;
- int line = 0;
-
-+#ifdef CRASH_MERGE
-+ if (!gdb_print_callback(addr)) {
-+ return 0;
-+ }
-+#endif
-+
- if (build_address_symbolic (gdbarch, addr, do_demangle, false, &name,
- &offset, &filename, &line, &unmapped))
- return 0;
-@@ -1221,6 +1230,43 @@ print_command_1 (const char *args, int voidprint)
- print_value (val, print_opts);
- }
-
-+static void
-+print_command_2 (const char *args, int voidprint)
-+{
-+ struct value *val;
-+ value_print_options print_opts;
-+
-+ get_user_print_options (&print_opts);
-+ /* Override global settings with explicit options, if any. */
-+ auto group = make_value_print_options_def_group (&print_opts);
-+ gdb::option::process_options
-+ (&args, gdb::option::PROCESS_OPTIONS_REQUIRE_DELIMITER, group);
-+
-+ print_command_parse_format (&args, "print", &print_opts);
-+
-+ const char *exp = args;
-+
-+ if (exp != nullptr && *exp)
-+ {
-+ expression_up expr = parse_expression (exp);
-+ val = evaluate_expression (expr.get ());
-+ }
-+ else
-+ val = access_value_history (0);
-+
-+ printf_filtered ("%d %d %ld %ld %ld %ld\n",
-+ check_typedef(value_type (val))->code(),
-+ TYPE_UNSIGNED (check_typedef(value_type (val))),
-+ TYPE_LENGTH (check_typedef(value_type(val))),
-+ value_offset (val), value_bitpos (val), value_bitsize(val));
-+}
-+
-+static void
-+printm_command (const char *exp, int from_tty)
-+{
-+ print_command_2 (exp, 1);
-+}
-+
- /* See valprint.h. */
-
- void
-@@ -2855,6 +2901,12 @@ but no count or size letter (see \"x\"
command)."),
- c = add_com ("print", class_vars, print_command, print_help.c_str ());
- set_cmd_completer_handle_brkchars (c, print_command_completer);
- add_com_alias ("p", "print", class_vars, 1);
-+
-+ c = add_com ("printm", class_vars, printm_command, _("\
-+Similar to \"print\" command, but it used to print the type, size, offset,\n\
-+bitpos and bitsize of the expression EXP."));
-+ set_cmd_completer (c, expression_completer);
-+
- add_com_alias ("inspect", "print", class_vars, 1);
-
- add_setshow_uinteger_cmd ("max-symbolic-offset", no_class,
---- gdb-10.2/gdb/psymtab.c.orig
-+++ gdb-10.2/gdb/psymtab.c
-@@ -283,6 +283,9 @@ find_pc_sect_psymtab_closer (struct objfile *objfile,
- return best_pst;
- }
-
-+#ifdef CRASH_MERGE
-+ extern "C" int gdb_line_number_callback(unsigned long, unsigned long,
unsigned long);
-+#endif
- /* Find which partial symtab contains PC and SECTION. Return NULL if
- none. We return the psymtab that contains a symbol whose address
- exactly matches PC, or, if we cannot find an exact match, the
-@@ -363,7 +366,12 @@ find_pc_sect_psymtab (struct objfile *objfile, CORE_ADDR pc,
-
- best_pst = find_pc_sect_psymtab_closer (objfile, pc, section, pst,
- msymbol);
-+#ifdef CRASH_MERGE
-+ if ((best_pst != NULL) &&
-+ gdb_line_number_callback(pc, pst->text_low (objfile), pst->text_high
(objfile)))
-+#else
- if (best_pst != NULL)
-+#endif
- return best_pst;
- }
-
---- gdb-10.2/gdb/symfile.c.orig
-+++ gdb-10.2/gdb/symfile.c
-@@ -652,7 +652,26 @@ default_symfile_offsets (struct objfile *objfile,
- for (cur_sec = abfd->sections; cur_sec != NULL; cur_sec = cur_sec->next)
- /* We do not expect this to happen; just skip this step if the
- relocatable file has a section with an assigned VMA. */
-- if (bfd_section_vma (cur_sec) != 0)
-+ if (bfd_section_vma (cur_sec) != 0
-+ /*
-+ * Kernel modules may have some non-zero VMAs, i.e., like the
-+ * __ksymtab and __ksymtab_gpl sections in this example:
-+ *
-+ * Section Headers:
-+ * [Nr] Name Type Address Offset
-+ * Size EntSize Flags Link Info Align
-+ * ...
-+ * [ 8] __ksymtab PROGBITS 0000000000000060 0000ad90
-+ * 0000000000000010 0000000000000000 A 0 0 16
-+ * [ 9] .rela__ksymtab RELA 0000000000000000 0000ada0
-+ * 0000000000000030 0000000000000018 43 8 8
-+ * [10] __ksymtab_gpl PROGBITS 0000000000000070 0000add0
-+ * 00000000000001a0 0000000000000000 A 0 0 16
-+ * ...
-+ *
-+ * but they should be treated as if they are NULL.
-+ */
-+ && strncmp (bfd_section_name (cur_sec), "__k", 3) != 0)
- break;
-
- if (cur_sec == NULL)
-@@ -1083,6 +1102,12 @@ symbol_file_add_with_addrs (bfd *abfd, const char *name,
- if (mainline)
- flags |= OBJF_MAINLINE;
- objfile = objfile::make (abfd, name, flags, parent);
-+#ifdef CRASH_MERGE
-+ if (add_flags & SYMFILE_MAINLINE) {
-+ extern struct objfile *gdb_kernel_objfile;
-+ gdb_kernel_objfile = objfile;
-+ }
-+#endif
-
- /* We either created a new mapped symbol table, mapped an existing
- symbol table file which has not had initial symbol reading
-@@ -1375,6 +1400,10 @@ show_debug_file_directory (struct ui_file *file, int from_tty,
- #if ! defined (DEBUG_SUBDIRECTORY)
- #define DEBUG_SUBDIRECTORY ".debug"
- #endif
-+#ifdef CRASH_MERGE
-+extern "C" int check_specified_module_tree(const char *, const char *);
-+extern "C" char *check_specified_kernel_debug_file();
-+#endif
-
- /* Find a separate debuginfo file for OBJFILE, using DIR as the directory
- where the original file resides (may not be the same as
-@@ -1410,6 +1439,15 @@ find_separate_debug_file (const char *dir,
- if (separate_debug_file_exists (debugfile, crc32, objfile))
- return debugfile;
-
-+#ifdef CRASH_MERGE
-+{
-+ if (check_specified_module_tree(objfile_name (objfile), debugfile.c_str()) &&
-+ separate_debug_file_exists(debugfile, crc32, objfile)) {
-+ return debugfile;
-+ }
-+}
-+#endif
-+
- /* Then try in the global debugfile directories.
-
- Keep backward compatibility so that DEBUG_FILE_DIRECTORY being "" will
-@@ -1568,6 +1606,14 @@ find_separate_debug_file_by_debuglink (struct objfile *objfile)
- }
- }
-
-+#ifdef CRASH_MERGE
-+ if (debugfile.empty ()) {
-+ char *name_copy;
-+ name_copy = check_specified_kernel_debug_file();
-+ return std::string (name_copy);
-+ }
-+#endif
-+
- return debugfile;
- }
-
-@@ -2334,8 +2380,10 @@ add_symbol_file_command (const char *args, int from_tty)
- else if (section_addrs.empty ())
- printf_unfiltered ("\n");
-
-+#ifndef CRASH_MERGE
- if (from_tty && (!query ("%s", "")))
- error (_("Not confirmed."));
-+#endif
-
- objf = symbol_file_add (filename.get (), add_flags, §ion_addrs,
- flags);
-@@ -3622,6 +3670,15 @@ bfd_byte *
- symfile_relocate_debug_section (struct objfile *objfile,
- asection *sectp, bfd_byte *buf)
- {
-+#ifdef CRASH_MERGE
-+ /* Executable files have all the relocations already resolved.
-+ * Handle files linked with --emit-relocs.
-+ *
http://sources.redhat.com/ml/gdb/2006-08/msg00137.html
-+ */
-+ bfd *abfd = objfile->obfd;
-+ if ((abfd->flags & EXEC_P) != 0)
-+ return NULL;
-+#endif
- gdb_assert (objfile->sf->sym_relocate);
-
- return (*objfile->sf->sym_relocate) (objfile, sectp, buf);
---- gdb-10.2/gdb/symtab.c.orig
-+++ gdb-10.2/gdb/symtab.c
-@@ -1870,27 +1870,46 @@ search_name_hash (enum language language, const char
*search_name)
- variable and thus can probably assume it will never hit the C++
- code). */
-
-+#ifdef CRASH_MERGE
-+static void gdb_bait_and_switch(char *, struct symbol *);
-+#endif
-+
- struct block_symbol
- lookup_symbol_in_language (const char *name, const struct block *block,
- const domain_enum domain, enum language lang,
- struct field_of_this_result *is_a_field_of_this)
- {
-+ struct block_symbol result;
- demangle_result_storage storage;
- const char *modified_name = demangle_for_lookup (name, lang, storage);
-
-- return lookup_symbol_aux (modified_name,
-+ result = lookup_symbol_aux (modified_name,
- symbol_name_match_type::FULL,
- block, domain, lang,
- is_a_field_of_this);
-+#ifdef CRASH_MERGE
-+ if (result.symbol && (domain == VAR_DOMAIN))
-+ gdb_bait_and_switch((char *)modified_name, result.symbol);
-+#endif
-+ return result;
- }
-
- /* See symtab.h. */
-
-+#ifdef CRASH_MERGE
-+static const struct block *gdb_get_crash_block(void);
-+#endif
-+
- struct block_symbol
- lookup_symbol (const char *name, const struct block *block,
- domain_enum domain,
- struct field_of_this_result *is_a_field_of_this)
- {
-+#ifdef CRASH_MERGE
-+ if (!block)
-+ block = gdb_get_crash_block();
-+#endif
-+
- return lookup_symbol_in_language (name, block, domain,
- current_language->la_language,
- is_a_field_of_this);
-@@ -6886,3 +6905,806 @@ If zero then the symbol cache is disabled."),
- gdb::observers::new_objfile.attach (symtab_new_objfile_observer);
- gdb::observers::free_objfile.attach (symtab_free_objfile_observer);
- }
-+
-+#ifdef CRASH_MERGE
-+#include "gdb-stabs.h"
-+#include "gdbsupport/version.h"
-+#define GDB_COMMON
-+#include "../../defs.h"
-+
-+static void get_member_data(struct gnu_request *, struct type *, long, int);
-+static void dump_enum(struct type *, struct gnu_request *);
-+static void eval_enum(struct type *, struct gnu_request *);
-+static void gdb_get_line_number(struct gnu_request *);
-+static void gdb_get_datatype(struct gnu_request *);
-+static void gdb_get_symbol_type(struct gnu_request *);
-+static void gdb_command_exists(struct gnu_request *);
-+static void gdb_debug_command(struct gnu_request *);
-+static void gdb_function_numargs(struct gnu_request *);
-+static void gdb_add_symbol_file(struct gnu_request *);
-+static void gdb_delete_symbol_file(struct gnu_request *);
-+static void gdb_patch_symbol_values(struct gnu_request *);
-+static void get_user_print_option_address(struct gnu_request *);
-+extern int get_frame_offset(CORE_ADDR);
-+static void gdb_set_crash_block(struct gnu_request *);
-+extern "C" void gdb_command_funnel(struct gnu_request *);
-+void gdb_command_funnel_1(struct gnu_request *);
-+static long lookup_struct_contents(struct gnu_request *);
-+static void iterate_datatypes(struct gnu_request *);
-+
-+struct objfile *gdb_kernel_objfile = { 0 };
-+
-+static ulong gdb_merge_flags = 0;
-+#define KERNEL_SYMBOLS_PATCHED (0x1)
-+
-+#undef STREQ
-+#define STREQ(A, B) (A && B && (strcmp(A, B) == 0))
-+#define TYPE_CODE(t) (t->code ())
-+#define TYPE_TAG_NAME(t) (TYPE_MAIN_TYPE(t)->name)
-+#define TYPE_NFIELDS(t) (t->num_fields ())
-+#define TYPE_NAME(t) (t->name ())
-+
-+/*
-+ * All commands from above come through here.
-+ */
-+void
-+gdb_command_funnel(struct gnu_request *req)
-+{
-+ try {
-+ gdb_command_funnel_1(req);
-+ } catch (const gdb_exception &ex) {
-+ if (req->flags & GNU_RETURN_ON_ERROR)
-+ req->flags |= GNU_COMMAND_FAILED;
-+ else
-+ throw ex;
-+ }
-+}
-+
-+void
-+gdb_command_funnel_1(struct gnu_request *req)
-+{
-+ struct symbol *sym;
-+
-+ if (req->command != GNU_VERSION && req->command !=
GNU_USER_PRINT_OPTION) {
-+ (dynamic_cast<stdio_file
*>gdb_stdout)->set_stream(req->fp);
-+ (dynamic_cast<stdio_file
*>gdb_stderr)->set_stream(req->fp);
-+ }
-+
-+ switch (req->command)
-+ {
-+ case GNU_VERSION:
-+ req->buf = (char *)version;
-+ break;
-+
-+ case GNU_PASS_THROUGH:
-+ execute_command(req->buf,
-+ req->flags & GNU_FROM_TTY_OFF ? FALSE : TRUE);
-+ break;
-+
-+ case GNU_USER_PRINT_OPTION:
-+ get_user_print_option_address(req);
-+ break;
-+
-+ case GNU_RESOLVE_TEXT_ADDR:
-+ sym = find_pc_function(req->addr);
-+ if (!sym || TYPE_CODE(sym->type) != TYPE_CODE_FUNC)
-+ req->flags |= GNU_COMMAND_FAILED;
-+ break;
-+
-+ case GNU_DISASSEMBLE:
-+ if (req->addr2)
-+ sprintf(req->buf, "disassemble 0x%lx 0x%lx",
-+ req->addr, req->addr2);
-+ else
-+ sprintf(req->buf, "disassemble 0x%lx",
req->addr);
-+ execute_command(req->buf, TRUE);
-+ break;
-+
-+ case GNU_ADD_SYMBOL_FILE:
-+ gdb_add_symbol_file(req);
-+ break;
-+
-+ case GNU_DELETE_SYMBOL_FILE:
-+ gdb_delete_symbol_file(req);
-+ break;
-+
-+ case GNU_GET_LINE_NUMBER:
-+ gdb_get_line_number(req);
-+ break;
-+
-+ case GNU_GET_DATATYPE:
-+ gdb_get_datatype(req);
-+ break;
-+
-+ case GNU_GET_SYMBOL_TYPE:
-+ gdb_get_symbol_type(req);
-+ break;
-+
-+ case GNU_COMMAND_EXISTS:
-+ gdb_command_exists(req);
-+ break;
-+
-+ case GNU_ALPHA_FRAME_OFFSET:
-+ req->value = 0;
-+ break;
-+
-+ case GNU_FUNCTION_NUMARGS:
-+ gdb_function_numargs(req);
-+ break;
-+
-+ case GNU_DEBUG_COMMAND:
-+ gdb_debug_command(req);
-+ break;
-+
-+ case GNU_PATCH_SYMBOL_VALUES:
-+ gdb_patch_symbol_values(req);
-+ break;
-+
-+ case GNU_SET_CRASH_BLOCK:
-+ gdb_set_crash_block(req);
-+ break;
-+
-+ case GNU_GET_FUNCTION_RANGE:
-+ {
-+ CORE_ADDR start, end;
-+ if (!find_pc_partial_function(req->pc, NULL, &start,
&end))
-+ req->flags |= GNU_COMMAND_FAILED;
-+ else {
-+ req->addr = (ulong)start;
-+ req->addr2 = (ulong)end;
-+ }
-+ }
-+ break;
-+
-+ case GNU_LOOKUP_STRUCT_CONTENTS:
-+ req->value = lookup_struct_contents(req);
-+ break;
-+
-+ case GNU_ITERATE_DATATYPES:
-+ iterate_datatypes(req);
-+ break;
-+
-+ default:
-+ req->flags |= GNU_COMMAND_FAILED;
-+ break;
-+ }
-+}
-+
-+/*
-+ * Given a PC value, return the file and line number.
-+ */
-+static void
-+gdb_get_line_number(struct gnu_request *req)
-+{
-+ struct symtab_and_line sal;
-+ struct objfile *objfile;
-+ CORE_ADDR pc;
-+
-+#define LASTCHAR(s) (s[strlen(s)-1])
-+
-+ /*
-+ * Prime the addrmap pump.
-+ */
-+ pc = req->addr;
-+
-+ sal = find_pc_line(pc, 0);
-+
-+ if (!sal.symtab) {
-+ /*
-+ * If a module address line number can't be found, it's
typically
-+ * due to its addrmap still containing offset values because its
-+ * objfile doesn't have full symbols loaded.
-+ */
-+ if (req->lm) {
-+ objfile = req->lm->loaded_objfile;
-+ if (!objfile_has_full_symbols(objfile) &&
objfile->sf) {
-+ objfile->sf->qf->expand_all_symtabs(objfile);
-+ sal = find_pc_line(pc, 0);
-+ }
-+ }
-+ if (!sal.symtab) {
-+ req->buf[0] = '\0';
-+ return;
-+ }
-+ }
-+
-+ if (sal.symtab->filename && SYMTAB_DIRNAME(sal.symtab)) {
-+ if (sal.symtab->filename[0] == '/')
-+ sprintf(req->buf, "%s: %d",
-+ sal.symtab->filename, sal.line);
-+ else
-+ sprintf(req->buf, "%s%s%s: %d",
-+ SYMTAB_DIRNAME(sal.symtab),
-+ LASTCHAR(SYMTAB_DIRNAME(sal.symtab)) == '/' ?
"" : "/",
-+ sal.symtab->filename, sal.line);
-+ }
-+}
-+
-+
-+/*
-+ * General purpose routine for determining datatypes.
-+ */
-+
-+static void
-+gdb_get_datatype(struct gnu_request *req)
-+{
-+ register struct type *type;
-+ register struct type *typedef_type;
-+ expression_up expr;
-+ struct symbol *sym;
-+ struct value *val;
-+
-+ if (gdb_CRASHDEBUG(2))
-+ console("gdb_get_datatype [%s] (a)\n", req->name);
-+
-+ req->typecode = TYPE_CODE_UNDEF;
-+
-+ /*
-+ * lookup_symbol() will pick up struct and union names.
-+ */
-+ sym = lookup_symbol(req->name, 0, STRUCT_DOMAIN, 0).symbol;
-+ if (sym) {
-+ req->typecode = TYPE_CODE(sym->type);
-+ req->length = TYPE_LENGTH(sym->type);
-+ if (req->member)
-+ get_member_data(req, sym->type, 0, 1);
-+
-+ if (TYPE_CODE(sym->type) == TYPE_CODE_ENUM) {
-+ if (req->flags & GNU_PRINT_ENUMERATORS)
-+ dump_enum(sym->type, req);
-+ }
-+
-+ return;
-+ }
-+
-+ /*
-+ * Otherwise parse the expression.
-+ */
-+ if (gdb_CRASHDEBUG(2))
-+ console("gdb_get_datatype [%s] (b)\n", req->name);
-+
-+ expr = parse_expression(req->name);
-+
-+
-+ switch (expr.get()->elts[0].opcode)
-+ {
-+ case OP_VAR_VALUE:
-+ if (gdb_CRASHDEBUG(2))
-+ console("expr->elts[0].opcode: OP_VAR_VALUE\n");
-+ type = expr.get()->elts[2].symbol->type;
-+ if (req->flags & GNU_VAR_LENGTH_TYPECODE) {
-+ req->typecode = TYPE_CODE(type);
-+ req->length = TYPE_LENGTH(type);
-+ }
-+ if (TYPE_CODE(type) == TYPE_CODE_ENUM) {
-+ req->typecode = TYPE_CODE(type);
-+ req->value = SYMBOL_VALUE(expr.get()->elts[2].symbol);
-+ req->tagname = (char *)TYPE_TAG_NAME(type);
-+ if (!req->tagname) {
-+ val = evaluate_type(expr.get());
-+ eval_enum(value_type(val), req);
-+ }
-+ }
-+ break;
-+
-+ case OP_TYPE:
-+ if (gdb_CRASHDEBUG(2))
-+ console("expr->elts[0].opcode: OP_TYPE\n");
-+ type = expr.get()->elts[1].type;
-+
-+ req->typecode = TYPE_CODE(type);
-+ req->length = TYPE_LENGTH(type);
-+
-+ if (TYPE_CODE(type) == TYPE_CODE_TYPEDEF) {
-+ req->is_typedef = TYPE_CODE_TYPEDEF;
-+ if ((typedef_type = check_typedef(type))) {
-+ req->typecode = TYPE_CODE(typedef_type);
-+ req->length = TYPE_LENGTH(typedef_type);
-+ type = typedef_type;
-+ }
-+ }
-+
-+ if (TYPE_CODE(type) == TYPE_CODE_ENUM) {
-+ if (req->is_typedef)
-+ if (req->flags & GNU_PRINT_ENUMERATORS) {
-+ if (req->is_typedef)
-+ fprintf_filtered(gdb_stdout,
-+ "typedef ");
-+ dump_enum(type, req);
-+ }
-+ }
-+
-+ if (req->member)
-+ get_member_data(req, type, 0, 1);
-+
-+ break;
-+
-+ default:
-+ if (gdb_CRASHDEBUG(2))
-+ console("expr.get()->elts[0].opcode: %d (?)\n",
-+ expr.get()->elts[0].opcode);
-+ break;
-+
-+ }
-+}
-+
-+/*
-+ * More robust enum list dump that gdb's, showing the value of each
-+ * identifier, each on its own line.
-+ */
-+static void
-+dump_enum(struct type *type, struct gnu_request *req)
-+{
-+ register int i;
-+ int len;
-+ long long lastval;
-+
-+ len = TYPE_NFIELDS (type);
-+ lastval = 0;
-+ if (TYPE_TAG_NAME(type))
-+ fprintf_filtered(gdb_stdout,
-+ "enum %s {\n", TYPE_TAG_NAME (type));
-+ else
-+ fprintf_filtered(gdb_stdout, "enum {\n");
-+
-+ for (i = 0; i < len; i++) {
-+ fprintf_filtered(gdb_stdout, " %s",
-+ TYPE_FIELD_NAME (type, i));
-+ if (lastval != TYPE_FIELD_ENUMVAL (type, i)) {
-+ fprintf_filtered (gdb_stdout, " = %s",
-+ plongest(TYPE_FIELD_ENUMVAL (type, i)));
-+ lastval = TYPE_FIELD_ENUMVAL (type, i);
-+ } else
-+ fprintf_filtered(gdb_stdout, " = %s",
plongest(lastval));
-+ fprintf_filtered(gdb_stdout, "\n");
-+ lastval++;
-+ }
-+ if (TYPE_TAG_NAME(type))
-+ fprintf_filtered(gdb_stdout, "};\n");
-+ else
-+ fprintf_filtered(gdb_stdout, "} %s;\n", req->name);
-+}
-+
-+/*
-+ * Given an enum type with no tagname, determine its value.
-+ */
-+static void
-+eval_enum(struct type *type, struct gnu_request *req)
-+{
-+ register int i;
-+ int len;
-+ long long lastval;
-+
-+ len = TYPE_NFIELDS (type);
-+ lastval = 0;
-+
-+ for (i = 0; i < len; i++) {
-+ if (lastval != TYPE_FIELD_ENUMVAL (type, i))
-+ lastval = TYPE_FIELD_ENUMVAL (type, i);
-+
-+ if (STREQ(TYPE_FIELD_NAME(type, i), req->name)) {
-+ req->tagname = "(unknown)";
-+ req->value = lastval;
-+ return;
-+ }
-+ lastval++;
-+ }
-+}
-+
-+/*
-+ * Walk through a struct type's list of fields looking for the desired
-+ * member field, and when found, return its relevant data.
-+ */
-+static void
-+get_member_data(struct gnu_request *req, struct type *type, long offset, int is_first)
-+{
-+ register short i;
-+ struct field *nextfield;
-+ short nfields;
-+ struct type *typedef_type, *target_type;
-+
-+ req->member_offset = -1;
-+
-+ nfields = TYPE_MAIN_TYPE(type)->nfields;
-+ nextfield = TYPE_MAIN_TYPE(type)->flds_bnds.fields;
-+
-+ if (nfields == 0 && is_first /* The first call */) {
-+ struct type *newtype;
-+ newtype = lookup_transparent_type(req->name);
-+ if (newtype) {
-+ console("get_member_data(%s.%s): switching type from %lx to
%lx\n",
-+ req->name, req->member, type, newtype);
-+ nfields = TYPE_MAIN_TYPE(newtype)->nfields;
-+ nextfield = TYPE_MAIN_TYPE(newtype)->flds_bnds.fields;
-+ }
-+ }
-+
-+ for (i = 0; i < nfields; i++) {
-+ if (STREQ(req->member, nextfield->name)) {
-+ req->member_offset = offset + nextfield->loc.bitpos;
-+ req->member_length = TYPE_LENGTH(nextfield->type());
-+ req->member_typecode = TYPE_CODE(nextfield->type());
-+ req->member_main_type_name = (char
*)TYPE_NAME(nextfield->type());
-+ req->member_main_type_tag_name = (char
*)TYPE_TAG_NAME(nextfield->type());
-+ target_type = TYPE_TARGET_TYPE(nextfield->type());
-+ if (target_type) {
-+ req->member_target_type_name = (char
*)TYPE_NAME(target_type);
-+ req->member_target_type_tag_name = (char
*)TYPE_TAG_NAME(target_type);
-+ }
-+ if ((req->member_typecode == TYPE_CODE_TYPEDEF) &&
-+ (typedef_type = check_typedef(nextfield->type())))
-+ req->member_length = TYPE_LENGTH(typedef_type);
-+ return;
-+ } else if (*nextfield->name == 0) { /* Anonymous struct/union */
-+ get_member_data(req, nextfield->type(),
-+ offset + nextfield->loc.bitpos, 0);
-+ if (req->member_offset != -1)
-+ return;
-+ }
-+ nextfield++;
-+ }
-+}
-+
-+/*
-+ * Check whether a command exists. If it doesn't, the command will be
-+ * returned indirectly via the error_hook.
-+ */
-+static void
-+gdb_command_exists(struct gnu_request *req)
-+{
-+ extern struct cmd_list_element *cmdlist;
-+
-+ req->value = FALSE;
-+ lookup_cmd((const char **)&req->name, cmdlist, "", NULL, 0,
1);
-+ req->value = TRUE;
-+}
-+
-+static void
-+gdb_function_numargs(struct gnu_request *req)
-+{
-+ struct symbol *sym;
-+
-+ sym = find_pc_function(req->pc);
-+
-+ if (!sym || TYPE_CODE(sym->type) != TYPE_CODE_FUNC) {
-+ req->flags |= GNU_COMMAND_FAILED;
-+ return;
-+ }
-+
-+ req->value = (ulong)TYPE_NFIELDS(sym->type);
-+}
-+
-+struct load_module *gdb_current_load_module = NULL;
-+
-+static void
-+gdb_add_symbol_file(struct gnu_request *req)
-+{
-+ struct load_module *lm;
-+ int i;
-+ int allsect = 0;
-+ char *secname;
-+ char buf[80];
-+
-+ gdb_current_load_module = lm = (struct load_module *)req->addr;
-+
-+ req->name = lm->mod_namelist;
-+ gdb_delete_symbol_file(req);
-+ lm->loaded_objfile = NULL;
-+
-+ if ((lm->mod_flags & MOD_NOPATCH) == 0) {
-+ for (i = 0 ; i < lm->mod_sections; i++) {
-+ if (STREQ(lm->mod_section_data[i].name, ".text")
&&
-+ (lm->mod_section_data[i].flags & SEC_FOUND))
-+ allsect = 1;
-+ }
-+
-+ if (!allsect) {
-+ sprintf(req->buf, "add-symbol-file %s 0x%lx %s",
lm->mod_namelist,
-+ lm->mod_text_start ? lm->mod_text_start :
lm->mod_base,
-+ lm->mod_flags & MOD_DO_READNOW ? "-readnow"
: "");
-+ if (lm->mod_data_start) {
-+ sprintf(buf, " -s .data 0x%lx",
lm->mod_data_start);
-+ strcat(req->buf, buf);
-+ }
-+ if (lm->mod_bss_start) {
-+ sprintf(buf, " -s .bss 0x%lx",
lm->mod_bss_start);
-+ strcat(req->buf, buf);
-+ }
-+ if (lm->mod_rodata_start) {
-+ sprintf(buf, " -s .rodata 0x%lx",
lm->mod_rodata_start);
-+ strcat(req->buf, buf);
-+ }
-+ } else {
-+ sprintf(req->buf, "add-symbol-file %s 0x%lx %s",
lm->mod_namelist,
-+ lm->mod_text_start, lm->mod_flags & MOD_DO_READNOW
?
-+ "-readnow" : "");
-+ for (i = 0; i < lm->mod_sections; i++) {
-+ secname = lm->mod_section_data[i].name;
-+ if ((lm->mod_section_data[i].flags & SEC_FOUND)
&&
-+ !STREQ(secname, ".text")) {
-+ sprintf(buf, " -s %s 0x%lx", secname,
-+ lm->mod_section_data[i].offset +
lm->mod_base);
-+ strcat(req->buf, buf);
-+ }
-+ }
-+ }
-+ }
-+
-+ if (gdb_CRASHDEBUG(1))
-+ fprintf_filtered(gdb_stdout, "%s\n", req->buf);
-+
-+ execute_command(req->buf, FALSE);
-+
-+ for (objfile *objfile : current_program_space->objfiles ()) {
-+ if (same_file((char *)objfile_name(objfile), lm->mod_namelist)) {
-+ if (objfile->separate_debug_objfile)
-+ lm->loaded_objfile =
objfile->separate_debug_objfile;
-+ else
-+ lm->loaded_objfile = objfile;
-+ break;
-+ }
-+ }
-+
-+ if (!lm->loaded_objfile)
-+ req->flags |= GNU_COMMAND_FAILED;
-+}
-+
-+static void
-+gdb_delete_symbol_file(struct gnu_request *req)
-+{
-+ for (objfile *objfile : current_program_space->objfiles ()) {
-+ if (STREQ(objfile_name(objfile), req->name) ||
-+ same_file((char *)objfile_name(objfile), req->name)) {
-+ objfile->unlink ();
-+ break;
-+ }
-+ }
-+
-+ if (gdb_CRASHDEBUG(2)) {
-+ fprintf_filtered(gdb_stdout, "current object files:\n");
-+ for (objfile *objfile : current_program_space->objfiles ())
-+ fprintf_filtered(gdb_stdout, " %s\n",
objfile_name(objfile));
-+ }
-+}
-+
-+/*
-+ * Walk through all minimal_symbols, patching their values with the
-+ * correct addresses.
-+ */
-+static void
-+gdb_patch_symbol_values(struct gnu_request *req)
-+{
-+ req->name = PATCH_KERNEL_SYMBOLS_START;
-+ patch_kernel_symbol(req);
-+
-+ for (objfile *objfile : current_program_space->objfiles ())
-+ for (minimal_symbol *msymbol : objfile->msymbols ())
-+ {
-+ req->name = (char *)msymbol->m_name;
-+ req->addr = (ulong)(&MSYMBOL_VALUE(msymbol));
-+ if (!patch_kernel_symbol(req)) {
-+ req->flags |= GNU_COMMAND_FAILED;
-+ break;
-+ }
-+ }
-+
-+ req->name = PATCH_KERNEL_SYMBOLS_STOP;
-+ patch_kernel_symbol(req);
-+
-+ clear_symtab_users(0);
-+ gdb_merge_flags |= KERNEL_SYMBOLS_PATCHED;
-+}
-+
-+static void
-+gdb_get_symbol_type(struct gnu_request *req)
-+{
-+ expression_up expr;
-+ struct value *val;
-+ struct type *type;
-+ struct type *target_type;
-+
-+ req->typecode = TYPE_CODE_UNDEF;
-+
-+ expr = parse_expression (req->name);
-+ val = evaluate_type (expr.get());
-+
-+ type = value_type(val);
-+
-+ req->type_name = (char *)TYPE_MAIN_TYPE(type)->name;
-+ req->typecode = TYPE_MAIN_TYPE(type)->code;
-+ req->length = type->length;
-+ req->type_tag_name = (char *)TYPE_TAG_NAME(type);
-+ target_type = TYPE_MAIN_TYPE(type)->target_type;
-+
-+ if (target_type) {
-+ req->target_typename = (char *)TYPE_MAIN_TYPE(target_type)->name;
-+ req->target_typecode = TYPE_MAIN_TYPE(target_type)->code;
-+ req->target_length = target_type->length;
-+ }
-+
-+ if (req->member)
-+ get_member_data(req, type, 0, 1);
-+}
-+
-+static void
-+gdb_debug_command(struct gnu_request *req)
-+{
-+
-+}
-+
-+/*
-+ * Only necessary on "patched" kernel symbol sessions, and called only by
-+ * lookup_symbol(), pull a symbol value bait-and-switch operation by altering
-+ * either a data symbol's address value or a text symbol's block start
address.
-+ */
-+static void
-+gdb_bait_and_switch(char *name, struct symbol *sym)
-+{
-+ struct bound_minimal_symbol msym;
-+ struct block *block;
-+
-+ if ((gdb_merge_flags & KERNEL_SYMBOLS_PATCHED) &&
-+ (msym = lookup_minimal_symbol(name, NULL, gdb_kernel_objfile)).minsym) {
-+ if (SYMBOL_CLASS(sym) == LOC_BLOCK) {
-+ block = (struct block *)SYMBOL_BLOCK_VALUE(sym);
-+ BLOCK_START(block) = BMSYMBOL_VALUE_ADDRESS(msym);
-+ } else
-+ SET_SYMBOL_VALUE_ADDRESS(sym, BMSYMBOL_VALUE_ADDRESS(msym));
-+ }
-+}
-+
-+#include "valprint.h"
-+
-+void
-+get_user_print_option_address(struct gnu_request *req)
-+{
-+ extern struct value_print_options user_print_options;
-+
-+ req->addr = 0;
-+
-+ if (strcmp(req->name, "output_format") == 0)
-+ req->addr = (ulong)&user_print_options.output_format;
-+ if (strcmp(req->name, "print_max") == 0)
-+ req->addr = (ulong)&user_print_options.print_max;
-+ if (strcmp(req->name, "prettyprint_structs") == 0)
-+ req->addr = (ulong)&user_print_options.prettyformat_structs;
-+ if (strcmp(req->name, "prettyprint_arrays") == 0)
-+ req->addr = (ulong)&user_print_options.prettyformat_arrays;
-+ if (strcmp(req->name, "repeat_count_threshold") == 0)
-+ req->addr = (ulong)&user_print_options.repeat_count_threshold;
-+ if (strcmp(req->name, "stop_print_at_null") == 0)
-+ req->addr = (ulong)&user_print_options.stop_print_at_null;
-+ if (strcmp(req->name, "output_radix") == 0)
-+ req->addr = (ulong)&output_radix;
-+}
-+
-+CORE_ADDR crash_text_scope;
-+
-+static void
-+gdb_set_crash_block(struct gnu_request *req)
-+{
-+ if (!req->addr) { /* debug */
-+ crash_text_scope = 0;
-+ return;
-+ }
-+
-+ if ((req->addr2 = (ulong)block_for_pc(req->addr)))
-+ crash_text_scope = req->addr;
-+ else {
-+ crash_text_scope = 0;
-+ req->flags |= GNU_COMMAND_FAILED;
-+ }
-+}
-+
-+static const struct block *
-+gdb_get_crash_block(void)
-+{
-+ if (crash_text_scope)
-+ return block_for_pc(crash_text_scope);
-+ else
-+ return NULL;
-+}
-+
-+static long
-+lookup_struct_contents(struct gnu_request *req)
-+{
-+ int i;
-+ long r;
-+ struct field *f;
-+ struct main_type *m;
-+ const char *n;
-+ struct main_type *top_m = (struct main_type *)req->addr;
-+ char *type_name = req->type_name;
-+
-+ if (!top_m || !type_name)
-+ return 0;
-+
-+ for (i = 0; i < top_m->nfields; i++)
-+ {
-+ f = top_m->flds_bnds.fields + i;
-+ if (!f->type())
-+ continue;
-+ m = f->type()->main_type;
-+
-+ // If the field is an array, check the target type -
-+ // it might be structure, or might not be.
-+ // - struct request_sock *syn_table[0];
-+ // here m->target_type->main_type->code is expected
-+ // to be TYPE_CODE_PTR
-+ // - struct list_head vec[TVN_SIZE];
-+ // here m->target_type->main_type->code should be
-+ // TYPE_CODE_STRUCT
-+ if (m->code == TYPE_CODE_ARRAY && m->target_type)
-+ m = m->target_type->main_type;
-+
-+ /* Here is a recursion.
-+ * If we have struct variable (not pointer),
-+ * scan this inner structure
-+ */
-+ if (m->code == TYPE_CODE_STRUCT) {
-+ req->addr = (ulong)m;
-+ r = lookup_struct_contents(req);
-+ req->addr = (ulong)top_m;
-+ if (r)
-+ return 1;
-+ }
-+
-+ if (m->code == TYPE_CODE_PTR && m->target_type)
-+ m = m->target_type->main_type;
-+ if (m->name)
-+ n = m->name;
-+ else
-+ continue;
-+
-+ if (strstr(n, type_name))
-+ return 1;
-+ }
-+
-+ return 0;
-+}
-+
-+static void
-+iterate_datatypes (struct gnu_request *req)
-+{
-+ for (objfile *objfile : current_program_space->objfiles ())
-+ {
-+ if (objfile->sf)
-+ objfile->sf->qf->expand_all_symtabs(objfile);
-+
-+ for (compunit_symtab *cust : objfile->compunits ())
-+ {
-+ const struct blockvector *bv = COMPUNIT_BLOCKVECTOR (cust);
-+
-+ for (int i = GLOBAL_BLOCK; i <= STATIC_BLOCK; ++i)
-+ {
-+ const struct block *b = BLOCKVECTOR_BLOCK (bv, i);
-+ struct block_iterator iter;
-+ struct symbol *sym;
-+
-+ ALL_BLOCK_SYMBOLS (b, iter, sym)
-+ {
-+ QUIT;
-+
-+ if (SYMBOL_CLASS (sym) != LOC_TYPEDEF)
-+ continue;
-+
-+ if (req->highest &&
-+ !(req->lowest <= sym->type->length &&
sym->type->length <= req->highest))
-+ continue;
-+
-+ req->addr = (ulong)(sym->type->main_type);
-+ req->name = (char *)(sym->m_name);
-+ req->length = sym->type->length;
-+
-+ if (req->member) {
-+ req->value = lookup_struct_contents(req);
-+ if (!req->value)
-+ continue;
-+ }
-+ req->callback(req, req->callback_data);
-+ }
-+ }
-+ }
-+ }
-+}
-+#endif
---- gdb-10.2/gdb/ui-file.h.orig
-+++ gdb-10.2/gdb/ui-file.h
-@@ -195,10 +195,10 @@ class stdio_file : public ui_file
-
- bool can_emit_style_escape () override;
-
--private:
- /* Sets the internal stream to FILE, and saves the FILE's file
- descriptor in M_FD. */
- void set_stream (FILE *file);
-+private:
-
- /* The file. */
- FILE *m_file;
---- gdb-10.2/gdb/xml-syscall.c.orig
-+++ gdb-10.2/gdb/xml-syscall.c
-@@ -37,7 +37,11 @@
- static void
- syscall_warn_user (void)
- {
-+#ifdef CRASH_MERGE
-+ static int have_warned = 1;
-+#else
- static int have_warned = 0;
-+#endif
- if (!have_warned)
- {
- have_warned = 1;
---- gdb-10.2/libiberty/Makefile.in.orig
-+++ gdb-10.2/libiberty/Makefile.in
-@@ -180,6 +180,7 @@ REQUIRED_OFILES = \
- ./getruntime.$(objext) ./hashtab.$(objext) ./hex.$(objext) \
- ./lbasename.$(objext) ./lrealpath.$(objext) \
- ./make-relative-prefix.$(objext) ./make-temp-file.$(objext) \
-+ ./mkstemps.$(objext) \
- ./objalloc.$(objext) \
- ./obstack.$(objext) \
- ./partition.$(objext) ./pexecute.$(objext) ./physmem.$(objext) \
-@@ -213,7 +214,7 @@ CONFIGURED_OFILES = ./asprintf.$(objext) ./atexit.$(objext) \
- ./index.$(objext) ./insque.$(objext) \
- ./memchr.$(objext) ./memcmp.$(objext) ./memcpy.$(objext) \
- ./memmem.$(objext) ./memmove.$(objext) \
-- ./mempcpy.$(objext) ./memset.$(objext) ./mkstemps.$(objext) \
-+ ./mempcpy.$(objext) ./memset.$(objext) \
- ./pex-djgpp.$(objext) ./pex-msdos.$(objext) \
- ./pex-unix.$(objext) ./pex-win32.$(objext) \
- ./putenv.$(objext) \
---- gdb-10.2/opcodes/i386-dis.c.orig
-+++ gdb-10.2/opcodes/i386-dis.c
-@@ -9778,6 +9778,10 @@ print_insn (bfd_vma pc, disassemble_info *info)
- threebyte = *codep;
- dp = &dis386_twobyte[threebyte];
- need_modrm = twobyte_has_modrm[*codep];
-+ if (dp->name && ((strcmp(dp->name, "ud2a") == 0) ||
(strcmp(dp->name, "ud2") == 0))) {
-+ extern int kernel_BUG_encoding_bytes(void);
-+ codep += kernel_BUG_encoding_bytes();
-+ }
- codep++;
- }
- else
---- gdb-10.2/readline/readline/misc.c.orig
-+++ gdb-10.2/readline/readline/misc.c
-@@ -403,7 +403,7 @@ _rl_history_set_point (void)
-
- #if defined (VI_MODE)
- if (rl_editing_mode == vi_mode && _rl_keymap != vi_insertion_keymap)
-- rl_point = 0;
-+ rl_point = rl_end;
- #endif /* VI_MODE */
-
- if (rl_editing_mode == emacs_mode)
---- gdb-10.2/readline/readline/readline.h.orig
-+++ gdb-10.2/readline/readline/readline.h
-@@ -395,7 +395,7 @@ extern int rl_crlf PARAMS((void));
- #if defined (USE_VARARGS) && defined (PREFER_STDARG)
- extern int rl_message (const char *, ...) __attribute__((__format__ (printf, 1, 2)));
- #else
--extern int rl_message ();
-+extern int rl_message (void);
- #endif
-
- extern int rl_show_char PARAMS((int));
---- gdb-10.2/readline/readline/rltypedefs.h.orig
-+++ gdb-10.2/readline/readline/rltypedefs.h
-@@ -32,10 +32,10 @@ extern "C" {
- # define _FUNCTION_DEF
-
- #if defined(__GNUC__) || defined(__clang__)
--typedef int Function () __attribute__ ((deprecated));
--typedef void VFunction () __attribute__ ((deprecated));
--typedef char *CPFunction () __attribute__ ((deprecated));
--typedef char **CPPFunction () __attribute__ ((deprecated));
-+typedef int Function (void) __attribute__ ((deprecated));
-+typedef void VFunction (void) __attribute__ ((deprecated));
-+typedef char *CPFunction (void) __attribute__ ((deprecated));
-+typedef char **CPPFunction (void) __attribute__ ((deprecated));
- #else
- typedef int Function ();
- typedef void VFunction ();
---- gdb-10.2/readline/readline/util.c.orig
-+++ gdb-10.2/readline/readline/util.c
-@@ -487,10 +487,13 @@ _rl_trace (va_alist)
-
- if (_rl_tracefp == 0)
- _rl_tropen ();
-+ if (!_rl_tracefp)
-+ goto out;
- vfprintf (_rl_tracefp, format, args);
- fprintf (_rl_tracefp, "\n");
- fflush (_rl_tracefp);
-
-+out:
- va_end (args);
- }
-
-@@ -513,16 +516,17 @@ _rl_tropen (void)
- sprintf (fnbuf, "/var/tmp/rltrace.%ld", (long) getpid ());
- #endif
- unlink (fnbuf);
-- _rl_tracefp = fopen (fnbuf, "w+");
-+ _rl_tracefp = fopen (fnbuf, "w+xe");
- return _rl_tracefp != 0;
- }
-
- int
- _rl_trclose (void)
- {
-- int r;
-+ int r = 0;
-
-- r = fclose (_rl_tracefp);
-+ if (_rl_tracefp)
-+ r = fclose (_rl_tracefp);
- _rl_tracefp = 0;
- return r;
- }
---- gdb-10.2/gdb/completer.c.orig
-+++ gdb-10.2/gdb/completer.c
-@@ -2949,6 +2949,8 @@
-
- /* How many items of MAX length can we fit in the screen window? */
- cols = gdb_complete_get_screenwidth (displayer);
-+ rl_reset_screen_size();
-+ rl_get_screen_size(NULL, &cols);
- max += 2;
- limit = cols / max;
- if (limit != 1 && (limit * max == cols))
---- gdb-10.2/gdb/ada-lang.c.orig
-+++ gdb-10.2/gdb/ada-lang.c
-@@ -997,7 +997,7 @@ ada_fold_name (gdb::string_view name)
- int len = name.size ();
- GROW_VECT (fold_buffer, fold_buffer_size, len + 1);
-
-- if (name[0] == '\'')
-+ if (!name.empty () && name[0] == '\'')
- {
- strncpy (fold_buffer, name.data () + 1, len - 2);
- fold_buffer[len - 2] = '\000';
-@@ -1006,8 +1006,9 @@ ada_fold_name (gdb::string_view name)
- {
- int i;
-
-- for (i = 0; i <= len; i += 1)
-+ for (i = 0; i < len; i += 1)
- fold_buffer[i] = tolower (name[i]);
-+ fold_buffer[i] = '\0';
- }
-
- return fold_buffer;
-@@ -13596,7 +13597,7 @@ ada_lookup_name_info::ada_lookup_name_info (const
lookup_name_info &lookup_name)
- {
- gdb::string_view user_name = lookup_name.name ();
-
-- if (user_name[0] == '<')
-+ if (!user_name.empty () && user_name[0] == '<')
- {
- if (user_name.back () == '>')
- m_encoded_name
---- gdb-10.2/gdb/Makefile.in.orig
-+++ gdb-10.2/gdb/Makefile.in
-@@ -1865,7 +1865,7 @@ libgdb.a: $(LIBGDB_OBS)
- # Removing the old gdb first works better if it is running, at least on SunOS.
- gdb$(EXEEXT): gdb.o $(LIBGDB_OBS) $(CDEPS) $(TDEPLIBS)
- $(SILENCE) rm -f gdb$(EXEEXT)
-- @(cd ../..; make --no-print-directory GDB_FLAGS=-DGDB_10_2 library)
-+ @$(MAKE) -C ../.. GDB_FLAGS=-DGDB_10_2 library
- $(ECHO_CXXLD) $(CC_LD) $(INTERNAL_LDFLAGS) $(WIN32LDAPP) \
- -o $(shell /bin/cat mergeobj) $(LIBGDB_OBS) \
- $(TDEPLIBS) $(TUI_LIBRARY) $(CLIBS) $(LOADLIBES) $(shell /bin/cat
mergelibs)
---- gdb-10.2/gdb/c-typeprint.c.orig
-+++ gdb-10.2/gdb/c-typeprint.c
-@@ -1202,6 +1202,9 @@ c_type_print_base_struct_union (struct t
- = podata->end_bitpos
- - TYPE_LENGTH (type->field (i).type ()) * TARGET_CHAR_BIT;
- }
-+ else if (strlen(TYPE_FIELD_NAME (type, i)) == 0)
-+ /* crash: Print details for unnamed struct and union. */
-+ newshow = show;
-
- c_print_type_1 (type->field (i).type (),
- TYPE_FIELD_NAME (type, i),
---- gdb-10.2/gdb/symfile.c.orig
-+++ gdb-10.2/gdb/symfile.c
-@@ -1610,7 +1610,7 @@ find_separate_debug_file_by_debuglink (struct objfile *objfile)
- if (debugfile.empty ()) {
- char *name_copy;
- name_copy = check_specified_kernel_debug_file();
-- return std::string (name_copy);
-+ return name_copy ? std::string (name_copy) : std::string ();
- }
- #endif
-
---- gdb-10.2/gdb/printcmd.c.orig
-+++ gdb-10.2/gdb/printcmd.c
-@@ -576,6 +576,10 @@ print_address_symbolic (struct gdbarch *gdbarch, CORE_ADDR addr,
-
- /* See valprint.h. */
-
-+#ifdef CRASH_MERGE
-+extern "C" char *gdb_lookup_module_symbol(unsigned long, unsigned long *);
-+#endif
-+
- int
- build_address_symbolic (struct gdbarch *gdbarch,
- CORE_ADDR addr, /* IN */
-@@ -682,7 +686,19 @@ build_address_symbolic (struct gdbarch *gdbarch,
- }
- }
- if (symbol == NULL && msymbol.minsym == NULL)
-+#ifdef CRASH_MERGE
-+ {
-+ char *name_ptr = gdb_lookup_module_symbol(addr, (unsigned long *)offset);
-+ if (name_ptr) {
-+ *name = name_ptr;
-+ return 0;
-+ } else {
-+ return 1;
-+ }
-+ }
-+#else
- return 1;
-+#endif
-
- /* If the nearest symbol is too far away, don't print anything symbolic. */
-
---- gdb-10.2/gdb/symtab.c.orig
-+++ gdb-10.2/gdb/symtab.c
-@@ -7128,8 +7128,8 @@ gdb_get_line_number(struct gnu_request *
- static void
- gdb_get_datatype(struct gnu_request *req)
- {
-- register struct type *type;
-- register struct type *typedef_type;
-+ struct type *type;
-+ struct type *typedef_type;
- expression_up expr;
- struct symbol *sym;
- struct value *val;
-@@ -7235,7 +7235,7 @@ gdb_get_datatype(struct gnu_request *req
- static void
- dump_enum(struct type *type, struct gnu_request *req)
- {
-- register int i;
-+ int i;
- int len;
- long long lastval;
-
-@@ -7271,7 +7271,7 @@ dump_enum(struct type *type, struct gnu_
- static void
- eval_enum(struct type *type, struct gnu_request *req)
- {
-- register int i;
-+ int i;
- int len;
- long long lastval;
-
-@@ -7298,7 +7298,7 @@ eval_enum(struct type *type, struct gnu_
- static void
- get_member_data(struct gnu_request *req, struct type *type, long offset, int is_first)
- {
-- register short i;
-+ short i;
- struct field *nextfield;
- short nfields;
- struct type *typedef_type, *target_type;
---- gdb-10.2/gdb/symtab.c.orig
-+++ gdb-10.2/gdb/symtab.c
-@@ -6913,7 +6913,7 @@
- #include "../../defs.h"
-
- static void get_member_data(struct gnu_request *, struct type *, long, int);
--static void dump_enum(struct type *, struct gnu_request *);
-+static void walk_enum(struct type *, struct gnu_request *);
- static void eval_enum(struct type *, struct gnu_request *);
- static void gdb_get_line_number(struct gnu_request *);
- static void gdb_get_datatype(struct gnu_request *);
-@@ -7122,6 +7122,79 @@
-
-
- /*
-+ * Follow the type linkage for full member and value type resolution, with callback
-+ */
-+static void drillDownType(struct gnu_request *req, struct type *type)
-+{
-+ while (type)
-+ {
-+ /* check out for stub types and pull in the definition instead */
-+ if (TYPE_STUB(type) && TYPE_TAG_NAME(type)) {
-+ struct symbol *sym;
-+ sym = lookup_symbol(TYPE_TAG_NAME(type), 0, STRUCT_DOMAIN,
0).symbol;
-+ if (sym)
-+ type = sym->type;
-+ }
-+ switch (TYPE_CODE(type)) {
-+ drill_ops_t op;
-+ long l1, l2;
-+ int typecode;
-+
-+ case TYPE_CODE_PTR:
-+ req->tcb(EOP_POINTER, req, 0, 0, 0, 0);
-+ break;
-+
-+ case TYPE_CODE_TYPEDEF:
-+ req->is_typedef = 1;
-+ req->typecode = TYPE_CODE(type);
-+ if (!req->tcb(EOP_TYPEDEF, req, TYPE_NAME(type), 0, 0, 0))
-+ return;
-+ break;
-+
-+ case TYPE_CODE_FUNC:
-+ req->tcb(EOP_FUNCTION, req, 0, 0, 0, 0);
-+ break;
-+
-+ case TYPE_CODE_ARRAY:
-+ l1 = TYPE_LENGTH (type);
-+ l2 = TYPE_LENGTH (check_typedef(TYPE_TARGET_TYPE (type)));
-+ req->tcb(EOP_ARRAY, req, &l1, &l2, 0, 0);
-+ break;
-+
-+ case TYPE_CODE_VOID:
-+ case TYPE_CODE_INT:
-+ case TYPE_CODE_BOOL:
-+ l1 = TYPE_LENGTH(type);
-+ req->tcb(EOP_INT, req, &l1, 0, 0, 0);
-+ break;
-+
-+ case TYPE_CODE_UNION:
-+ op = EOP_UNION;
-+ goto label;
-+
-+ case TYPE_CODE_ENUM:
-+ op = EOP_ENUM;
-+ goto label;
-+
-+ case TYPE_CODE_STRUCT:
-+ op = EOP_STRUCT;
-+ goto label;
-+
-+ default:
-+ typecode = TYPE_CODE(type);
-+ req->tcb(EOP_OOPS, req, &typecode, "Unknown
typecode", 0, 0);
-+ return; /* not reached */
-+
-+ label:
-+ l1 = TYPE_LENGTH(type);
-+ req->tcb(op, req, &l1, type, TYPE_TAG_NAME(type), 0);
-+ }
-+ type = TYPE_TARGET_TYPE(type);
-+ }
-+ req->tcb(EOP_DONE, req, 0, 0, 0, 0);
-+}
-+
-+/*
- * General purpose routine for determining datatypes.
- */
-
-@@ -7149,10 +7222,8 @@
- if (req->member)
- get_member_data(req, sym->type, 0, 1);
-
-- if (TYPE_CODE(sym->type) == TYPE_CODE_ENUM) {
-- if (req->flags & GNU_PRINT_ENUMERATORS)
-- dump_enum(sym->type, req);
-- }
-+ if (TYPE_CODE(sym->type) == TYPE_CODE_ENUM)
-+ walk_enum(sym->type, req);
-
- return;
- }
-@@ -7172,17 +7243,25 @@
- if (gdb_CRASHDEBUG(2))
- console("expr->elts[0].opcode: OP_VAR_VALUE\n");
- type = expr.get()->elts[2].symbol->type;
-- if (req->flags & GNU_VAR_LENGTH_TYPECODE) {
-+ if (req->tcb) {
-+ long value = SYMBOL_VALUE(expr->elts[2].symbol);
-+ /* callback with symbol value */
- req->typecode = TYPE_CODE(type);
-- req->length = TYPE_LENGTH(type);
-- }
-- if (TYPE_CODE(type) == TYPE_CODE_ENUM) {
-- req->typecode = TYPE_CODE(type);
-- req->value = SYMBOL_VALUE(expr.get()->elts[2].symbol);
-- req->tagname = (char *)TYPE_TAG_NAME(type);
-- if (!req->tagname) {
-- val = evaluate_type(expr.get());
-- eval_enum(value_type(val), req);
-+ req->tcb(EOP_VALUE, req, &value, 0, 0, 0);
-+ drillDownType(req, type);
-+ } else {
-+ if (req->flags & GNU_VAR_LENGTH_TYPECODE) {
-+ req->typecode = TYPE_CODE(type);
-+ req->length = TYPE_LENGTH(type);
-+ }
-+ if (TYPE_CODE(type) == TYPE_CODE_ENUM) {
-+ req->typecode = TYPE_CODE(type);
-+ req->value = SYMBOL_VALUE(expr->elts[2].symbol);
-+ req->tagname = (char *)TYPE_TAG_NAME(type);
-+ if (!req->tagname) {
-+ val = evaluate_type(expr.get());
-+ eval_enum(value_type(val), req);
-+ }
- }
- }
- break;
-@@ -7192,26 +7271,21 @@
- console("expr->elts[0].opcode: OP_TYPE\n");
- type = expr.get()->elts[1].type;
-
-- req->typecode = TYPE_CODE(type);
-- req->length = TYPE_LENGTH(type);
--
-- if (TYPE_CODE(type) == TYPE_CODE_TYPEDEF) {
-- req->is_typedef = TYPE_CODE_TYPEDEF;
-- if ((typedef_type = check_typedef(type))) {
-- req->typecode = TYPE_CODE(typedef_type);
-- req->length = TYPE_LENGTH(typedef_type);
-- type = typedef_type;
-- }
-- }
--
-- if (TYPE_CODE(type) == TYPE_CODE_ENUM) {
-- if (req->is_typedef)
-- if (req->flags & GNU_PRINT_ENUMERATORS) {
-- if (req->is_typedef)
-- fprintf_filtered(gdb_stdout,
-- "typedef ");
-- dump_enum(type, req);
-+ if (req->tcb) {
-+ drillDownType(req, type);
-+ } else {
-+ req->typecode = TYPE_CODE(type);
-+ req->length = TYPE_LENGTH(type);
-+ if (TYPE_CODE(type) == TYPE_CODE_TYPEDEF) {
-+ req->is_typedef = TYPE_CODE_TYPEDEF;
-+ if ((typedef_type = check_typedef(type))) {
-+ req->typecode = TYPE_CODE(typedef_type);
-+ req->length = TYPE_LENGTH(typedef_type);
-+ type = typedef_type;
-+ }
- }
-+ if (TYPE_CODE(type) == TYPE_CODE_ENUM)
-+ walk_enum(type, req);
- }
-
- if (req->member)
-@@ -7233,36 +7307,38 @@
- * identifier, each on its own line.
- */
- static void
--dump_enum(struct type *type, struct gnu_request *req)
-+walk_enum(struct type *type, struct gnu_request *req)
- {
- int i;
-- int len;
-+ int len, print = (req->flags & GNU_PRINT_ENUMERATORS);
- long long lastval;
-
-- len = TYPE_NFIELDS (type);
-- lastval = 0;
-- if (TYPE_TAG_NAME(type))
-- fprintf_filtered(gdb_stdout,
-- "enum %s {\n", TYPE_TAG_NAME (type));
-- else
-- fprintf_filtered(gdb_stdout, "enum {\n");
-+ if (print) {
-+ if (req->is_typedef)
-+ fprintf_filtered(gdb_stdout, "typedef ");
-+ if (TYPE_TAG_NAME(type))
-+ fprintf_filtered(gdb_stdout, "enum %s {\n",
TYPE_TAG_NAME (type));
-+ else
-+ fprintf_filtered(gdb_stdout, "enum {\n");
-+ }
-
-+ len = TYPE_NFIELDS (type);
- for (i = 0; i < len; i++) {
-- fprintf_filtered(gdb_stdout, " %s",
-- TYPE_FIELD_NAME (type, i));
-- if (lastval != TYPE_FIELD_ENUMVAL (type, i)) {
-- fprintf_filtered (gdb_stdout, " = %s",
-- plongest(TYPE_FIELD_ENUMVAL (type, i)));
-- lastval = TYPE_FIELD_ENUMVAL (type, i);
-- } else
-+ if (print)
-+ fprintf_filtered(gdb_stdout, " %s", TYPE_FIELD_NAME
(type, i));
-+ lastval = TYPE_FIELD_ENUMVAL (type, i);
-+ if (print) {
- fprintf_filtered(gdb_stdout, " = %s",
plongest(lastval));
-- fprintf_filtered(gdb_stdout, "\n");
-- lastval++;
-+ fprintf_filtered(gdb_stdout, "\n");
-+ } else if (req->tcb)
-+ req->tcb(EOP_ENUMVAL, req, TYPE_FIELD_NAME (type, i),
&lastval, 0, 0);
-+ }
-+ if (print) {
-+ if (TYPE_TAG_NAME(type))
-+ fprintf_filtered(gdb_stdout, "};\n");
-+ else
-+ fprintf_filtered(gdb_stdout, "} %s;\n",
req->name);
- }
-- if (TYPE_TAG_NAME(type))
-- fprintf_filtered(gdb_stdout, "};\n");
-- else
-- fprintf_filtered(gdb_stdout, "} %s;\n", req->name);
- }
-
- /*
-@@ -7320,26 +7396,43 @@
- }
-
- for (i = 0; i < nfields; i++) {
-- if (STREQ(req->member, nextfield->name)) {
-- req->member_offset = offset + nextfield->loc.bitpos;
-- req->member_length = TYPE_LENGTH(nextfield->type());
-- req->member_typecode = TYPE_CODE(nextfield->type());
-- req->member_main_type_name = (char
*)TYPE_NAME(nextfield->type());
-- req->member_main_type_tag_name = (char
*)TYPE_TAG_NAME(nextfield->type());
-- target_type = TYPE_TARGET_TYPE(nextfield->type());
-- if (target_type) {
-- req->member_target_type_name = (char
*)TYPE_NAME(target_type);
-- req->member_target_type_tag_name = (char
*)TYPE_TAG_NAME(target_type);
-- }
-- if ((req->member_typecode == TYPE_CODE_TYPEDEF) &&
-- (typedef_type = check_typedef(nextfield->type())))
-- req->member_length = TYPE_LENGTH(typedef_type);
-- return;
-- } else if (*nextfield->name == 0) { /* Anonymous struct/union */
-+ if (*nextfield->name == 0) { /* Anonymous struct/union */
- get_member_data(req, nextfield->type(),
- offset + nextfield->loc.bitpos, 0);
- if (req->member_offset != -1)
- return;
-+ } else {
-+ /* callback may be just looking for a specific member name */
-+ if (req->tcb) {
-+ if (req->tcb(EOP_MEMBER_NAME, req,
nextfield->name, 0, 0, 0)) {
-+ long bitpos = FIELD_BITPOS(*nextfield);
-+ long bitsize = FIELD_BITSIZE(*nextfield);
-+ long len = TYPE_LENGTH(nextfield->type());
-+ long byteOffset;
-+ offset += nextfield->loc.bitpos;
-+ byteOffset = offset/8;
-+ console("EOP_MEMBER_SIZES\n");
-+ req->tcb(EOP_MEMBER_SIZES, req,
&byteOffset, &len, &bitpos, &bitsize);
-+ /* callback with full type info */
-+ drillDownType(req, nextfield->type());
-+ }
-+ } else if (STREQ(req->member, nextfield->name)) {
-+ req->member_offset = offset +
nextfield->loc.bitpos;
-+ req->member_length =
TYPE_LENGTH(nextfield->type());
-+ req->member_typecode =
TYPE_CODE(nextfield->type());
-+ req->member_main_type_name = (char
*)TYPE_NAME(nextfield->type());
-+ req->member_main_type_tag_name = (char
*)TYPE_TAG_NAME(nextfield->type());
-+ target_type = TYPE_TARGET_TYPE(nextfield->type());
-+ if (target_type) {
-+ req->member_target_type_name = (char
*)TYPE_NAME(target_type);
-+ req->member_target_type_tag_name = (char
*)TYPE_TAG_NAME(target_type);
-+ }
-+ if ((req->member_typecode == TYPE_CODE_TYPEDEF)
&&
-+ (typedef_type =
check_typedef(nextfield->type()))) {
-+ req->member_length =
TYPE_LENGTH(typedef_type);
-+ }
-+ return;
-+ }
- }
- nextfield++;
- }
---- gdb-10.2/gdb/gdbtypes.c.orig
-+++ gdb-10.2/gdb/gdbtypes.c
-@@ -5492,27 +5492,25 @@ copy_type_recursive (struct objfile *objfile,
- }
-
- /* Make a copy of the given TYPE, except that the pointer & reference
-- types are not preserved.
--
-- This function assumes that the given type has an associated objfile.
-- This objfile is used to allocate the new type. */
-+ types are not preserved. */
-
- struct type *
- copy_type (const struct type *type)
- {
-- struct type *new_type;
--
-- gdb_assert (TYPE_OBJFILE_OWNED (type));
-+ struct type *new_type = alloc_type_copy (type);
-
-- new_type = alloc_type_copy (type);
- TYPE_INSTANCE_FLAGS (new_type) = TYPE_INSTANCE_FLAGS (type);
- TYPE_LENGTH (new_type) = TYPE_LENGTH (type);
- memcpy (TYPE_MAIN_TYPE (new_type), TYPE_MAIN_TYPE (type),
- sizeof (struct main_type));
- if (type->main_type->dyn_prop_list != NULL)
-- new_type->main_type->dyn_prop_list
-- = copy_dynamic_prop_list (&TYPE_OBJFILE (type) -> objfile_obstack,
-- type->main_type->dyn_prop_list);
-+ {
-+ struct obstack *storage = (TYPE_OBJFILE_OWNED (type)
-+ ? &TYPE_OBJFILE (type)->objfile_obstack
-+ : gdbarch_obstack (TYPE_OWNER (type).gdbarch));
-+ new_type->main_type->dyn_prop_list
-+ = copy_dynamic_prop_list (storage, type->main_type->dyn_prop_list);
-+ }
-
- return new_type;
- }
---- gdb-10.2/gdb/dwarf2/read.c.orig
-+++ gdb-10.2/gdb/dwarf2/read.c
-@@ -4925,7 +4925,10 @@ dw2_find_pc_sect_compunit_symtab (struct objfile *objfile,
- result = recursively_find_pc_sect_compunit_symtab
- (dw2_instantiate_symtab (data, per_objfile, false), pc);
-
-- gdb_assert (result != NULL);
-+ if (warn_if_readin && result == nullptr)
-+ warning (_("(Error: pc %s in address map, but not in symtab.)"),
-+ paddress (objfile->arch (), pc));
-+
- return result;
- }
-
---- gdb-10.2/gdb/symtab.c.orig
-+++ gdb-10.2/gdb/symtab.c
-@@ -7476,7 +7476,7 @@ gdb_add_symbol_file(struct gnu_request *
- int i;
- int allsect = 0;
- char *secname;
-- char buf[80];
-+ char buf[96];
-
- gdb_current_load_module = lm = (struct load_module *)req->addr;
-
-@@ -7515,8 +7515,11 @@ gdb_add_symbol_file(struct gnu_request *
- secname = lm->mod_section_data[i].name;
- if ((lm->mod_section_data[i].flags & SEC_FOUND)
&&
- !STREQ(secname, ".text")) {
-- sprintf(buf, " -s %s 0x%lx", secname,
-- lm->mod_section_data[i].offset +
lm->mod_base);
-+ if (lm->mod_section_data[i].addr)
-+ sprintf(buf, " -s %s 0x%lx", secname,
lm->mod_section_data[i].addr);
-+ else
-+ sprintf(buf, " -s %s 0x%lx", secname,
-+ lm->mod_section_data[i].offset +
lm->mod_base);
- strcat(req->buf, buf);
- }
- }
---- gdb-10.2/gdb/ada-lang.c.orig
-+++ gdb-10.2/gdb/ada-lang.c
-@@ -1158,7 +1158,7 @@ ada_decode (const char *encoded)
- i -= 1;
- if (i > 1 && encoded[i] == '_' && encoded[i - 1] ==
'_')
- len0 = i - 1;
-- else if (encoded[i] == '$')
-+ else if (i >= 0 && encoded[i] == '$')
- len0 = i;
- }
-
---- gdb-10.2/gdb/coffread.c.orig
-+++ gdb-10.2/gdb/coffread.c
-@@ -159,6 +159,7 @@ static long linetab_offset;
- static unsigned long linetab_size;
-
- static char *stringtab = NULL;
-+static long stringtab_length = 0;
-
- extern void stabsread_clear_cache (void);
-
-@@ -1297,6 +1298,7 @@ init_stringtab (bfd *abfd, long offset,
gdb::unique_xmalloc_ptr<char> *storage)
- /* This is in target format (probably not very useful, and not
- currently used), not host format. */
- memcpy (stringtab, lengthbuf, sizeof lengthbuf);
-+ stringtab_length = length;
- if (length == sizeof length) /* Empty table -- just the count. */
- return 0;
-
-@@ -1316,8 +1318,9 @@ getsymname (struct internal_syment *symbol_entry)
-
- if (symbol_entry->_n._n_n._n_zeroes == 0)
- {
-- /* FIXME: Probably should be detecting corrupt symbol files by
-- seeing whether offset points to within the stringtab. */
-+ if (symbol_entry->_n._n_n._n_offset > stringtab_length)
-+ error (_("COFF Error: string table offset (%ld) outside string table
(length %ld)"),
-+ symbol_entry->_n._n_n._n_offset, stringtab_length);
- result = stringtab + symbol_entry->_n._n_n._n_offset;
- }
- else
---- gdb-10.2/gdb/objfiles.h.orig
-+++ gdb-10.2/gdb/objfiles.h
-@@ -712,6 +712,8 @@ struct objfile
- next time. If an objfile does not have the symbols, it will
- never have them. */
- bool skip_jit_symbol_lookup = false;
-+
-+ bool all_symtabs_expanded = false;
- };
-
- /* A deleter for objfile. */
---- gdb-10.2/gdb/symfile.c.orig
-+++ gdb-10.2/gdb/symfile.c
-@@ -1133,8 +1133,10 @@ symbol_file_add_with_addrs (bfd *abfd, const char *name,
- printf_filtered (_("Expanding full symbols from %ps...\n"),
- styled_string (file_name_style.style (), name));
-
-- if (objfile->sf)
-+ if (objfile->sf) {
- objfile->sf->qf->expand_all_symtabs (objfile);
-+ objfile->all_symtabs_expanded = true;
-+ }
- }
-
- /* Note that we only print a message if we have no symbols and have
---- gdb-10.2/gdb/symtab.c.orig
-+++ gdb-10.2/gdb/symtab.c
-@@ -7097,8 +7097,9 @@ gdb_get_line_number(struct gnu_request *req)
- */
- if (req->lm) {
- objfile = req->lm->loaded_objfile;
-- if (!objfile_has_full_symbols(objfile) &&
objfile->sf) {
-+ if (!objfile->all_symtabs_expanded && objfile->sf)
{
- objfile->sf->qf->expand_all_symtabs(objfile);
-+ objfile->all_symtabs_expanded = true;
- sal = find_pc_line(pc, 0);
- }
- }
-@@ -7761,8 +7765,10 @@ iterate_datatypes (struct gnu_request *req)
- {
- for (objfile *objfile : current_program_space->objfiles ())
- {
-- if (objfile->sf)
-+ if (objfile->sf) {
- objfile->sf->qf->expand_all_symtabs(objfile);
-+ objfile->all_symtabs_expanded = true;
-+ }
-
- for (compunit_symtab *cust : objfile->compunits ())
- {
---- gdb-10.2/gdb/minsyms.c.orig
-+++ gdb-10.2/gdb/minsyms.c
-@@ -535,7 +535,9 @@ lookup_minimal_symbol_linkage (const char *name, struct objfile
*objf)
- {
- if (strcmp (msymbol->linkage_name (), name) == 0
- && (MSYMBOL_TYPE (msymbol) == mst_data
-- || MSYMBOL_TYPE (msymbol) == mst_bss))
-+ || MSYMBOL_TYPE (msymbol) == mst_bss
-+ || MSYMBOL_TYPE (msymbol) == mst_file_bss
-+ || MSYMBOL_TYPE (msymbol) == mst_file_data))
- return {msymbol, objfile};
- }
- }
---- gdb-10.2/gdb/symtab.h.orig
-+++ gdb-10.2/gdb/symtab.h
-@@ -1110,7 +1110,7 @@ struct symbol : public general_symbol_info, public
allocate_on_obstack
- is_objfile_owned (1),
- is_argument (0),
- is_inlined (0),
-- maybe_copied (0),
-+ maybe_copied (1), /* The objfile potentially supports copy relocations. */
- subclass (SYMBOL_NONE)
- {
- /* We can't use an initializer list for members of a base class, and
---- gdb-10.2/gdb/ui-file.h.orig
-+++ gdb-10.2/gdb/ui-file.h
-@@ -195,6 +195,7 @@ public:
-
- bool can_emit_style_escape () override;
-
-+ FILE *get_stream(void);
- /* Sets the internal stream to FILE, and saves the FILE's file
- descriptor in M_FD. */
- void set_stream (FILE *file);
---- gdb-10.2/gdb/ui-file.c.orig
-+++ gdb-10.2/gdb/ui-file.c
-@@ -161,6 +161,12 @@ stdio_file::~stdio_file ()
- fclose (m_file);
- }
-
-+FILE*
-+stdio_file::get_stream(void)
-+{
-+ return m_file;
-+}
-+
- void
- stdio_file::set_stream (FILE *file)
- {
---- gdb-10.2/gdb/symtab.c.orig
-+++ gdb-10.2/gdb/symtab.c
-@@ -6964,8 +6964,12 @@ void
- gdb_command_funnel_1(struct gnu_request *req)
- {
- struct symbol *sym;
-+ FILE *original_stdout_stream = nullptr;
-+ FILE *original_stderr_stream = nullptr;
-
- if (req->command != GNU_VERSION && req->command !=
GNU_USER_PRINT_OPTION) {
-+ original_stdout_stream = (dynamic_cast< stdio_file *
>gdb_stdout)->get_stream();
-+ original_stderr_stream = (dynamic_cast< stdio_file *
>gdb_stderr)->get_stream();
- (dynamic_cast<stdio_file
*>gdb_stdout)->set_stream(req->fp);
- (dynamic_cast<stdio_file
*>gdb_stderr)->set_stream(req->fp);
- }
-@@ -7068,6 +7072,12 @@ gdb_command_funnel_1(struct gnu_request *req)
- req->flags |= GNU_COMMAND_FAILED;
- break;
- }
-+
-+ /* Restore the streams gdb output was using */
-+ if (original_stdout_stream)
-+ (dynamic_cast<stdio_file
*>gdb_stdout)->set_stream(original_stdout_stream);
-+ if (original_stderr_stream)
-+ (dynamic_cast<stdio_file
*>gdb_stderr)->set_stream(original_stderr_stream);
- }
-
- /*
---- gdb-10.2/gdb/stack.c.orig
-+++ gdb-10.2/gdb/stack.c
-@@ -1990,6 +1990,11 @@
- /* Print briefly all stack frames or just the innermost COUNT_EXP
- frames. */
-
-+#ifdef CRASH_MERGE
-+extern "C" int is_kvaddr(ulong);
-+extern "C" int gdb_CRASHDEBUG(ulong);
-+#endif
-+
- static void
- backtrace_command_1 (const frame_print_options &fp_opts,
- const backtrace_cmd_options &bt_opts,
-@@ -2082,6 +2086,17 @@
- hand, perhaps the code does or could be fixed to make sure
- the frame->prev field gets set to NULL in that case). */
-
-+#ifdef CRASH_MERGE
-+ CORE_ADDR pc = 0;
-+ get_frame_pc_if_available (fi, &pc);
-+ if (!is_kvaddr(pc)) {
-+ if (gdb_CRASHDEBUG(1)) {
-+ printf_filtered (_("Backtrace stopped: due to non-kernel addr:
0x%lx\n"),pc);
-+ }
-+ fi = NULL;
-+ break;
-+ }
-+#endif
- print_frame_info (fp_opts, fi, 1, LOCATION, 1, 0);
- if ((flags & PRINT_LOCALS) != 0)
- {
---- gdb-10.2/gdb/stack.c.orig
-+++ gdb-10.2/gdb/stack.c
-@@ -2127,7 +2127,7 @@
- enum unwind_stop_reason reason;
-
- reason = get_frame_unwind_stop_reason (trailing);
-- if (reason >= UNWIND_FIRST_ERROR)
-+ if (reason >= UNWIND_FIRST_ERROR && gdb_CRASHDEBUG(1))
- printf_filtered (_("Backtrace stopped: %s\n"),
- frame_stop_reason_string (trailing));
- }
---- gdb-10.2/gdb/frame.c.orig
-+++ gdb-10.2/gdb/frame.c
-@@ -944,6 +944,10 @@ frame_find_by_id (struct frame_id id)
- return NULL;
- }
-
-+#if defined(CRASH_MERGE) && defined(ARM64)
-+extern "C" void crash_decode_ptrauth_pc(ulong* pc);
-+#endif
-+
- static CORE_ADDR
- frame_unwind_pc (struct frame_info *this_frame)
- {
-@@ -974,6 +978,9 @@ frame_unwind_pc (struct frame_info *this_frame)
- try
- {
- pc = gdbarch_unwind_pc (prev_gdbarch, this_frame);
-+#if defined(CRASH_MERGE) && defined(ARM64)
-+ crash_decode_ptrauth_pc(&pc);
-+#endif
- pc_p = true;
- }
- catch (const gdb_exception_error &ex)
---- gdb-10.2/readline/readline/signals.c.orig
-+++ gdb-10.2/readline/readline/signals.c
-@@ -48,23 +48,11 @@
-
- #if defined (HANDLE_SIGNALS)
-
--#if !defined (RETSIGTYPE)
--# if defined (VOID_SIGHANDLER)
--# define RETSIGTYPE void
--# else
--# define RETSIGTYPE int
--# endif /* !VOID_SIGHANDLER */
--#endif /* !RETSIGTYPE */
--
--#if defined (VOID_SIGHANDLER)
--# define SIGHANDLER_RETURN return
--#else
--# define SIGHANDLER_RETURN return (0)
--#endif
-+#define SIGHANDLER_RETURN return
-
- /* This typedef is equivalent to the one for Function; it allows us
- to say SigHandler *foo = signal (SIGKILL, SIG_IGN); */
--typedef RETSIGTYPE SigHandler ();
-+typedef void SigHandler (int);
-
- #if defined (HAVE_POSIX_SIGNALS)
- typedef struct sigaction sighandler_cxt;
-@@ -78,12 +66,12 @@ typedef struct { SigHandler *sa_handler; int sa_mask, sa_flags; }
sighandler_cxt
- # define SA_RESTART 0
- #endif
-
--static SigHandler *rl_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *));
--static void rl_maybe_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *));
--static void rl_maybe_restore_sighandler PARAMS((int, sighandler_cxt *));
-+static SigHandler *rl_set_sighandler (int, SigHandler *, sighandler_cxt *);
-+static void rl_maybe_set_sighandler (int, SigHandler *, sighandler_cxt *);
-+static void rl_maybe_restore_sighandler (int, sighandler_cxt *);
-
--static RETSIGTYPE rl_signal_handler PARAMS((int));
--static RETSIGTYPE _rl_handle_signal PARAMS((int));
-+static void rl_signal_handler (int);
-+static void _rl_handle_signal (int);
-
- /* Exported variables for use by applications. */
-
-@@ -137,7 +125,7 @@ void *_rl_sigcleanarg;
- /* Readline signal handler functions. */
-
- /* Called from RL_CHECK_SIGNALS() macro */
--RETSIGTYPE
-+void
- _rl_signal_handler (int sig)
- {
- _rl_caught_signal = 0; /* XXX */
-@@ -160,7 +148,7 @@ _rl_signal_handler (int sig)
- SIGHANDLER_RETURN;
- }
-
--static RETSIGTYPE
-+static void
- rl_signal_handler (int sig)
- {
- if (_rl_interrupt_immediately)
-@@ -174,7 +162,7 @@ rl_signal_handler (int sig)
- SIGHANDLER_RETURN;
- }
-
--static RETSIGTYPE
-+static void
- _rl_handle_signal (int sig)
- {
- #if defined (HAVE_POSIX_SIGNALS)
-@@ -291,7 +279,7 @@ _rl_handle_signal (int sig)
- }
-
- #if defined (SIGWINCH)
--static RETSIGTYPE
-+static void
- rl_sigwinch_handler (int sig)
- {
- SigHandler *oh;
diff --git a/gdb-16.2.patch b/gdb-16.2.patch
new file mode 100644
index 0000000..05aa77a
--- /dev/null
+++ b/gdb-16.2.patch
@@ -0,0 +1,2254 @@
+
+# When this file is updated in an existing source tree, it gets re-applied
+# during the next build using "patch -N --fuzz=0", which ignores patches
+# that have already been applied. However, if a gdb file has been modified
+# multiple times, the subsequent patching may fail to recognize that a
+# given patch has been previously applied, and will attempt to re-apply it.
+# To prevent any unintended consequences, this file also acts as a
+# shell script that can restore any gdb file to its original state prior
+# to all subsequent patch applications.
+
+tar xvzmf gdb-16.2.tar.gz \
+ gdb-16.2/gdb/symtab.c \
+ gdb-16.2/gdb/printcmd.c \
+ gdb-16.2/gdb/symfile.c \
+ gdb-16.2/gdb/Makefile.in \
+ gdb-16.2/gdb/dwarf2/read.c \
+ gdb-16.2/gdb/ada-lang.c \
+ gdb-16.2/gdb/stack.c \
+ gdb-16.2/gdb/ui-file.h
+
+exit 0
+
+--- gdb-16.2/Makefile.in.orig
++++ gdb-16.2/Makefile.in
+@@ -369,6 +369,9 @@ CC_FOR_BUILD = @CC_FOR_BUILD@
+ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@
+ CPP_FOR_BUILD = @CPP_FOR_BUILD@
+ CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@
++ifeq (${CRASH_TARGET}, PPC64)
++CFLAGS_FOR_BUILD += -m64 -fPIC
++endif
+ CXXFLAGS_FOR_BUILD = @CXXFLAGS_FOR_BUILD@
+ CXX_FOR_BUILD = @CXX_FOR_BUILD@
+ DLLTOOL_FOR_BUILD = @DLLTOOL_FOR_BUILD@
+@@ -441,6 +444,9 @@ GNATBIND = @GNATBIND@
+ GNATMAKE = @GNATMAKE@
+
+ CFLAGS = @CFLAGS@
++ifeq (${CRASH_TARGET}, PPC64)
++CFLAGS += -m64 -fPIC
++endif
+ LDFLAGS = @LDFLAGS@
+ LIBCFLAGS = $(CFLAGS)
+ CXXFLAGS = @CXXFLAGS@
+--- gdb-16.2/gdb/Makefile.in.orig
++++ gdb-16.2/gdb/Makefile.in
+@@ -603,7 +603,7 @@
+ # It is also possible that you will need to add -I/usr/include/sys if
+ # your system doesn't have fcntl.h in /usr/include (which is where it
+ # should be according to Posix).
+-DEFS = @DEFS@
++DEFS = -DCRASH_MERGE -D${CRASH_TARGET} @DEFS@
+ GDB_INCLUDED_HEADER = -include $(srcdir)/defs.h
+ GDB_CFLAGS = \
+ -I. \
+@@ -1220,6 +1220,7 @@ COMMON_SFILES = \
+ symmisc.c \
+ symtab.c \
+ target.c \
++ ../../crash_target.c \
+ target-connection.c \
+ target-dcache.c \
+ target-descriptions.c \
+@@ -1906,7 +1907,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
+ $(SUBDIR_TARGET_OBS) \
+ $(SUBDIR_GCC_COMPILE_OBS)
+
+-SUBDIRS = doc @subdirs@ data-directory
++SUBDIRS = build_no_subdirs
+ CLEANDIRS = $(SUBDIRS)
+
+ # List of subdirectories in the build tree that must exist.
+@@ -1947,8 +1948,8 @@
+ # Flags needed to compile Python code
+ PYTHON_CFLAGS = @PYTHON_CFLAGS@
+
+-all: gdb$(EXEEXT) $(CONFIG_ALL) gdb-gdb.py gdb-gdb.gdb gcore gstack
+- @$(MAKE) $(FLAGS_TO_PASS) DO=all "DODIRS=$(SUBDIRS)" subdir_do
++all: gdb$(EXEEXT) gdb-gdb.py gdb-gdb.gdb gcore gstack
++ @$(MAKE) -s $(FLAGS_TO_PASS) DO=all "DODIRS=$(SUBDIRS)" subdir_do
+
+ # Rule for compiling .c files in the top-level gdb directory.
+ # The order-only dependencies ensure that we create the build subdirectories.
+@@ -2230,9 +2231,10 @@ libgdb.a: $(LIBGDB_OBS)
+ # Removing the old gdb first works better if it is running, at least on SunOS.
+ gdb$(EXEEXT): gdb.o $(LIBGDB_OBS) $(CDEPS) $(TDEPLIBS)
+ $(SILENCE) rm -f gdb$(EXEEXT)
++ @(cd ../..; make --no-print-directory GDB_FLAGS=-DGDB_16_2 library)
+ $(ECHO_CXXLD) $(CC_LD) $(INTERNAL_LDFLAGS) $(WIN32LDAPP) \
+- -o gdb$(EXEEXT) gdb.o $(LIBGDB_OBS) \
+- $(TDEPLIBS) $(TUI_LIBRARY) $(CLIBS) $(LOADLIBES)
++ -o $(shell /bin/cat mergeobj) $(LIBGDB_OBS) \
++ $(TDEPLIBS) $(TUI_LIBRARY) $(CLIBS) $(LOADLIBES) $(shell /bin/cat
mergelibs)
+ ifneq ($(CODESIGN_CERT),)
+ $(ECHO_SIGN) $(CODESIGN) -s $(CODESIGN_CERT) gdb$(EXEEXT)
+ endif
+@@ -2699,9 +2701,9 @@ ifeq ($(DEPMODE),depmode=gcc3)
+ # into place if the compile succeeds. We need this because gcc does
+ # not atomically write the dependency output file.
+ override COMPILE.post = -c -o $@ -MT $@ -MMD -MP \
+- -MF $(@D)/$(DEPDIR)/$(basename $((a)F)).Tpo
+-override POSTCOMPILE = @mv $(@D)/$(DEPDIR)/$(basename $((a)F)).Tpo \
+- $(@D)/$(DEPDIR)/$(basename $((a)F)).Po
++ -MF $(subst ../..,.,$(@D))/$(DEPDIR)/$(basename $((a)F)).Tpo
++override POSTCOMPILE = @mv $(subst ../..,.,$(@D))/$(DEPDIR)/$(basename $((a)F)).Tpo \
++ $(subst ../..,.,$(@D))/$(DEPDIR)/$(basename $((a)F)).Po
+ else
+ override COMPILE.pre = source='$<' object='$@' libtool=no \
+ DEPDIR=$(DEPDIR) $(DEPMODE) $(depcomp) \
+--- gdb-16.2/gdb/cli/cli-cmds.c.orig
++++ gdb-16.2/gdb/cli/cli-cmds.c
+@@ -427,6 +427,11 @@ complete_command (const char *arg, int from_tty)
+ }
+ }
+
++#ifdef CRASH_MERGE
++static int crash_from_tty = 0;
++extern "C" void untrusted_file(FILE *, char *);
++#endif
++
+ int
+ is_complete_command (struct cmd_list_element *c)
+ {
+@@ -659,8 +664,32 @@ find_and_open_script (const char *script_file, int search_path)
+ close (fd);
+ errno = save_errno;
+ }
+- else
+- opened.emplace (gdb_file_up (result), std::move (full_path));
++#ifdef CRASH_MERGE
++ /*
++ * Only allow trusted versions of .gdbinit files to be
++ * sourced during session initialization.
++ */
++ if (crash_from_tty == -1)
++ {
++ struct stat statbuf;
++ FILE *stream = result;
++ int _fd = fileno (stream);
++ if (fstat (_fd, &statbuf) < 0)
++ {
++ perror_with_name (full_path.get());
++ fclose (stream);
++ return opened;
++ }
++ if (statbuf.st_uid != getuid () || (statbuf.st_mode & S_IWOTH))
++ {
++ untrusted_file(NULL, full_path.get());
++ fclose (stream);
++ return opened;
++ }
++ }
++#endif
++ opened.emplace (gdb_file_up (result), std::move (full_path));
++
+
+ return opened;
+ }
+@@ -724,7 +753,11 @@ source_script_with_search (const char *file, int from_tty, int
search_path)
+ If the source command was invoked interactively, throw an
+ error. Otherwise (e.g. if it was invoked by a script),
+ just emit a warning, rather than cause an error. */
++#ifdef CRASH_MERGE
++ if (from_tty > 0)
++#else
+ if (from_tty)
++#endif
+ perror_with_name (file);
+ else
+ {
+@@ -756,7 +789,14 @@ source_script_with_search (const char *file, int from_tty, int
search_path)
+ void
+ source_script (const char *file, int from_tty)
+ {
++#ifdef CRASH_MERGE
++ crash_from_tty = from_tty;
++#endif
+ source_script_with_search (file, from_tty, 0);
++#ifdef CRASH_MERGE
++ crash_from_tty = 0;
++#endif
++
+ }
+
+ static void
+--- gdb-16.2/gdb/defs.h.orig
++++ gdb-16.2/gdb/defs.h
+@@ -407,4 +407,7 @@ DEF_ENUM_FLAGS_TYPE (enum user_selected_what_flag,
user_selected_what);
+
+ #include "utils.h"
+
++#ifdef CRASH_MERGE
++extern "C" int gdb_main_entry(int, char **);
++#endif
+ #endif /* GDB_DEFS_H */
+--- gdb-16.2/gdb/dwarf2/read-gdb-index.c.orig
++++ gdb-16.2/gdb/dwarf2/read-gdb-index.c
+@@ -369,7 +369,11 @@ read_gdb_index_from_buffer (const char *filename,
+ indices. */
+ if (version < 4)
+ {
++#ifdef CRASH_MERGE
++ static int warning_printed = 1;
++#else
+ static int warning_printed = 0;
++#endif
+ if (!warning_printed)
+ {
+ warning (_("Skipping obsolete .gdb_index section in %s."),
+@@ -388,7 +392,11 @@ read_gdb_index_from_buffer (const char *filename,
+ "set use-deprecated-index-sections on". */
+ if (version < 6 && !deprecated_ok)
+ {
++#ifdef CRASH_MERGE
++ static int warning_printed = 1;
++#else
+ static int warning_printed = 0;
++#endif
+ if (!warning_printed)
+ {
+ warning (_("\
+--- gdb-16.2/gdb/main.c.orig
++++ gdb-16.2/gdb/main.c
+@@ -442,6 +442,14 @@ start_event_loop ()
+ return;
+ }
+
++#ifdef CRASH_MERGE
++extern "C" void update_gdb_hooks(void);
++extern "C" void main_loop(void);
++extern "C" unsigned long crash_get_kaslr_offset(void);
++extern "C" int console(const char *, ...);
++void crash_target_init (void);
++#endif
++
+ /* Call command_loop. */
+
+ /* Prevent inlining this function for the benefit of GDB's selftests
+@@ -1031,7 +1039,11 @@ captured_main_1 (struct captured_main_args *context)
+ }
+ }
+
++#ifdef CRASH_MERGE
++ save_original_signals_state (1);
++#else
+ save_original_signals_state (quiet);
++#endif
+
+ /* Try to set up an alternate signal stack for SIGSEGV handlers. */
+ gdb::alternate_signal_stack signal_stack;
+@@ -1129,7 +1141,7 @@ captured_main_1 (struct captured_main_args *context)
+ if (print_version)
+ {
+ print_gdb_version (gdb_stdout, false);
+- gdb_printf ("\n");
++ gdb_printf ("\n\n");
+ exit (0);
+ }
+
+@@ -1150,6 +1162,10 @@ captured_main_1 (struct captured_main_args *context)
+ look at things by now. Initialize the default interpreter. */
+ set_top_level_interpreter (interpreter_p.c_str (), false);
+
++#ifdef CRASH_MERGE
++ update_gdb_hooks();
++#endif
++
+ /* The interpreter should have installed the real uiout by now. */
+ gdb_assert (current_uiout != temp_uiout.get ());
+ temp_uiout = nullptr;
+@@ -1177,7 +1193,11 @@ captured_main_1 (struct captured_main_args *context)
+ if (!system_gdbinit.empty () && !inhibit_gdbinit)
+ {
+ for (const std::string &file : system_gdbinit)
++#ifdef CRASH_MERGE
++ ret = catch_command_errors (source_script, file.c_str (), -1);
++#else
+ ret = catch_command_errors (source_script, file.c_str (), 0);
++#endif
+ }
+
+ /* Read and execute $HOME/.gdbinit file, if it exists. This is done
+@@ -1186,7 +1206,11 @@ captured_main_1 (struct captured_main_args *context)
+ debugging or what directory you are in. */
+
+ if (!home_gdbinit.empty () && !inhibit_gdbinit &&
!inhibit_home_gdbinit)
++#ifdef CRASH_MERGE
++ ret = catch_command_errors (source_script, home_gdbinit.c_str (), -1);
++#else
+ ret = catch_command_errors (source_script, home_gdbinit.c_str (), 0);
++#endif
+
+ /* Process '-ix' and '-iex' options early. */
+ execute_cmdargs (&cmdarg_vec, CMDARG_INIT_FILE, CMDARG_INIT_COMMAND, &ret);
+@@ -1217,7 +1241,11 @@ captured_main_1 (struct captured_main_args *context)
+ !batch_flag);
+ if (ret != 0)
+ ret = catch_command_errors (symbol_file_add_main_adapter,
++#ifdef CRASH_MERGE
++ symarg, 0);
++#else
+ symarg, !batch_flag);
++#endif
+ }
+ else
+ {
+@@ -1291,7 +1319,11 @@ captured_main_1 (struct captured_main_args *context)
+ {
+ auto_load_local_gdbinit_loaded = 1;
+
++#ifdef CRASH_MERGE
++ ret = catch_command_errors (source_script, local_gdbinit.c_str (), -1);
++#else
+ ret = catch_command_errors (source_script, local_gdbinit.c_str (), 0);
++#endif
+ }
+ }
+ }
+@@ -1332,6 +1364,16 @@ captured_main (void *data)
+
+ captured_main_1 (context);
+
++#ifdef CRASH_MERGE
++ /* Relocate the vmlinux. */
++ objfile_rebase (current_program_space->symfile_object_file,
crash_get_kaslr_offset());
++
++ crash_target_init();
++
++ /* Back to crash. */
++ main_loop();
++#endif
++
+ /* NOTE: cagney/1999-11-07: There is probably no reason for not
+ moving this loop and the code found in captured_command_loop()
+ into the command_loop() proper. The main thing holding back that
+@@ -1350,6 +1392,9 @@ captured_main (void *data)
+ {
+ exception_print (gdb_stderr, ex);
+ }
++#ifdef CRASH_MERGE
++ console("<CAPTURED_MAIN WHILE LOOP>\n");
++#endif
+ }
+ /* No exit -- exit is through quit_command. */
+ }
+@@ -1371,6 +1416,24 @@ gdb_main (struct captured_main_args *args)
+ return 1;
+ }
+
++#ifdef CRASH_MERGE
++/*
++ * NOTE: adapted from gdb.c, which is no longer built in; changed name of
++ * original main() to gdb_main_entry() for use as crash entry point
++ */
++extern bool is_main_thread ();
++int
++gdb_main_entry (int argc, char **argv)
++{
++ struct captured_main_args args;
++ gdb_assert (is_main_thread ());
++ memset (&args, 0, sizeof args);
++ args.argc = argc;
++ args.argv = argv;
++ args.interpreter_p = INTERP_CONSOLE;
++ return gdb_main (&args);
++}
++#endif
+
+ /* Don't use *_filtered for printing help. We don't want to prompt
+ for continue no matter how small the screen or how much we're going
+--- gdb-16.2/gdb/objfiles.h.orig
++++ gdb-16.2/gdb/objfiles.h
+@@ -951,11 +951,11 @@ extern bool objfile_has_symbols (objfile *objfile);
+
+ /* Return true if any objfile of PSPACE has partial symbols. */
+
+-extern bool have_partial_symbols (program_space *pspace);
++extern "C" bool have_partial_symbols (program_space *pspace);
+
+ /* Return true if any objfile of PSPACE has full symbols. */
+
+-extern bool have_full_symbols (program_space *pspace);
++extern "C" bool have_full_symbols (program_space *pspace);
+
+ extern void objfile_set_sym_fns (struct objfile *objfile,
+ const struct sym_fns *sf);
+--- gdb-16.2/gdb/printcmd.c.orig
++++ gdb-16.2/gdb/printcmd.c
+@@ -552,6 +552,9 @@ set_next_address (struct gdbarch *gdbarch, CORE_ADDR addr)
+ form. However note that DO_DEMANGLE can be overridden by the specific
+ settings of the demangle and asm_demangle variables. Returns
+ non-zero if anything was printed; zero otherwise. */
++#ifdef CRASH_MERGE
++extern "C" int gdb_print_callback(unsigned long);
++#endif
+
+ int
+ print_address_symbolic (struct gdbarch *gdbarch, CORE_ADDR addr,
+@@ -563,6 +566,12 @@ print_address_symbolic (struct gdbarch *gdbarch, CORE_ADDR addr,
+ int offset = 0;
+ int line = 0;
+
++#ifdef CRASH_MERGE
++ if (!gdb_print_callback(addr)) {
++ return 0;
++ }
++#endif
++
+ if (build_address_symbolic (gdbarch, addr, do_demangle, false, &name,
+ &offset, &filename, &line, &unmapped))
+ return 0;
+@@ -1242,6 +1251,43 @@ print_command_parse_format (const char **expp, const char
*cmdname,
+ *expp = exp;
+ }
+
++static void
++print_command_2 (const char *args, int voidprint)
++{
++ struct value *val;
++ value_print_options print_opts;
++
++ get_user_print_options (&print_opts);
++ /* Override global settings with explicit options, if any. */
++ auto group = make_value_print_options_def_group (&print_opts);
++ gdb::option::process_options
++ (&args, gdb::option::PROCESS_OPTIONS_REQUIRE_DELIMITER, group);
++
++ print_command_parse_format (&args, "print", &print_opts);
++
++ const char *exp = args;
++
++ if (exp != nullptr && *exp)
++ {
++ expression_up expr = parse_expression (exp);
++ val = expr->evaluate ();
++ }
++ else
++ val = access_value_history (0);
++
++ gdb_printf("%d %d %ld %ld %ld %ld\n",
++ check_typedef(val->type ())->code(),
++ check_typedef(val->type ())->is_unsigned(),
++ check_typedef(val->type ())->length(),
++ val->offset(), val->bitpos(), val->bitsize());
++}
++
++static void
++printm_command (const char *exp, int from_tty)
++{
++ print_command_2 (exp, 1);
++}
++
+ /* See valprint.h. */
+
+ void
+@@ -3357,6 +3403,12 @@ but no count or size letter (see \"x\"
command)."),
+ = add_com ("print", class_vars, print_command, print_help.c_str ());
+ set_cmd_completer_handle_brkchars (print_cmd, print_command_completer);
+ add_com_alias ("p", print_cmd, class_vars, 1);
++
++ c = add_com ("printm", class_vars, printm_command, _("\
++Similar to \"print\" command, but it used to print the type, size, offset,\n\
++bitpos and bitsize of the expression EXP."));
++ set_cmd_completer (c, expression_completer);
++
+ add_com_alias ("inspect", print_cmd, class_vars, 1);
+
+ add_setshow_uinteger_cmd ("max-symbolic-offset", no_class,
+--- gdb-16.2/gdb/psymtab.c.orig
++++ gdb-16.2/gdb/psymtab.c
+@@ -80,6 +80,9 @@ psymbol_functions::partial_symbols (struct objfile *objfile)
+ return m_partial_symtabs->range ();
+ }
+
++#ifdef CRASH_MERGE
++ extern "C" int gdb_line_number_callback(unsigned long, unsigned long,
unsigned long);
++#endif
+ /* Find which partial symtab contains PC and SECTION starting at psymtab PST.
+ We may find a different psymtab than PST. See FIND_PC_SECT_PSYMTAB. */
+
+@@ -170,7 +173,12 @@ psymbol_functions::find_pc_sect_psymtab (struct objfile *objfile,
+
+ best_pst = find_pc_sect_psymtab_closer (objfile, pc, section, pst,
+ msymbol);
++#ifdef CRASH_MERGE
++ if ((best_pst != NULL) &&
++ gdb_line_number_callback(pc, pst->text_low (objfile), pst->text_high
(objfile)))
++#else
+ if (best_pst != NULL)
++#endif
+ return best_pst;
+ }
+
+--- gdb-16.2/gdb/symfile.c.orig
++++ gdb-16.2/gdb/symfile.c
+@@ -633,7 +633,26 @@ default_symfile_offsets (struct objfile *objfile,
+ for (cur_sec = abfd->sections; cur_sec != NULL; cur_sec = cur_sec->next)
+ /* We do not expect this to happen; just skip this step if the
+ relocatable file has a section with an assigned VMA. */
+- if (bfd_section_vma (cur_sec) != 0)
++ if (bfd_section_vma (cur_sec) != 0
++ /*
++ * Kernel modules may have some non-zero VMAs, i.e., like the
++ * __ksymtab and __ksymtab_gpl sections in this example:
++ *
++ * Section Headers:
++ * [Nr] Name Type Address Offset
++ * Size EntSize Flags Link Info Align
++ * ...
++ * [ 8] __ksymtab PROGBITS 0000000000000060 0000ad90
++ * 0000000000000010 0000000000000000 A 0 0 16
++ * [ 9] .rela__ksymtab RELA 0000000000000000 0000ada0
++ * 0000000000000030 0000000000000018 43 8 8
++ * [10] __ksymtab_gpl PROGBITS 0000000000000070 0000add0
++ * 00000000000001a0 0000000000000000 A 0 0 16
++ * ...
++ *
++ * but they should be treated as if they are NULL.
++ */
++ && strncmp (bfd_section_name (cur_sec), "__k", 3) != 0)
+ break;
+
+ if (cur_sec == NULL)
+@@ -1069,6 +1088,12 @@
+
+ objfile *objfile
+ = objfile::make (abfd, current_program_space, name, flags, parent);
++#ifdef CRASH_MERGE
++ if (add_flags & SYMFILE_MAINLINE) {
++ extern struct objfile *gdb_kernel_objfile;
++ gdb_kernel_objfile = objfile;
++ }
++#endif
+
+ /* We either created a new mapped symbol table, mapped an existing
+ symbol table file which has not had initial symbol reading
+@@ -1352,6 +1377,10 @@ show_debug_file_directory (struct ui_file *file, int from_tty,
+ #if ! defined (DEBUG_SUBDIRECTORY)
+ #define DEBUG_SUBDIRECTORY ".debug"
+ #endif
++#ifdef CRASH_MERGE
++extern "C" int check_specified_module_tree(const char *, const char *);
++extern "C" char *check_specified_kernel_debug_file();
++#endif
+
+ /* Find a separate debuginfo file for OBJFILE, using DIR as the directory
+ where the original file resides (may not be the same as
+@@ -1390,6 +1419,15 @@ find_separate_debug_file (const char *dir,
+ if (separate_debug_file_exists (debugfile, crc32, objfile, warnings))
+ return debugfile;
+
++#ifdef CRASH_MERGE
++{
++ if (check_specified_module_tree(objfile_name (objfile), debugfile.c_str()) &&
++ separate_debug_file_exists(debugfile, crc32, objfile, warnings)) {
++ return debugfile;
++ }
++}
++#endif
++
+ /* Then try in the global debugfile directories.
+
+ Keep backward compatibility so that DEBUG_FILE_DIRECTORY being "" will
+@@ -1545,6 +1583,14 @@ find_separate_debug_file_by_debuglink
+ }
+ }
+
++#ifdef CRASH_MERGE
++ if (debugfile.empty ()) {
++ char *name_copy;
++ name_copy = check_specified_kernel_debug_file();
++ return std::string (name_copy);
++ }
++#endif
++
+ return debugfile;
+ }
+
+@@ -2318,8 +2364,10 @@ add_symbol_file_command (const char *args, int from_tty)
+ else if (section_addrs.empty ())
+ gdb_printf ("\n");
+
++#ifndef CRASH_MERGE
+ if (from_tty && (!query ("%s", "")))
+ error (_("Not confirmed."));
++#endif
+
+ objf = symbol_file_add (filename.get (), add_flags, §ion_addrs,
+ flags);
+@@ -3638,6 +3638,15 @@ bfd_byte *
+ symfile_relocate_debug_section (struct objfile *objfile,
+ asection *sectp, bfd_byte *buf)
+ {
++#ifdef CRASH_MERGE
++ /* Executable files have all the relocations already resolved.
++ * Handle files linked with --emit-relocs.
++ *
http://sources.redhat.com/ml/gdb/2006-08/msg00137.html
++ */
++ bfd *abfd = objfile->obfd.get();
++ if ((abfd->flags & EXEC_P) != 0)
++ return NULL;
++#endif
+ gdb_assert (objfile->sf->sym_relocate);
+
+ return (*objfile->sf->sym_relocate) (objfile, sectp, buf);
+--- gdb-16.2/gdb/symtab.c.orig
++++ gdb-16.2/gdb/symtab.c
+@@ -2012,6 +2012,10 @@ search_name_hash (enum language language, const char
*search_name)
+ variable and thus can probably assume it will never hit the C++
+ code). */
+
++#ifdef CRASH_MERGE
++static void gdb_bait_and_switch(char *, struct symbol *);
++#endif
++
+ struct block_symbol
+ lookup_symbol_in_language (const char *name, const struct block *block,
+ const domain_search_flags domain,
+@@ -2020,22 +2024,37 @@ lookup_symbol_in_language (const char *name, const struct block
*block,
+ {
+ SYMBOL_LOOKUP_SCOPED_DEBUG_ENTER_EXIT;
+
++ struct block_symbol result;
+ demangle_result_storage storage;
+ const char *modified_name = demangle_for_lookup (name, lang, storage);
+
+- return lookup_symbol_aux (modified_name,
++ result = lookup_symbol_aux (modified_name,
+ symbol_name_match_type::FULL,
+ block, domain, lang,
+ is_a_field_of_this);
++#ifdef CRASH_MERGE
++ if (result.symbol && (domain & SEARCH_TYPE_DOMAIN))
++ gdb_bait_and_switch((char *)modified_name, result.symbol);
++#endif
++ return result;
+ }
+
+ /* See symtab.h. */
+
++#ifdef CRASH_MERGE
++static const struct block *gdb_get_crash_block(void);
++#endif
++
+ struct block_symbol
+ lookup_symbol (const char *name, const struct block *block,
+ domain_search_flags domain,
+ struct field_of_this_result *is_a_field_of_this)
+ {
++#ifdef CRASH_MERGE
++ if (!block)
++ block = gdb_get_crash_block();
++#endif
++
+ return lookup_symbol_in_language (name, block, domain,
+ current_language->la_language,
+ is_a_field_of_this);
+@@ -7320,3 +7339,805 @@ the use of prologue scanners."),
+ "symtab");
+ gdb::observers::free_objfile.attach (symtab_free_objfile_observer,
"symtab");
+ }
++
++#ifdef CRASH_MERGE
++#include "gdb-stabs.h"
++#include "gdbsupport/version.h"
++#define GDB_COMMON
++#include "../../defs.h"
++
++static void get_member_data(struct gnu_request *, struct type *, long, int);
++static void dump_enum(struct type *, struct gnu_request *);
++static void eval_enum(struct type *, struct gnu_request *);
++static void gdb_get_line_number(struct gnu_request *);
++static void gdb_get_datatype(struct gnu_request *);
++static void gdb_get_symbol_type(struct gnu_request *);
++static void gdb_command_exists(struct gnu_request *);
++static void gdb_debug_command(struct gnu_request *);
++static void gdb_function_numargs(struct gnu_request *);
++static void gdb_add_symbol_file(struct gnu_request *);
++static void gdb_delete_symbol_file(struct gnu_request *);
++static void gdb_patch_symbol_values(struct gnu_request *);
++static void get_user_print_option_address(struct gnu_request *);
++extern int get_frame_offset(CORE_ADDR);
++static void gdb_set_crash_block(struct gnu_request *);
++extern "C" void gdb_command_funnel(struct gnu_request *);
++void gdb_command_funnel_1(struct gnu_request *);
++static long lookup_struct_contents(struct gnu_request *);
++static void iterate_datatypes(struct gnu_request *);
++extern void execute_command (const char *, int);
++
++struct objfile *gdb_kernel_objfile = { 0 };
++
++static ulong gdb_merge_flags = 0;
++#define KERNEL_SYMBOLS_PATCHED (0x1)
++
++#undef STREQ
++#define STREQ(A, B) (A && B && (strcmp(A, B) == 0))
++#define TYPE_CODE(t) (t->code ())
++#define TYPE_TAG_NAME(t) (TYPE_MAIN_TYPE(t)->name)
++#define TYPE_NFIELDS(t) (t->num_fields ())
++#define TYPE_NAME(t) (t->name ())
++
++/*
++ * All commands from above come through here.
++ */
++void
++gdb_command_funnel(struct gnu_request *req)
++{
++ try {
++ gdb_command_funnel_1(req);
++ } catch (const gdb_exception &ex) {
++ if (req->flags & GNU_RETURN_ON_ERROR)
++ req->flags |= GNU_COMMAND_FAILED;
++ else
++ throw ex;
++ }
++}
++
++void
++gdb_command_funnel_1(struct gnu_request *req)
++{
++ struct symbol *sym;
++
++ if (req->command != GNU_VERSION && req->command !=
GNU_USER_PRINT_OPTION) {
++ (dynamic_cast<stdio_file
*>gdb_stdout)->set_stream(req->fp);
++ (dynamic_cast<stdio_file
*>gdb_stderr)->set_stream(req->fp);
++ }
++
++ switch (req->command)
++ {
++ case GNU_VERSION:
++ req->buf = (char *)version;
++ break;
++
++ case GNU_PASS_THROUGH:
++ execute_command(req->buf,
++ req->flags & GNU_FROM_TTY_OFF ? FALSE : TRUE);
++ break;
++
++ case GNU_USER_PRINT_OPTION:
++ get_user_print_option_address(req);
++ break;
++
++ case GNU_RESOLVE_TEXT_ADDR:
++ sym = find_pc_function(req->addr);
++ if (!sym || TYPE_CODE(sym->type()) != TYPE_CODE_FUNC)
++ req->flags |= GNU_COMMAND_FAILED;
++ break;
++
++ case GNU_DISASSEMBLE:
++ if (req->addr2)
++ sprintf(req->buf, "disassemble 0x%lx 0x%lx",
++ req->addr, req->addr2);
++ else
++ sprintf(req->buf, "disassemble 0x%lx",
req->addr);
++ execute_command(req->buf, TRUE);
++ break;
++
++ case GNU_ADD_SYMBOL_FILE:
++ gdb_add_symbol_file(req);
++ break;
++
++ case GNU_DELETE_SYMBOL_FILE:
++ gdb_delete_symbol_file(req);
++ break;
++
++ case GNU_GET_LINE_NUMBER:
++ gdb_get_line_number(req);
++ break;
++
++ case GNU_GET_DATATYPE:
++ gdb_get_datatype(req);
++ break;
++
++ case GNU_GET_SYMBOL_TYPE:
++ gdb_get_symbol_type(req);
++ break;
++
++ case GNU_COMMAND_EXISTS:
++ gdb_command_exists(req);
++ break;
++
++ case GNU_ALPHA_FRAME_OFFSET:
++ req->value = 0;
++ break;
++
++ case GNU_FUNCTION_NUMARGS:
++ gdb_function_numargs(req);
++ break;
++
++ case GNU_DEBUG_COMMAND:
++ gdb_debug_command(req);
++ break;
++
++ case GNU_PATCH_SYMBOL_VALUES:
++ gdb_patch_symbol_values(req);
++ break;
++
++ case GNU_SET_CRASH_BLOCK:
++ gdb_set_crash_block(req);
++ break;
++
++ case GNU_GET_FUNCTION_RANGE:
++ {
++ CORE_ADDR start, end;
++ if (!find_pc_partial_function(req->pc, NULL, &start,
&end))
++ req->flags |= GNU_COMMAND_FAILED;
++ else {
++ req->addr = (ulong)start;
++ req->addr2 = (ulong)end;
++ }
++ }
++ break;
++
++ case GNU_LOOKUP_STRUCT_CONTENTS:
++ req->value = lookup_struct_contents(req);
++ break;
++
++ case GNU_ITERATE_DATATYPES:
++ iterate_datatypes(req);
++ break;
++
++ default:
++ req->flags |= GNU_COMMAND_FAILED;
++ break;
++ }
++}
++
++/*
++ * Given a PC value, return the file and line number.
++ */
++static void
++gdb_get_line_number(struct gnu_request *req)
++{
++ struct symtab_and_line sal;
++ struct objfile *objfile;
++ CORE_ADDR pc;
++
++#define LASTCHAR(s) (s[strlen(s)-1])
++
++ /*
++ * Prime the addrmap pump.
++ */
++ pc = req->addr;
++
++ sal = find_pc_line(pc, 0);
++
++ if (!sal.symtab) {
++ /*
++ * If a module address line number can't be found, it's
typically
++ * due to its addrmap still containing offset values because its
++ * objfile doesn't have full symbols loaded.
++ */
++ if (req->lm) {
++ objfile = req->lm->loaded_objfile;
++ if (!objfile_has_full_symbols(objfile) &&
objfile->sf) {
++ objfile->expand_all_symtabs();
++ sal = find_pc_line(pc, 0);
++ }
++ }
++ if (!sal.symtab) {
++ req->buf[0] = '\0';
++ return;
++ }
++ }
++
++ if (sal.symtab->filename && (sal.symtab)->compunit ()->dirname
()) {
++ if (sal.symtab->filename[0] == '/')
++ sprintf(req->buf, "%s: %d",
++ sal.symtab->filename, sal.line);
++ else
++ sprintf(req->buf, "%s%s%s: %d",
++ (sal.symtab)->compunit ()->dirname (),
++ LASTCHAR((sal.symtab)->compunit ()->dirname ()) ==
'/' ? "" : "/",
++ sal.symtab->filename, sal.line);
++ }
++}
++
++
++/*
++ * General purpose routine for determining datatypes.
++ */
++
++static void
++gdb_get_datatype(struct gnu_request *req)
++{
++ register struct type *type;
++ register struct type *typedef_type;
++ expression_up expr;
++ struct symbol *sym;
++ struct value *val;
++
++ if (gdb_CRASHDEBUG(2))
++ console("gdb_get_datatype [%s] (a)\n", req->name);
++
++ req->typecode = TYPE_CODE_UNDEF;
++
++ /*
++ * lookup_symbol() will pick up struct and union names.
++ */
++ sym = lookup_symbol(req->name, 0, SEARCH_STRUCT_DOMAIN, 0).symbol;
++ if (sym) {
++ req->typecode = TYPE_CODE(sym->type());
++ req->length = sym->type()->length();
++ if (req->member)
++ get_member_data(req, sym->type(), 0, 1);
++
++ if (TYPE_CODE(sym->type()) == TYPE_CODE_ENUM) {
++ if (req->flags & GNU_PRINT_ENUMERATORS)
++ dump_enum(sym->type(), req);
++ }
++
++ return;
++ }
++
++ /*
++ * Otherwise parse the expression.
++ */
++ if (gdb_CRASHDEBUG(2))
++ console("gdb_get_datatype [%s] (b)\n", req->name);
++
++ expr = parse_expression(req->name);
++
++
++ switch (expr->first_opcode())
++ {
++ case OP_VAR_VALUE:
++ if (gdb_CRASHDEBUG(2))
++ console("expr->first_opcode(): OP_VAR_VALUE\n");
++ type = expr->evaluate_type()->type();
++ if (req->flags & GNU_VAR_LENGTH_TYPECODE) {
++ req->typecode = TYPE_CODE(type);
++ req->length = type->length();
++ }
++ if (TYPE_CODE(type) == TYPE_CODE_ENUM) {
++ req->typecode = TYPE_CODE(type);
++ req->value = value_as_long(expr->evaluate());
++ req->tagname = (char *)TYPE_TAG_NAME(type);
++ if (!req->tagname) {
++ val = expr->evaluate_type();
++ eval_enum(val->type(), req);
++ }
++ }
++ break;
++
++ case OP_TYPE:
++ if (gdb_CRASHDEBUG(2))
++ console("expr->first_opcode(): OP_TYPE\n");
++ type = expr->evaluate_type()->type();
++
++ req->typecode = TYPE_CODE(type);
++ req->length = type->length();
++
++ if (TYPE_CODE(type) == TYPE_CODE_TYPEDEF) {
++ req->is_typedef = TYPE_CODE_TYPEDEF;
++ if ((typedef_type = check_typedef(type))) {
++ req->typecode = TYPE_CODE(typedef_type);
++ req->length = typedef_type->length();
++ type = typedef_type;
++ }
++ }
++
++ if (TYPE_CODE(type) == TYPE_CODE_ENUM) {
++ if (req->is_typedef)
++ if (req->flags & GNU_PRINT_ENUMERATORS) {
++ if (req->is_typedef)
++ gdb_printf(gdb_stdout,
++ "typedef ");
++ dump_enum(type, req);
++ }
++ }
++
++ if (req->member)
++ get_member_data(req, type, 0, 1);
++
++ break;
++
++ default:
++ if (gdb_CRASHDEBUG(2))
++ console("expr->first_opcode(): %d (?)\n",
++ expr->first_opcode());
++ break;
++
++ }
++}
++
++/*
++ * More robust enum list dump that gdb's, showing the value of each
++ * identifier, each on its own line.
++ */
++static void
++dump_enum(struct type *type, struct gnu_request *req)
++{
++ register int i;
++ int len;
++ long long lastval;
++
++ len = TYPE_NFIELDS (type);
++ lastval = 0;
++ if (TYPE_TAG_NAME(type))
++ gdb_printf(gdb_stdout,
++ "enum %s {\n", TYPE_TAG_NAME (type));
++ else
++ gdb_printf(gdb_stdout, "enum {\n");
++
++ for (i = 0; i < len; i++) {
++ gdb_printf(gdb_stdout, " %s",
++ type->field(i).name());
++ if (lastval != type->field(i).loc_enumval()) {
++ gdb_printf (gdb_stdout, " = %s",
++ plongest(type->field(i).loc_enumval()));
++ lastval = type->field(i).loc_enumval();
++ } else
++ gdb_printf(gdb_stdout, " = %s", plongest(lastval));
++ gdb_printf(gdb_stdout, "\n");
++ lastval++;
++ }
++ if (TYPE_TAG_NAME(type))
++ gdb_printf(gdb_stdout, "};\n");
++ else
++ gdb_printf(gdb_stdout, "} %s;\n", req->name);
++}
++
++/*
++ * Given an enum type with no tagname, determine its value.
++ */
++static void
++eval_enum(struct type *type, struct gnu_request *req)
++{
++ register int i;
++ int len;
++ long long lastval;
++
++ len = TYPE_NFIELDS (type);
++ lastval = 0;
++
++ for (i = 0; i < len; i++) {
++ if (lastval != type->field(i).loc_enumval())
++ lastval = type->field(i).loc_enumval();
++
++ if (STREQ(type->field(i).name(), req->name)) {
++ req->tagname = "(unknown)";
++ req->value = lastval;
++ return;
++ }
++ lastval++;
++ }
++}
++
++/*
++ * Walk through a struct type's list of fields looking for the desired
++ * member field, and when found, return its relevant data.
++ */
++static void
++get_member_data(struct gnu_request *req, struct type *type, long offset, int is_first)
++{
++ register short i;
++ struct field *nextfield;
++ short nfields;
++ struct type *typedef_type, *target_type;
++
++ req->member_offset = -1;
++
++ nfields = TYPE_MAIN_TYPE(type)->m_nfields;
++ nextfield = TYPE_MAIN_TYPE(type)->flds_bnds.fields;
++
++ if (nfields == 0 && is_first /* The first call */) {
++ struct type *newtype;
++ newtype = lookup_transparent_type(req->name);
++ if (newtype) {
++ console("get_member_data(%s.%s): switching type from %lx to
%lx\n",
++ req->name, req->member, type, newtype);
++ nfields = TYPE_MAIN_TYPE(newtype)->m_nfields;
++ nextfield = TYPE_MAIN_TYPE(newtype)->flds_bnds.fields;
++ }
++ }
++
++ for (i = 0; i < nfields; i++) {
++ if (STREQ(req->member, nextfield->m_name)) {
++ req->member_offset = offset + nextfield->m_loc.bitpos;
++ req->member_length = nextfield->type()->length();
++ req->member_typecode = TYPE_CODE(nextfield->type());
++ req->member_main_type_name = (char
*)TYPE_NAME(nextfield->type());
++ req->member_main_type_tag_name = (char
*)TYPE_TAG_NAME(nextfield->type());
++ target_type = nextfield->type()->target_type();
++ if (target_type) {
++ req->member_target_type_name = (char
*)TYPE_NAME(target_type);
++ req->member_target_type_tag_name = (char
*)TYPE_TAG_NAME(target_type);
++ }
++ if ((req->member_typecode == TYPE_CODE_TYPEDEF) &&
++ (typedef_type = check_typedef(nextfield->type())))
++ req->member_length = typedef_type->length();
++ return;
++ } else if (*nextfield->m_name == 0) { /* Anonymous struct/union */
++ get_member_data(req, nextfield->type(),
++ offset + nextfield->m_loc.bitpos, 0);
++ if (req->member_offset != -1)
++ return;
++ }
++ nextfield++;
++ }
++}
++
++/*
++ * Check whether a command exists. If it doesn't, the command will be
++ * returned indirectly via the error_hook.
++ */
++static void
++gdb_command_exists(struct gnu_request *req)
++{
++ extern struct cmd_list_element *cmdlist;
++
++ req->value = FALSE;
++ lookup_cmd((const char **)&req->name, cmdlist, "", NULL, 0,
1);
++ req->value = TRUE;
++}
++
++static void
++gdb_function_numargs(struct gnu_request *req)
++{
++ struct symbol *sym;
++
++ sym = find_pc_function(req->pc);
++
++ if (!sym || TYPE_CODE(sym->type()) != TYPE_CODE_FUNC) {
++ req->flags |= GNU_COMMAND_FAILED;
++ return;
++ }
++
++ req->value = (ulong)TYPE_NFIELDS(sym->type());
++}
++
++struct load_module *gdb_current_load_module = NULL;
++
++static void
++gdb_add_symbol_file(struct gnu_request *req)
++{
++ struct load_module *lm;
++ int i;
++ int allsect = 0;
++ char *secname;
++ char buf[80];
++
++ gdb_current_load_module = lm = (struct load_module *)req->addr;
++
++ req->name = lm->mod_namelist;
++ gdb_delete_symbol_file(req);
++ lm->loaded_objfile = NULL;
++
++ if ((lm->mod_flags & MOD_NOPATCH) == 0) {
++ for (i = 0 ; i < lm->mod_sections; i++) {
++ if (STREQ(lm->mod_section_data[i].name, ".text")
&&
++ (lm->mod_section_data[i].flags & SEC_FOUND))
++ allsect = 1;
++ }
++
++ if (!allsect) {
++ sprintf(req->buf, "add-symbol-file %s 0x%lx %s",
lm->mod_namelist,
++ lm->mod_text_start ? lm->mod_text_start :
lm->mod_base,
++ lm->mod_flags & MOD_DO_READNOW ? "-readnow"
: "");
++ if (lm->mod_data_start) {
++ sprintf(buf, " -s .data 0x%lx",
lm->mod_data_start);
++ strcat(req->buf, buf);
++ }
++ if (lm->mod_bss_start) {
++ sprintf(buf, " -s .bss 0x%lx",
lm->mod_bss_start);
++ strcat(req->buf, buf);
++ }
++ if (lm->mod_rodata_start) {
++ sprintf(buf, " -s .rodata 0x%lx",
lm->mod_rodata_start);
++ strcat(req->buf, buf);
++ }
++ } else {
++ sprintf(req->buf, "add-symbol-file %s 0x%lx %s",
lm->mod_namelist,
++ lm->mod_text_start, lm->mod_flags & MOD_DO_READNOW
?
++ "-readnow" : "");
++ for (i = 0; i < lm->mod_sections; i++) {
++ secname = lm->mod_section_data[i].name;
++ if ((lm->mod_section_data[i].flags & SEC_FOUND)
&&
++ !STREQ(secname, ".text")) {
++ sprintf(buf, " -s %s 0x%lx", secname,
++ lm->mod_section_data[i].offset +
lm->mod_base);
++ strcat(req->buf, buf);
++ }
++ }
++ }
++ }
++
++ if (gdb_CRASHDEBUG(1))
++ gdb_printf(gdb_stdout, "%s\n", req->buf);
++
++ execute_command(req->buf, FALSE);
++
++ for (objfile *objfile : current_program_space->objfiles ()) {
++ if (same_file((char *)objfile_name(objfile), lm->mod_namelist)) {
++ if (objfile->separate_debug_objfile)
++ lm->loaded_objfile =
objfile->separate_debug_objfile;
++ else
++ lm->loaded_objfile = objfile;
++ break;
++ }
++ }
++
++ if (!lm->loaded_objfile)
++ req->flags |= GNU_COMMAND_FAILED;
++}
++
++static void
++gdb_delete_symbol_file(struct gnu_request *req)
++{
++ for (objfile *objfile : current_program_space->objfiles ()) {
++ if (STREQ(objfile_name(objfile), req->name) ||
++ same_file((char *)objfile_name(objfile), req->name)) {
++ objfile->unlink ();
++ break;
++ }
++ }
++
++ if (gdb_CRASHDEBUG(2)) {
++ gdb_printf(gdb_stdout, "current object files:\n");
++ for (objfile *objfile : current_program_space->objfiles ())
++ gdb_printf(gdb_stdout, " %s\n",
objfile_name(objfile));
++ }
++}
++
++/*
++ * Walk through all minimal_symbols, patching their values with the
++ * correct addresses.
++ */
++static void
++gdb_patch_symbol_values(struct gnu_request *req)
++{
++ req->name = PATCH_KERNEL_SYMBOLS_START;
++ patch_kernel_symbol(req);
++
++ for (objfile *objfile : current_program_space->objfiles ())
++ for (minimal_symbol *msymbol : objfile->msymbols ())
++ {
++ req->name = (char *)msymbol->m_name;
++ req->addr = (ulong)(&msymbol->m_value.ivalue);
++ if (!patch_kernel_symbol(req)) {
++ req->flags |= GNU_COMMAND_FAILED;
++ break;
++ }
++ }
++
++ req->name = PATCH_KERNEL_SYMBOLS_STOP;
++ patch_kernel_symbol(req);
++
++ clear_symtab_users(0);
++ gdb_merge_flags |= KERNEL_SYMBOLS_PATCHED;
++}
++
++static void
++gdb_get_symbol_type(struct gnu_request *req)
++{
++ expression_up expr;
++ struct value *val;
++ struct type *type;
++ struct type *target_type;
++
++ req->typecode = TYPE_CODE_UNDEF;
++
++ expr = parse_expression (req->name);
++ val = expr->evaluate_type();
++
++ type = val->type();
++
++ req->type_name = (char *)TYPE_MAIN_TYPE(type)->name;
++ req->typecode = TYPE_MAIN_TYPE(type)->code;
++ req->length = type->m_length;
++ req->type_tag_name = (char *)TYPE_TAG_NAME(type);
++ target_type = TYPE_MAIN_TYPE(type)->m_target_type;
++
++ if (target_type) {
++ req->target_typename = (char *)TYPE_MAIN_TYPE(target_type)->name;
++ req->target_typecode = TYPE_MAIN_TYPE(target_type)->code;
++ req->target_length = target_type->m_length;
++ }
++
++ if (req->member)
++ get_member_data(req, type, 0, 1);
++}
++
++static void
++gdb_debug_command(struct gnu_request *req)
++{
++
++}
++
++/*
++ * Only necessary on "patched" kernel symbol sessions, and called only by
++ * lookup_symbol(), pull a symbol value bait-and-switch operation by altering
++ * either a data symbol's address value or a text symbol's block start
address.
++ */
++static void
++gdb_bait_and_switch(char *name, struct symbol *sym)
++{
++ struct bound_minimal_symbol msym;
++ struct block *block;
++
++ if ((gdb_merge_flags & KERNEL_SYMBOLS_PATCHED) &&
++ (msym = lookup_minimal_symbol(current_program_space, name,
gdb_kernel_objfile, NULL)).minsym) {
++ if (sym->aclass() == LOC_BLOCK) {
++ block = (struct block *)(sym->value_block());
++ block->set_start(msym.value_address());
++ } else
++ sym->set_value_address(msym.value_address());
++ }
++}
++
++#include "valprint.h"
++
++void
++get_user_print_option_address(struct gnu_request *req)
++{
++ extern struct value_print_options user_print_options;
++
++ req->addr = 0;
++
++ if (strcmp(req->name, "output_format") == 0)
++ req->addr = (ulong)&user_print_options.output_format;
++ if (strcmp(req->name, "print_max") == 0)
++ req->addr = (ulong)&user_print_options.print_max;
++ if (strcmp(req->name, "prettyprint_structs") == 0)
++ req->addr = (ulong)&user_print_options.prettyformat_structs;
++ if (strcmp(req->name, "prettyprint_arrays") == 0)
++ req->addr = (ulong)&user_print_options.prettyformat_arrays;
++ if (strcmp(req->name, "repeat_count_threshold") == 0)
++ req->addr = (ulong)&user_print_options.repeat_count_threshold;
++ if (strcmp(req->name, "stop_print_at_null") == 0)
++ req->addr = (ulong)&user_print_options.stop_print_at_null;
++ if (strcmp(req->name, "output_radix") == 0)
++ req->addr = (ulong)&output_radix;
++}
++
++CORE_ADDR crash_text_scope;
++
++static void
++gdb_set_crash_block(struct gnu_request *req)
++{
++ if (!req->addr) { /* debug */
++ crash_text_scope = 0;
++ return;
++ }
++
++ if ((req->addr2 = (ulong)block_for_pc(req->addr)))
++ crash_text_scope = req->addr;
++ else {
++ crash_text_scope = 0;
++ req->flags |= GNU_COMMAND_FAILED;
++ }
++}
++
++static const struct block *
++gdb_get_crash_block(void)
++{
++ if (crash_text_scope)
++ return block_for_pc(crash_text_scope);
++ else
++ return NULL;
++}
++
++static long
++lookup_struct_contents(struct gnu_request *req)
++{
++ int i;
++ long r;
++ struct field *f;
++ struct main_type *m;
++ const char *n;
++ struct main_type *top_m = (struct main_type *)req->addr;
++ char *type_name = req->type_name;
++
++ if (!top_m || !type_name)
++ return 0;
++
++ for (i = 0; i < top_m->m_nfields; i++)
++ {
++ f = top_m->flds_bnds.fields + i;
++ if (!f->type())
++ continue;
++ m = f->type()->main_type;
++
++ // If the field is an array, check the target type -
++ // it might be structure, or might not be.
++ // - struct request_sock *syn_table[0];
++ // here m->target_type->main_type->code is expected
++ // to be TYPE_CODE_PTR
++ // - struct list_head vec[TVN_SIZE];
++ // here m->target_type->main_type->code should be
++ // TYPE_CODE_STRUCT
++ if (m->code == TYPE_CODE_ARRAY && m->m_target_type)
++ m = m->m_target_type->main_type;
++
++ /* Here is a recursion.
++ * If we have struct variable (not pointer),
++ * scan this inner structure
++ */
++ if (m->code == TYPE_CODE_STRUCT) {
++ req->addr = (ulong)m;
++ r = lookup_struct_contents(req);
++ req->addr = (ulong)top_m;
++ if (r)
++ return 1;
++ }
++
++ if (m->code == TYPE_CODE_PTR && m->m_target_type)
++ m = m->m_target_type->main_type;
++ if (m->name)
++ n = m->name;
++ else
++ continue;
++
++ if (strstr(n, type_name))
++ return 1;
++ }
++
++ return 0;
++}
++
++static void
++iterate_datatypes (struct gnu_request *req)
++{
++ for (objfile *objfile : current_program_space->objfiles ())
++ {
++ if (objfile->sf)
++ objfile->expand_all_symtabs();
++
++ for (compunit_symtab *cust : objfile->compunits ())
++ {
++ const struct blockvector *bv = cust->blockvector();
++
++ for (int i = GLOBAL_BLOCK; i <= STATIC_BLOCK; ++i)
++ {
++ const struct block *b = bv->block(i);
++
++ for (struct symbol *sym : block_iterator_range (b))
++ {
++ QUIT;
++
++ if (sym->aclass() != LOC_TYPEDEF)
++ continue;
++
++ if (req->highest &&
++ !(req->lowest <= sym->type()->m_length &&
sym->type()->m_length <= req->highest))
++ continue;
++
++ req->addr = (ulong)(sym->type()->main_type);
++ req->name = (char *)(sym->m_name);
++ req->length = sym->type()->m_length;
++
++ if (req->member) {
++ req->value = lookup_struct_contents(req);
++ if (!req->value)
++ continue;
++ }
++ req->callback(req, req->callback_data);
++ }
++ }
++ }
++ }
++}
++#endif
+--- gdb-16.2/gdb/ui-file.h.orig
++++ gdb-16.2/gdb/ui-file.h
+@@ -273,10 +273,10 @@ class stdio_file : public ui_file
+ int fd () const override
+ { return m_fd; }
+
+-private:
+ /* Sets the internal stream to FILE, and saves the FILE's file
+ descriptor in M_FD. */
+ void set_stream (FILE *file);
++private:
+
+ /* The file. */
+ FILE *m_file;
+--- gdb-16.2/gdb/xml-syscall.c.orig
++++ gdb-16.2/gdb/xml-syscall.c
+@@ -36,7 +36,11 @@
+ static void
+ syscall_warn_user (void)
+ {
++#ifdef CRASH_MERGE
++ static int have_warned = 1;
++#else
+ static int have_warned = 0;
++#endif
+ if (!have_warned)
+ {
+ have_warned = 1;
+--- gdb-16.2/libiberty/Makefile.in.orig
++++ gdb-16.2/libiberty/Makefile.in
+@@ -181,6 +181,7 @@ REQUIRED_OFILES = \
+ ./getruntime.$(objext) ./hashtab.$(objext) ./hex.$(objext) \
+ ./lbasename.$(objext) ./lrealpath.$(objext) \
+ ./make-relative-prefix.$(objext) ./make-temp-file.$(objext) \
++ ./mkstemps.$(objext) \
+ ./objalloc.$(objext) \
+ ./obstack.$(objext) \
+ ./partition.$(objext) ./pexecute.$(objext) ./physmem.$(objext) \
+@@ -214,7 +215,7 @@ CONFIGURED_OFILES = ./asprintf.$(objext) ./atexit.$(objext) \
+ ./index.$(objext) ./insque.$(objext) \
+ ./memchr.$(objext) ./memcmp.$(objext) ./memcpy.$(objext) \
+ ./memmem.$(objext) ./memmove.$(objext) \
+- ./mempcpy.$(objext) ./memset.$(objext) ./mkstemps.$(objext) \
++ ./mempcpy.$(objext) ./memset.$(objext) \
+ ./pex-djgpp.$(objext) ./pex-msdos.$(objext) \
+ ./pex-unix.$(objext) ./pex-win32.$(objext) \
+ ./putenv.$(objext) \
+--- gdb-16.2/opcodes/i386-dis.c.orig
++++ gdb-16.2/opcodes/i386-dis.c
+@@ -9589,6 +9589,10 @@ print_insn (bfd_vma pc, disassemble_info *info, int intel_syntax)
+
+ dp = &dis386_twobyte[*ins.codep];
+ ins.need_modrm = twobyte_has_modrm[*ins.codep];
++ if (dp->name && ((strcmp(dp->name, "ud2a") == 0) ||
(strcmp(dp->name, "ud2") == 0))) {
++ extern int kernel_BUG_encoding_bytes(void);
++ ins.codep += kernel_BUG_encoding_bytes();
++ }
+ }
+ else
+ {
+--- gdb-16.2/readline/readline/misc.c.orig
++++ gdb-16.2/readline/readline/misc.c
+@@ -411,7 +411,7 @@ _rl_history_set_point (void)
+
+ #if defined (VI_MODE)
+ if (rl_editing_mode == vi_mode && _rl_keymap != vi_insertion_keymap)
+- rl_point = 0;
++ rl_point = rl_end;
+ #endif /* VI_MODE */
+
+ if (rl_editing_mode == emacs_mode)
+--- gdb-16.2/readline/readline/readline.h.orig
++++ gdb-16.2/readline/readline/readline.h
+@@ -407,7 +407,7 @@ extern int rl_mark_active_p (void);
+ #if defined (USE_VARARGS) && defined (PREFER_STDARG)
+ extern int rl_message (const char *, ...) __attribute__((__format__ (printf, 1, 2)));
+ #else
+-extern int rl_message ();
++extern int rl_message (void);
+ #endif
+
+ extern int rl_show_char (int);
+--- gdb-16.2/readline/readline/rltypedefs.h.orig
++++ gdb-16.2/readline/readline/rltypedefs.h
+@@ -32,10 +32,10 @@ extern "C" {
+ # define _FUNCTION_DEF
+
+ #if defined(__GNUC__) || defined(__clang__)
+-typedef int Function () __attribute__((deprecated));
+-typedef void VFunction () __attribute__((deprecated));
+-typedef char *CPFunction () __attribute__((deprecated));
+-typedef char **CPPFunction () __attribute__((deprecated));
++typedef int Function (void) __attribute__ ((deprecated));
++typedef void VFunction (void) __attribute__ ((deprecated));
++typedef char *CPFunction (void) __attribute__ ((deprecated));
++typedef char **CPPFunction (void) __attribute__ ((deprecated));
+ #else
+ typedef int Function ();
+ typedef void VFunction ();
+--- gdb-16.2/readline/readline/util.c.orig
++++ gdb-16.2/readline/readline/util.c
+@@ -489,10 +489,13 @@ _rl_trace (va_alist)
+
+ if (_rl_tracefp == 0)
+ _rl_tropen ();
++ if (!_rl_tracefp)
++ goto out;
+ vfprintf (_rl_tracefp, format, args);
+ fprintf (_rl_tracefp, "\n");
+ fflush (_rl_tracefp);
+
++out:
+ va_end (args);
+ }
+
+@@ -512,16 +515,17 @@ _rl_tropen (void)
+ #endif
+ snprintf (fnbuf, sizeof (fnbuf), "%s/rltrace.%ld", x, (long)getpid());
+ unlink(fnbuf);
+- _rl_tracefp = fopen (fnbuf, "w+");
++ _rl_tracefp = fopen (fnbuf, "w+xe");
+ return _rl_tracefp != 0;
+ }
+
+ int
+ _rl_trclose (void)
+ {
+- int r;
++ int r = 0;
+
+- r = fclose (_rl_tracefp);
++ if (_rl_tracefp)
++ r = fclose (_rl_tracefp);
+ _rl_tracefp = 0;
+ return r;
+ }
+--- gdb-16.2/gdb/completer.c.orig
++++ gdb-16.2/gdb/completer.c
+@@ -3315,6 +3315,8 @@ gdb_display_match_list_1 (char **matches, int len, int max,
+
+ /* How many items of MAX length can we fit in the screen window? */
+ cols = gdb_complete_get_screenwidth (displayer);
++ rl_reset_screen_size();
++ rl_get_screen_size(NULL, &cols);
+ max += 2;
+ limit = cols / max;
+ if (limit != 1 && (limit * max == cols))
+--- gdb-16.2/gdb/Makefile.in.orig
++++ gdb-16.2/gdb/Makefile.in
+@@ -2231,7 +2231,7 @@ libgdb.a: $(LIBGDB_OBS)
+ # Removing the old gdb first works better if it is running, at least on SunOS.
+ gdb$(EXEEXT): gdb.o $(LIBGDB_OBS) $(CDEPS) $(TDEPLIBS)
+ $(SILENCE) rm -f gdb$(EXEEXT)
+- @(cd ../..; make --no-print-directory GDB_FLAGS=-DGDB_16_2 library)
++ @$(MAKE) -C ../.. GDB_FLAGS=-DGDB_16_2 library
+ $(ECHO_CXXLD) $(CC_LD) $(INTERNAL_LDFLAGS) $(WIN32LDAPP) \
+ -o $(shell /bin/cat mergeobj) $(LIBGDB_OBS) \
+ $(TDEPLIBS) $(TUI_LIBRARY) $(CLIBS) $(LOADLIBES) $(shell /bin/cat
mergelibs)
+--- gdb-16.2/gdb/c-typeprint.c.orig
++++ gdb-16.2/gdb/c-typeprint.c
+@@ -1066,6 +1066,9 @@ c_type_print_base_struct_union (struct type *type, struct ui_file
*stream,
+ = podata->end_bitpos
+ - type->field (i).type ()->length () * TARGET_CHAR_BIT;
+ }
++ else if (strlen(type->field(i).name()) == 0)
++ /* crash: Print details for unnamed struct and union. */
++ newshow = show;
+
+ c_print_type_1 (type->field (i).type (),
+ type->field (i).name (),
+--- gdb-16.2/gdb/symfile.c.orig
++++ gdb-16.2/gdb/symfile.c
+@@ -1587,7 +1587,7 @@ find_separate_debug_file_by_debuglink
+ if (debugfile.empty ()) {
+ char *name_copy;
+ name_copy = check_specified_kernel_debug_file();
+- return std::string (name_copy);
++ return name_copy ? std::string (name_copy) : std::string ();
+ }
+ #endif
+
+--- gdb-16.2/gdb/printcmd.c.orig
++++ gdb-16.2/gdb/printcmd.c
+@@ -604,6 +604,10 @@ print_address_symbolic (struct gdbarch *gdbarch, CORE_ADDR addr,
+
+ /* See valprint.h. */
+
++#ifdef CRASH_MERGE
++extern "C" char *gdb_lookup_module_symbol(unsigned long, unsigned long *);
++#endif
++
+ int
+ build_address_symbolic (struct gdbarch *gdbarch,
+ CORE_ADDR addr, /* IN */
+@@ -710,7 +714,19 @@ build_address_symbolic (struct gdbarch *gdbarch,
+ }
+ }
+ if (symbol == NULL && msymbol.minsym == NULL)
++#ifdef CRASH_MERGE
++ {
++ char *name_ptr = gdb_lookup_module_symbol(addr, (unsigned long *)offset);
++ if (name_ptr) {
++ *name = name_ptr;
++ return 0;
++ } else {
++ return 1;
++ }
++ }
++#else
+ return 1;
++#endif
+
+ /* If the nearest symbol is too far away, don't print anything symbolic. */
+
+--- gdb-16.2/gdb/symtab.c.orig
++++ gdb-16.2/gdb/symtab.c
+@@ -7563,8 +7563,8 @@ gdb_get_line_number(struct gnu_request *req)
+ static void
+ gdb_get_datatype(struct gnu_request *req)
+ {
+- register struct type *type;
+- register struct type *typedef_type;
++ struct type *type;
++ struct type *typedef_type;
+ expression_up expr;
+ struct symbol *sym;
+ struct value *val;
+@@ -7670,7 +7670,7 @@ gdb_get_datatype(struct gnu_request *req)
+ static void
+ dump_enum(struct type *type, struct gnu_request *req)
+ {
+- register int i;
++ int i;
+ int len;
+ long long lastval;
+
+@@ -7706,7 +7706,7 @@ dump_enum(struct type *type, struct gnu_request *req)
+ static void
+ eval_enum(struct type *type, struct gnu_request *req)
+ {
+- register int i;
++ int i;
+ int len;
+ long long lastval;
+
+@@ -7733,7 +7733,7 @@ eval_enum(struct type *type, struct gnu_request *req)
+ static void
+ get_member_data(struct gnu_request *req, struct type *type, long offset, int is_first)
+ {
+- register short i;
++ short i;
+ struct field *nextfield;
+ short nfields;
+ struct type *typedef_type, *target_type;
+--- gdb-16.2/gdb/symtab.c.orig
++++ gdb-16.2/gdb/symtab.c
+@@ -7347,7 +7347,7 @@ the use of prologue scanners."),
+ #include "../../defs.h"
+
+ static void get_member_data(struct gnu_request *, struct type *, long, int);
+-static void dump_enum(struct type *, struct gnu_request *);
++static void walk_enum(struct type *, struct gnu_request *);
+ static void eval_enum(struct type *, struct gnu_request *);
+ static void gdb_get_line_number(struct gnu_request *);
+ static void gdb_get_datatype(struct gnu_request *);
+@@ -7556,6 +7556,79 @@ gdb_get_line_number(struct gnu_request *req)
+ }
+
+
++/*
++ * Follow the type linkage for full member and value type resolution, with callback
++ */
++static void drillDownType(struct gnu_request *req, struct type *type)
++{
++ while (type)
++ {
++ /* check out for stub types and pull in the definition instead */
++ if (type->is_stub() && TYPE_TAG_NAME(type)) {
++ struct symbol *sym;
++ sym = lookup_symbol(TYPE_TAG_NAME(type), 0,
SEARCH_STRUCT_DOMAIN, 0).symbol;
++ if (sym)
++ type = sym->type();
++ }
++ switch (TYPE_CODE(type)) {
++ drill_ops_t op;
++ long l1, l2;
++ int typecode;
++
++ case TYPE_CODE_PTR:
++ req->tcb(EOP_POINTER, req, 0, 0, 0, 0);
++ break;
++
++ case TYPE_CODE_TYPEDEF:
++ req->is_typedef = 1;
++ req->typecode = TYPE_CODE(type);
++ if (!req->tcb(EOP_TYPEDEF, req, TYPE_NAME(type), 0, 0, 0))
++ return;
++ break;
++
++ case TYPE_CODE_FUNC:
++ req->tcb(EOP_FUNCTION, req, 0, 0, 0, 0);
++ break;
++
++ case TYPE_CODE_ARRAY:
++ l1 = type->length();
++ l2 = check_typedef(type->target_type())->length();
++ req->tcb(EOP_ARRAY, req, &l1, &l2, 0, 0);
++ break;
++
++ case TYPE_CODE_VOID:
++ case TYPE_CODE_INT:
++ case TYPE_CODE_BOOL:
++ l1 = type->length();
++ req->tcb(EOP_INT, req, &l1, 0, 0, 0);
++ break;
++
++ case TYPE_CODE_UNION:
++ op = EOP_UNION;
++ goto label;
++
++ case TYPE_CODE_ENUM:
++ op = EOP_ENUM;
++ goto label;
++
++ case TYPE_CODE_STRUCT:
++ op = EOP_STRUCT;
++ goto label;
++
++ default:
++ typecode = TYPE_CODE(type);
++ req->tcb(EOP_OOPS, req, &typecode, "Unknown
typecode", 0, 0);
++ return; /* not reached */
++
++ label:
++ l1 = type->length();
++ req->tcb(op, req, &l1, type, TYPE_TAG_NAME(type), 0);
++ }
++ type = type->target_type();
++ }
++ req->tcb(EOP_DONE, req, 0, 0, 0, 0);
++}
++
+ /*
+ * General purpose routine for determining datatypes.
+ */
+@@ -7584,10 +7657,8 @@ gdb_get_datatype(struct gnu_request *req)
+ if (req->member)
+ get_member_data(req, sym->type(), 0, 1);
+
+- if (TYPE_CODE(sym->type()) == TYPE_CODE_ENUM) {
+- if (req->flags & GNU_PRINT_ENUMERATORS)
+- dump_enum(sym->type(), req);
+- }
++ if (TYPE_CODE(sym->type()) == TYPE_CODE_ENUM)
++ walk_enum(sym->type(), req);
+
+ return;
+ }
+@@ -7607,17 +7678,25 @@ gdb_get_datatype(struct gnu_request *req)
+ if (gdb_CRASHDEBUG(2))
+ console("expr->first_opcode(): OP_VAR_VALUE\n");
+ type = expr->evaluate_type()->type();
+- if (req->flags & GNU_VAR_LENGTH_TYPECODE) {
++ if (req->tcb) {
++ long value = value_as_long(expr->evaluate());
++ /* callback with symbol value */
+ req->typecode = TYPE_CODE(type);
+- req->length = type->length();
+- }
+- if (TYPE_CODE(type) == TYPE_CODE_ENUM) {
+- req->typecode = TYPE_CODE(type);
+- req->value = value_as_long(expr->evaluate());
+- req->tagname = (char *)TYPE_TAG_NAME(type);
+- if (!req->tagname) {
+- val = expr->evaluate_type();
+- eval_enum(val->type(), req);
++ req->tcb(EOP_VALUE, req, &value, 0, 0, 0);
++ drillDownType(req, type);
++ } else {
++ if (req->flags & GNU_VAR_LENGTH_TYPECODE) {
++ req->typecode = TYPE_CODE(type);
++ req->length = type->length();
++ }
++ if (TYPE_CODE(type) == TYPE_CODE_ENUM) {
++ req->typecode = TYPE_CODE(type);
++ req->value = value_as_long(expr->evaluate());
++ req->tagname = (char *)TYPE_TAG_NAME(type);
++ if (!req->tagname) {
++ val = expr->evaluate_type();
++ eval_enum(val->type(), req);
++ }
+ }
+ }
+ break;
+@@ -7627,26 +7706,21 @@ gdb_get_datatype(struct gnu_request *req)
+ console("expr->first_opcode(): OP_TYPE\n");
+ type = expr->evaluate_type()->type();
+
+- req->typecode = TYPE_CODE(type);
+- req->length = type->length();
+-
+- if (TYPE_CODE(type) == TYPE_CODE_TYPEDEF) {
+- req->is_typedef = TYPE_CODE_TYPEDEF;
+- if ((typedef_type = check_typedef(type))) {
+- req->typecode = TYPE_CODE(typedef_type);
+- req->length = typedef_type->length();
+- type = typedef_type;
+- }
+- }
+-
+- if (TYPE_CODE(type) == TYPE_CODE_ENUM) {
+- if (req->is_typedef)
+- if (req->flags & GNU_PRINT_ENUMERATORS) {
+- if (req->is_typedef)
+- gdb_printf(gdb_stdout,
+- "typedef ");
+- dump_enum(type, req);
++ if (req->tcb) {
++ drillDownType(req, type);
++ } else {
++ req->typecode = TYPE_CODE(type);
++ req->length = type->length();
++ if (TYPE_CODE(type) == TYPE_CODE_TYPEDEF) {
++ req->is_typedef = TYPE_CODE_TYPEDEF;
++ if ((typedef_type = check_typedef(type))) {
++ req->typecode = TYPE_CODE(typedef_type);
++ req->length = typedef_type->length();
++ type = typedef_type;
++ }
+ }
++ if (TYPE_CODE(type) == TYPE_CODE_ENUM)
++ walk_enum(type, req);
+ }
+
+ if (req->member)
+@@ -7668,36 +7742,38 @@ gdb_get_datatype(struct gnu_request *req)
+ * identifier, each on its own line.
+ */
+ static void
+-dump_enum(struct type *type, struct gnu_request *req)
++walk_enum(struct type *type, struct gnu_request *req)
+ {
+ int i;
+- int len;
++ int len, print = (req->flags & GNU_PRINT_ENUMERATORS);
+ long long lastval;
+
+- len = TYPE_NFIELDS (type);
+- lastval = 0;
+- if (TYPE_TAG_NAME(type))
+- gdb_printf(gdb_stdout,
+- "enum %s {\n", TYPE_TAG_NAME (type));
+- else
+- gdb_printf(gdb_stdout, "enum {\n");
++ if (print) {
++ if (req->is_typedef)
++ gdb_printf(gdb_stdout, "typedef ");
++ if (TYPE_TAG_NAME(type))
++ gdb_printf(gdb_stdout, "enum %s {\n", TYPE_TAG_NAME
(type));
++ else
++ gdb_printf(gdb_stdout, "enum {\n");
++ }
+
++ len = TYPE_NFIELDS (type);
+ for (i = 0; i < len; i++) {
+- gdb_printf(gdb_stdout, " %s",
+- type->field(i).name());
+- if (lastval != type->field(i).loc_enumval()) {
+- gdb_printf (gdb_stdout, " = %s",
+- plongest(type->field(i).loc_enumval()));
+- lastval = type->field(i).loc_enumval();
+- } else
++ if (print)
++ gdb_printf(gdb_stdout, " %s",
type->field(i).name());
++ lastval = type->field(i).loc_enumval();
++ if (print) {
+ gdb_printf(gdb_stdout, " = %s", plongest(lastval));
+- gdb_printf(gdb_stdout, "\n");
+- lastval++;
++ gdb_printf(gdb_stdout, "\n");
++ } else if (req->tcb)
++ req->tcb(EOP_ENUMVAL, req, type->field(i).name(),
&lastval, 0, 0);
++ }
++ if (print) {
++ if (TYPE_TAG_NAME(type))
++ gdb_printf(gdb_stdout, "};\n");
++ else
++ gdb_printf(gdb_stdout, "} %s;\n", req->name);
+ }
+- if (TYPE_TAG_NAME(type))
+- gdb_printf(gdb_stdout, "};\n");
+- else
+- gdb_printf(gdb_stdout, "} %s;\n", req->name);
+ }
+
+ /*
+@@ -7755,26 +7831,43 @@ get_member_data(struct gnu_request *req, struct type *type, long
offset, int is_
+ }
+
+ for (i = 0; i < nfields; i++) {
+- if (STREQ(req->member, nextfield->m_name)) {
+- req->member_offset = offset + nextfield->m_loc.bitpos;
+- req->member_length = nextfield->type()->length();
+- req->member_typecode = TYPE_CODE(nextfield->type());
+- req->member_main_type_name = (char
*)TYPE_NAME(nextfield->type());
+- req->member_main_type_tag_name = (char
*)TYPE_TAG_NAME(nextfield->type());
+- target_type = nextfield->type()->target_type();
+- if (target_type) {
+- req->member_target_type_name = (char
*)TYPE_NAME(target_type);
+- req->member_target_type_tag_name = (char
*)TYPE_TAG_NAME(target_type);
+- }
+- if ((req->member_typecode == TYPE_CODE_TYPEDEF) &&
+- (typedef_type = check_typedef(nextfield->type())))
+- req->member_length = typedef_type->length();
+- return;
+- } else if (*nextfield->m_name == 0) { /* Anonymous struct/union */
++ if (*nextfield->m_name == 0) { /* Anonymous struct/union */
+ get_member_data(req, nextfield->type(),
+ offset + nextfield->m_loc.bitpos, 0);
+ if (req->member_offset != -1)
+ return;
++ } else {
++ /* callback may be just looking for a specific member name */
++ if (req->tcb) {
++ if (req->tcb(EOP_MEMBER_NAME, req,
nextfield->m_name, 0, 0, 0)) {
++ long bitpos = nextfield->loc_bitpos();
++ long bitsize = nextfield->bitsize();
++ long len = nextfield->type()->length();
++ long byteOffset;
++ offset += nextfield->m_loc.bitpos;
++ byteOffset = offset/8;
++ console("EOP_MEMBER_SIZES\n");
++ req->tcb(EOP_MEMBER_SIZES, req,
&byteOffset, &len, &bitpos, &bitsize);
++ /* callback with full type info */
++ drillDownType(req, nextfield->type());
++ }
++ } else if (STREQ(req->member, nextfield->m_name)) {
++ req->member_offset = offset +
nextfield->m_loc.bitpos;
++ req->member_length =
nextfield->type()->length();
++ req->member_typecode =
TYPE_CODE(nextfield->type());
++ req->member_main_type_name = (char
*)TYPE_NAME(nextfield->type());
++ req->member_main_type_tag_name = (char
*)TYPE_TAG_NAME(nextfield->type());
++ target_type = nextfield->type()->target_type();
++ if (target_type) {
++ req->member_target_type_name = (char
*)TYPE_NAME(target_type);
++ req->member_target_type_tag_name = (char
*)TYPE_TAG_NAME(target_type);
++ }
++ if ((req->member_typecode == TYPE_CODE_TYPEDEF)
&&
++ (typedef_type =
check_typedef(nextfield->type()))) {
++ req->member_length =
typedef_type->length();
++ }
++ return;
++ }
+ }
+ nextfield++;
+ }
+--- gdb-16.2/gdb/symtab.c.orig
++++ gdb-16.2/gdb/symtab.c
+@@ -7911,7 +7911,7 @@ gdb_add_symbol_file(struct gnu_request *req)
+ int i;
+ int allsect = 0;
+ char *secname;
+- char buf[80];
++ char buf[96];
+
+ gdb_current_load_module = lm = (struct load_module *)req->addr;
+
+@@ -7950,8 +7950,11 @@ gdb_add_symbol_file(struct gnu_request *req)
+ secname = lm->mod_section_data[i].name;
+ if ((lm->mod_section_data[i].flags & SEC_FOUND)
&&
+ !STREQ(secname, ".text")) {
+- sprintf(buf, " -s %s 0x%lx", secname,
+- lm->mod_section_data[i].offset +
lm->mod_base);
++ if (lm->mod_section_data[i].addr)
++ sprintf(buf, " -s %s 0x%lx", secname,
lm->mod_section_data[i].addr);
++ else
++ sprintf(buf, " -s %s 0x%lx", secname,
++ lm->mod_section_data[i].offset +
lm->mod_base);
+ strcat(req->buf, buf);
+ }
+ }
+--- gdb-16.2/gdb/objfiles.h.orig
++++ gdb-16.2/gdb/objfiles.h
+@@ -891,6 +891,8 @@ struct objfile
+ mechanism as ELF should set this flag too. This flag is used in
+ conjunction with the minimal_symbol::maybe_copied method. */
+ bool object_format_has_copy_relocs = false;
++
++ bool all_symtabs_expanded = false;
+ };
+
+ /* A deleter for objfile. */
+--- gdb-16.2/gdb/symfile.c.orig
++++ gdb-16.2/gdb/symfile.c
+@@ -1120,6 +1120,7 @@ symbol_file_add_with_addrs (const gdb_bfd_ref_ptr &abfd, const
char *name,
+ styled_string (file_name_style.style (), name));
+
+ objfile->expand_all_symtabs ();
++ objfile->all_symtabs_expanded = true;
+ }
+
+ /* Note that we only print a message if we have no symbols and have
+--- gdb-16.2/gdb/symfile.c.orig
++++ gdb-16.2/gdb/symfile.c
+@@ -2709,6 +2709,7 @@ reread_symbols (int from_tty)
+ objfile_name (objfile)));
+
+ objfile->expand_all_symtabs ();
++ objfile->all_symtabs_expanded = true;
+ }
+
+ if (!objfile_has_symbols (objfile))
+--- gdb-16.2/gdb/symtab.c.orig
++++ gdb-16.2/gdb/symtab.c
+@@ -7532,8 +7532,9 @@ gdb_get_line_number(struct gnu_request *req)
+ */
+ if (req->lm) {
+ objfile = req->lm->loaded_objfile;
+- if (!objfile_has_full_symbols(objfile) &&
objfile->sf) {
++ if (!objfile->all_symtabs_expanded && objfile->sf)
{
+ objfile->expand_all_symtabs();
++ objfile->all_symtabs_expanded = true;
+ sal = find_pc_line(pc, 0);
+ }
+ }
+@@ -8199,8 +8200,10 @@ iterate_datatypes (struct gnu_request *req)
+ {
+ for (objfile *objfile : current_program_space->objfiles ())
+ {
+- if (objfile->sf)
++ if (objfile->sf) {
+ objfile->expand_all_symtabs();
++ objfile->all_symtabs_expanded = true;
++ }
+
+ for (compunit_symtab *cust : objfile->compunits ())
+ {
+--- gdb-16.2/gdb/minsyms.c.orig
++++ gdb-16.2/gdb/minsyms.c
+@@ -575,6 +575,8 @@ lookup_minimal_symbol_linkage (const char *name, struct objfile
*objf,
+ if (strcmp (msymbol->linkage_name (), name) == 0
+ && (msymbol->type () == mst_data
+ || msymbol->type () == mst_bss
++ || msymbol->type () == mst_file_bss
++ || msymbol->type () == mst_file_data
+ || (match_static_type
+ && (msymbol->type () == mst_file_data
+ || msymbol->type () == mst_file_bss))))
+--- gdb-16.2/gdb/ui-file.h.orig
++++ gdb-16.2/gdb/ui-file.h
+@@ -273,6 +273,7 @@ class stdio_file : public ui_file
+ int fd () const override
+ { return m_fd; }
+
++ FILE *get_stream(void);
+ /* Sets the internal stream to FILE, and saves the FILE's file
+ descriptor in M_FD. */
+ void set_stream (FILE *file);
+--- gdb-16.2/gdb/ui-file.c.orig
++++ gdb-16.2/gdb/ui-file.c
+@@ -251,6 +251,12 @@ stdio_file::~stdio_file ()
+ fclose (m_file);
+ }
+
++FILE*
++stdio_file::get_stream(void)
++{
++ return m_file;
++}
++
+ void
+ stdio_file::set_stream (FILE *file)
+ {
+--- gdb-16.2/gdb/symtab.c.orig
++++ gdb-16.2/gdb/symtab.c
+@@ -7399,8 +7399,12 @@ void
+ gdb_command_funnel_1(struct gnu_request *req)
+ {
+ struct symbol *sym;
++ FILE *original_stdout_stream = nullptr;
++ FILE *original_stderr_stream = nullptr;
+
+ if (req->command != GNU_VERSION && req->command !=
GNU_USER_PRINT_OPTION) {
++ original_stdout_stream = (dynamic_cast< stdio_file *
>gdb_stdout)->get_stream();
++ original_stderr_stream = (dynamic_cast< stdio_file *
>gdb_stderr)->get_stream();
+ (dynamic_cast<stdio_file
*>gdb_stdout)->set_stream(req->fp);
+ (dynamic_cast<stdio_file
*>gdb_stderr)->set_stream(req->fp);
+ }
+@@ -7503,6 +7507,12 @@ gdb_command_funnel_1(struct gnu_request *req)
+ req->flags |= GNU_COMMAND_FAILED;
+ break;
+ }
++
++ /* Restore the streams gdb output was using */
++ if (original_stdout_stream)
++ (dynamic_cast<stdio_file
*>gdb_stdout)->set_stream(original_stdout_stream);
++ if (original_stderr_stream)
++ (dynamic_cast<stdio_file
*>gdb_stderr)->set_stream(original_stderr_stream);
+ }
+
+ /*
+--- gdb-16.2/gdb/stack.c.orig
++++ gdb-16.2/gdb/stack.c
+@@ -1968,6 +1968,11 @@ static frame_command_helper <select_frame_command_core>
select_frame_cmd;
+ /* Print briefly all stack frames or just the innermost COUNT_EXP
+ frames. */
+
++#ifdef CRASH_MERGE
++extern "C" int is_kvaddr(ulong);
++extern "C" int gdb_CRASHDEBUG(ulong);
++#endif
++
+ static void
+ backtrace_command_1 (const frame_print_options &fp_opts,
+ const backtrace_cmd_options &bt_opts,
+@@ -2062,6 +2067,17 @@ backtrace_command_1 (const frame_print_options &fp_opts,
+ hand, perhaps the code does or could be fixed to make sure
+ the frame->prev field gets set to NULL in that case). */
+
++#ifdef CRASH_MERGE
++ CORE_ADDR pc = 0;
++ get_frame_pc_if_available (fi, &pc);
++ if (!is_kvaddr(pc)) {
++ if (gdb_CRASHDEBUG(1)) {
++ gdb_printf(_("Backtrace stopped: due to non-kernel addr:
0x%lx\n"),pc);
++ }
++ fi = NULL;
++ break;
++ }
++#endif
+ print_frame_info (fp_opts, fi, 1, LOCATION, 1, 0);
+ if ((flags & PRINT_LOCALS) != 0)
+ print_frame_local_vars (fi, false, NULL, NULL, 1, gdb_stdout);
+--- gdb-16.2/gdb/stack.c.orig
++++ gdb-16.2/gdb/stack.c
+@@ -2097,7 +2097,7 @@ backtrace_command_1 (const frame_print_options &fp_opts,
+ enum unwind_stop_reason reason;
+
+ reason = get_frame_unwind_stop_reason (trailing);
+- if (reason >= UNWIND_FIRST_ERROR)
++ if (reason >= UNWIND_FIRST_ERROR && gdb_CRASHDEBUG(1))
+ gdb_printf (_("Backtrace stopped: %s\n"),
+ frame_stop_reason_string (trailing));
+ }
+--- gdb-16.2/gdb/frame.c.orig
++++ gdb-16.2/gdb/frame.c
+@@ -966,6 +966,10 @@ frame_find_by_id (struct frame_id id)
+ return NULL;
+ }
+
++#if defined(CRASH_MERGE) && defined(ARM64)
++extern "C" void crash_decode_ptrauth_pc(ulong* pc);
++#endif
++
+ static CORE_ADDR
+ frame_unwind_pc (const frame_info_ptr &this_frame)
+ {
+@@ -996,6 +1000,9 @@ frame_unwind_pc (const frame_info_ptr &this_frame)
+ try
+ {
+ pc = gdbarch_unwind_pc (prev_gdbarch, this_frame);
++#if defined(CRASH_MERGE) && defined(ARM64)
++ crash_decode_ptrauth_pc(&pc);
++#endif
+ pc_p = true;
+ }
+ catch (const gdb_exception_error &ex)
+--- gdb-16.2/gdb/event-top.c.orig
++++ gdb-16.2/gdb/event-top.c
+@@ -1558,6 +1558,10 @@
+ {
+ struct ui *ui = current_ui;
+
++ if (!batch_silent)
++ gdb_stdout = new stdio_file (ui->outstream);
++ gdb_stderr = new stderr_file (ui->errstream);
++
+ /* If the input stream is connected to a terminal, turn on editing.
+ However, that is only allowed on the main UI, as we can only have
+ one instance of readline. Also, INSTREAM might be nullptr when
+--- gdb-16.2/gdb/symtab.c.orig
++++ gdb-16.2/gdb/symtab.c
+@@ -3023,7 +3023,7 @@
+ for (objfile *objf : current_program_space->objfiles ())
+ {
+ struct compunit_symtab *result
+- = objf->find_pc_sect_compunit_symtab (msymbol, pc, section, 1);
++ = objf->find_pc_sect_compunit_symtab (msymbol, pc, section, 0);
+ if (result != NULL)
+ return result;
+ }
diff --git a/gdb_interface.c b/gdb_interface.c
index c2e99f5..fa2e85b 100644
--- a/gdb_interface.c
+++ b/gdb_interface.c
@@ -17,7 +17,7 @@
#include "defs.h"
-#ifndef GDB_10_2
+#if !defined(GDB_10_2) && !defined(GDB_16_2)
static void exit_after_gdb_info(void);
#endif
static int is_restricted_command(char *, ulong);
@@ -71,7 +71,7 @@ gdb_main_loop(int argc, char **argv)
}
optind = 0;
-#ifndef GDB_10_2
+#if !defined(GDB_10_2) && !defined(GDB_16_2)
#if defined(GDB_5_3) || defined(GDB_6_0) || defined(GDB_6_1)
command_loop_hook = main_loop;
#else
@@ -122,7 +122,7 @@ void
display_gdb_banner(void)
{
optind = 0;
-#ifndef GDB_10_2
+#if !defined(GDB_10_2) && !defined(GDB_16_2)
#if defined(GDB_5_3) || defined(GDB_6_0) || defined(GDB_6_1)
command_loop_hook = exit_after_gdb_info;
#else
@@ -134,7 +134,7 @@ display_gdb_banner(void)
gdb_main_entry(2, args);
}
-#ifndef GDB_10_2
+#if !defined(GDB_10_2) && !defined(GDB_16_2)
static void
exit_after_gdb_info(void)
{
@@ -159,13 +159,15 @@ get_gdb_version(void)
}
}
+extern void *current_program_space;
+
void
gdb_session_init(void)
{
struct gnu_request *req;
int debug_data_pulled_in;
- if (!have_partial_symbols() && !have_full_symbols())
+ if (!have_partial_symbols(current_program_space) &&
!have_full_symbols(current_program_space))
no_debugging_data(FATAL);
/*
@@ -300,7 +302,7 @@ retry:
sprintf(req->buf, "set width 0");
gdb_interface(req);
-#ifdef GDB_10_2
+#if defined(GDB_10_2) || defined(GDB_16_2)
req->command = GNU_PASS_THROUGH;
req->name = NULL, req->flags = 0;
sprintf(req->buf, "set max-value-size unlimited");
diff --git a/kernel.c b/kernel.c
index 1adbfab..612b956 100644
--- a/kernel.c
+++ b/kernel.c
@@ -23,7 +23,7 @@
#include <ctype.h>
#include <stdbool.h>
#include "xendump.h"
-#if defined(GDB_7_6) || defined(GDB_10_2)
+#if defined(GDB_7_6) || defined(GDB_10_2) || defined(GDB_16_2)
#define __CONFIG_H__ 1
#include "config.h"
#endif
@@ -1574,8 +1574,8 @@ list_source_code(struct gnu_request *req, int count_entered)
error(FATAL,
"%s: source code is not available\n\n", req->buf);
- sprintf(buf3, "%s: No such file or directory.", file);
- if (decimal(argv[0], 0) && strstr(buf1, buf3))
+ sprintf(buf3, "%s: No such file or directory", file);
+ if ((decimal(argv[0], 0) || decimal(argv[1], 0)) && strstr(buf1, buf3))
error(FATAL,
"%s: source code is not available\n\n", req->buf);
diff --git a/symbols.c b/symbols.c
index f6f52bd..6385d02 100644
--- a/symbols.c
+++ b/symbols.c
@@ -17,7 +17,7 @@
#include "defs.h"
#include <elf.h>
-#if defined(GDB_7_6) || defined(GDB_10_2)
+#if defined(GDB_7_6) || defined(GDB_10_2) || defined(GDB_16_2)
#define __CONFIG_H__ 1
#include "config.h"
#endif
@@ -479,7 +479,7 @@ separate_debug_file_exists(const char *name, unsigned long crc, int
*exists)
#ifdef GDB_5_3
file_crc = calc_crc32(file_crc, buffer, count);
#else
-#if defined(GDB_7_6) || defined(GDB_10_2)
+#if defined(GDB_7_6) || defined(GDB_10_2) || defined(GDB_16_2)
file_crc = bfd_calc_gnu_debuglink_crc32(file_crc,
(unsigned char *)buffer, count);
#else
--
2.47.0