mirror of
https://github.com/crash-utility/crash
synced 2025-02-21 16:06:49 +00:00
1. The maximum number of tab completion candidates is limited to 200 by default. Set it unlimited. 2. The output of tab completion is not wrapped with the screen width. Get and use it when tab completion is invoked. Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
1594 lines
52 KiB
Diff
1594 lines
52 KiB
Diff
|
|
# When this file is updated in an existing source tree, it gets re-applied
|
|
# during the next build using "patch -N --fuzz=0", which ignores patches
|
|
# that have already been applied. However, if a gdb file has been modified
|
|
# multiple times, the subsequent patching may fail to recognize that a
|
|
# given patch has been previously applied, and will attempt to re-apply it.
|
|
# To prevent any uninintended consequences, this file also acts as a
|
|
# shell script that can restore any gdb file to its original state prior
|
|
# to all subsequent patch applications.
|
|
|
|
--- 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 @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))
|