# When this file is updated in an existing source tree, it gets re-applied # during the next build using "patch -N --fuzz=0", which ignores patches # that have already been applied. However, if a gdb file has been modified # multiple times, the subsequent patching may fail to recognize that a # given patch has been previously applied, and will attempt to re-apply it. # To prevent any uninintended consequences, this file also acts as a # shell script that can restore any gdb file to its original state prior # to all subsequent patch applications. # The gdb-7.6-ppc64le-support.patch will have modified both files below # during the initial build, so continue previous behavior. if [ "$1" = "PPC64" ] then exit 0 fi tar xvzmf gdb-7.6.tar.gz \ gdb-7.6/gdb/symtab.c \ gdb-7.6/gdb/printcmd.c exit 0 --- gdb-7.6/libiberty/Makefile.in.orig +++ gdb-7.6/libiberty/Makefile.in @@ -175,6 +175,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) \ @@ -206,7 +207,7 @@ CONFIGURED_OFILES = ./asprintf.$(objext) ./index.$(objext) ./insque.$(objext) \ ./memchr.$(objext) ./memcmp.$(objext) ./memcpy.$(objext) \ ./memmem.$(objext) ./memmove.$(objext) \ - ./mempcpy.$(objext) ./memset.$(objext) ./mkstemps.$(objext) \ + ./mempcpy.$(objext) ./memset.$(objext) \ ./pex-djgpp.$(objext) ./pex-msdos.$(objext) \ ./pex-unix.$(objext) ./pex-win32.$(objext) \ ./putenv.$(objext) \ --- gdb-7.6/opcodes/i386-dis.c.orig +++ gdb-7.6/opcodes/i386-dis.c @@ -11510,6 +11510,10 @@ print_insn (bfd_vma pc, disassemble_info threebyte = *++codep; dp = &dis386_twobyte[threebyte]; need_modrm = twobyte_has_modrm[*codep]; + if (dp->name && ((strcmp(dp->name, "ud2a") == 0) || (strcmp(dp->name, "ud2") == 0))) { + extern int kernel_BUG_encoding_bytes(void); + codep += kernel_BUG_encoding_bytes(); + } codep++; } else --- gdb-7.6/gdb/dwarf2read.c.orig +++ gdb-7.6/gdb/dwarf2read.c @@ -2670,7 +2670,11 @@ read_index_from_section (struct objfile 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."), @@ -2689,7 +2693,11 @@ read_index_from_section (struct objfile "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-7.6/gdb/amd64-linux-nat.c.orig +++ gdb-7.6/gdb/amd64-linux-nat.c @@ -45,6 +45,17 @@ /* ezannoni-2003-07-09: I think this is fixed. The extraneous defs have been removed from ptrace.h in the kernel. However, better safe than sorry. */ +#ifdef CRASH_MERGE +/* + * When compiling within a 2.6.25-based Fedora build environment with + * gcc 4.3, four new "typedef unsigned int u32;" declarations were + * required due to a new ptrace_bts_config structure declaration in + * "asm-x86/ptrace-abi.h" that used u32 members, but u32 is defined in + * "asm-x86/types.h" within a __KERNEL__ section. They've been changed + * to __u32, but this patch remains for building in that environment. + */ +typedef unsigned int u32; +#endif #include #include #include "gdb_proc_service.h" --- gdb-7.6/gdb/symfile.c.orig +++ gdb-7.6/gdb/symfile.c @@ -693,7 +693,26 @@ default_symfile_offsets (struct objfile for (cur_sec = abfd->sections; cur_sec != NULL; cur_sec = cur_sec->next) /* We do not expect this to happen; just skip this step if the relocatable file has a section with an assigned VMA. */ - if (bfd_section_vma (abfd, cur_sec) != 0) + if (bfd_section_vma (abfd, 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_get_section_name (abfd, cur_sec), "__k", 3) != 0) break; if (cur_sec == NULL) @@ -1122,6 +1141,12 @@ symbol_file_add_with_addrs_or_offsets (b error (_("Not confirmed.")); objfile = allocate_objfile (abfd, flags | (mainline ? OBJF_MAINLINE : 0)); +#ifdef CRASH_MERGE + if (add_flags & SYMFILE_MAINLINE) { + extern struct objfile *gdb_kernel_objfile; + gdb_kernel_objfile = objfile; + } +#endif if (parent) add_separate_debug_objfile (objfile, parent); @@ -1484,6 +1509,9 @@ find_separate_debug_file (const char *di VEC (char_ptr) *debugdir_vec; struct cleanup *back_to; int ix; +#ifdef CRASH_MERGE + extern int check_specified_module_tree(char *, char *); +#endif /* Set I to max (strlen (canon_dir), strlen (dir)). */ i = strlen (dir); @@ -1513,6 +1541,15 @@ find_separate_debug_file (const char *di if (separate_debug_file_exists (debugfile, crc32, objfile)) return debugfile; +#ifdef CRASH_MERGE +{ + if (check_specified_module_tree(objfile->name, debugfile) && + 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 @@ -1583,6 +1620,10 @@ find_separate_debug_file_by_debuglink (s char *debugfile; unsigned long crc32; struct cleanup *cleanups; +#ifdef CRASH_MERGE + char *name_copy; + extern char *check_specified_kernel_debug_file(); +#endif debuglink = get_debug_link_info (objfile, &crc32); @@ -1635,6 +1676,12 @@ find_separate_debug_file_by_debuglink (s } do_cleanups (cleanups); +#ifdef CRASH_MERGE + if (debugfile == NULL) { + name_copy = check_specified_kernel_debug_file(); + return (name_copy ? xstrdup(name_copy) : NULL); + } +#endif return debugfile; } @@ -2409,8 +2456,10 @@ add_symbol_file_command (char *args, int so we can't determine what section names are valid. */ } +#ifndef CRASH_MERGE if (from_tty && (!query ("%s", ""))) error (_("Not confirmed.")); +#endif symbol_file_add (filename, from_tty ? SYMFILE_VERBOSE : 0, section_addrs, flags); @@ -3690,6 +3739,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-7.6/gdb/cli/cli-cmds.c.orig +++ gdb-7.6/gdb/cli/cli-cmds.c @@ -466,6 +466,10 @@ show_script_ext_mode (struct ui_file *fi If SEARCH_PATH is non-zero, and the file isn't found in cwd, search for it in the source search path. */ +#ifdef CRASH_MERGE +static int crash_from_tty = 0; +#endif + int find_and_open_script (const char *script_file, int search_path, FILE **streamp, char **full_pathp) @@ -508,6 +512,32 @@ find_and_open_script (const char *script return 0; } +#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 = *streamp; + int fd = fileno (stream); + if (fstat (fd, &statbuf) < 0) + { + perror_with_name (*full_pathp); + fclose (stream); + return 0; + } + if (statbuf.st_uid != getuid () || (statbuf.st_mode & S_IWOTH)) + { + extern void untrusted_file(FILE *, char *); + untrusted_file(NULL, *full_pathp); + fclose (stream); + return 0; + } + } +#endif + return 1; } @@ -566,7 +596,11 @@ source_script_with_search (const char *f If the source command was invoked interactively, throw an error. Otherwise (e.g. if it was invoked by a script), silently ignore the error. */ +#ifdef CRASH_MERGE + if (from_tty > 0) +#else if (from_tty) +#endif perror_with_name (file); else return; @@ -589,7 +623,14 @@ source_script_with_search (const char *f void source_script (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 + } /* Return the source_verbose global variable to its previous state --- gdb-7.6/gdb/psymtab.c.orig +++ gdb-7.6/gdb/psymtab.c @@ -305,10 +305,14 @@ find_pc_sect_psymtab (struct objfile *ob struct minimal_symbol *msymbol) { struct partial_symtab *pst; +#ifdef CRASH_MERGE + extern int gdb_line_number_callback(unsigned long, unsigned long, unsigned long); +#endif /* Try just the PSYMTABS_ADDRMAP mapping first as it has better granularity than the later used TEXTLOW/TEXTHIGH one. */ +#ifndef __i386__ if (objfile->psymtabs_addrmap != NULL) { pst = addrmap_find (objfile->psymtabs_addrmap, pc); @@ -343,6 +347,7 @@ find_pc_sect_psymtab (struct objfile *ob } next: +#endif /* Existing PSYMTABS_ADDRMAP mapping is present even for PARTIAL_SYMTABs which still have no corresponding full SYMTABs read. But it is not @@ -361,7 +366,12 @@ find_pc_sect_psymtab (struct objfile *ob best_pst = find_pc_sect_psymtab_closer (objfile, pc, section, pst, msymbol); +#ifdef CRASH_MERGE + if ((best_pst != NULL) && + gdb_line_number_callback(pc, pst->textlow, pst->texthigh)) +#else if (best_pst != NULL) +#endif return best_pst; } --- gdb-7.6/gdb/symtab.c.orig +++ gdb-7.6/gdb/symtab.c @@ -1198,7 +1198,9 @@ demangle_for_lookup (const char *name, e doesn't affect these calls since they are looking for a known 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 symbol * lookup_symbol_in_language (const char *name, const struct block *block, const domain_enum domain, enum language lang, @@ -1212,17 +1214,30 @@ lookup_symbol_in_language (const char *n is_a_field_of_this); do_cleanups (cleanup); +#ifdef CRASH_MERGE + if (returnval && (domain == VAR_DOMAIN)) + gdb_bait_and_switch((char *)modified_name, returnval); +#endif + return returnval; } /* Behave like lookup_symbol_in_language, but performed with the current language. */ +#ifdef CRASH_MERGE +static struct block *gdb_get_crash_block(void); +#endif + struct 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); @@ -5100,3 +5115,662 @@ When enabled, debugging messages are pri observer_attach_executable_changed (symtab_observer_executable_changed); } + +#ifdef CRASH_MERGE +#include "gdb-stabs.h" +#include "version.h" +#define GDB_COMMON +#include "../../defs.h" + +static void get_member_data(struct gnu_request *, struct type *); +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 *); +extern void replace_ui_file_FILE(struct ui_file *, FILE *); +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 *); +void gdb_command_funnel(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)) + +/* + * All commands from above come through here. + */ +void +gdb_command_funnel(struct gnu_request *req) +{ + struct symbol *sym; + + if (req->command != GNU_VERSION) { + replace_ui_file_FILE(gdb_stdout, req->fp); + replace_ui_file_FILE(gdb_stderr, req->fp); + do_cleanups(all_cleanups()); + } + + 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; + + 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 symbol *sym; + CORE_ADDR pc; + +#define LASTCHAR(s) (s[strlen(s)-1]) + + /* + * Prime the addrmap pump. + */ + if (req->name) + sym = lookup_symbol(req->name, 0, VAR_DOMAIN, 0); + + pc = req->addr; + + sal = find_pc_line(pc, 0); + + if (!sal.symtab) { + req->buf[0] = '\0'; + return; + } + + if (sal.symtab->filename && sal.symtab->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->dirname, + LASTCHAR(sal.symtab->dirname) == '/' ? "" : "/", + sal.symtab->filename, sal.line); + } +} + + +/* + * General purpose routine for determining datatypes. + */ + +static void +gdb_get_datatype(struct gnu_request *req) +{ + register struct cleanup *old_chain = NULL; + register struct type *type; + register struct type *typedef_type; + struct expression *expr; + struct symbol *sym; + register int i; + struct field *nextfield; + 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); + if (sym) { + req->typecode = TYPE_CODE(sym->type); + req->length = TYPE_LENGTH(sym->type); + if (req->member) + get_member_data(req, sym->type); + + 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); + + old_chain = make_cleanup(free_current_contents, &expr); + + + switch (expr->elts[0].opcode) + { + case OP_VAR_VALUE: + if (gdb_CRASHDEBUG(2)) + console("expr->elts[0].opcode: OP_VAR_VALUE\n"); + type = expr->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->elts[2].symbol); + req->tagname = (char *)TYPE_TAG_NAME(type); + if (!req->tagname) { + val = evaluate_type(expr); + eval_enum(value_type(val), req); + } + } + break; + + case OP_TYPE: + if (gdb_CRASHDEBUG(2)) + console("expr->elts[0].opcode: OP_TYPE\n"); + type = expr->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); + + break; + + default: + if (gdb_CRASHDEBUG(2)) + console("expr->elts[0].opcode: %d (?)\n", + expr->elts[0].opcode); + break; + + } + + do_cleanups(old_chain); +} + +/* + * 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; + int 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_BITPOS (type, i)) { + fprintf_filtered (gdb_stdout, " = %d", + TYPE_FIELD_BITPOS (type, i)); + lastval = TYPE_FIELD_BITPOS (type, i); + } else + fprintf_filtered(gdb_stdout, " = %d", 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; + int lastval; + + len = TYPE_NFIELDS (type); + lastval = 0; + + for (i = 0; i < len; i++) { + if (lastval != TYPE_FIELD_BITPOS (type, i)) { + lastval = TYPE_FIELD_BITPOS (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) +{ + register short i; + struct field *nextfield; + short nfields; + struct type *typedef_type; + + req->member_offset = -1; + + nfields = TYPE_MAIN_TYPE(type)->nfields; + nextfield = TYPE_MAIN_TYPE(type)->flds_bnds.fields; + + if (nfields == 0) { + 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 = nextfield->loc.bitpos; + req->member_length = TYPE_LENGTH(nextfield->type); + req->member_typecode = TYPE_CODE(nextfield->type); + if ((req->member_typecode == TYPE_CODE_TYPEDEF) && + (typedef_type = check_typedef(nextfield->type))) + req->member_length = TYPE_LENGTH(typedef_type); + 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; + register struct cmd_list_element *c; + + req->value = FALSE; + c = lookup_cmd(&req->name, cmdlist, "", 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) +{ + register struct objfile *loaded_objfile = NULL; + register struct objfile *objfile; + register struct minimal_symbol *m; + struct load_module *lm; + int external, subsequent, found; + off_t offset; + ulong value, adjusted; + struct symbol *sym; + struct expression *expr; + struct cleanup *old_chain; + 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); + + 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); + + ALL_OBJFILES(objfile) { + if (same_file(objfile->name, lm->mod_namelist)) { + loaded_objfile = objfile; + break; + } + } + + if (!loaded_objfile) + req->flags |= GNU_COMMAND_FAILED; +} + +static void +gdb_delete_symbol_file(struct gnu_request *req) +{ + register struct objfile *objfile; + + ALL_OBJFILES(objfile) { + if (STREQ(objfile->name, req->name) || + same_file(objfile->name, req->name)) { + free_objfile(objfile); + break; + } + } + + if (gdb_CRASHDEBUG(2)) { + fprintf_filtered(gdb_stdout, "current object files:\n"); + ALL_OBJFILES(objfile) + fprintf_filtered(gdb_stdout, " %s\n", objfile->name); + } +} + +/* + * Walk through all minimal_symbols, patching their values with the + * correct addresses. + */ +static void +gdb_patch_symbol_values(struct gnu_request *req) +{ + struct minimal_symbol *msymbol; + struct objfile *objfile; + + req->name = PATCH_KERNEL_SYMBOLS_START; + patch_kernel_symbol(req); + + ALL_MSYMBOLS (objfile, msymbol) + { + req->name = (char *)msymbol->ginfo.name; + req->addr = (ulong)(&SYMBOL_VALUE_ADDRESS(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) +{ + struct expression *expr; + struct value *val; + struct cleanup *old_chain = NULL; + struct type *type; + struct type *target_type; + + req->typecode = TYPE_CODE_UNDEF; + + expr = parse_expression (req->name); + old_chain = make_cleanup (free_current_contents, &expr); + val = evaluate_type (expr); + + type = value_type(val); + + req->type_name = (char *)TYPE_MAIN_TYPE(type)->name; + req->typecode = TYPE_MAIN_TYPE(type)->code; + req->length = type->length; + 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); + + do_cleanups (old_chain); +} + +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 minimal_symbol *msym; + struct block *block; + + if ((gdb_merge_flags & KERNEL_SYMBOLS_PATCHED) && + (msym = lookup_minimal_symbol(name, NULL, gdb_kernel_objfile))) { + if (sym->aclass == LOC_BLOCK) { + block = (struct block *)SYMBOL_BLOCK_VALUE(sym); + BLOCK_START(block) = SYMBOL_VALUE_ADDRESS(msym); + } else + SYMBOL_VALUE_ADDRESS(sym) = SYMBOL_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.prettyprint_structs; + if (strcmp(req->name, "prettyprint_arrays") == 0) + req->addr = (ulong)&user_print_options.prettyprint_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 struct block * +gdb_get_crash_block(void) +{ + if (crash_text_scope) + return block_for_pc(crash_text_scope); + else + return NULL; +} +#endif --- gdb-7.6/gdb/c-typeprint.c.orig +++ gdb-7.6/gdb/c-typeprint.c @@ -1097,7 +1097,8 @@ c_type_print_base (struct type *type, st fprintf_filtered (stream, "static "); c_print_type (TYPE_FIELD_TYPE (type, i), TYPE_FIELD_NAME (type, i), - stream, show - 1, level + 4, + stream, strlen(TYPE_FIELD_NAME (type, i)) ? + show - 1 : show, level + 4, &local_flags); if (!field_is_static (&TYPE_FIELD (type, i)) && TYPE_FIELD_PACKED (type, i)) --- gdb-7.6/gdb/xml-syscall.c.orig +++ gdb-7.6/gdb/xml-syscall.c @@ -38,7 +38,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-7.6/gdb/exceptions.c.orig +++ gdb-7.6/gdb/exceptions.c @@ -218,6 +218,10 @@ exceptions_state_mc_action_iter_1 (void) /* Return EXCEPTION to the nearest containing catch_errors(). */ +#ifdef CRASH_MERGE +void (*error_hook) (void) ATTRIBUTE_NORETURN; +#endif + void throw_exception (struct gdb_exception exception) { @@ -225,6 +229,13 @@ throw_exception (struct gdb_exception ex immediate_quit = 0; do_cleanups (all_cleanups ()); +#ifdef CRASH_MERGE + if (error_hook) { + fprintf_filtered(gdb_stderr, "%s\n", exception.message); + (*error_hook)(); + } else + fprintf_filtered(gdb_stderr, "gdb called without error_hook: %s\n", exception.message); +#endif /* Jump to the containing catch_errors() call, communicating REASON to that call via setjmp's return value. Note that REASON can't --- gdb-7.6/gdb/valprint.h.orig +++ gdb-7.6/gdb/valprint.h @@ -152,11 +152,17 @@ extern void print_function_pointer_addre struct gdbarch *gdbarch, CORE_ADDR address, struct ui_file *stream); - +#ifdef CRASH_MERGE +extern int valprint_read_string (CORE_ADDR addr, int len, int width, + unsigned int fetchlimit, + enum bfd_endian byte_order, gdb_byte **buffer, + int *bytes_read); +#else extern int read_string (CORE_ADDR addr, int len, int width, unsigned int fetchlimit, enum bfd_endian byte_order, gdb_byte **buffer, int *bytes_read); +#endif extern void val_print_optimized_out (struct ui_file *stream); --- gdb-7.6/gdb/target.c.orig +++ gdb-7.6/gdb/target.c @@ -1779,6 +1779,13 @@ target_xfer_partial (struct target_ops * int target_read_memory (CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len) { +#ifdef CRASH_MERGE + extern int gdb_readmem_callback(unsigned long, void *, int, int); + if (gdb_readmem_callback(memaddr, (void *)myaddr, len, 0)) + return 0; + else + return EIO; +#endif /* Dispatch to the topmost target, not the flattened current_target. Memory accesses check target->to_has_(all_)memory, and the flattened target doesn't inherit those. */ @@ -1814,6 +1821,13 @@ target_read_stack (CORE_ADDR memaddr, gd int target_write_memory (CORE_ADDR memaddr, const gdb_byte *myaddr, ssize_t len) { +#ifdef CRASH_MERGE + extern int gdb_readmem_callback(unsigned long, void *, int, int); + if (gdb_readmem_callback(memaddr, (void *)myaddr, len, 1)) + return 0; + else + return EIO; +#endif /* Dispatch to the topmost target, not the flattened current_target. Memory accesses check target->to_has_(all_)memory, and the flattened target doesn't inherit those. */ --- gdb-7.6/gdb/printcmd.c.orig +++ gdb-7.6/gdb/printcmd.c @@ -1001,11 +1001,62 @@ print_command_1 (char *exp, int voidprin } static void +print_command_2 (char *exp, int inspect, int voidprint) +{ + struct expression *expr; + struct cleanup *old_chain = 0; + char format = 0; + struct value *val; + struct format_data fmt; + int cleanup = 0; + + if (exp && *exp == '/') + { + exp++; + fmt = decode_format (&exp, last_format, 0); + validate_format (fmt, "print"); + last_format = format = fmt.format; + } + else + { + fmt.count = 1; + fmt.format = 0; + fmt.size = 0; + fmt.raw = 0; + } + + if (exp && *exp) + { + expr = parse_expression (exp); + old_chain = make_cleanup (free_current_contents, &expr); + cleanup = 1; + val = evaluate_expression (expr); + } + else + val = access_value_history (0); + + printf_filtered ("%d %d %d %d %d %d\n", + TYPE_CODE (check_typedef(value_type (val))), + TYPE_UNSIGNED (check_typedef(value_type (val))), + TYPE_LENGTH (check_typedef(value_type(val))), + value_offset (val), value_bitpos (val), value_bitsize(val)); + + if (cleanup) + do_cleanups (old_chain); +} + +static void print_command (char *exp, int from_tty) { print_command_1 (exp, 1); } +static void +printm_command (char *exp, int from_tty) +{ + print_command_2 (exp, 0, 1); +} + /* Same as print, except it doesn't print void results. */ static void call_command (char *exp, int from_tty) @@ -2593,6 +2644,12 @@ EXP may be preceded with /FMT, where FMT but no count or size letter (see \"x\" command).")); set_cmd_completer (c, expression_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-7.6/gdb/ui-file.c.orig +++ gdb-7.6/gdb/ui-file.c @@ -671,6 +671,17 @@ gdb_fopen (char *name, char *mode) return stdio_file_new (f, 1); } +#ifdef CRASH_MERGE +void +replace_ui_file_FILE(struct ui_file *file, FILE *fp) +{ + struct stdio_file *stdio_file; + + stdio_file = (struct stdio_file *)ui_file_data(file); + stdio_file->file = fp; +} +#endif + /* ``struct ui_file'' implementation that maps onto two ui-file objects. */ static ui_file_write_ftype tee_file_write; --- gdb-7.6/gdb/main.c.orig +++ gdb-7.6/gdb/main.c @@ -806,7 +806,7 @@ captured_main (void *data) { print_gdb_version (gdb_stdout); wrap_here (""); - printf_filtered ("\n"); + printf_filtered ("\n\n"); exit (0); } @@ -853,6 +853,13 @@ captured_main (void *data) } } +#ifdef CRASH_MERGE +{ + extern void update_gdb_hooks(void); + 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 @@ -880,7 +887,11 @@ captured_main (void *data) processed; it sets global parameters, which are independent of what file you are debugging or what directory you are in. */ if (system_gdbinit && !inhibit_gdbinit) +#ifdef CRASH_MERGE + catch_command_errors (source_script, system_gdbinit, -1, RETURN_MASK_ALL); +#else catch_command_errors (source_script, system_gdbinit, 0, RETURN_MASK_ALL); +#endif /* Read and execute $HOME/.gdbinit file, if it exists. This is done *before* all the command line arguments are processed; it sets @@ -888,7 +899,11 @@ captured_main (void *data) debugging or what directory you are in. */ if (home_gdbinit && !inhibit_gdbinit && !inhibit_home_gdbinit) +#ifdef CRASH_MERGE + catch_command_errors (source_script, home_gdbinit, -1, RETURN_MASK_ALL); +#else catch_command_errors (source_script, home_gdbinit, 0, RETURN_MASK_ALL); +#endif /* Process '-ix' and '-iex' options early. */ for (i = 0; VEC_iterate (cmdarg_s, cmdarg_vec, i, cmdarg_p); i++) @@ -929,8 +944,12 @@ captured_main (void *data) catch_command_errors returns non-zero on success! */ if (catch_command_errors (exec_file_attach, execarg, !batch_flag, RETURN_MASK_ALL)) +#ifdef CRASH_MERGE + catch_command_errors (symbol_file_add_main, symarg, 0, RETURN_MASK_ALL); +#else catch_command_errors (symbol_file_add_main, symarg, !batch_flag, RETURN_MASK_ALL); +#endif } else { @@ -992,8 +1011,12 @@ captured_main (void *data) { auto_load_local_gdbinit_loaded = 1; +#ifdef CRASH_MERGE + catch_command_errors (source_script, local_gdbinit, -1, RETURN_MASK_ALL); +#else catch_command_errors (source_script, local_gdbinit, 0, RETURN_MASK_ALL); +#endif } } @@ -1039,6 +1062,12 @@ captured_main (void *data) while (1) { catch_errors (captured_command_loop, 0, "", RETURN_MASK_ALL); +#ifdef CRASH_MERGE + { + int console(char *, ...); + console("\n"); + } +#endif } /* No exit -- exit is through quit_command. */ } @@ -1053,6 +1082,23 @@ gdb_main (struct captured_main_args *arg return 1; } +#ifdef CRASH_MERGE +/* + * NOTE: adapted from gdb.c, which is no longer built in; changed name of + * original main() to gdb_main_entry() for use as crash entry point + */ +int +gdb_main_entry (int argc, char **argv) +{ + struct captured_main_args args; + memset (&args, 0, sizeof args); + args.argc = argc; + args.argv = argv; + args.use_windows = 0; + 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-7.6/gdb/valprint.c.orig +++ gdb-7.6/gdb/valprint.c @@ -1768,8 +1768,13 @@ partial_memory_read (CORE_ADDR memaddr, this function instead? */ int +#ifdef CRASH_MERGE +valprint_read_string (CORE_ADDR addr, int len, int width, unsigned int fetchlimit, + enum bfd_endian byte_order, gdb_byte **buffer, int *bytes_read) +#else read_string (CORE_ADDR addr, int len, int width, unsigned int fetchlimit, enum bfd_endian byte_order, gdb_byte **buffer, int *bytes_read) +#endif { int found_nul; /* Non-zero if we found the nul char. */ int errcode; /* Errno returned from bad reads. */ @@ -2472,8 +2477,13 @@ val_print_string (struct type *elttype, fetchlimit = (len == -1 ? options->print_max : min (len, options->print_max)); +#ifdef CRASH_MERGE + errcode = valprint_read_string (addr, len, width, fetchlimit, byte_order, + &buffer, &bytes_read); +#else errcode = read_string (addr, len, width, fetchlimit, byte_order, &buffer, &bytes_read); +#endif old_chain = make_cleanup (xfree, buffer); addr += bytes_read; --- gdb-7.6/gdb/Makefile.in.orig +++ gdb-7.6/gdb/Makefile.in @@ -422,7 +422,7 @@ CONFIG_UNINSTALL = @CONFIG_UNINSTALL@ # 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)/common -I$(srcdir)/config \ -DLOCALEDIR="\"$(localedir)\"" $(DEFS) @@ -934,7 +934,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $ TSOBS = inflow.o -SUBDIRS = doc @subdirs@ data-directory $(GNULIB_BUILDDIR) +SUBDIRS = build_no_subdirs CLEANDIRS = $(SUBDIRS) # List of subdirectories in the build tree that must exist. @@ -969,8 +969,8 @@ generated_files = config.h observer.h ob $(COMPILE) $< $(POSTCOMPILE) -all: gdb$(EXEEXT) $(CONFIG_ALL) - @$(MAKE) $(FLAGS_TO_PASS) DO=all "DODIRS=`echo $(SUBDIRS) | sed 's/testsuite//'`" subdir_do +all: gdb$(EXEEXT) + @$(MAKE) -s $(FLAGS_TO_PASS) DO=all "DODIRS=`echo $(SUBDIRS) | sed 's/testsuite//'`" subdir_do installcheck: @@ -1172,15 +1172,16 @@ 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) $(ADD_DEPS) $(CDEPS) $(TDEPLIBS) - rm -f gdb$(EXEEXT) + @rm -f gdb$(EXEEXT) + @(cd ../..; make --no-print-directory GDB_FLAGS=-DGDB_7_6 library) $(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) # Convenience rule to handle recursion. $(LIBGNU) $(GNULIB_H): all-lib all-lib: $(GNULIB_BUILDDIR)/Makefile - @$(MAKE) $(FLAGS_TO_PASS) DO=all DODIRS=$(GNULIB_BUILDDIR) subdir_do + @$(MAKE) $(FLAGS_TO_PASS) DO=all DODIRS=$(GNULIB_BUILDDIR) subdir_do -s .PHONY: all-lib # Convenience rule to handle recursion. @@ -1389,12 +1390,12 @@ $(srcdir)/copying.c: @MAINTAINER_MODE_TR mv $(srcdir)/copying.tmp $(srcdir)/copying.c version.c: Makefile version.in - rm -f version.c-tmp version.c - echo '#include "version.h"' >> version.c-tmp - echo 'const char version[] = "'"`sed q ${srcdir}/version.in`"'";' >> version.c-tmp - echo 'const char host_name[] = "$(host_alias)";' >> version.c-tmp - echo 'const char target_name[] = "$(target_alias)";' >> version.c-tmp - mv version.c-tmp version.c + @rm -f version.c-tmp version.c + @echo '#include "version.h"' >> version.c-tmp + @echo 'const char version[] = "'"`sed q ${srcdir}/version.in`"'";' >> version.c-tmp + @echo 'const char host_name[] = "$(host_alias)";' >> version.c-tmp + @echo 'const char target_name[] = "$(target_alias)";' >> version.c-tmp + @mv version.c-tmp version.c observer.h: observer.sh doc/observer.texi ${srcdir}/observer.sh h ${srcdir}/doc/observer.texi observer.h --- gdb-7.6/gdb/c-lang.c.orig +++ gdb-7.6/gdb/c-lang.c @@ -307,7 +307,11 @@ c_get_string (struct value *value, gdb_b { CORE_ADDR addr = value_as_address (value); +#ifdef CRASH_MERGE + err = valprint_read_string (addr, *length, width, fetchlimit, +#else err = read_string (addr, *length, width, fetchlimit, +#endif byte_order, buffer, length); if (err) { --- gdb-7.6/readline/rltypedefs.h.orig +++ gdb-7.6/readline/rltypedefs.h @@ -31,10 +31,10 @@ extern "C" { #if !defined (_FUNCTION_DEF) # define _FUNCTION_DEF -typedef int Function (); -typedef void VFunction (); -typedef char *CPFunction (); -typedef char **CPPFunction (); +typedef int Function (void); +typedef void VFunction (void); +typedef char *CPFunction (void); +typedef char **CPPFunction (void); #endif /* _FUNCTION_DEF */ --- gdb-7.6/readline/readline.h.orig +++ gdb-7.6/readline/readline.h @@ -378,7 +378,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-7.6/readline/misc.c.orig +++ gdb-7.6/readline/misc.c @@ -405,7 +405,7 @@ _rl_history_set_point () #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-7.6/Makefile.in.orig +++ gdb-7.6/Makefile.in @@ -342,6 +342,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@ @@ -407,6 +410,9 @@ GNATBIND = @GNATBIND@ GNATMAKE = @GNATMAKE@ CFLAGS = @CFLAGS@ +ifeq (${CRASH_TARGET}, PPC64) +CFLAGS += -m64 -fPIC +endif LDFLAGS = @LDFLAGS@ LIBCFLAGS = $(CFLAGS) CXXFLAGS = @CXXFLAGS@ --- gdb-7.6/gdb/defs.h.orig +++ gdb-7.6/gdb/defs.h @@ -802,4 +802,8 @@ enum block_enum #include "utils.h" +#ifdef CRASH_MERGE +extern int gdb_main_entry(int, char **); +extern void replace_ui_file_FILE(struct ui_file *, FILE *); +#endif #endif /* #ifndef DEFS_H */ --- gdb-7.6/bfd/elflink.c.orig +++ gdb-7.6/bfd/elflink.c @@ -4730,7 +4730,7 @@ error_free_dyn: struct elf_link_hash_entry *hlook; asection *slook; bfd_vma vlook; - size_t i, j, idx; + size_t i, j, idx = 0; hlook = weaks; weaks = hlook->u.weakdef; --- gdb-7.6/gdb/s390-nat.c.orig +++ gdb-7.6/gdb/s390-nat.c @@ -37,6 +37,8 @@ #include #include +#include + #ifndef HWCAP_S390_HIGH_GPRS #define HWCAP_S390_HIGH_GPRS 512 #endif --- gdb-7.6/gdb/printcmd.c.orig +++ gdb-7.6/gdb/printcmd.c @@ -573,11 +573,21 @@ print_address_symbolic (struct gdbarch * int unmapped = 0; int offset = 0; int line = 0; +#ifdef CRASH_MERGE + extern int gdb_print_callback(unsigned long); +#endif /* Throw away both name and filename. */ struct cleanup *cleanup_chain = make_cleanup (free_current_contents, &name); make_cleanup (free_current_contents, &filename); +#ifdef CRASH_MERGE + if (!gdb_print_callback(addr)) { + do_cleanups (cleanup_chain); + return 0; + } +#endif + if (build_address_symbolic (gdbarch, addr, do_demangle, &name, &offset, &filename, &line, &unmapped)) { --- gdb-7.6/bfd/bfd-in.h.orig +++ gdb-7.6/bfd/bfd-in.h @@ -294,9 +294,6 @@ typedef struct bfd_section *sec_ptr; #define bfd_is_com_section(ptr) (((ptr)->flags & SEC_IS_COMMON) != 0) -#define bfd_set_section_vma(bfd, ptr, val) (((ptr)->vma = (ptr)->lma = (val)), ((ptr)->user_set_vma = TRUE), TRUE) -#define bfd_set_section_alignment(bfd, ptr, val) (((ptr)->alignment_power = (val)),TRUE) -#define bfd_set_section_userdata(bfd, ptr, val) (((ptr)->userdata = (val)),TRUE) /* Find the address one past the end of SEC. */ #define bfd_get_section_limit(bfd, sec) \ (((bfd)->direction != write_direction && (sec)->rawsize != 0 \ @@ -519,7 +516,6 @@ extern void warn_deprecated (const char #define bfd_get_symbol_leading_char(abfd) ((abfd)->xvec->symbol_leading_char) -#define bfd_set_cacheable(abfd,bool) (((abfd)->cacheable = bool), TRUE) extern bfd_boolean bfd_cache_close (bfd *abfd); --- gdb-7.6/bfd/bfd-in2.h.orig +++ gdb-7.6/bfd/bfd-in2.h @@ -301,9 +301,6 @@ typedef struct bfd_section *sec_ptr; #define bfd_is_com_section(ptr) (((ptr)->flags & SEC_IS_COMMON) != 0) -#define bfd_set_section_vma(bfd, ptr, val) (((ptr)->vma = (ptr)->lma = (val)), ((ptr)->user_set_vma = TRUE), TRUE) -#define bfd_set_section_alignment(bfd, ptr, val) (((ptr)->alignment_power = (val)),TRUE) -#define bfd_set_section_userdata(bfd, ptr, val) (((ptr)->userdata = (val)),TRUE) /* Find the address one past the end of SEC. */ #define bfd_get_section_limit(bfd, sec) \ (((bfd)->direction != write_direction && (sec)->rawsize != 0 \ @@ -526,7 +523,6 @@ extern void warn_deprecated (const char #define bfd_get_symbol_leading_char(abfd) ((abfd)->xvec->symbol_leading_char) -#define bfd_set_cacheable(abfd,bool) (((abfd)->cacheable = bool), TRUE) extern bfd_boolean bfd_cache_close (bfd *abfd); @@ -1572,6 +1568,32 @@ struct relax_table { int size; }; +/* Note: the following are provided as inline functions rather than macros + because not all callers use the return value. A macro implementation + would use a comma expression, eg: "((ptr)->foo = val, TRUE)" and some + compilers will complain about comma expressions that have no effect. */ +static inline bfd_boolean +bfd_set_section_userdata (bfd * abfd ATTRIBUTE_UNUSED, asection * ptr, void * val) +{ + ptr->userdata = val; + return TRUE; +} + +static inline bfd_boolean +bfd_set_section_vma (bfd * abfd ATTRIBUTE_UNUSED, asection * ptr, bfd_vma val) +{ + ptr->vma = ptr->lma = val; + ptr->user_set_vma = TRUE; + return TRUE; +} + +static inline bfd_boolean +bfd_set_section_alignment (bfd * abfd ATTRIBUTE_UNUSED, asection * ptr, unsigned int val) +{ + ptr->alignment_power = val; + return TRUE; +} + /* These sections are global, and are managed by BFD. The application and target back end are not permitted to change the values in these sections. */ @@ -6095,6 +6117,14 @@ struct bfd unsigned int selective_search : 1; }; +/* See note beside bfd_set_section_userdata. */ +static inline bfd_boolean +bfd_set_cacheable (bfd * abfd, bfd_boolean val) +{ + abfd->cacheable = val; + return TRUE; +} + typedef enum bfd_error { bfd_error_no_error = 0, --- gdb-7.6/gdb/symtab.c.orig +++ gdb-7.6/gdb/symtab.c @@ -5405,7 +5405,7 @@ dump_enum(struct type *type, struct gnu_ { register int i; int len; - int lastval; + long long lastval; len = TYPE_NFIELDS (type); lastval = 0; @@ -5418,12 +5418,12 @@ dump_enum(struct type *type, struct gnu_ for (i = 0; i < len; i++) { fprintf_filtered(gdb_stdout, " %s", TYPE_FIELD_NAME (type, i)); - if (lastval != TYPE_FIELD_BITPOS (type, i)) { - fprintf_filtered (gdb_stdout, " = %d", - TYPE_FIELD_BITPOS (type, i)); - lastval = TYPE_FIELD_BITPOS (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, " = %d", lastval); + fprintf_filtered(gdb_stdout, " = %s", plongest(lastval)); fprintf_filtered(gdb_stdout, "\n"); lastval++; } --- gdb-7.6/gdb/aarch64-linux-nat.c.orig +++ gdb-7.6/gdb/aarch64-linux-nat.c @@ -32,6 +32,7 @@ #include "elf/common.h" #include +#include #include #include "gregset.h" --- gdb-7.6/sim/igen/Makefile.in.orig +++ gdb-7.6/sim/igen/Makefile.in @@ -117,7 +117,7 @@ IGEN_OBJS=\ gen.o igen: igen.o $(IGEN_OBJS) - $(CC_FOR_BUILD) $(BUILD_LDFLAGS) -o igen igen.o $(IGEN_OBJS) $(LIBIBERTY_LIB) + $(CC_FOR_BUILD) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) -o igen igen.o $(IGEN_OBJS) $(LIBIBERTY_LIB) igen.o: igen.c misc.h filter_host.h lf.h table.h ld-decode.h ld-cache.h ld-insn.h filter.h gen-model.h gen-itable.h gen-icache.h gen-idecode.h gen-engine.h gen-semantics.h gen-support.h gen.h igen.h $(CC_FOR_BUILD) $(BUILD_CFLAGS) -c $(srcdir)/igen.c --- gdb-7.6/sim/mips/cp1.c.orig +++ gdb-7.6/sim/mips/cp1.c @@ -1359,7 +1359,7 @@ fp_rsqrt2(sim_cpu *cpu, /* Conversion operations. */ uword64 -convert (sim_cpu *cpu, +sim_mips_convert (sim_cpu *cpu, address_word cia, int rm, uword64 op, --- gdb-7.6/sim/mips/sim-main.h.orig +++ gdb-7.6/sim/mips/sim-main.h @@ -770,8 +770,8 @@ unsigned64 fp_nmadd (SIM_STATE, unsigned64 op1, unsigned64 op2, unsigned64 fp_nmsub (SIM_STATE, unsigned64 op1, unsigned64 op2, unsigned64 op3, FP_formats fmt); #define NegMultiplySub(op1,op2,op3,fmt) fp_nmsub(SIM_ARGS, op1, op2, op3, fmt) -unsigned64 convert (SIM_STATE, int rm, unsigned64 op, FP_formats from, FP_formats to); -#define Convert(rm,op,from,to) convert (SIM_ARGS, rm, op, from, to) +unsigned64 sim_mips_convert (SIM_STATE, int rm, unsigned64 op, FP_formats from, FP_formats to); +#define Convert(rm,op,from,to) sim_mips_convert (SIM_ARGS, rm, op, from, to) unsigned64 convert_ps (SIM_STATE, int rm, unsigned64 op, FP_formats from, FP_formats to); #define ConvertPS(rm,op,from,to) convert_ps (SIM_ARGS, rm, op, from, to) --- gdb-7.6/readline/util.c +++ gdb-7.6/readline/util.c @@ -493,10 +493,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); } @@ -509,16 +512,17 @@ _rl_tropen () fclose (_rl_tracefp); sprintf (fnbuf, "/var/tmp/rltrace.%ld", getpid()); unlink(fnbuf); - _rl_tracefp = fopen (fnbuf, "w+"); + _rl_tracefp = fopen (fnbuf, "w+xe"); return _rl_tracefp != 0; } int _rl_trclose () { - int r; + int r = 0; - r = fclose (_rl_tracefp); + if (_rl_tracefp) + r = fclose (_rl_tracefp); _rl_tracefp = 0; return r; } --- gdb-7.6/gdb/symtab.c.orig +++ gdb-7.6/gdb/symtab.c @@ -5447,9 +5447,9 @@ eval_enum(struct type *type, struct gnu_ lastval = 0; for (i = 0; i < len; i++) { - if (lastval != TYPE_FIELD_BITPOS (type, i)) { - lastval = TYPE_FIELD_BITPOS (type, 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; --- gdb-7.6/gdb/symtab.c.orig +++ gdb-7.6/gdb/symtab.c @@ -5236,6 +5236,12 @@ gdb_command_funnel(struct gnu_request *r gdb_set_crash_block(req); break; + case GNU_GET_FUNCTION_RANGE: + sym = lookup_symbol(req->name, 0, VAR_DOMAIN, 0); + if (!find_pc_partial_function(req->pc, NULL, &req->addr, &req->addr2)) + req->flags |= GNU_COMMAND_FAILED; + break; + default: req->flags |= GNU_COMMAND_FAILED; break; --- gdb-7.6/opcodes/i386-dis.c.orig +++ gdb-7.6/opcodes/i386-dis.c @@ -11300,6 +11300,29 @@ get_sib (disassemble_info *info) } } +static char * +check_for_extensions(struct dis_private *priv) +{ + unsigned char ModRM; + + if ((priv->the_buffer[0] == 0x66) && + (priv->the_buffer[1] == 0x0f) && + (priv->the_buffer[2] == 0xae)) { + ModRM = priv->the_buffer[3]; + if (ModRM == 0xf8) + return "pcommit"; + + switch ((ModRM >> 3)) + { + case 0x6: + return "clwb"; + case 0x7: + return "clflushopt"; + } + } + return NULL; +} + static int print_insn (bfd_vma pc, disassemble_info *info) { @@ -11312,6 +11335,7 @@ print_insn (bfd_vma pc, disassemble_info struct dis_private priv; int prefix_length; int default_prefixes; + char *extension; priv.orig_sizeflag = AFLAG | DFLAG; if ((info->mach & bfd_mach_i386_i386) != 0) @@ -11575,6 +11599,7 @@ print_insn (bfd_vma pc, disassemble_info need_vex = 0; need_vex_reg = 0; vex_w_done = 0; + extension = NULL; if (dp->name == NULL && dp->op[0].bytemode == FLOATCODE) { @@ -11610,9 +11635,14 @@ print_insn (bfd_vma pc, disassemble_info name = prefix_name (all_prefixes[i], priv.orig_sizeflag); if (name == NULL) name = INTERNAL_DISASSEMBLER_ERROR; - (*info->fprintf_func) (info->stream, "%s", name); - return 1; - } + if ((extension = check_for_extensions(&priv))) { + strcpy(obuf, extension); + obufp = &obuf[strlen(obuf)]; + } else { + (*info->fprintf_func) (info->stream, "%s", name); + return 1; + } + } } /* Check if the REX prefix is used. */ @@ -11637,7 +11667,7 @@ print_insn (bfd_vma pc, disassemble_info all_prefixes[last_data_prefix] = 0; prefix_length = 0; - for (i = 0; i < (int) ARRAY_SIZE (all_prefixes); i++) + for (i = 0; !extension && i < (int) ARRAY_SIZE (all_prefixes); i++) if (all_prefixes[i]) { const char *name; @@ -11655,7 +11685,8 @@ print_insn (bfd_vma pc, disassemble_info return MAX_CODE_LENGTH; } - obufp = mnemonicendp; + if (!extension) + obufp = mnemonicendp; for (i = strlen (obuf) + prefix_length; i < 6; i++) oappend (" "); oappend (" "); --- gdb-7.6/bfd/coff-i386.c.orig +++ gdb-7.6/bfd/coff-i386.c @@ -141,7 +141,7 @@ coff_i386_reloc (bfd *abfd, #define DOIT(x) \ x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask)) - if (diff != 0) + if (diff != 0) { reloc_howto_type *howto = reloc_entry->howto; unsigned char *addr = (unsigned char *) data + reloc_entry->address; --- gdb-7.6/bfd/coff-x86_64.c.orig +++ gdb-7.6/bfd/coff-x86_64.c @@ -139,7 +139,7 @@ coff_amd64_reloc (bfd *abfd, #define DOIT(x) \ x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask)) - if (diff != 0) + if (diff != 0) { reloc_howto_type *howto = reloc_entry->howto; unsigned char *addr = (unsigned char *) data + reloc_entry->address; --- gdb-7.6/opcodes/arm-dis.c.orig +++ gdb-7.6/opcodes/arm-dis.c @@ -2103,7 +2103,7 @@ print_insn_coprocessor (bfd_vma pc, /* Is ``imm'' a negative number? */ if (imm & 0x40) - imm |= (-1 << 7); + imm -= 0x80; func (stream, "%d", imm); } diff -up gdb-7.6/bfd/elf64-ppc.c.orig gdb-7.6/bfd/elf64-ppc.c --- gdb-7.6/bfd/elf64-ppc.c.orig 2016-02-02 11:04:25.436527347 -0500 +++ gdb-7.6/bfd/elf64-ppc.c 2016-02-02 11:11:51.926468454 -0500 @@ -11743,7 +11743,7 @@ ppc64_elf_size_stubs (struct bfd_link_in stub_sec = stub_sec->next) if ((stub_sec->flags & SEC_LINKER_CREATED) == 0) stub_sec->size = ((stub_sec->size + (1 << htab->plt_stub_align) - 1) - & (-1 << htab->plt_stub_align)); + & -(1 << htab->plt_stub_align)); for (stub_sec = htab->stub_bfd->sections; stub_sec != NULL; @@ -12093,7 +12093,7 @@ ppc64_elf_build_stubs (bfd_boolean emit_ stub_sec = stub_sec->next) if ((stub_sec->flags & SEC_LINKER_CREATED) == 0) stub_sec->size = ((stub_sec->size + (1 << htab->plt_stub_align) - 1) - & (-1 << htab->plt_stub_align)); + & -(1 << htab->plt_stub_align)); for (stub_sec = htab->stub_bfd->sections; stub_sec != NULL; --- gdb-7.6/include/opcode/ppc.h.orig +++ gdb-7.6/include/opcode/ppc.h @@ -278,7 +278,7 @@ extern const unsigned int num_powerpc_op /* Use with the shift field of a struct powerpc_operand to indicate that BITM and SHIFT cannot be used to determine where the operand goes in the insn. */ -#define PPC_OPSHIFT_INV (-1 << 31) +#define PPC_OPSHIFT_INV (-1U << 31) /* Values defined for the flags field of a struct powerpc_operand. */ --- gdb-7.6/opcodes/mips-dis.c.orig +++ gdb-7.6/opcodes/mips-dis.c @@ -245,18 +245,6 @@ static const char * const mips_cp0_names "c0_taglo", "c0_taghi", "c0_errorepc", "$31" }; -static const struct mips_cp0sel_name mips_cp0sel_names_mipsr5900[] = -{ - { 24, 2, "c0_iab" }, - { 24, 3, "c0_iabm" }, - { 24, 4, "c0_dab" }, - { 24, 5, "c0_dabm" }, - { 24, 6, "c0_dvb" }, - { 24, 7, "c0_dvbm" }, - { 25, 1, "c0_perfcnt,1" }, - { 25, 2, "c0_perfcnt,2" } -}; - static const char * const mips_cp0_names_mips3264[32] = { "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1", --- gdb-7.6/gdb/ada-lang.c.orig +++ gdb-7.6/gdb/ada-lang.c @@ -10503,7 +10503,7 @@ ada_evaluate_subexp (struct type *expect } else arg1 = ada_value_struct_elt (arg1, &exp->elts[pc + 2].string, 0); - arg1 = unwrap_value (arg1); + arg1 = unwrap_value (arg1); return ada_to_fixed_value (arg1); case OP_TYPE: --- gdb-7.6/gdb/linux-record.c.orig +++ gdb-7.6/gdb/linux-record.c @@ -112,7 +112,7 @@ record_linux_sockaddr (struct regcache * "memory at addr = 0x%s len = %d.\n", phex_nz (len, tdep->size_pointer), tdep->size_int); - return -1; + return -1; } addrlen = (int) extract_unsigned_integer (a, tdep->size_int, byte_order); if (addrlen <= 0 || addrlen > tdep->size_sockaddr) @@ -150,7 +150,7 @@ record_linux_msghdr (struct regcache *re "len = %d.\n", phex_nz (addr, tdep->size_pointer), tdep->size_msghdr); - return -1; + return -1; } /* msg_name msg_namelen */ @@ -186,7 +186,7 @@ record_linux_msghdr (struct regcache *re "len = %d.\n", phex_nz (addr,tdep->size_pointer), tdep->size_iovec); - return -1; + return -1; } tmpaddr = (CORE_ADDR) extract_unsigned_integer (iov, tdep->size_pointer, @@ -948,7 +948,7 @@ Do you want to stop the program?"), "memory at addr = 0x%s len = %d.\n", OUTPUT_REG (tmpulongest, tdep->arg2), tdep->size_ulong); - return -1; + return -1; } tmpulongest = extract_unsigned_integer (a, tdep->size_ulong, byte_order); --- gdb-7.6/gdb/inflow.c.orig +++ gdb-7.6/gdb/inflow.c @@ -391,7 +391,7 @@ terminal_ours_1 (int output_only) if (tinfo->run_terminal != NULL || gdb_has_a_terminal () == 0) return; - { + { #ifdef SIGTTOU /* Ignore this signal since it will happen when we try to set the pgrp. */ --- gdb-7.6/gdb/printcmd.c.orig +++ gdb-7.6/gdb/printcmd.c @@ -1045,7 +1045,7 @@ print_command_2 (char *exp, int inspect, else val = access_value_history (0); - printf_filtered ("%d %d %d %d %d %d\n", + printf_filtered ("%d %d %d %d %d %d\n", TYPE_CODE (check_typedef(value_type (val))), TYPE_UNSIGNED (check_typedef(value_type (val))), TYPE_LENGTH (check_typedef(value_type(val))), --- gdb-7.6/gdb/c-typeprint.c.orig +++ gdb-7.6/gdb/c-typeprint.c @@ -1293,7 +1293,7 @@ c_type_print_base (struct type *type, st if (TYPE_NFIELDS (type) != 0 || TYPE_NFN_FIELDS (type) != 0) fprintf_filtered (stream, "\n"); - for (i = 0; i < TYPE_TYPEDEF_FIELD_COUNT (type); i++) + for (i = 0; i < TYPE_TYPEDEF_FIELD_COUNT (type); i++) { struct type *target = TYPE_TYPEDEF_FIELD_TYPE (type, i); --- gdb-7.6/gdb/symtab.c.orig +++ gdb-7.6/gdb/symtab.c @@ -5139,6 +5139,8 @@ static void get_user_print_option_addres extern int get_frame_offset(CORE_ADDR); static void gdb_set_crash_block(struct gnu_request *); void gdb_command_funnel(struct gnu_request *); +static long lookup_struct_contents(struct gnu_request *); +static void iterate_datatypes(struct gnu_request *); struct objfile *gdb_kernel_objfile = { 0 }; @@ -5242,6 +5244,14 @@ gdb_command_funnel(struct gnu_request *r req->flags |= GNU_COMMAND_FAILED; break; + case GNU_LOOKUP_STRUCT_CONTENTS: + req->value = lookup_struct_contents(req); + break; + + case GNU_GET_NEXT_DATATYPE: + iterate_datatypes(req); + break; + default: req->flags |= GNU_COMMAND_FAILED; break; @@ -5779,4 +5789,135 @@ gdb_get_crash_block(void) 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 if (m->tag_name) + n = m->tag_name; + else + continue; + + if (strstr(n, type_name)) + return 1; + } + + return 0; +} + +static void +iterate_datatypes (struct gnu_request *req) +{ + static struct block_iterator bi; // Keeping this static will simplify code + struct block *b; + int do_return = 0; + struct global_iterator *gi = &req->global_iterator; + + if (gi->finished) + return; + + if (gi->obj == NULL) + { + gi->obj = current_program_space->objfiles; + gi->symtab = NULL; + do_return = 1; // The initial case - we don't need to make next step. + } + + for (; gi->obj; gi->obj = gi->obj->next, gi->symtab = NULL) + { + if (gi->symtab == NULL) + { + // Symtab `symtab` is nullified for every objfile + if (gi->obj->sf) + gi->obj->sf->qf->expand_all_symtabs(gi->obj); + gi->symtab = gi->obj->symtabs; + gi->sym = NULL; + } + + for (; gi->symtab; gi->symtab = gi->symtab->next, gi->block_index = -1) + { + if (!gi->symtab->primary) + continue; + + if (gi->block_index == -1) + { + gi->block_index = GLOBAL_BLOCK; + gi->sym = NULL; + } + for (; gi->block_index <= STATIC_BLOCK; gi->block_index++, gi->sym = NULL) + { + if (!gi->sym) + { + b = BLOCKVECTOR_BLOCK(BLOCKVECTOR(gi->symtab), gi->block_index); + gi->sym = block_iterator_first(b, &bi); + } + for (; gi->sym; gi->sym = block_iterator_next(&bi)) + { + QUIT; + + if (SYMBOL_CLASS (gi->sym) != LOC_TYPEDEF) + continue; + + // Iteration 1 (do_return == 0): initialization + // Iteration 2 (do_return == 1): iterate symbol + if (do_return++ == 0) + continue; + + // Yield the current symbol and its size + req->addr = (ulong)(gi->sym->type->main_type); + req->name = (char *)(gi->sym->ginfo.name); + req->length = gi->sym->type->length; + + return; + } + } + } + } + gi->finished = 1; +} #endif --- gdb-7.6/bfd/elf64-s390.c.orig +++ gdb-7.6/bfd/elf64-s390.c @@ -323,10 +323,10 @@ elf_s390_reloc_name_lookup (bfd *abfd AT && strcasecmp (elf_howto_table[i].name, r_name) == 0) return &elf_howto_table[i]; - if (strcasecmp (elf64_s390_vtinherit_howto.name, r_name) == 0) - return &elf64_s390_vtinherit_howto; - if (strcasecmp (elf64_s390_vtentry_howto.name, r_name) == 0) - return &elf64_s390_vtentry_howto; + if (strcasecmp (elf64_s390_vtinherit_howto.name, r_name) == 0) + return &elf64_s390_vtinherit_howto; + if (strcasecmp (elf64_s390_vtentry_howto.name, r_name) == 0) + return &elf64_s390_vtentry_howto; return NULL; } --- gdb-7.6/gdb/symtab.c.orig +++ gdb-7.6/gdb/symtab.c @@ -5122,7 +5122,7 @@ When enabled, debugging messages are pri #define GDB_COMMON #include "../../defs.h" -static void get_member_data(struct gnu_request *, struct type *); +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 *); @@ -5327,7 +5327,7 @@ gdb_get_datatype(struct gnu_request *req req->typecode = TYPE_CODE(sym->type); req->length = TYPE_LENGTH(sym->type); if (req->member) - get_member_data(req, sym->type); + get_member_data(req, sym->type, 0, 1); if (TYPE_CODE(sym->type) == TYPE_CODE_ENUM) { if (req->flags & GNU_PRINT_ENUMERATORS) @@ -5397,7 +5397,7 @@ gdb_get_datatype(struct gnu_request *req } if (req->member) - get_member_data(req, type); + get_member_data(req, type, 0, 1); break; @@ -5480,7 +5480,7 @@ eval_enum(struct type *type, struct gnu_ * member field, and when found, return its relevant data. */ static void -get_member_data(struct gnu_request *req, struct type *type) +get_member_data(struct gnu_request *req, struct type *type, long offset, int is_first) { register short i; struct field *nextfield; @@ -5492,7 +5492,7 @@ get_member_data(struct gnu_request *req, nfields = TYPE_MAIN_TYPE(type)->nfields; nextfield = TYPE_MAIN_TYPE(type)->flds_bnds.fields; - if (nfields == 0) { + if (nfields == 0 && is_first /* The first call */) { struct type *newtype; newtype = lookup_transparent_type(req->name); if (newtype) { @@ -5505,13 +5505,18 @@ get_member_data(struct gnu_request *req, for (i = 0; i < nfields; i++) { if (STREQ(req->member, nextfield->name)) { - req->member_offset = nextfield->loc.bitpos; + req->member_offset = offset + nextfield->loc.bitpos; req->member_length = TYPE_LENGTH(nextfield->type); req->member_typecode = TYPE_CODE(nextfield->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++; } @@ -5706,7 +5711,7 @@ gdb_get_symbol_type(struct gnu_request * } if (req->member) - get_member_data(req, type); + get_member_data(req, type, 0, 1); do_cleanups (old_chain); } diff -up gdb-7.6/bfd/configure.orig gdb-7.6/bfd/configure --- gdb-7.6/bfd/configure.orig 2017-02-17 17:19:51.654898822 -0500 +++ gdb-7.6/bfd/configure 2017-02-17 17:19:57.922038757 -0500 @@ -12193,7 +12193,7 @@ fi NO_WERROR= if test "${ERROR_ON_WARNING}" = yes ; then - GCC_WARN_CFLAGS="$GCC_WARN_CFLAGS -Werror" + GCC_WARN_CFLAGS="$GCC_WARN_CFLAGS" NO_WERROR="-Wno-error" fi diff -up gdb-7.6/opcodes/configure.orig gdb-7.6/opcodes/configure --- gdb-7.6/opcodes/configure.orig 2017-02-17 17:19:08.849943016 -0500 +++ gdb-7.6/opcodes/configure 2017-02-17 17:19:23.256264699 -0500 @@ -11539,7 +11539,7 @@ fi NO_WERROR= if test "${ERROR_ON_WARNING}" = yes ; then - GCC_WARN_CFLAGS="$GCC_WARN_CFLAGS -Werror" + GCC_WARN_CFLAGS="$GCC_WARN_CFLAGS" NO_WERROR="-Wno-error" fi --- gdb-7.6/gdb/symtab.c.orig +++ gdb-7.6/gdb/symtab.c @@ -5266,6 +5266,7 @@ gdb_get_line_number(struct gnu_request * { struct symtab_and_line sal; struct symbol *sym; + struct objfile *objfile; CORE_ADDR pc; #define LASTCHAR(s) (s[strlen(s)-1]) @@ -5281,8 +5282,22 @@ gdb_get_line_number(struct gnu_request * sal = find_pc_line(pc, 0); if (!sal.symtab) { - req->buf[0] = '\0'; - return; + /* + * 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 && sal.symtab->dirname) { @@ -5557,7 +5572,6 @@ struct load_module *gdb_current_load_mod static void gdb_add_symbol_file(struct gnu_request *req) { - register struct objfile *loaded_objfile = NULL; register struct objfile *objfile; register struct minimal_symbol *m; struct load_module *lm; @@ -5576,6 +5590,7 @@ gdb_add_symbol_file(struct gnu_request * 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++) { @@ -5623,12 +5638,15 @@ gdb_add_symbol_file(struct gnu_request * ALL_OBJFILES(objfile) { if (same_file(objfile->name, lm->mod_namelist)) { - loaded_objfile = objfile; + if (objfile->separate_debug_objfile) + lm->loaded_objfile = objfile->separate_debug_objfile; + else + lm->loaded_objfile = objfile; break; } } - if (!loaded_objfile) + if (!lm->loaded_objfile) req->flags |= GNU_COMMAND_FAILED; } --- gdb-7.6/gdb/symtab.c.orig +++ gdb-7.6/gdb/symtab.c @@ -5500,7 +5500,7 @@ get_member_data(struct gnu_request *req, register short i; struct field *nextfield; short nfields; - struct type *typedef_type; + struct type *typedef_type, *target_type; req->member_offset = -1; @@ -5523,6 +5523,13 @@ get_member_data(struct gnu_request *req, 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); --- gdb-7.6/gdb/symtab.c.orig +++ gdb-7.6/gdb/symtab.c @@ -5727,6 +5727,7 @@ gdb_get_symbol_type(struct gnu_request * 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) { --- gdb-7.6/gdb/common/linux-ptrace.c.orig +++ gdb-7.6/gdb/common/linux-ptrace.c @@ -108,14 +108,14 @@ linux_ptrace_test_ret_to_nx (void) ".globl linux_ptrace_test_ret_to_nx_instr;" "linux_ptrace_test_ret_to_nx_instr:" "ret" - : : "r" (return_address) : "%esp", "memory"); + : : "r" (return_address) : "memory"); #elif defined __x86_64__ asm volatile ("pushq %0;" ".globl linux_ptrace_test_ret_to_nx_instr;" "linux_ptrace_test_ret_to_nx_instr:" "ret" : : "r" ((uint64_t) (uintptr_t) return_address) - : "%rsp", "memory"); + : "memory"); #else # error "!__i386__ && !__x86_64__" #endif