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