Fully redone gdb-7.6.patch to gdb-10.1.patch to keep all
functionality.

Main difference between gdb-7.6 and gdb-10.1 is the last
one was rewritten in C++.
I continue to keep crash code in C. Mark transition
functions as extern "C" to resolve linking issues.

Eliminated error_hook() and SJLJ while running in C++ code
(after gdb_command_funnel()) use try-catch mechanism instead.

request_types() was redone to do not call
GNU_GET_NEXT_DATATYPE multiple times but single usage of
GNU_ITERATE_DATATYPES with proper callback instead.
Complete iteration happens on C++ side now.
Removed "struct global_iterator" from request structure,
but added several fields (including callback pointer) to
be able to perform iteration on C++ side.

Type of "linux_banner" symbol is reported as 'D' by new
gdb as its section ".rodata" marked as writable in vmlinux.

BFD API has changed.

deprecated_command_loop_hook got deprecated. So, call crash
main_loop() directly from gdb captured_main().

Added symbol file (vmlinux) rebase in gdb by kaslr_offset.
by using new function: objfile_rebase().
As result, we do not need kernel symbol patching as well as
bait_and_switch hook anymore.

Added crash_target for gdb to provide target operations
such as xfer_partial to read and write crash dump memory.
Removed previously used hooks for that in target.c.
Keep crash_target.c as a file in crash folder instead of
in gdb-10.1.patch for easier development and history
tracking.
crash_target can be enhanced in future to provide access
to CPU registers, so backtrace and frame related commands
from gdb can be used.

Extra: add VMware copyright to the version info.

TODO:
1) remove gdb-7.6.patch.
2) remove gdb-7.6-proc_service.h.patch is not required as
gdb-10.1 already has this change.
3) update gdb-10.1-ppc64le-support.patch
4) deprecate #if defined(GDB_X_Y) code as crash really
supports only the latest gdb (only one patch).
5) move gdb_funnel_command() and subfunctions to separate
file, similar to crash_target.c
6) remove legacy kernel patching and bait_and_switch hook.

Signed-off-by: Alexey Makhalov <[email protected]>
---
 Makefile                                           |   11 +-
 configure.c                                        |   20 +-
 crash_target.c                                     |  104 ++
 defs.h                                             |   31 +-
 ...support.patch => gdb-10.1-ppc64le-support.patch |    0
 gdb-10.1.patch                                     | 1629 ++++++++++++++++++++
 gdb_interface.c                                    |   60 +-
 help.c                                             |    1 +
 kernel.c                                           |    2 +-
 main.c                                             |    1 -
 symbols.c                                          |  125 +-
 x86_64.c                                           |    2 +-
 12 files changed, 1861 insertions(+), 125 deletions(-)
 create mode 100644 crash_target.c
 rename gdb-7.6-ppc64le-support.patch => gdb-10.1-ppc64le-support.patch (100%)
 create mode 100644 gdb-10.1.patch

diff --git a/Makefile b/Makefile
index 31a3d3d..a4c7bdb 100644
--- a/Makefile
+++ b/Makefile
@@ -182,6 +182,9 @@ GDB_7.3.1_OFILES=${GDB}/gdb/symtab.o
 GDB_7.6_FILES=
 GDB_7.6_OFILES=${GDB}/gdb/symtab.o
 
+GDB_10.1_FILES=
+GDB_10.1_OFILES=${GDB}/gdb/symtab.o
+
 # 
 # GDB_FLAGS is passed up from the gdb Makefile.
 #
@@ -207,7 +210,7 @@ TAR_FILES=${SOURCE_FILES} Makefile ${GPL_FILES} README 
.rh_rpm_package crash.8 \
        ${EXTENSION_SOURCE_FILES} ${MEMORY_DRIVER_FILES}
 CSCOPE_FILES=${SOURCE_FILES}
 
-READLINE_DIRECTORY=./${GDB}/readline
+READLINE_DIRECTORY=./${GDB}/readline/readline
 BFD_DIRECTORY=./${GDB}/bfd
 GDB_INCLUDE_DIRECTORY=./${GDB}/include
 
@@ -272,12 +275,6 @@ gdb_patch:
        if [ "${ARCH}" = "x86_64" ] && [ "${TARGET}" = "PPC64" ] && [ -f 
${GDB}-ppc64le-support.patch ]; then \
                patch -d ${GDB} -p1 -F0 < ${GDB}-ppc64le-support.patch ; \
        fi
-       if [ -f /usr/include/proc_service.h ]; then \
-               grep 'extern ps_err_e ps_get_thread_area (struct' 
/usr/include/proc_service.h; \
-               if [ $$? -eq 0 ]; then \
-                       patch -p0 < ${GDB}-proc_service.h.patch; \
-               fi; \
-       fi
 
 library: make_build_data ${OBJECT_FILES}
        ar -rs ${PROGRAM}lib.a ${OBJECT_FILES}
diff --git a/configure.c b/configure.c
index 9480829..9cd3f9f 100644
--- a/configure.c
+++ b/configure.c
@@ -177,9 +177,10 @@ void add_extra_lib(char *);
 #define GDB_7_0   (3)
 #define GDB_7_3_1 (4)
 #define GDB_7_6   (5)
-#define SUPPORTED_GDB_VERSIONS (GDB_7_6 + 1)
+#define GDB_10_1   (6)
+#define SUPPORTED_GDB_VERSIONS (GDB_10_1 + 1)
 
-int default_gdb = GDB_7_6;
+int default_gdb = GDB_10_1;
 
 struct supported_gdb_version {
        char *GDB;
@@ -244,6 +245,15 @@ struct supported_gdb_version {
            "GDB_FLAGS=-DGDB_7_6",
            "GPLv3"
        },
+       {
+           "GDB=gdb-10.1",
+           "10.1",
+           "GDB_FILES=${GDB_10.1_FILES}",
+           "GDB_OFILES=${GDB_10.1_OFILES}",
+           "GDB_PATCH_FILES=gdb-10.1.patch gdb-10.1-ppc64le-support.patch",
+           "GDB_FLAGS=-DGDB_10_1",
+           "GPLv3"
+       },
 };
 
 #define DAEMON  0x1
@@ -1494,6 +1504,12 @@ setup_gdb_defaults(void)
                        fprintf(stderr, ".gdb configuration: %s\n", 
sp->GDB_VERSION_IN);
                        return store_gdb_defaults(sp);
                }
+               if (strcmp(buf, "10.1") == 0) {
+                       fclose(fp);
+                       sp = &supported_gdb_versions[GDB_10_1];
+                       fprintf(stderr, ".gdb configuration: %s\n", 
sp->GDB_VERSION_IN);
+                       return store_gdb_defaults(sp);
+               }
 
         }
        
diff --git a/crash_target.c b/crash_target.c
new file mode 100644
index 0000000..303578f
--- /dev/null
+++ b/crash_target.c
@@ -0,0 +1,104 @@
+/*
+ * crash_target.c
+ *
+ * Copyright (c) 2021 VMware, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Author: Alexey Makhalov <[email protected]>
+ */
+
+#include <defs.h>
+#include "top.h"
+#include "target.h"
+#include "inferior.h"
+#include "regcache.h"
+#include "gdbarch.h"
+
+void crash_target_init (void);
+
+extern "C" int gdb_readmem_callback(unsigned long, void *, int, int);
+extern "C" int crash_get_nr_cpus(void);
+
+
+/* The crash target.  */
+
+static const target_info crash_target_info = {
+  "crash",
+  N_("Local core dump file"),
+  N_("Use a built-in crash instance as a target.")
+};
+
+class crash_target final : public process_stratum_target
+{
+public:
+
+  const target_info &info () const override
+  { return crash_target_info; }
+
+  enum target_xfer_status xfer_partial (enum target_object object,
+                                       const char *annex,
+                                       gdb_byte *readbuf,
+                                       const gdb_byte *writebuf,
+                                       ULONGEST offset, ULONGEST len,
+                                       ULONGEST *xfered_len) override;
+
+  bool has_all_memory () override { return true; }
+  bool has_memory () override { return true; }
+  bool has_stack () override { return true; }
+  bool has_registers () override { return false; }
+  bool thread_alive (ptid_t ptid) override { return true; }
+  std::string pid_to_str (ptid_t ptid) override
+  { return string_printf ("CPU %ld", ptid.tid ()); }
+
+};
+
+
+enum target_xfer_status
+crash_target::xfer_partial (enum target_object object, const char *annex,
+                          gdb_byte *readbuf, const gdb_byte *writebuf,
+                          ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
+{
+  if (object != TARGET_OBJECT_MEMORY && object != TARGET_OBJECT_STACK_MEMORY
+      && object != TARGET_OBJECT_CODE_MEMORY)
+       return TARGET_XFER_E_IO;
+
+  if (gdb_readmem_callback(offset, (void *)(readbuf ? readbuf : writebuf), 
len, !readbuf))
+    {
+      *xfered_len = len;
+      return TARGET_XFER_OK;
+    }
+
+  return TARGET_XFER_E_IO;
+}
+
+#define CRASH_INFERIOR_PID 1
+
+void
+crash_target_init (void)
+{
+  int nr_cpus = crash_get_nr_cpus();
+  crash_target *target = new crash_target ();
+
+  /* Own the target until it is successfully pushed.  */
+  target_ops_up target_holder (target);
+
+  push_target (std::move (target_holder));
+
+  inferior_appeared (current_inferior (), CRASH_INFERIOR_PID);
+  for (int i = 0; i < nr_cpus; i++)
+    {
+      thread_info *thread = add_thread_silent (target,
+                                       ptid_t(CRASH_INFERIOR_PID, 0, i));
+      if (!i)
+        switch_to_thread (thread);
+    }
+}
diff --git a/defs.h b/defs.h
index 35b983a..241ee24 100644
--- a/defs.h
+++ b/defs.h
@@ -502,7 +502,6 @@ struct program_context {
        struct sigaction gdb_sigaction; /* gdb's SIGINT sigaction. */
        jmp_buf main_loop_env;          /* longjmp target default */
        jmp_buf foreach_loop_env;       /* longjmp target within foreach */
-        jmp_buf gdb_interface_env;      /* longjmp target for gdb error catch 
*/
        struct termios termios_orig;    /* non-raw settings */
        struct termios termios_raw;     /* while gathering command input */
        int ncmds;                      /* number of commands in menu */
@@ -2568,7 +2567,7 @@ struct datatype_member {        /* minimal definition of 
a structure/union */
        long member_size;
        int member_typecode;
        ulong flags;
-       char *tagname;         /* tagname and value for enums */
+       const char *tagname;         /* tagname and value for enums */
        long value;
        ulong vaddr;
 };
@@ -4663,7 +4662,7 @@ struct gnu_request {
        long member_length;
        int member_typecode;
        long value;
-       char *tagname;
+       const char *tagname;
        ulong pc;
        ulong sp;
        ulong ra;
@@ -4675,13 +4674,10 @@ struct gnu_request {
        ulong task;
        ulong debug;
        struct stack_hook *hookp;
-       struct global_iterator {
-               int finished; 
-               int block_index;
-               struct symtab *symtab;
-               struct symbol *sym;
-               struct objfile *obj;
-       } global_iterator;
+       ulong lowest;
+       ulong highest;
+       void (*callback) (struct gnu_request *req, void *data);
+       void *callback_data;
        struct load_module *lm;
        char *member_main_type_name;
        char *member_main_type_tag_name;
@@ -4711,7 +4707,7 @@ struct gnu_request {
 #define GNU_USER_PRINT_OPTION       (16)
 #define GNU_SET_CRASH_BLOCK         (17)
 #define GNU_GET_FUNCTION_RANGE      (18)
-#define GNU_GET_NEXT_DATATYPE       (19)
+#define GNU_ITERATE_DATATYPES       (19)
 #define GNU_LOOKUP_STRUCT_CONTENTS  (20)
 #define GNU_DEBUG_COMMAND           (100)
 /*
@@ -4736,14 +4732,15 @@ struct gnu_request {
 /*
  *  function prototypes required by modified gdb source files.
  */
-int console(char *, ...);
-int gdb_CRASHDEBUG(ulong);
+extern "C" int console(char *, ...);
+extern "C" int gdb_CRASHDEBUG(ulong);
 int gdb_readmem_callback(ulong, void *, int, int);
 void patch_load_module(struct objfile *objfile, struct minimal_symbol 
*msymbol);
-int patch_kernel_symbol(struct gnu_request *);
+extern "C" int patch_kernel_symbol(struct gnu_request *);
 struct syment *symbol_search(char *);
 int gdb_line_number_callback(ulong, ulong, ulong);
 int gdb_print_callback(ulong);
+extern "C" int same_file(char *, char *);
 #endif
 
 #ifndef GDB_COMMON
@@ -4757,8 +4754,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)
-#if defined(GDB_7_0) || defined(GDB_7_3_1) || defined(GDB_7_6)
+#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_1)
+#if defined(GDB_7_0) || defined(GDB_7_3_1) || defined(GDB_7_6) || 
defined(GDB_10_1)
   TYPE_CODE_FLAGS,              /* Bit flags type */
 #endif
   TYPE_CODE_FUNC,               /* Function type */
@@ -5422,9 +5419,7 @@ int file_dump(ulong, ulong, ulong, int, int);
 #define DUMP_DENTRY_ONLY    0x4
 #define DUMP_EMPTY_FILE     0x8
 #define DUMP_FILE_NRPAGES  0x10
-#endif  /* !GDB_COMMON */
 int same_file(char *, char *);
-#ifndef GDB_COMMON
 int cleanup_memory_driver(void);
 
 
diff --git a/gdb-7.6-ppc64le-support.patch b/gdb-10.1-ppc64le-support.patch
similarity index 100%
rename from gdb-7.6-ppc64le-support.patch
rename to gdb-10.1-ppc64le-support.patch
diff --git a/gdb-10.1.patch b/gdb-10.1.patch
new file mode 100644
index 0000000..86ad3b4
--- /dev/null
+++ b/gdb-10.1.patch
@@ -0,0 +1,1629 @@
+
+# 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 uninintended 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.
+
+# The gdb-7.6-ppc64le-support.patch will have modified both files below
+# during the initial build, so continue previous behavior.
+
+if [ "$1" = "PPC64" ]
+then
+  exit 0
+fi
+
+tar xvzmf gdb-10.1.tar.gz \
+       gdb-10.1/gdb/main.c \
+       gdb-10.1/gdb/symtab.c \
+       gdb-10.1/gdb/printcmd.c
+
+exit 0
+
+diff -aurp -X diff_exclude gdb-10.1.orig/gdb/cli/cli-cmds.c 
gdb-10.1/gdb/cli/cli-cmds.c
+--- gdb-10.1.orig/gdb/cli/cli-cmds.c   2020-10-23 21:23:02.000000000 -0700
++++ gdb-10.1/gdb/cli/cli-cmds.c        2020-11-10 13:06:56.423569114 -0800
+@@ -435,6 +435,11 @@ complete_command (const char *arg, int f
+     }
+ }
+ 
++#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
+       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 *f
+          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 *f
+ 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
+diff -aurp -X diff_exclude gdb-10.1.orig/gdb/defs.h gdb-10.1/gdb/defs.h
+--- gdb-10.1.orig/gdb/defs.h   2020-09-12 19:33:41.000000000 -0700
++++ gdb-10.1/gdb/defs.h        2020-11-10 13:06:56.423569114 -0800
+@@ -629,4 +629,7 @@ DEF_ENUM_FLAGS_TYPE (enum user_selected_
+ 
+ #include "utils.h"
+ 
++#ifdef CRASH_MERGE
++extern "C" int gdb_main_entry(int, char **);
++#endif
+ #endif /* #ifndef DEFS_H */
+diff -aurp -X diff_exclude gdb-10.1.orig/gdb/dwarf2/read.c 
gdb-10.1/gdb/dwarf2/read.c
+--- gdb-10.1.orig/gdb/dwarf2/read.c    2020-10-23 21:23:02.000000000 -0700
++++ gdb-10.1/gdb/dwarf2/read.c 2020-11-10 13:06:56.427569136 -0800
+@@ -3003,7 +3003,11 @@ read_gdb_index_from_buffer (const char *
+      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."),
+@@ -3022,7 +3026,11 @@ read_gdb_index_from_buffer (const char *
+      "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 (_("\
+diff -aurp -X diff_exclude gdb-10.1.orig/gdb/main.c gdb-10.1/gdb/main.c
+--- gdb-10.1.orig/gdb/main.c   2020-09-12 19:33:41.000000000 -0700
++++ gdb-10.1/gdb/main.c        2020-11-12 21:59:25.181230400 -0800
+@@ -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_ar
+       }
+   }
+ 
++#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_ar
+     {
+       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_ar
+      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_ar
+   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_ar
+      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_ar
+                                 !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_ar
+       {
+         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 *arg
+   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
+diff -aurp -X diff_exclude gdb-10.1.orig/gdb/Makefile.in 
gdb-10.1/gdb/Makefile.in
+--- gdb-10.1.orig/gdb/Makefile.in      2020-10-23 21:23:02.000000000 -0700
++++ gdb-10.1/gdb/Makefile.in   2020-11-12 18:51:04.273363098 -0800
+@@ -571,7 +571,7 @@ CONFIG_DEP_SUBDIR = $(addsuffix /$(DEPDI
+ # 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 @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) $
+       $(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_1 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 $(@F)).Tpo
+-override POSTCOMPILE = @mv $(@D)/$(DEPDIR)/$(basename $(@F)).Tpo \
+-      $(@D)/$(DEPDIR)/$(basename $(@F)).Po
++      -MF $(subst ../..,.,$(@D))/$(DEPDIR)/$(basename $(@F)).Tpo
++override POSTCOMPILE = @mv $(subst ../..,.,$(@D))/$(DEPDIR)/$(basename 
$(@F)).Tpo \
++      $(subst ../..,.,$(@D))/$(DEPDIR)/$(basename $(@F)).Po
+ else
+ override COMPILE.pre = source='$<' object='$@' libtool=no \
+       DEPDIR=$(DEPDIR) $(DEPMODE) $(depcomp) \
+diff -aurp -X diff_exclude gdb-10.1.orig/gdb/objfiles.h gdb-10.1/gdb/objfiles.h
+--- gdb-10.1.orig/gdb/objfiles.h       2020-09-12 19:33:41.000000000 -0700
++++ gdb-10.1/gdb/objfiles.h    2020-11-10 13:06:56.431569157 -0800
+@@ -747,9 +747,9 @@ extern int objfile_has_full_symbols (str
+ 
+ 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);
+diff -aurp -X diff_exclude gdb-10.1.orig/gdb/printcmd.c gdb-10.1/gdb/printcmd.c
+--- gdb-10.1.orig/gdb/printcmd.c       2020-10-23 21:23:02.000000000 -0700
++++ gdb-10.1/gdb/printcmd.c    2020-11-10 13:06:56.431569157 -0800
+@@ -524,6 +524,9 @@ set_next_address (struct gdbarch *gdbarc
+    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 *
+   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 v
+     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\" c
+   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,
+diff -aurp -X diff_exclude gdb-10.1.orig/gdb/psymtab.c gdb-10.1/gdb/psymtab.c
+--- gdb-10.1.orig/gdb/psymtab.c        2020-10-23 21:23:02.000000000 -0700
++++ gdb-10.1/gdb/psymtab.c     2020-11-10 13:06:56.431569157 -0800
+@@ -283,6 +283,9 @@ find_pc_sect_psymtab_closer (struct objf
+   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
+@@ -305,6 +308,7 @@ find_pc_sect_psymtab (struct objfile *ob
+      partial symtabs then we will end up returning a pointer to an object
+      that is not a partial_symtab, which doesn't end well.  */
+ 
++#ifndef __i386__
+   if (objfile->partial_symtabs->psymtabs != NULL
+       && objfile->partial_symtabs->psymtabs_addrmap != NULL)
+     {
+@@ -345,6 +349,7 @@ find_pc_sect_psymtab (struct objfile *ob
+     }
+ 
+  next:
++#endif
+ 
+   /* Existing PSYMTABS_ADDRMAP mapping is present even for PARTIAL_SYMTABs
+      which still have no corresponding full SYMTABs read.  But it is not
+@@ -363,7 +368,12 @@ find_pc_sect_psymtab (struct objfile *ob
+ 
+       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;
+       }
+ 
+diff -aurp -X diff_exclude gdb-10.1.orig/gdb/symfile.c gdb-10.1/gdb/symfile.c
+--- gdb-10.1.orig/gdb/symfile.c        2020-10-23 21:23:02.000000000 -0700
++++ gdb-10.1/gdb/symfile.c     2020-11-10 13:06:56.431569157 -0800
+@@ -652,7 +652,26 @@ default_symfile_offsets (struct 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, c
+   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_fil
+ #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 *di
+   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,13 @@ find_separate_debug_file_by_debuglink (s
+       }
+     }
+ 
++#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 +2379,10 @@ add_symbol_file_command (const char *arg
+   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, &section_addrs,
+                         flags);
+@@ -3622,6 +3669,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);
+diff -aurp -X diff_exclude gdb-10.1.orig/gdb/symtab.c gdb-10.1/gdb/symtab.c
+--- gdb-10.1.orig/gdb/symtab.c 2020-10-23 21:23:02.000000000 -0700
++++ gdb-10.1/gdb/symtab.c      2020-12-29 01:15:23.879160974 -0800
+@@ -1870,27 +1870,44 @@ search_name_hash (enum language language
+    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 +6903,806 @@ If zero then the symbol cache is disable
+   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
+diff -aurp -X diff_exclude gdb-10.1.orig/gdb/ui-file.h gdb-10.1/gdb/ui-file.h
+--- gdb-10.1.orig/gdb/ui-file.h        2020-09-12 19:33:41.000000000 -0700
++++ gdb-10.1/gdb/ui-file.h     2020-11-10 13:06:56.435569179 -0800
+@@ -195,10 +195,10 @@ public:
+ 
+   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;
+diff -aurp -X diff_exclude gdb-10.1.orig/gdb/xml-syscall.c 
gdb-10.1/gdb/xml-syscall.c
+--- gdb-10.1.orig/gdb/xml-syscall.c    2020-10-23 21:23:02.000000000 -0700
++++ gdb-10.1/gdb/xml-syscall.c 2020-11-10 13:06:56.435569179 -0800
+@@ -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;
+diff -aurp -X diff_exclude gdb-10.1.orig/libiberty/Makefile.in 
gdb-10.1/libiberty/Makefile.in
+--- gdb-10.1.orig/libiberty/Makefile.in        2020-09-12 19:33:41.000000000 
-0700
++++ gdb-10.1/libiberty/Makefile.in     2020-11-10 13:06:56.439569200 -0800
+@@ -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)
+       ./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)                                             \
+diff -aurp -X diff_exclude gdb-10.1.orig/Makefile.in gdb-10.1/Makefile.in
+--- gdb-10.1.orig/Makefile.in  2020-10-23 21:25:19.000000000 -0700
++++ gdb-10.1/Makefile.in       2020-11-10 13:06:56.447569243 -0800
+@@ -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@
+diff -aurp -X diff_exclude gdb-10.1.orig/opcodes/i386-dis.c 
gdb-10.1/opcodes/i386-dis.c
+--- gdb-10.1.orig/opcodes/i386-dis.c   2020-10-23 21:23:02.000000000 -0700
++++ gdb-10.1/opcodes/i386-dis.c        2020-11-10 13:06:56.451569264 -0800
+@@ -9778,6 +9778,10 @@ print_insn (bfd_vma pc, disassemble_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
+diff -aurp -X diff_exclude gdb-10.1.orig/readline/readline/misc.c 
gdb-10.1/readline/readline/misc.c
+--- gdb-10.1.orig/readline/readline/misc.c     2020-09-12 19:33:41.000000000 
-0700
++++ gdb-10.1/readline/readline/misc.c  2020-11-10 13:06:56.451569264 -0800
+@@ -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)
+diff -aurp -X diff_exclude gdb-10.1.orig/readline/readline/readline.h 
gdb-10.1/readline/readline/readline.h
+--- gdb-10.1.orig/readline/readline/readline.h 2020-09-12 19:33:41.000000000 
-0700
++++ gdb-10.1/readline/readline/readline.h      2020-11-10 13:06:56.451569264 
-0800
+@@ -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));
+diff -aurp -X diff_exclude gdb-10.1.orig/readline/readline/rltypedefs.h 
gdb-10.1/readline/readline/rltypedefs.h
+--- gdb-10.1.orig/readline/readline/rltypedefs.h       2020-09-12 
19:33:41.000000000 -0700
++++ gdb-10.1/readline/readline/rltypedefs.h    2020-11-10 13:06:56.451569264 
-0800
+@@ -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 ();
+diff -aurp -X diff_exclude gdb-10.1.orig/readline/readline/util.c 
gdb-10.1/readline/readline/util.c
+--- gdb-10.1.orig/readline/readline/util.c     2020-09-12 19:33:41.000000000 
-0700
++++ gdb-10.1/readline/readline/util.c  2020-11-10 13:06:56.451569264 -0800
+@@ -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;
+ }
diff --git a/gdb_interface.c b/gdb_interface.c
index f4f4dd3..5a41992 100644
--- a/gdb_interface.c
+++ b/gdb_interface.c
@@ -17,7 +17,9 @@
 
 #include "defs.h"
 
+#ifndef GDB_10_1
 static void exit_after_gdb_info(void);
+#endif
 static int is_restricted_command(char *, ulong);
 static void strip_redirection(char *);
 int get_frame_offset(ulong);
@@ -29,6 +31,7 @@ int *gdb_prettyprint_arrays;
 int *gdb_repeat_count_threshold;
 int *gdb_stop_print_at_null;
 unsigned int *gdb_output_radix;
+static void gdb_error_debug(void);
 
 static ulong gdb_user_print_option_address(char *);
 
@@ -68,11 +71,13 @@ gdb_main_loop(int argc, char **argv)
        }
 
         optind = 0;
+#ifndef GDB_10_1
 #if defined(GDB_5_3) || defined(GDB_6_0) || defined(GDB_6_1)
         command_loop_hook = main_loop;
 #else
        deprecated_command_loop_hook = main_loop;
 #endif
+#endif
         gdb_main_entry(argc, argv);
 }
 
@@ -117,22 +122,26 @@ void
 display_gdb_banner(void)
 {
        optind = 0;
+#ifndef GDB_10_1
 #if defined(GDB_5_3) || defined(GDB_6_0) || defined(GDB_6_1)
         command_loop_hook = exit_after_gdb_info;
 #else
         deprecated_command_loop_hook = exit_after_gdb_info;
 #endif
+#endif
        args[0] = "gdb";
        args[1] = "-version";
        gdb_main_entry(2, args);
 }
 
+#ifndef GDB_10_1
 static void
 exit_after_gdb_info(void)
 {
         fprintf(fp, "\n");
         clean_exit(0);
 }
+#endif
 
 /* 
  *  Stash a copy of the gdb version locally.  This can be called before
@@ -291,6 +300,7 @@ retry:
        sprintf(req->buf, "set width 0");
        gdb_interface(req);
 
+#if 0
        /*
         *  Patch gdb's symbol values with the correct values from either
         *  the System.map or non-debug vmlinux, whichever is in effect.
@@ -303,9 +313,13 @@ retry:
                if (req->flags & GNU_COMMAND_FAILED)
                        error(FATAL, "patching of gdb symbol values failed\n");
        } else if (!(pc->flags & SILENT))
+#else
+       if (!(pc->flags & SILENT))
+#endif
                fprintf(fp, "\n");
 
 
+
        FREEBUF(req->buf);
        FREEBUF(req);
 }
@@ -364,19 +378,6 @@ gdb_interface(struct gnu_request *req)
        pc->cur_req = req;
        pc->cur_gdb_cmd = req->command;
 
-       if (req->flags & GNU_RETURN_ON_ERROR) {
-               error_hook = gdb_error_hook;
-               if (setjmp(pc->gdb_interface_env)) {
-                       pc->last_gdb_cmd = pc->cur_gdb_cmd;
-                       pc->cur_gdb_cmd = 0;
-                       pc->cur_req = NULL;
-                       req->flags |= GNU_COMMAND_FAILED;
-                       pc->flags &= ~IN_GDB;
-                       return;
-               }
-       } else
-               error_hook = NULL;
-
        if (CRASHDEBUG(2))
                dump_gnu_request(req, IN_GDB);
 
@@ -400,10 +401,12 @@ gdb_interface(struct gnu_request *req)
        SIGACTION(SIGINT, restart, &pc->sigaction, NULL);
        SIGACTION(SIGSEGV, SIG_DFL, &pc->sigaction, NULL);
 
+       if (req->flags & GNU_COMMAND_FAILED)
+               gdb_error_debug();
+
        if (CRASHDEBUG(2))
                dump_gnu_request(req, !IN_GDB);
 
-       error_hook = NULL;
         pc->last_gdb_cmd = pc->cur_gdb_cmd;
         pc->cur_gdb_cmd = 0;
        pc->cur_req = NULL;
@@ -627,8 +630,6 @@ restore_gdb_sanity(void)
         *gdb_prettyprint_structs = 1;   /* these may piss somebody off... */
        *gdb_repeat_count_threshold = 0x7fffffff;
 
-       error_hook = NULL;
-
        if (st->flags & ADD_SYMBOL_FILE) {
                error(INFO, 
                    "%s\n     gdb add-symbol-file command failed\n", 
@@ -948,8 +949,8 @@ gdb_print_callback(ulong addr)
 /*
  *  Used by gdb_interface() to catch gdb-related errors, if desired.
  */
-void
-gdb_error_hook(void)
+static void
+gdb_error_debug(void)
 {
        char buf1[BUFSIZE];
        char buf2[BUFSIZE];
@@ -968,14 +969,6 @@ gdb_error_hook(void)
                console("%s: returned via gdb_error_hook %s",
                        gdb_command_string(pc->cur_gdb_cmd, buf1, TRUE), buf2);
        }
-
-#ifdef GDB_7_6
-       do_cleanups(all_cleanups()); 
-#else
-       do_cleanups(NULL); 
-#endif
-
-       longjmp(pc->gdb_interface_env, 1);
 }
 
 
@@ -1066,3 +1059,18 @@ get_frame_offset(ulong pc)
 #endif /* !ALPHA */ 
 
 
+unsigned long crash_get_kaslr_offset(void);
+unsigned long crash_get_kaslr_offset(void)
+{
+       return kt->relocate * -1;
+}
+
+/* Callbacks for crash_target */
+int crash_get_nr_cpus(void);
+
+int crash_get_nr_cpus(void)
+{
+       /* Just CPU #0 */
+       return 1;
+}
+
diff --git a/help.c b/help.c
index 531f50a..983ef16 100644
--- a/help.c
+++ b/help.c
@@ -8266,6 +8266,7 @@ char *version_info[] = {
 "Copyright (C) 2005, 2011  NEC Corporation",
 "Copyright (C) 1999, 2002, 2007  Silicon Graphics, Inc.",
 "Copyright (C) 1999, 2000, 2001, 2002  Mission Critical Linux, Inc.",
+"Copyright (C) 2015, 2021  VMware, Inc.",
 "This program is free software, covered by the GNU General Public License,",
 "and you are welcome to change it and/or distribute copies of it under",
 "certain conditions.  Enter \"help copying\" to see the conditions.",
diff --git a/kernel.c b/kernel.c
index 735263c..b51b11f 100644
--- a/kernel.c
+++ b/kernel.c
@@ -1048,7 +1048,7 @@ verify_version(void)
 
        if (!(sp = symbol_search("linux_banner")))
                error(FATAL, "linux_banner symbol does not exist?\n");
-       else if ((sp->type == 'R') || (sp->type == 'r') ||
+       else if ((sp->type == 'R') || (sp->type == 'r') || (sp->type == 'D') ||
                 (machine_type("ARM") && sp->type == 'T') ||
                 (machine_type("ARM64")))
                linux_banner = symbol_value("linux_banner");
diff --git a/main.c b/main.c
index 388ac46..71c59d2 100644
--- a/main.c
+++ b/main.c
@@ -1704,7 +1704,6 @@ dump_program_context(void)
        fprintf(fp, "    gdb_sigaction: %lx\n", (ulong)&pc->gdb_sigaction);
        fprintf(fp, "    main_loop_env: %lx\n", (ulong)&pc->main_loop_env);
        fprintf(fp, " foreach_loop_env: %lx\n", (ulong)&pc->foreach_loop_env);
-       fprintf(fp, "gdb_interface_env: %lx\n", (ulong)&pc->gdb_interface_env);
        fprintf(fp, "     termios_orig: %lx\n", (ulong)&pc->termios_orig);
        fprintf(fp, "      termios_raw: %lx\n", (ulong)&pc->termios_raw);
        fprintf(fp, "            ncmds: %d\n", pc->ncmds);
diff --git a/symbols.c b/symbols.c
index 215d523..3321625 100644
--- a/symbols.c
+++ b/symbols.c
@@ -17,7 +17,7 @@
 
 #include "defs.h"
 #include <elf.h>
-#ifdef GDB_7_6
+#if defined(GDB_7_6) || defined(GDB_10_1)
 #define __CONFIG_H__ 1
 #include "config.h"
 #endif
@@ -34,7 +34,7 @@ static int compare_mods(const void *, const void *);
 static int compare_prios(const void *v1, const void *v2);
 static int compare_size_name(const void *, const void *);
 struct type_request;
-static void append_struct_symbol (struct type_request *, struct gnu_request *);
+static void append_struct_symbol (struct gnu_request *, void *);
 static void request_types(ulong, ulong, char *);
 static asection *get_kernel_section(char *);
 static char * get_section(ulong vaddr, char *buf);
@@ -278,7 +278,7 @@ check_gnu_debuglink(bfd *bfd)
                return FALSE;
        }
 
-       debuglink_size = bfd_section_size(bfd, sect);
+       debuglink_size = bfd_section_size(sect);
 
        contents = GETBUF(debuglink_size);
 
@@ -443,7 +443,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
-#ifdef GDB_7_6
+#if defined(GDB_7_6) || defined(GDB_10_1)
                file_crc = bfd_calc_gnu_debuglink_crc32(file_crc, 
                        (unsigned char *)buffer, count);
 #else
@@ -524,9 +524,8 @@ get_text_init_space(void)
                return;
        }
 
-        kt->stext_init = (ulong)bfd_get_section_vma(st->bfd, section);
-        kt->etext_init = kt->stext_init +
-               (ulong)bfd_section_size(st->bfd, section);
+       kt->stext_init = (ulong)bfd_section_vma(section);
+       kt->etext_init = kt->stext_init + (ulong)bfd_section_size(section);
 
        if (kt->relocate) {
                kt->stext_init -= kt->relocate;
@@ -774,7 +773,6 @@ store_symbols(bfd *abfd, int dynamic, void *minisyms, long 
symcount,
 
                bfd_get_symbol_info(abfd, sym, &syminfo);
                name = strip_symbol_end(syminfo.name, buf);
-
                if (machdep->verify_symbol(name, syminfo.value, 
                    syminfo.type)) {
                        if (kt->flags & (RELOC_SET|RELOC_FORCE))
@@ -2864,10 +2862,8 @@ is_kernel_text(ulong value)
                for (i = 0; i < st->bfd->section_count; i++, sec++) {
                        section = *sec;
                        if (section->flags & SEC_CODE) {
-                               start = (ulong)bfd_get_section_vma(st->bfd, 
-                                       section);
-                               end = start + (ulong)bfd_section_size(st->bfd, 
-                                       section);
+                               start = (ulong)bfd_section_vma(section);
+                               end = start + (ulong)bfd_section_size(section);
 
                                if (kt->flags2 & KASLR) {
                                        start += (kt->relocate * -1);
@@ -3470,8 +3466,8 @@ dump_symbol_table(void)
                section = *sec;
                fprintf(fp, "%25s  vma: %.*lx  size: %ld\n", 
                        section->name, VADDR_PRLEN,
-                       (ulong)bfd_get_section_vma(st->bfd, section),
-                       (ulong)bfd_section_size(st->bfd, section));
+                       (ulong)bfd_section_vma(section),
+                       (ulong)bfd_section_size(section));
        }
        fprintf(fp, "\n           downsized: ");
        if (st->downsized.name) {
@@ -4353,12 +4349,11 @@ get_section(ulong vaddr, char *buf)
                sec = (asection **)st->sections;
                for (i = 0; i < st->bfd->section_count; i++, sec++) {
                        section = *sec;
-                       start = (ulong)bfd_get_section_vma(st->bfd, section);
-                       end = start + (ulong)bfd_section_size(st->bfd, section);
+                       start = (ulong)bfd_section_vma(section);
+                       end = start + (ulong)bfd_section_size(section);
        
                        if ((vaddr >= start) && (vaddr < end)) {
-                               strcpy(buf, bfd_get_section_name(st->bfd, 
-                                       section));
+                               strcpy(buf, bfd_section_name(section));
                                break;
                        }
                }
@@ -6986,8 +6981,9 @@ compare_size_name(const void *va, const void *vb) {
 }
 
 static void
-append_struct_symbol (struct type_request *treq,  struct gnu_request *req)
+append_struct_symbol (struct gnu_request *req, void *data)
 {
+       struct type_request *treq = (struct type_request *)data;
        int i; 
        long s;
 
@@ -7027,22 +7023,13 @@ request_types(ulong lowest, ulong highest, char 
*member_name)
        request.type_name = member_name;
 #endif
 
-       while (!request.global_iterator.finished) {
-               request.command = GNU_GET_NEXT_DATATYPE;
-               gdb_interface(&request);
-               if (highest && 
-                   !(lowest <= request.length && request.length <= highest))
-                       continue;
-
-               if (member_name) {
-                       request.command = GNU_LOOKUP_STRUCT_CONTENTS;
-                       gdb_interface(&request);
-                       if (!request.value)
-                               continue;
-               }
-
-               append_struct_symbol(&typereq, &request);               
-       }
+       request.command = GNU_ITERATE_DATATYPES;
+       request.lowest = lowest;
+       request.highest = highest;
+       request.member = member_name;
+       request.callback = append_struct_symbol;
+       request.callback_data = (void *)&typereq;
+       gdb_interface(&request);
 
        qsort(typereq.types, typereq.idx, sizeof(struct type_info), 
compare_size_name);
 
@@ -11160,39 +11147,39 @@ section_header_info(bfd *bfd, asection *section, void 
*reqptr)
                        sec++;
                *sec = section;
 
-               if (STREQ(bfd_get_section_name(bfd, section), ".text.init") ||
-                   STREQ(bfd_get_section_name(bfd, section), ".init.text")) {
+               if (STREQ(bfd_section_name(section), ".text.init") ||
+                   STREQ(bfd_section_name(section), ".init.text")) {
                        kt->stext_init = (ulong)
-                               bfd_get_section_vma(bfd, section);
+                               bfd_section_vma(section);
                        kt->etext_init = kt->stext_init +
-                               (ulong)bfd_section_size(bfd, section);
+                               (ulong)bfd_section_size(section);
                }
 
-               if (STREQ(bfd_get_section_name(bfd, section), ".text")) {
+               if (STREQ(bfd_section_name(section), ".text")) {
                        st->first_section_start = (ulong)
-                               bfd_get_section_vma(bfd, section);
+                               bfd_section_vma(section);
                }
-                if (STREQ(bfd_get_section_name(bfd, section), ".text") ||
-                    STREQ(bfd_get_section_name(bfd, section), ".data")) {
-                        if (!(bfd_get_section_flags(bfd, section) & SEC_LOAD))
+                if (STREQ(bfd_section_name(section), ".text") ||
+                    STREQ(bfd_section_name(section), ".data")) {
+                        if (!(bfd_section_flags(section) & SEC_LOAD))
                                 st->flags |= NO_SEC_LOAD;
-                        if (!(bfd_get_section_flags(bfd, section) &
+                        if (!(bfd_section_flags(section) &
                             SEC_HAS_CONTENTS))
                                 st->flags |= NO_SEC_CONTENTS;
                 }
-                if (STREQ(bfd_get_section_name(bfd, section), ".eh_frame")) {
+                if (STREQ(bfd_section_name(section), ".eh_frame")) {
                        st->dwarf_eh_frame_file_offset = 
(off_t)section->filepos;
-                       st->dwarf_eh_frame_size = (ulong)bfd_section_size(bfd, 
section);
+                       st->dwarf_eh_frame_size = 
(ulong)bfd_section_size(section);
                }
-                if (STREQ(bfd_get_section_name(bfd, section), ".debug_frame")) 
{
+                if (STREQ(bfd_section_name(section), ".debug_frame")) {
                        st->dwarf_debug_frame_file_offset = 
(off_t)section->filepos;
-                       st->dwarf_debug_frame_size = 
(ulong)bfd_section_size(bfd, section);
+                       st->dwarf_debug_frame_size = 
(ulong)bfd_section_size(section);
                }
 
                if (st->first_section_start != 0) {
                        section_end_address =
-                               (ulong) bfd_get_section_vma(bfd, section) +
-                               (ulong) bfd_section_size(bfd, section);
+                               (ulong) bfd_section_vma(section) +
+                               (ulong) bfd_section_size(section);
                        if (section_end_address > st->last_section_end)
                                st->last_section_end = section_end_address;
                }
@@ -11204,21 +11191,21 @@ section_header_info(bfd *bfd, asection *section, void 
*reqptr)
                break;
 
        case (ulong)VERIFY_SECTIONS:
-               if (STREQ(bfd_get_section_name(bfd, section), ".text") ||
-                   STREQ(bfd_get_section_name(bfd, section), ".data")) {
-                       if (!(bfd_get_section_flags(bfd, section) & SEC_LOAD))
+               if (STREQ(bfd_section_name(section), ".text") ||
+                   STREQ(bfd_section_name(section), ".data")) {
+                       if (!(bfd_section_flags(section) & SEC_LOAD))
                                st->flags |= NO_SEC_LOAD;
-                       if (!(bfd_get_section_flags(bfd, section) & 
+                       if (!(bfd_section_flags(section) &
                            SEC_HAS_CONTENTS))
                                st->flags |= NO_SEC_CONTENTS;
                }
-                if (STREQ(bfd_get_section_name(bfd, section), ".eh_frame")) {
+                if (STREQ(bfd_section_name(section), ".eh_frame")) {
                        st->dwarf_eh_frame_file_offset = 
(off_t)section->filepos;
-                       st->dwarf_eh_frame_size = (ulong)bfd_section_size(bfd, 
section);
+                       st->dwarf_eh_frame_size = 
(ulong)bfd_section_size(section);
                }
-                if (STREQ(bfd_get_section_name(bfd, section), ".debug_frame")) 
{
+                if (STREQ(bfd_section_name(section), ".debug_frame")) {
                        st->dwarf_debug_frame_file_offset = 
(off_t)section->filepos;
-                       st->dwarf_debug_frame_size = 
(ulong)bfd_section_size(bfd, section);
+                       st->dwarf_debug_frame_size = 
(ulong)bfd_section_size(section);
                }
                break;
 
@@ -11258,7 +11245,7 @@ store_section_data(struct load_module *lm, bfd *bfd, 
asection *section)
        char *name;
 
        prio = 0;
-       name = (char *)bfd_get_section_name(bfd, section);
+       name = (char *)bfd_section_name(section);
 
         if (name[0] != '.' || strlen(name) != 10 || strcmp(name + 5, ".init")) 
                prio |= 32;
@@ -11280,10 +11267,10 @@ store_section_data(struct load_module *lm, bfd *bfd, 
asection *section)
         */
        if (lm->mod_percpu &&
            (STREQ(name,".data.percpu") || STREQ(name, ".data..percpu"))) {
-               lm->mod_percpu_size = bfd_section_size(bfd, section);
+               lm->mod_percpu_size = bfd_section_size(section);
                lm->mod_section_data[i].flags |= SEC_FOUND;
        }
-       lm->mod_section_data[i].size = bfd_section_size(bfd, section);
+       lm->mod_section_data[i].size = bfd_section_size(section);
        lm->mod_section_data[i].offset = 0;
        if (strlen(name) < MAX_MOD_SEC_NAME)
                strcpy(lm->mod_section_data[i].name, name);
@@ -11361,7 +11348,7 @@ calculate_load_order_v1(struct load_module *lm, bfd 
*bfd)
        for (i = (lm->mod_sections-1); i >= 0; i--) {
                section = lm->mod_section_data[i].section;
 
-                       alignment = power(2, bfd_get_section_alignment(bfd, 
section));
+               alignment = power(2, bfd_section_alignment(section));
 
                 if (alignment && (offset & (alignment - 1)))
                        offset = (offset | (alignment - 1)) + 1;
@@ -11390,9 +11377,9 @@ calculate_load_order_v1(struct load_module *lm, bfd 
*bfd)
                 if (STREQ(lm->mod_section_data[i].name, ".rodata"))
                         lm->mod_rodata_start = lm->mod_base + offset;
 
-               offset += bfd_section_size(bfd, section);
+               offset += bfd_section_size(section);
 
-                if (STREQ(bfd_get_section_name(bfd, section), ".kstrtab"))
+                if (STREQ(bfd_section_name(section), ".kstrtab"))
                        offset += strlen(lm->mod_name)+1;
         }
 }
@@ -11469,7 +11456,7 @@ calculate_load_order_v2(struct load_module *lm, bfd 
*bfd, int dynamic,
                                 (long) syminfo.value);
                     }
                    if (strcmp(syminfo.name, s1->name) == 0) {
-                           secname = (char *)bfd_get_section_name(bfd, 
sym->section);
+                           secname = (char *)bfd_section_name(sym->section);
                            break;
                    }
 
@@ -12217,7 +12204,7 @@ store_load_module_symbols(bfd *bfd, int dynamic, void 
*minisyms,
 
                 bfd_get_symbol_info(bfd, sym, &syminfo);
 
-               secname = (char *)bfd_get_section_name(bfd, sym->section);
+               secname = (char *)bfd_section_name(sym->section);
                 found = 0;
 
                 if (kt->flags & KMOD_V1) {
@@ -12774,8 +12761,8 @@ numeric_forward(const void *P_x, const void *P_y)
                        st->saved_command_line_vmlinux = valueof(y);
        }
 
-       xs = bfd_get_section(x);
-       ys = bfd_get_section(y);
+       xs = bfd_asymbol_section(x);
+       ys = bfd_asymbol_section(y);
 
        if (bfd_is_und_section(xs)) {
                if (!bfd_is_und_section(ys))
diff --git a/x86_64.c b/x86_64.c
index f5b2f7b..e69a347 100644
--- a/x86_64.c
+++ b/x86_64.c
@@ -7057,7 +7057,7 @@ x86_64_virt_phys_base(void)
        ulong phys, linux_banner_phys;
 
        if (!(sp = symbol_search("linux_banner")) ||
-           !((sp->type == 'R') || (sp->type == 'r')))
+           !((sp->type == 'R') || (sp->type == 'r') || (sp->type == 'D')))
                return FALSE;
 
        linux_banner_phys = sp->value - __START_KERNEL_map;
-- 
2.11.0

--
Crash-utility mailing list
[email protected]
https://listman.redhat.com/mailman/listinfo/crash-utility

Reply via email to