diff --git a/gdb-6.3-readnever-20050907.patch b/gdb-6.3-readnever-20050907.patch index c2f0ea8..0bdf948 100644 --- a/gdb-6.3-readnever-20050907.patch +++ b/gdb-6.3-readnever-20050907.patch @@ -11,10 +11,10 @@ * gdb.texinfo (File Options): Document --readnever. -Index: gdb-7.1.90.20100711/gdb/doc/gdb.texinfo +Index: gdb-7.1.90.20100721/gdb/doc/gdb.texinfo =================================================================== ---- gdb-7.1.90.20100711.orig/gdb/doc/gdb.texinfo 2010-07-01 19:40:04.000000000 +0200 -+++ gdb-7.1.90.20100711/gdb/doc/gdb.texinfo 2010-07-12 10:41:11.000000000 +0200 +--- gdb-7.1.90.20100721.orig/gdb/doc/gdb.texinfo 2010-07-22 11:57:09.000000000 +0200 ++++ gdb-7.1.90.20100721/gdb/doc/gdb.texinfo 2010-07-22 11:57:34.000000000 +0200 @@ -998,6 +998,12 @@ Read each symbol file's entire symbol ta the default, which is to read it incrementally as it is needed. This makes startup slower, but makes future operations faster. @@ -28,11 +28,11 @@ Index: gdb-7.1.90.20100711/gdb/doc/gdb.texinfo @end table @node Mode Options -Index: gdb-7.1.90.20100711/gdb/main.c +Index: gdb-7.1.90.20100721/gdb/main.c =================================================================== ---- gdb-7.1.90.20100711.orig/gdb/main.c 2010-07-12 10:17:26.000000000 +0200 -+++ gdb-7.1.90.20100711/gdb/main.c 2010-07-12 10:41:34.000000000 +0200 -@@ -388,6 +388,7 @@ captured_main (void *data) +--- gdb-7.1.90.20100721.orig/gdb/main.c 2010-07-22 11:57:10.000000000 +0200 ++++ gdb-7.1.90.20100721/gdb/main.c 2010-07-22 11:57:49.000000000 +0200 +@@ -391,6 +391,7 @@ captured_main (void *data) {"xdb", no_argument, &xdb_commands, 1}, {"dbx", no_argument, &dbx_commands, 1}, {"readnow", no_argument, &readnow_symbol_files, 1}, @@ -40,18 +40,18 @@ Index: gdb-7.1.90.20100711/gdb/main.c {"r", no_argument, &readnow_symbol_files, 1}, {"quiet", no_argument, &quiet, 1}, {"q", no_argument, &quiet, 1}, -@@ -980,6 +981,7 @@ Options:\n\n\ - fputs_unfiltered (_(" file.\n\ +@@ -1038,6 +1039,7 @@ Options:\n\n\ + fputs_unfiltered (_("\ --quiet Do not print version number on startup.\n\ --readnow Fully read symbol files on first access.\n\ + --readnever Do not read symbol files.\n\ "), stream); fputs_unfiltered (_("\ --se=FILE Use FILE as symbol file and executable file.\n\ -Index: gdb-7.1.90.20100711/gdb/symfile.c +Index: gdb-7.1.90.20100721/gdb/symfile.c =================================================================== ---- gdb-7.1.90.20100711.orig/gdb/symfile.c 2010-06-03 01:01:00.000000000 +0200 -+++ gdb-7.1.90.20100711/gdb/symfile.c 2010-07-12 10:41:11.000000000 +0200 +--- gdb-7.1.90.20100721.orig/gdb/symfile.c 2010-07-22 11:57:09.000000000 +0200 ++++ gdb-7.1.90.20100721/gdb/symfile.c 2010-07-22 11:57:34.000000000 +0200 @@ -80,6 +80,7 @@ static void clear_symtab_users_cleanup ( /* Global variables owned by this file */ @@ -60,19 +60,19 @@ Index: gdb-7.1.90.20100711/gdb/symfile.c /* External variables and functions referenced. */ -Index: gdb-7.1.90.20100711/gdb/dwarf2read.c +Index: gdb-7.1.90.20100721/gdb/dwarf2read.c =================================================================== ---- gdb-7.1.90.20100711.orig/gdb/dwarf2read.c 2010-07-12 10:00:56.000000000 +0200 -+++ gdb-7.1.90.20100711/gdb/dwarf2read.c 2010-07-12 10:43:53.000000000 +0200 -@@ -51,6 +51,7 @@ - #include "typeprint.h" - #include "jv-lang.h" +--- gdb-7.1.90.20100721.orig/gdb/dwarf2read.c 2010-07-22 11:57:10.000000000 +0200 ++++ gdb-7.1.90.20100721/gdb/dwarf2read.c 2010-07-22 11:58:05.000000000 +0200 +@@ -53,6 +53,7 @@ #include "psympriv.h" + #include "exceptions.h" + #include "gdb_stat.h" +#include "top.h" #include #include "gdb_string.h" -@@ -1161,8 +1162,9 @@ dwarf2_has_info (struct objfile *objfile +@@ -1282,8 +1283,9 @@ dwarf2_has_info (struct objfile *objfile bfd_map_over_sections (objfile->obfd, dwarf2_locate_sections, NULL); dwarf2_per_objfile->objfile = objfile; } @@ -84,10 +84,10 @@ Index: gdb-7.1.90.20100711/gdb/dwarf2read.c } /* When loading sections, we can either look for ".", or for -Index: gdb-7.1.90.20100711/gdb/top.h +Index: gdb-7.1.90.20100721/gdb/top.h =================================================================== ---- gdb-7.1.90.20100711.orig/gdb/top.h 2010-04-07 18:54:39.000000000 +0200 -+++ gdb-7.1.90.20100711/gdb/top.h 2010-07-12 10:41:11.000000000 +0200 +--- gdb-7.1.90.20100721.orig/gdb/top.h 2010-04-07 18:54:39.000000000 +0200 ++++ gdb-7.1.90.20100721/gdb/top.h 2010-07-22 11:57:34.000000000 +0200 @@ -61,6 +61,7 @@ extern void set_prompt (char *); /* From random places. */ diff --git a/gdb-6.6-buildid-locate-rpm.patch b/gdb-6.6-buildid-locate-rpm.patch index 8271992..e11fb3c 100644 --- a/gdb-6.6-buildid-locate-rpm.patch +++ b/gdb-6.6-buildid-locate-rpm.patch @@ -1,7 +1,7 @@ -Index: gdb-7.1.90.20100711/gdb/event-top.c +Index: gdb-7.1.90.20100721/gdb/event-top.c =================================================================== ---- gdb-7.1.90.20100711.orig/gdb/event-top.c 2010-06-26 08:44:47.000000000 +0200 -+++ gdb-7.1.90.20100711/gdb/event-top.c 2010-07-12 11:37:04.000000000 +0200 +--- gdb-7.1.90.20100721.orig/gdb/event-top.c 2010-06-26 08:44:47.000000000 +0200 ++++ gdb-7.1.90.20100721/gdb/event-top.c 2010-07-22 11:58:24.000000000 +0200 @@ -33,6 +33,7 @@ #include "cli/cli-script.h" /* for reset_command_nest_depth */ #include "main.h" @@ -28,10 +28,10 @@ Index: gdb-7.1.90.20100711/gdb/event-top.c /* Each interpreter has its own rules on displaying the command prompt. */ if (!current_interp_display_prompt_p ()) -Index: gdb-7.1.90.20100711/gdb/elfread.c +Index: gdb-7.1.90.20100721/gdb/elfread.c =================================================================== ---- gdb-7.1.90.20100711.orig/gdb/elfread.c 2010-07-12 11:30:30.000000000 +0200 -+++ gdb-7.1.90.20100711/gdb/elfread.c 2010-07-12 11:37:04.000000000 +0200 +--- gdb-7.1.90.20100721.orig/gdb/elfread.c 2010-07-22 11:58:14.000000000 +0200 ++++ gdb-7.1.90.20100721/gdb/elfread.c 2010-07-22 11:58:24.000000000 +0200 @@ -42,6 +42,7 @@ #include "gdbcore.h" #include "gdbcmd.h" @@ -40,7 +40,7 @@ Index: gdb-7.1.90.20100711/gdb/elfread.c extern void _initialize_elfread (void); -@@ -1368,8 +1369,353 @@ build_id_to_filename (struct build_id *b +@@ -1371,8 +1372,353 @@ build_id_to_filename (struct build_id *b return retval; } @@ -395,7 +395,7 @@ Index: gdb-7.1.90.20100711/gdb/elfread.c avoidance. */ struct missing_filepair -@@ -1423,11 +1769,17 @@ missing_filepair_change (void) +@@ -1426,11 +1772,17 @@ missing_filepair_change (void) /* All their memory came just from missing_filepair_OBSTACK. */ missing_filepair_hash = NULL; } @@ -413,7 +413,7 @@ Index: gdb-7.1.90.20100711/gdb/elfread.c missing_filepair_change (); } -@@ -1494,14 +1846,34 @@ debug_print_missing (const char *binary, +@@ -1497,14 +1849,34 @@ debug_print_missing (const char *binary, *slot = missing_filepair; @@ -455,11 +455,11 @@ Index: gdb-7.1.90.20100711/gdb/elfread.c } static char * -Index: gdb-7.1.90.20100711/gdb/symfile.h +Index: gdb-7.1.90.20100721/gdb/symfile.h =================================================================== ---- gdb-7.1.90.20100711.orig/gdb/symfile.h 2010-07-12 11:06:18.000000000 +0200 -+++ gdb-7.1.90.20100711/gdb/symfile.h 2010-07-12 11:37:04.000000000 +0200 -@@ -568,6 +568,7 @@ extern struct build_id *build_id_addr_ge +--- gdb-7.1.90.20100721.orig/gdb/symfile.h 2010-07-22 11:58:14.000000000 +0200 ++++ gdb-7.1.90.20100721/gdb/symfile.h 2010-07-22 11:58:24.000000000 +0200 +@@ -577,6 +577,7 @@ extern struct build_id *build_id_addr_ge extern char *build_id_to_filename (struct build_id *build_id, char **link_return, int add_debug_suffix); extern void debug_print_missing (const char *binary, const char *debug); @@ -467,11 +467,11 @@ Index: gdb-7.1.90.20100711/gdb/symfile.h /* From dwarf2read.c */ -Index: gdb-7.1.90.20100711/gdb/testsuite/lib/gdb.exp +Index: gdb-7.1.90.20100721/gdb/testsuite/lib/gdb.exp =================================================================== ---- gdb-7.1.90.20100711.orig/gdb/testsuite/lib/gdb.exp 2010-07-12 11:05:57.000000000 +0200 -+++ gdb-7.1.90.20100711/gdb/testsuite/lib/gdb.exp 2010-07-12 11:37:04.000000000 +0200 -@@ -1353,7 +1353,7 @@ proc default_gdb_start { } { +--- gdb-7.1.90.20100721.orig/gdb/testsuite/lib/gdb.exp 2010-07-22 11:58:14.000000000 +0200 ++++ gdb-7.1.90.20100721/gdb/testsuite/lib/gdb.exp 2010-07-22 11:58:24.000000000 +0200 +@@ -1359,7 +1359,7 @@ proc default_gdb_start { } { warning "Couldn't set the width to 0." } } @@ -480,10 +480,10 @@ Index: gdb-7.1.90.20100711/gdb/testsuite/lib/gdb.exp send_gdb "set build-id-verbose 0\n" gdb_expect 10 { -re "$gdb_prompt $" { -Index: gdb-7.1.90.20100711/gdb/testsuite/lib/mi-support.exp +Index: gdb-7.1.90.20100721/gdb/testsuite/lib/mi-support.exp =================================================================== ---- gdb-7.1.90.20100711.orig/gdb/testsuite/lib/mi-support.exp 2010-07-12 11:05:57.000000000 +0200 -+++ gdb-7.1.90.20100711/gdb/testsuite/lib/mi-support.exp 2010-07-12 11:37:04.000000000 +0200 +--- gdb-7.1.90.20100721.orig/gdb/testsuite/lib/mi-support.exp 2010-07-22 11:58:14.000000000 +0200 ++++ gdb-7.1.90.20100721/gdb/testsuite/lib/mi-support.exp 2010-07-22 11:58:24.000000000 +0200 @@ -221,7 +221,7 @@ proc default_mi_gdb_start { args } { } } @@ -493,10 +493,10 @@ Index: gdb-7.1.90.20100711/gdb/testsuite/lib/mi-support.exp send_gdb "190-gdb-set build-id-verbose 0\n" gdb_expect 10 { -re ".*190-gdb-set build-id-verbose 0\r\n190\\\^done\r\n$mi_gdb_prompt$" { -Index: gdb-7.1.90.20100711/gdb/tui/tui-interp.c +Index: gdb-7.1.90.20100721/gdb/tui/tui-interp.c =================================================================== ---- gdb-7.1.90.20100711.orig/gdb/tui/tui-interp.c 2010-05-18 00:21:43.000000000 +0200 -+++ gdb-7.1.90.20100711/gdb/tui/tui-interp.c 2010-07-12 11:37:04.000000000 +0200 +--- gdb-7.1.90.20100721.orig/gdb/tui/tui-interp.c 2010-05-18 00:21:43.000000000 +0200 ++++ gdb-7.1.90.20100721/gdb/tui/tui-interp.c 2010-07-22 11:58:24.000000000 +0200 @@ -30,6 +30,7 @@ #include "tui/tui.h" #include "tui/tui-io.h" @@ -514,10 +514,10 @@ Index: gdb-7.1.90.20100711/gdb/tui/tui-interp.c /* Tell readline what the prompt to display is and what function it will need to call after a whole line is read. This also displays the first prompt. */ -Index: gdb-7.1.90.20100711/gdb/aclocal.m4 +Index: gdb-7.1.90.20100721/gdb/aclocal.m4 =================================================================== ---- gdb-7.1.90.20100711.orig/gdb/aclocal.m4 2010-05-23 02:56:59.000000000 +0200 -+++ gdb-7.1.90.20100711/gdb/aclocal.m4 2010-07-12 11:37:04.000000000 +0200 +--- gdb-7.1.90.20100721.orig/gdb/aclocal.m4 2010-05-23 02:56:59.000000000 +0200 ++++ gdb-7.1.90.20100721/gdb/aclocal.m4 2010-07-22 11:58:24.000000000 +0200 @@ -19,6 +19,162 @@ You have another version of autoconf. I If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically `autoreconf'.])]) @@ -681,10 +681,10 @@ Index: gdb-7.1.90.20100711/gdb/aclocal.m4 # Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation -Index: gdb-7.1.90.20100711/gdb/config.in +Index: gdb-7.1.90.20100721/gdb/config.in =================================================================== ---- gdb-7.1.90.20100711.orig/gdb/config.in 2010-07-06 21:03:11.000000000 +0200 -+++ gdb-7.1.90.20100711/gdb/config.in 2010-07-12 11:38:30.000000000 +0200 +--- gdb-7.1.90.20100721.orig/gdb/config.in 2010-07-22 11:57:09.000000000 +0200 ++++ gdb-7.1.90.20100721/gdb/config.in 2010-07-22 11:58:24.000000000 +0200 @@ -46,6 +46,9 @@ /* Define to BFD's default target vector. */ #undef DEFAULT_BFD_VEC @@ -695,7 +695,7 @@ Index: gdb-7.1.90.20100711/gdb/config.in /* Define to 1 if translation of program messages to the user's native language is requested. */ #undef ENABLE_NLS -@@ -232,6 +235,9 @@ +@@ -231,6 +234,9 @@ /* Define if Python 2.7 is being used. */ #undef HAVE_LIBPYTHON2_7 @@ -705,10 +705,10 @@ Index: gdb-7.1.90.20100711/gdb/config.in /* Define if libunwind library is being used. */ #undef HAVE_LIBUNWIND -Index: gdb-7.1.90.20100711/gdb/configure +Index: gdb-7.1.90.20100721/gdb/configure =================================================================== ---- gdb-7.1.90.20100711.orig/gdb/configure 2010-07-07 19:36:39.000000000 +0200 -+++ gdb-7.1.90.20100711/gdb/configure 2010-07-12 11:38:15.000000000 +0200 +--- gdb-7.1.90.20100721.orig/gdb/configure 2010-07-22 11:57:09.000000000 +0200 ++++ gdb-7.1.90.20100721/gdb/configure 2010-07-22 11:59:13.000000000 +0200 @@ -679,6 +679,9 @@ REPORT_BUGS_TO PKGVERSION TARGET_OBS @@ -716,18 +716,18 @@ Index: gdb-7.1.90.20100711/gdb/configure +RPM_LIBS +RPM_CFLAGS +PKG_CONFIG + pythondir + GDB_DATADIR_PATH GDB_DATADIR - DEBUGDIR - am__fastdepCC_FALSE -@@ -945,6 +948,7 @@ enable_dependency_tracking - with_separate_debug_dir +@@ -948,6 +951,7 @@ with_separate_debug_dir with_gdb_datadir with_relocated_sources + with_pythondir +with_rpm enable_targets enable_64_bit_bfd enable_gdbcli -@@ -985,6 +989,9 @@ LDFLAGS +@@ -988,6 +992,9 @@ LDFLAGS LIBS CPPFLAGS CPP @@ -737,16 +737,16 @@ Index: gdb-7.1.90.20100711/gdb/configure YACC YFLAGS XMKMF' -@@ -1646,6 +1653,8 @@ Optional Packages: +@@ -1653,6 +1660,8 @@ Optional Packages: [DATADIR/gdb] - --with-relocated-sources=PATH - automatically relocate this path for source files + --with-pythondir install Python data files in this path + [DATADIR/gdb/python] + --with-rpm query rpm database for missing debuginfos (yes/no, + def. auto=librpm.so) --with-libunwind use libunwind frame unwinding support --with-curses use the curses library instead of the termcap library -@@ -1681,6 +1690,9 @@ Some influential environment variables: +@@ -1688,6 +1697,9 @@ Some influential environment variables: CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor @@ -756,7 +756,7 @@ Index: gdb-7.1.90.20100711/gdb/configure YACC The `Yet Another C Compiler' implementation to use. Defaults to the first program found out of: `bison -y', `byacc', `yacc'. YFLAGS The list of arguments that will be passed by default to $YACC. -@@ -7878,6 +7890,486 @@ _ACEOF +@@ -7951,6 +7963,485 @@ _ACEOF fi @@ -1239,17 +1239,16 @@ Index: gdb-7.1.90.20100711/gdb/configure + fi + fi +fi -+ - subdirs="$subdirs doc testsuite" -Index: gdb-7.1.90.20100711/gdb/configure.ac + +Index: gdb-7.1.90.20100721/gdb/configure.ac =================================================================== ---- gdb-7.1.90.20100711.orig/gdb/configure.ac 2010-07-07 19:36:39.000000000 +0200 -+++ gdb-7.1.90.20100711/gdb/configure.ac 2010-07-12 11:38:02.000000000 +0200 -@@ -108,6 +108,199 @@ AS_HELP_STRING([--with-relocated-sources - [Relocated directory for source files. ]) - ]) +--- gdb-7.1.90.20100721.orig/gdb/configure.ac 2010-07-22 11:57:09.000000000 +0200 ++++ gdb-7.1.90.20100721/gdb/configure.ac 2010-07-22 11:59:04.000000000 +0200 +@@ -152,6 +152,198 @@ else + fi + AC_SUBST(pythondir) +# Integration with rpm library to support missing debuginfo suggestions. +# --without-rpm: Disable any rpm support. @@ -1443,14 +1442,13 @@ Index: gdb-7.1.90.20100711/gdb/configure.ac + fi + fi +fi -+ + AC_CONFIG_SUBDIRS(doc testsuite) - # Check whether to support alternative target configurations -Index: gdb-7.1.90.20100711/gdb/acinclude.m4 +Index: gdb-7.1.90.20100721/gdb/acinclude.m4 =================================================================== ---- gdb-7.1.90.20100711.orig/gdb/acinclude.m4 2010-05-27 05:40:45.000000000 +0200 -+++ gdb-7.1.90.20100711/gdb/acinclude.m4 2010-07-12 11:37:04.000000000 +0200 +--- gdb-7.1.90.20100721.orig/gdb/acinclude.m4 2010-05-27 05:40:45.000000000 +0200 ++++ gdb-7.1.90.20100721/gdb/acinclude.m4 2010-07-22 11:58:24.000000000 +0200 @@ -1,3 +1,5 @@ +# serial 1 + diff --git a/gdb-archer.patch b/gdb-archer.patch index c14a4be..6c8cd56 100644 --- a/gdb-archer.patch +++ b/gdb-archer.patch @@ -2,18 +2,122 @@ http://sourceware.org/gdb/wiki/ProjectArcher http://sourceware.org/gdb/wiki/ArcherBranchManagement GIT snapshot: -commit 0bc9a93725d7a7bcf1e30f072a12cc5186e41dc2 +commit 202f4d0e3af8d8a8d7c0b408d9e0a8cb69f912b6 branch `archer' - the merge of branches: archer-jankratochvil-vla archer-jankratochvil-watchpoint3 archer-jankratochvil-ifunc archer-pmuldoon-next-over-throw2 -#TODO:archer-tromey-python (possibly only extracted parts) -#TODO:archer-tromey-optional-psymtab (more fresh patches are at gdb-patches@) +archer-tromey-python (not a merge) +archer-tromey-optional-psymtab (cherry-picked from post-7.2 master) #TODO:archer-tromey-threaded-dwarf +diff --git a/gdb/Makefile.in b/gdb/Makefile.in +index 6dbb284..6133da3 100644 +--- a/gdb/Makefile.in ++++ b/gdb/Makefile.in +@@ -169,6 +169,12 @@ TARGET_SYSTEM_ROOT = @TARGET_SYSTEM_ROOT@ + TARGET_SYSTEM_ROOT_DEFINE = @TARGET_SYSTEM_ROOT_DEFINE@ + + # Did the user give us a --with-gdb-datadir option? ++GDB_DATADIR_PATH = @GDB_DATADIR_PATH@ ++ ++# The argument to --with-pythondir. If not given, this is ++# GDB_DATADIR_PATH/python. ++pythondir = @pythondir@ ++ + GDB_DATADIR = @GDB_DATADIR@ + + # Helper code from gnulib. +@@ -295,13 +301,13 @@ SUBDIR_PYTHON_SRCS = \ + python/py-cmd.c \ + python/py-frame.c \ + python/py-function.c \ ++ python/py-hooks.c \ + python/py-inferior.c \ + python/py-infthread.c \ + python/py-lazy-string.c \ + python/py-objfile.c \ + python/py-param.c \ + python/py-prettyprint.c \ +- python/py-progspace.c \ + python/py-symbol.c \ + python/py-symtab.c \ + python/py-type.c \ +@@ -780,8 +786,8 @@ config/rs6000/nm-rs6000.h top.h bsd-kvm.h gdb-stabs.h reggroups.h \ + annotate.h sim-regno.h dictionary.h dfp.h main.h frame-unwind.h \ + remote-fileio.h i386-linux-tdep.h vax-tdep.h objc-lang.h \ + sentinel-frame.h bcache.h symfile.h windows-tdep.h linux-tdep.h \ +-gdb_usleep.h jit.h xml-syscall.h ada-operator.inc microblaze-tdep.h \ +-psymtab.h psympriv.h ++gdb_usleep.h jit.h python/python.h python/python-internal.h \ ++xml-syscall.h ada-operator.inc microblaze-tdep.h + + # Header files that already have srcdir in them, or which are in objdir. + +@@ -1299,6 +1305,12 @@ stamp-h: $(srcdir)/config.in config.status + CONFIG_LINKS= \ + $(SHELL) config.status + ++.gdbinit: $(srcdir)/gdbinit.in config.status ++ CONFIG_FILES=".gdbinit:gdbinit.in" \ ++ CONFIG_COMMANDS= \ ++ CONFIG_HEADERS= \ ++ $(SHELL) config.status ++ + config.status: $(srcdir)/configure configure.tgt configure.host + $(SHELL) config.status --recheck + +@@ -2022,6 +2034,10 @@ py-function.o: $(srcdir)/python/py-function.c + $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-function.c + $(POSTCOMPILE) + ++py-hooks.o: $(srcdir)/python/py-hooks.c ++ $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-hooks.c ++ $(POSTCOMPILE) ++ + py-inferior.o: $(srcdir)/python/py-inferior.c + $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-inferior.c + $(POSTCOMPILE) +@@ -2070,6 +2086,36 @@ py-value.o: $(srcdir)/python/py-value.c + $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-value.c + $(POSTCOMPILE) + ++# All python library files, with the "python/lib" stripped off. ++# Note that we should only install files in the "gdb" module. ++PY_FILES = gdb/FrameIterator.py gdb/FrameWrapper.py gdb/command/alias.py \ ++ gdb/command/backtrace.py gdb/command/require.py \ ++ gdb/command/pahole.py gdb/command/upto.py gdb/command/__init__.py \ ++ gdb/command/ignore_errors.py gdb/command/save_breakpoints.py \ ++ gdb/function/caller_is.py gdb/function/in_scope.py \ ++ gdb/function/__init__.py gdb/backtrace.py gdb/__init__.py ++ ++# Install the Python library. Python library files go under ++# $(pythondir). ++install-python: ++ files='$(PY_FILES)'; for file in $$files; do \ ++ dir=`echo "$$file" | sed 's,/[^/]*$$,,'`; \ ++ $(SHELL) $(srcdir)/../mkinstalldirs $(DESTDIR)$(pythondir)/$$dir; \ ++ $(INSTALL_DATA) $(srcdir)/python/lib/$$file $(DESTDIR)$(pythondir)/$$file; \ ++ done ++ ++# Other packages may have their files installed in $(pythondir). ++uninstall-python: ++ files='$(PY_FILES)'; for file in $$files; do \ ++ slashdir=`echo "/$$file" | sed 's,/[^/]*$$,,'`; \ ++ rm -f $(DESTDIR)$(pythondir)/$$file; \ ++ while test "x$$file" != "x$$slashdir"; do \ ++ rmdir 2>/dev/null "$(DESTDIR)$(pythondir)$$slashdir"; \ ++ file="$$slashdir"; \ ++ slashdir=`echo "$$file" | sed 's,/[^/]*$$,,'`; \ ++ done \ ++ done ++ + # + # Dependency tracking. Most of this is conditional on GNU Make being + # found by configure; if GNU Make is not found, we fall back to a diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index 1d4c38b..cafb88e 100644 --- a/gdb/ada-lang.c @@ -185,7 +289,7 @@ index 0348bf4..f01d0ee 100644 /* Return the innermost stack frame executing inside of BLOCK, diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c -index 4affe0a..52105b5 100644 +index 4affe0a..584c68e 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -62,6 +62,7 @@ @@ -227,6 +331,15 @@ index 4affe0a..52105b5 100644 /* Assuming we're creating a static tracepoint, does S look like a static tracepoint marker spec ("-m MARKER_ID")? */ #define is_marker_spec(s) \ +@@ -430,7 +441,7 @@ static int tracepoint_count; + + static struct cmd_list_element *breakpoint_set_cmdlist; + static struct cmd_list_element *breakpoint_show_cmdlist; +-static struct cmd_list_element *save_cmdlist; ++struct cmd_list_element *save_cmdlist; + + /* Return whether a breakpoint is an active enabled breakpoint. */ + static int @@ -1252,6 +1263,22 @@ watchpoint_in_thread_scope (struct breakpoint *b) && !is_executing (inferior_ptid))); } @@ -1207,6 +1320,395 @@ index 926ae2f..a59b965 100644 && !TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED (type)) fprintf_filtered (stream, "%d", (TYPE_LENGTH (type) +diff --git a/gdb/config.in b/gdb/config.in +index 1fc457d..f4c846a 100644 +--- a/gdb/config.in ++++ b/gdb/config.in +@@ -50,11 +50,10 @@ + language is requested. */ + #undef ENABLE_NLS + +-/* look for global separate data files in this path [DATADIR/gdb] */ ++/* Global directory for GDB data files. */ + #undef GDB_DATADIR + +-/* Define if the gdb-datadir directory should be relocated when GDB is moved. +- */ ++/* Define if GDB datadir should be relocated when GDB is moved. */ + #undef GDB_DATADIR_RELOCATABLE + + /* Define to be a string naming the default host character set. */ +@@ -769,6 +768,9 @@ + 'ptrdiff_t'. */ + #undef PTRDIFF_T_SUFFIX + ++/* Define to install path for Python sources */ ++#undef PYTHONDIR ++ + /* Define if the python directory should be relocated when GDB is moved. */ + #undef PYTHON_PATH_RELOCATABLE + +diff --git a/gdb/configure b/gdb/configure +index 94eb9b9..e49da08 100755 +--- a/gdb/configure ++++ b/gdb/configure +@@ -679,6 +679,8 @@ REPORT_BUGS_TO + PKGVERSION + TARGET_OBS + subdirs ++pythondir ++GDB_DATADIR_PATH + GDB_DATADIR + DEBUGDIR + am__fastdepCC_FALSE +@@ -945,6 +947,7 @@ enable_dependency_tracking + with_separate_debug_dir + with_gdb_datadir + with_relocated_sources ++with_pythondir + enable_targets + enable_64_bit_bfd + enable_gdbcli +@@ -1646,6 +1649,10 @@ Optional Packages: + [DATADIR/gdb] + --with-relocated-sources=PATH + automatically relocate this path for source files ++ --with-gdb-datadir look for global separate data files in this path ++ [DATADIR/gdb] ++ --with-pythondir install Python data files in this path ++ [DATADIR/gdb/python] + --with-libunwind use libunwind frame unwinding support + --with-curses use the curses library instead of the termcap + library +@@ -7878,6 +7885,73 @@ _ACEOF + fi + + ++# GDB's datadir relocation ++ ++gdbdatadir=${datadir}/gdb ++ ++ ++# Check whether --with-gdb-datadir was given. ++if test "${with_gdb_datadir+set}" = set; then : ++ withval=$with_gdb_datadir; gdbdatadir="${withval}" ++fi ++ ++ ++ ++ test "x$prefix" = xNONE && prefix="$ac_default_prefix" ++ test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' ++ ac_define_dir=`eval echo $gdbdatadir` ++ ac_define_dir=`eval echo $ac_define_dir` ++ ++cat >>confdefs.h <<_ACEOF ++#define GDB_DATADIR "$ac_define_dir" ++_ACEOF ++ ++ ++ ++if test "x$exec_prefix" = xNONE || test "x$exec_prefix" = 'x${prefix}'; then ++ if test "x$prefix" = xNONE; then ++ test_prefix=/usr/local ++ else ++ test_prefix=$prefix ++ fi ++else ++ test_prefix=$exec_prefix ++fi ++ ++case ${gdbdatadir} in ++ "${test_prefix}"|"${test_prefix}/"*|\ ++ '${exec_prefix}'|'${exec_prefix}/'*) ++ ++$as_echo "#define GDB_DATADIR_RELOCATABLE 1" >>confdefs.h ++ ++ ;; ++esac ++GDB_DATADIR_PATH=${gdbdatadir} ++ ++ ++ ++# Check whether --with-pythondir was given. ++if test "${with_pythondir+set}" = set; then : ++ withval=$with_pythondir; pythondir="${withval}" ++else ++ pythondir=no ++fi ++ ++ ++# If the user passed in a path, define it. Otherwise, compute it at ++# runtime based on the possibly-relocatable datadir. ++if test "$pythondir" = "no"; then ++ pythondir='$(GDB_DATADIR_PATH)/python' ++else ++ ++cat >>confdefs.h <<_ACEOF ++#define PYTHONDIR "$pythondir" ++_ACEOF ++ ++fi ++ ++ ++ + + + subdirs="$subdirs doc testsuite" +@@ -10881,6 +10955,8 @@ $as_echo "#define HAVE_PYTHON 1" >>confdefs.h + CONFIG_OBS="$CONFIG_OBS \$(SUBDIR_PYTHON_OBS)" + CONFIG_DEPS="$CONFIG_DEPS \$(SUBDIR_PYTHON_DEPS)" + CONFIG_SRCS="$CONFIG_SRCS \$(SUBDIR_PYTHON_SRCS)" ++ CONFIG_INSTALL="$CONFIG_INSTALL install-python" ++ CONFIG_UNINSTALL="$CONFIG_UNINSTALL uninstall-python" + ENABLE_CFLAGS="$ENABLE_CFLAGS \$(SUBDIR_PYTHON_CFLAGS)" + + # Flags needed to compile Python code (taken from python-config --cflags). +diff --git a/gdb/configure.ac b/gdb/configure.ac +index 9300544..380473a 100644 +--- a/gdb/configure.ac ++++ b/gdb/configure.ac +@@ -108,6 +108,51 @@ AS_HELP_STRING([--with-relocated-sources=PATH], [automatically relocate this pat + [Relocated directory for source files. ]) + ]) + ++# GDB's datadir relocation ++ ++gdbdatadir=${datadir}/gdb ++ ++AC_ARG_WITH([gdb-datadir], ++ [AS_HELP_STRING([--with-gdb-datadir], ++ [look for global separate data files in this path [DATADIR/gdb]])], [gdbdatadir="${withval}"]) ++ ++AC_DEFINE_DIR(GDB_DATADIR, gdbdatadir, ++ [Global directory for GDB data files. ]) ++ ++if test "x$exec_prefix" = xNONE || test "x$exec_prefix" = 'x${prefix}'; then ++ if test "x$prefix" = xNONE; then ++ test_prefix=/usr/local ++ else ++ test_prefix=$prefix ++ fi ++else ++ test_prefix=$exec_prefix ++fi ++ ++case ${gdbdatadir} in ++ "${test_prefix}"|"${test_prefix}/"*|\ ++ '${exec_prefix}'|'${exec_prefix}/'*) ++ AC_DEFINE(GDB_DATADIR_RELOCATABLE, 1, [Define if GDB datadir should be relocated when GDB is moved.]) ++ ;; ++esac ++GDB_DATADIR_PATH=${gdbdatadir} ++AC_SUBST(GDB_DATADIR_PATH) ++ ++AC_ARG_WITH([pythondir], ++ [AS_HELP_STRING([--with-pythondir], ++ [install Python data files in this path [DATADIR/gdb/python]])], [pythondir="${withval}"], [pythondir=no]) ++ ++# If the user passed in a path, define it. Otherwise, compute it at ++# runtime based on the possibly-relocatable datadir. ++if test "$pythondir" = "no"; then ++ pythondir='$(GDB_DATADIR_PATH)/python' ++else ++ AC_DEFINE_UNQUOTED(PYTHONDIR, "$pythondir", ++ [Define to install path for Python sources]) ++fi ++AC_SUBST(pythondir) ++ ++ + AC_CONFIG_SUBDIRS(doc testsuite) + + # Check whether to support alternative target configurations +@@ -828,6 +873,8 @@ if test "${have_libpython}" != no; then + CONFIG_OBS="$CONFIG_OBS \$(SUBDIR_PYTHON_OBS)" + CONFIG_DEPS="$CONFIG_DEPS \$(SUBDIR_PYTHON_DEPS)" + CONFIG_SRCS="$CONFIG_SRCS \$(SUBDIR_PYTHON_SRCS)" ++ CONFIG_INSTALL="$CONFIG_INSTALL install-python" ++ CONFIG_UNINSTALL="$CONFIG_UNINSTALL uninstall-python" + ENABLE_CFLAGS="$ENABLE_CFLAGS \$(SUBDIR_PYTHON_CFLAGS)" + + # Flags needed to compile Python code (taken from python-config --cflags). +diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog +index 04f1683..a2a6e30 100644 +--- a/gdb/doc/ChangeLog ++++ b/gdb/doc/ChangeLog +@@ -1,5 +1,9 @@ + 2010-07-13 Tom Tromey + ++ * gdb.texinfo (Index Files): New node. ++ ++2010-07-13 Tom Tromey ++ + * gdb.texinfo (GDB/MI Variable Objects): Remove extra 'for'. + + 2010-07-01 Pedro Alves +diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo +index 1297175..c030b65 100644 +--- a/gdb/doc/gdb.texinfo ++++ b/gdb/doc/gdb.texinfo +@@ -1162,6 +1162,16 @@ for remote debugging. + Run using @var{device} for your program's standard input and output. + @c FIXME: kingdon thinks there is more to -tty. Investigate. + ++@item -P ++@cindex @code{-P} ++@itemx --python ++@cindex @code{--python} ++Change interpretation of command line so that the argument immediately ++following this switch is taken to be the name of a Python script file. ++This option stops option processing; subsequent options are passed to ++Python as @code{sys.argv}. This option is only available if Python ++scripting support was enabled when @value{GDBN} was configured. ++ + @c resolve the situation of these eventually + @item -tui + @cindex @code{--tui} +@@ -14282,6 +14292,7 @@ program. To debug a core dump of a previous run, you must also tell + @menu + * Files:: Commands to specify files + * Separate Debug Files:: Debugging information in separate files ++* Index Files:: Index files speed up GDB + * Symbol Errors:: Errors reading symbol files + * Data Files:: GDB data files + @end menu +@@ -15171,6 +15182,46 @@ gnu_debuglink_crc32 (unsigned long crc, + This computation does not apply to the ``build ID'' method. + + ++@node Index Files ++@section Index Files Speed Up @value{GDBN} ++@cindex index files ++@cindex @samp{.gdb_index} section ++ ++When @value{GDBN} finds a symbol file, it scans the symbols in the ++file in order to construct an internal symbol table. This lets most ++@value{GDBN} operations work quickly---at the cost of a delay early ++on. For large programs, this delay can be quite lengthy, so ++@value{GDBN} provides a way to build an index, which speeds up ++startup. ++ ++The index is stored as a section in the symbol file. @value{GDBN} can ++write the index to a file, then you can put it into the symbol file ++using @command{objcopy}. ++ ++To create an index file, use the @code{save gdb-index} command: ++ ++@table @code ++@item save gdb-index @var{directory} ++@kindex save gdb-index ++Create an index file for each symbol file currently known by ++@value{GDBN}. Each file is named after its corresponding symbol file, ++with @samp{.gdb-index} appended, and is written into the given ++@var{directory}. ++@end table ++ ++Once you have created an index file you can merge it into your symbol ++file, here named @file{symfile}, using @command{objcopy}: ++ ++@smallexample ++$ objcopy --add-section .gdb_index=symfile.gdb-index \ ++ --set-section-flags .gdb_index=readonly symfile symfile ++@end smallexample ++ ++There are currently some limitation on indices. They only work when ++for DWARF debugging information, not stabs. And, they do not ++currently work for programs using Ada. ++ ++ + @node Symbol Errors + @section Errors Reading Symbol Files + +@@ -20310,8 +20361,6 @@ containing @code{end}. For example: + + @smallexample + (@value{GDBP}) python +-Type python script +-End with a line saying just "end". + >print 23 + >end + 23 +@@ -20324,6 +20373,14 @@ in a Python script. This can be controlled using @code{maint set + python print-stack}: if @code{on}, the default, then Python stack + printing is enabled; if @code{off}, then Python stack printing is + disabled. ++ ++@kindex maint set python auto-load ++@item maint set python auto-load ++By default, @value{GDBN} will attempt to automatically load Python ++code when an object file is opened. This can be controlled using ++@code{maint set python auto-load}: if @code{on}, the default, then ++Python auto-loading is enabled; if @code{off}, then Python ++auto-loading is disabled. + @end table + + It is also possible to execute a Python script from the @value{GDBN} +@@ -20345,6 +20402,14 @@ and thus is always available. + @cindex python api + @cindex programming in python + ++You can get quick online help for @value{GDBN}'s Python API by issuing ++the command @w{@kbd{python help (gdb)}}. ++ ++Functions and methods which have two or more optional arguments allow ++them to be specified using keyword syntax. This allows passing some ++optional arguments while skipping others. Example: ++@w{@code{gdb.some_function ('foo', bar = 1, baz = 2)}}. ++ + @cindex python stdout + @cindex python pagination + At startup, @value{GDBN} overrides Python's @code{sys.stdout} and +@@ -20356,7 +20421,7 @@ situation, a Python @code{KeyboardInterrupt} exception is thrown. + @menu + * Basic Python:: Basic Python Functions. + * Exception Handling:: +-* Values From Inferior:: ++* Values From Inferior:: Python representation of values. + * Types In Python:: Python representation of types. + * Pretty Printing API:: Pretty-printing values. + * Selecting Pretty-Printers:: How GDB chooses a pretty-printer. +@@ -20415,6 +20480,12 @@ Return a sequence holding all of @value{GDBN}'s breakpoints. + @xref{Breakpoints In Python}, for more information. + @end defun + ++@findex gdb.breakpoints ++@defun breakpoints ++Return a sequence holding all of @value{GDBN}'s breakpoints. ++@xref{Breakpoints In Python}, for more information. ++@end defun ++ + @findex gdb.parameter + @defun parameter parameter + Return the value of a @value{GDBN} parameter. @var{parameter} is a +@@ -20431,6 +20502,7 @@ a Python value of the appropriate type, and returned. + @defun history number + Return a value from @value{GDBN}'s value history (@pxref{Value + History}). @var{number} indicates which history element to return. ++ + If @var{number} is negative, then @value{GDBN} will take its absolute value + and count backward from the last element (i.e., the most recent element) to + find the value to return. If @var{number} is zero, then @value{GDBN} will +@@ -20455,6 +20527,21 @@ compute values, for example, it is the only way to get the value of a + convenience variable (@pxref{Convenience Vars}) as a @code{gdb.Value}. + @end defun + ++@findex gdb.post_event ++@defun post_event event ++Put @var{event}, a callable object taking no arguments, into ++@value{GDBN}'s internal event queue. This callable will be invoked at ++some later point, during @value{GDBN}'s event processing. Events ++posted using @code{post_event} will be run in the order in which they ++were posted; however, there is no way to know when they will be ++processed relative to other events inside @value{GDBN}. ++ ++@value{GDBN} is not thread-safe. If your Python program uses multiple ++threads, you must be careful to only call @value{GDBN}-specific ++functions in the main @value{GDBN} thread. @code{post_event} ensures ++this. ++@end defun ++ + @findex gdb.write + @defun write string + Print a string to @value{GDBN}'s paginated standard output stream. diff --git a/gdb/doc/gdbint.texinfo b/gdb/doc/gdbint.texinfo index 54187dd..320b501 100644 --- a/gdb/doc/gdbint.texinfo @@ -1744,10 +2246,141 @@ index 826bc45..1e7d8dc 100644 #endif /* dwarf2loc.h */ diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c -index 16381de..ec31cf1 100644 +index 16381de..31a7d83 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c -@@ -1083,6 +1083,9 @@ static int attr_form_is_section_offset (struct attribute *); +@@ -51,6 +51,8 @@ + #include "typeprint.h" + #include "jv-lang.h" + #include "psympriv.h" ++#include "exceptions.h" ++#include "gdb_stat.h" + + #include + #include "gdb_string.h" +@@ -129,6 +131,33 @@ struct dwarf2_section_info + int readin; + }; + ++/* All offsets in the index are of this type. It must be ++ architecture-independent. */ ++typedef uint32_t offset_type; ++ ++DEF_VEC_I (offset_type); ++ ++/* A description of the mapped index. The file format is described in ++ a comment by the code that writes the index. */ ++struct mapped_index ++{ ++ /* The total length of the buffer. */ ++ off_t total_size; ++ /* A pointer to the address table data. */ ++ const gdb_byte *address_table; ++ /* Size of the address table data in bytes. */ ++ offset_type address_table_size; ++ /* The hash table. */ ++ const offset_type *index_table; ++ /* Size in slots, each slot is 2 offset_types. */ ++ offset_type index_table_slots; ++ /* A pointer to the constant pool. */ ++ const char *constant_pool; ++}; ++ ++typedef struct dwarf2_per_cu_data *dwarf2_per_cu_data_ptr; ++DEF_VEC_P (dwarf2_per_cu_data_ptr); ++ + struct dwarf2_per_objfile + { + struct dwarf2_section_info info; +@@ -141,6 +170,7 @@ struct dwarf2_per_objfile + struct dwarf2_section_info types; + struct dwarf2_section_info frame; + struct dwarf2_section_info eh_frame; ++ struct dwarf2_section_info gdb_index; + + /* Back link. */ + struct objfile *objfile; +@@ -163,6 +193,12 @@ struct dwarf2_per_objfile + /* A flag indicating wether this objfile has a section loaded at a + VMA of 0. */ + int has_section_at_zero; ++ ++ /* True if we are using the mapped index. */ ++ unsigned char using_index; ++ ++ /* The mapped index. */ ++ struct mapped_index *index_table; + }; + + static struct dwarf2_per_objfile *dwarf2_per_objfile; +@@ -182,6 +218,7 @@ static struct dwarf2_per_objfile *dwarf2_per_objfile; + #define TYPES_SECTION "debug_types" + #define FRAME_SECTION "debug_frame" + #define EH_FRAME_SECTION "eh_frame" ++#define GDB_INDEX_SECTION "gdb_index" + + /* local data types */ + +@@ -307,6 +344,32 @@ struct dwarf2_cu + unsigned int has_namespace_info : 1; + }; + ++/* When using the index (and thus not using psymtabs), each CU has an ++ object of this type. This is used to hold information needed by ++ the various "quick" methods. */ ++struct dwarf2_per_cu_quick_data ++{ ++ /* The line table. This can be NULL if there was no line table. */ ++ struct line_header *lines; ++ ++ /* The file names from the line table. */ ++ const char **file_names; ++ /* The file names from the line table after being run through ++ gdb_realpath. */ ++ const char **full_names; ++ ++ /* The corresponding symbol table. This is NULL if symbols for this ++ CU have not yet been read. */ ++ struct symtab *symtab; ++ ++ /* A temporary mark bit used when iterating over all CUs in ++ expand_symtabs_matching. */ ++ unsigned int mark : 1; ++ ++ /* True if we've tried to read the line table. */ ++ unsigned int read_lines : 1; ++}; ++ + /* Persistent data held for a compilation unit, even when not + processing it. We put a pointer to this structure in the + read_symtab_private field of the psymtab. If we encounter +@@ -347,10 +410,21 @@ struct dwarf2_per_cu_data + it. */ + htab_t type_hash; + +- /* The partial symbol table associated with this compilation unit, +- or NULL for partial units (which do not have an associated +- symtab). */ +- struct partial_symtab *psymtab; ++ /* The corresponding objfile. */ ++ struct objfile *objfile; ++ ++ /* When using partial symbol tables, the 'psymtab' field is active. ++ Otherwise the 'quick' field is active. */ ++ union ++ { ++ /* The partial symbol table associated with this compilation unit, ++ or NULL for partial units (which do not have an associated ++ symtab). */ ++ struct partial_symtab *psymtab; ++ ++ /* Data needed by the "quick" functions. */ ++ struct dwarf2_per_cu_quick_data *quick; ++ } v; + }; + + /* Entry in the signatured_types hash table. */ +@@ -1083,6 +1157,9 @@ static int attr_form_is_section_offset (struct attribute *); static int attr_form_is_constant (struct attribute *); @@ -1757,7 +2390,7 @@ index 16381de..ec31cf1 100644 static void dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym, struct dwarf2_cu *cu); -@@ -1113,6 +1116,9 @@ static void age_cached_comp_units (void); +@@ -1113,6 +1190,9 @@ static void age_cached_comp_units (void); static void free_one_cached_comp_unit (void *); @@ -1767,17 +2400,1268 @@ index 16381de..ec31cf1 100644 static struct type *set_die_type (struct die_info *, struct type *, struct dwarf2_cu *); -@@ -1132,6 +1138,9 @@ static void dwarf2_clear_marks (struct dwarf2_per_cu_data *); +@@ -1132,6 +1212,56 @@ static void dwarf2_clear_marks (struct dwarf2_per_cu_data *); static struct type *get_die_type (struct die_info *die, struct dwarf2_cu *cu); +static struct dwarf2_locexpr_baton *dwarf2_attr_to_locexpr_baton + (struct attribute *attr, struct dwarf2_cu *cu); ++ ++static void dwarf2_release_queue (void *dummy); ++ ++static void queue_comp_unit (struct dwarf2_per_cu_data *per_cu, ++ struct objfile *objfile); ++ ++static void process_queue (struct objfile *objfile); ++ ++static void find_file_and_directory (struct die_info *die, ++ struct dwarf2_cu *cu, ++ char **name, char **comp_dir); ++ ++static char *file_full_name (int file, struct line_header *lh, ++ const char *comp_dir); ++ ++static gdb_byte *partial_read_comp_unit_head (struct comp_unit_head *header, ++ gdb_byte *info_ptr, ++ gdb_byte *buffer, ++ unsigned int buffer_size, ++ bfd *abfd); ++ ++static void init_cu_die_reader (struct die_reader_specs *reader, ++ struct dwarf2_cu *cu); ++ ++#if WORDS_BIGENDIAN ++ ++/* Convert VALUE between big- and little-endian. */ ++static offset_type ++byte_swap (offset_type value) ++{ ++ offset_type result; ++ ++ result = (value & 0xff) << 24; ++ result |= (value & 0xff00) << 8; ++ result |= (value & 0xff0000) >> 8; ++ result |= (value & 0xff000000) >> 24; ++ return result; ++} ++ ++#define MAYBE_SWAP(V) byte_swap (V) ++ ++#else ++#define MAYBE_SWAP(V) (V) ++#endif /* WORDS_BIGENDIAN */ ++ ++/* The suffix for an index file. */ ++#define INDEX_SUFFIX ".gdb-index" + /* Try to locate the sections we need for DWARF 2 debugging information and return true if we have enough to do something. */ -@@ -5531,6 +5540,29 @@ process_enumeration_scope (struct die_info *die, struct dwarf2_cu *cu) +@@ -1230,6 +1360,11 @@ dwarf2_locate_sections (bfd *abfd, asection *sectp, void *ignore_ptr) + dwarf2_per_objfile->types.asection = sectp; + dwarf2_per_objfile->types.size = bfd_get_section_size (sectp); + } ++ else if (section_is_p (sectp->name, GDB_INDEX_SECTION)) ++ { ++ dwarf2_per_objfile->gdb_index.asection = sectp; ++ dwarf2_per_objfile->gdb_index.size = bfd_get_section_size (sectp); ++ } + + if ((bfd_get_section_flags (abfd, sectp) & SEC_LOAD) + && bfd_section_vma (abfd, sectp) == 0) +@@ -1349,91 +1484,944 @@ dwarf2_read_section (struct objfile *objfile, struct dwarf2_section_info *info) + } + } + +-#ifdef HAVE_MMAP +- if (pagesize == 0) +- pagesize = getpagesize (); ++#ifdef HAVE_MMAP ++ if (pagesize == 0) ++ pagesize = getpagesize (); ++ ++ /* Only try to mmap sections which are large enough: we don't want to ++ waste space due to fragmentation. Also, only try mmap for sections ++ without relocations. */ ++ ++ if (info->size > 4 * pagesize && (sectp->flags & SEC_RELOC) == 0) ++ { ++ off_t pg_offset = sectp->filepos & ~(pagesize - 1); ++ size_t map_length = info->size + sectp->filepos - pg_offset; ++ caddr_t retbuf = bfd_mmap (abfd, 0, map_length, PROT_READ, ++ MAP_PRIVATE, pg_offset); ++ ++ if (retbuf != MAP_FAILED) ++ { ++ info->was_mmapped = 1; ++ info->buffer = retbuf + (sectp->filepos & (pagesize - 1)) ; ++#if HAVE_POSIX_MADVISE ++ posix_madvise (retbuf, map_length, POSIX_MADV_WILLNEED); ++#endif ++ return; ++ } ++ } ++#endif ++ ++ /* If we get here, we are a normal, not-compressed section. */ ++ info->buffer = buf ++ = obstack_alloc (&objfile->objfile_obstack, info->size); ++ ++ /* When debugging .o files, we may need to apply relocations; see ++ http://sourceware.org/ml/gdb-patches/2002-04/msg00136.html . ++ We never compress sections in .o files, so we only need to ++ try this when the section is not compressed. */ ++ retbuf = symfile_relocate_debug_section (objfile, sectp, buf); ++ if (retbuf != NULL) ++ { ++ info->buffer = retbuf; ++ return; ++ } ++ ++ if (bfd_seek (abfd, sectp->filepos, SEEK_SET) != 0 ++ || bfd_bread (buf, info->size, abfd) != info->size) ++ error (_("Dwarf Error: Can't read DWARF data from '%s'"), ++ bfd_get_filename (abfd)); ++} ++ ++/* Fill in SECTP, BUFP and SIZEP with section info, given OBJFILE and ++ SECTION_NAME. */ ++ ++void ++dwarf2_get_section_info (struct objfile *objfile, const char *section_name, ++ asection **sectp, gdb_byte **bufp, ++ bfd_size_type *sizep) ++{ ++ struct dwarf2_per_objfile *data ++ = objfile_data (objfile, dwarf2_objfile_data_key); ++ struct dwarf2_section_info *info; ++ ++ /* We may see an objfile without any DWARF, in which case we just ++ return nothing. */ ++ if (data == NULL) ++ { ++ *sectp = NULL; ++ *bufp = NULL; ++ *sizep = 0; ++ return; ++ } ++ if (section_is_p (section_name, EH_FRAME_SECTION)) ++ info = &data->eh_frame; ++ else if (section_is_p (section_name, FRAME_SECTION)) ++ info = &data->frame; ++ else ++ gdb_assert (0); ++ ++ if (info->asection != NULL && info->size != 0 && info->buffer == NULL) ++ /* We haven't read this section in yet. Do it now. */ ++ dwarf2_read_section (objfile, info); ++ ++ *sectp = info->asection; ++ *bufp = info->buffer; ++ *sizep = info->size; ++} ++ ++ ++ ++/* Read in the symbols for PER_CU. OBJFILE is the objfile from which ++ this CU came. */ ++static void ++dw2_do_instantiate_symtab (struct objfile *objfile, ++ struct dwarf2_per_cu_data *per_cu) ++{ ++ struct cleanup *back_to; ++ ++ back_to = make_cleanup (dwarf2_release_queue, NULL); ++ ++ queue_comp_unit (per_cu, objfile); ++ ++ if (per_cu->from_debug_types) ++ read_signatured_type_at_offset (objfile, per_cu->offset); ++ else ++ load_full_comp_unit (per_cu, objfile); ++ ++ process_queue (objfile); ++ ++ /* Age the cache, releasing compilation units that have not ++ been used recently. */ ++ age_cached_comp_units (); ++ ++ do_cleanups (back_to); ++} ++ ++/* Ensure that the symbols for PER_CU have been read in. OBJFILE is ++ the objfile from which this CU came. Returns the resulting symbol ++ table. */ ++static struct symtab * ++dw2_instantiate_symtab (struct objfile *objfile, ++ struct dwarf2_per_cu_data *per_cu) ++{ ++ if (!per_cu->v.quick->symtab) ++ { ++ struct cleanup *back_to = make_cleanup (free_cached_comp_units, NULL); ++ increment_reading_symtab (); ++ dw2_do_instantiate_symtab (objfile, per_cu); ++ do_cleanups (back_to); ++ } ++ return per_cu->v.quick->symtab; ++} ++ ++/* A helper function that knows how to read a 64-bit value in a way ++ that doesn't make gdb die. Returns 1 if the conversion went ok, 0 ++ otherwise. */ ++static int ++extract_cu_value (const char *bytes, ULONGEST *result) ++{ ++ if (sizeof (ULONGEST) < 8) ++ { ++ int i; ++ ++ /* Ignore the upper 4 bytes if they are all zero. */ ++ for (i = 0; i < 4; ++i) ++ if (bytes[i + 4] != 0) ++ return 0; ++ ++ *result = extract_unsigned_integer (bytes, 4, BFD_ENDIAN_LITTLE); ++ } ++ else ++ *result = extract_unsigned_integer (bytes, 8, BFD_ENDIAN_LITTLE); ++ return 1; ++} ++ ++/* Read the CU list from the mapped index, and use it to create all ++ the CU objects for this objfile. Return 0 if something went wrong, ++ 1 if everything went ok. */ ++static int ++create_cus_from_index (struct objfile *objfile, struct mapped_index *index, ++ const gdb_byte *cu_list, offset_type cu_list_elements) ++{ ++ offset_type i; ++ const char *entry; ++ ++ dwarf2_per_objfile->n_comp_units = cu_list_elements / 2; ++ dwarf2_per_objfile->all_comp_units ++ = obstack_alloc (&objfile->objfile_obstack, ++ dwarf2_per_objfile->n_comp_units ++ * sizeof (struct dwarf2_per_cu_data *)); ++ ++ for (i = 0; i < cu_list_elements; i += 2) ++ { ++ struct dwarf2_per_cu_data *the_cu; ++ ULONGEST offset, length; ++ ++ if (!extract_cu_value (cu_list, &offset) ++ || !extract_cu_value (cu_list + 8, &length)) ++ return 0; ++ cu_list += 2 * 8; ++ ++ the_cu = OBSTACK_ZALLOC (&objfile->objfile_obstack, ++ struct dwarf2_per_cu_data); ++ the_cu->offset = offset; ++ the_cu->length = length; ++ the_cu->objfile = objfile; ++ the_cu->v.quick = OBSTACK_ZALLOC (&objfile->objfile_obstack, ++ struct dwarf2_per_cu_quick_data); ++ dwarf2_per_objfile->all_comp_units[i / 2] = the_cu; ++ } ++ ++ return 1; ++} ++ ++/* Read the address map data from the mapped index, and use it to ++ populate the objfile's psymtabs_addrmap. */ ++static void ++create_addrmap_from_index (struct objfile *objfile, struct mapped_index *index) ++{ ++ const gdb_byte *iter, *end; ++ struct obstack temp_obstack; ++ struct addrmap *mutable_map; ++ struct cleanup *cleanup; ++ CORE_ADDR baseaddr; ++ ++ obstack_init (&temp_obstack); ++ cleanup = make_cleanup_obstack_free (&temp_obstack); ++ mutable_map = addrmap_create_mutable (&temp_obstack); ++ ++ iter = index->address_table; ++ end = iter + index->address_table_size; ++ ++ baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); ++ ++ while (iter < end) ++ { ++ ULONGEST hi, lo, cu_index; ++ lo = extract_unsigned_integer (iter, 8, BFD_ENDIAN_LITTLE); ++ iter += 8; ++ hi = extract_unsigned_integer (iter, 8, BFD_ENDIAN_LITTLE); ++ iter += 8; ++ cu_index = extract_unsigned_integer (iter, 4, BFD_ENDIAN_LITTLE); ++ iter += 4; ++ ++ addrmap_set_empty (mutable_map, lo + baseaddr, hi + baseaddr - 1, ++ dwarf2_per_objfile->all_comp_units[cu_index]); ++ } ++ ++ objfile->psymtabs_addrmap = addrmap_create_fixed (mutable_map, ++ &objfile->objfile_obstack); ++ do_cleanups (cleanup); ++} ++ ++/* The hash function for strings in the mapped index. This is the ++ same as the hashtab.c hash function, but we keep a separate copy to ++ maintain control over the implementation. This is necessary ++ because the hash function is tied to the format of the mapped index ++ file. */ ++static hashval_t ++mapped_index_string_hash (const void *p) ++{ ++ const unsigned char *str = (const unsigned char *) p; ++ hashval_t r = 0; ++ unsigned char c; ++ ++ while ((c = *str++) != 0) ++ r = r * 67 + c - 113; ++ ++ return r; ++} ++ ++/* Find a slot in the mapped index INDEX for the object named NAME. ++ If NAME is found, set *VEC_OUT to point to the CU vector in the ++ constant pool and return 1. If NAME cannot be found, return 0. */ ++static int ++find_slot_in_mapped_hash (struct mapped_index *index, const char *name, ++ offset_type **vec_out) ++{ ++ offset_type hash = mapped_index_string_hash (name); ++ offset_type slot, step; ++ ++ slot = hash & (index->index_table_slots - 1); ++ step = ((hash * 17) & (index->index_table_slots - 1)) | 1; ++ ++ for (;;) ++ { ++ /* Convert a slot number to an offset into the table. */ ++ offset_type i = 2 * slot; ++ const char *str; ++ if (index->index_table[i] == 0 && index->index_table[i + 1] == 0) ++ return 0; ++ ++ str = index->constant_pool + MAYBE_SWAP (index->index_table[i]); ++ if (!strcmp (name, str)) ++ { ++ *vec_out = (offset_type *) (index->constant_pool ++ + MAYBE_SWAP (index->index_table[i + 1])); ++ return 1; ++ } ++ ++ slot = (slot + step) & (index->index_table_slots - 1); ++ } ++} ++ ++/* Read the index file. If everything went ok, initialize the "quick" ++ elements of all the CUs and return 1. Otherwise, return 0. */ ++static int ++dwarf2_read_index (struct objfile *objfile) ++{ ++ char *addr; ++ struct mapped_index *map; ++ offset_type *metadata; ++ const gdb_byte *cu_list; ++ offset_type cu_list_elements; ++ ++ if (dwarf2_per_objfile->gdb_index.asection == NULL ++ || dwarf2_per_objfile->gdb_index.size == 0) ++ return 0; ++ dwarf2_read_section (objfile, &dwarf2_per_objfile->gdb_index); ++ ++ addr = dwarf2_per_objfile->gdb_index.buffer; ++ /* Version check. */ ++ if (MAYBE_SWAP (*(offset_type *) addr) != 1) ++ return 0; ++ ++ map = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct mapped_index); ++ map->total_size = dwarf2_per_objfile->gdb_index.size; ++ ++ metadata = (offset_type *) (addr + sizeof (offset_type)); ++ cu_list = addr + MAYBE_SWAP (metadata[0]); ++ cu_list_elements = ((MAYBE_SWAP (metadata[1]) - MAYBE_SWAP (metadata[0])) ++ / 8); ++ map->address_table = addr + MAYBE_SWAP (metadata[1]); ++ map->address_table_size = (MAYBE_SWAP (metadata[2]) ++ - MAYBE_SWAP (metadata[1])); ++ map->index_table = (offset_type *) (addr + MAYBE_SWAP (metadata[2])); ++ map->index_table_slots = ((MAYBE_SWAP (metadata[3]) ++ - MAYBE_SWAP (metadata[2])) ++ / (2 * sizeof (offset_type))); ++ map->constant_pool = addr + MAYBE_SWAP (metadata[3]); ++ ++ if (!create_cus_from_index (objfile, map, cu_list, cu_list_elements)) ++ return 0; ++ ++ create_addrmap_from_index (objfile, map); ++ ++ dwarf2_per_objfile->index_table = map; ++ dwarf2_per_objfile->using_index = 1; ++ ++ return 1; ++} ++ ++/* A helper for the "quick" functions which sets the global ++ dwarf2_per_objfile according to OBJFILE. */ ++static void ++dw2_setup (struct objfile *objfile) ++{ ++ dwarf2_per_objfile = objfile_data (objfile, dwarf2_objfile_data_key); ++ gdb_assert (dwarf2_per_objfile); ++} ++ ++/* A helper for the "quick" functions which attempts to read the line ++ table for THIS_CU. */ ++static void ++dw2_require_line_header (struct objfile *objfile, ++ struct dwarf2_per_cu_data *this_cu) ++{ ++ bfd *abfd = objfile->obfd; ++ struct line_header *lh = NULL; ++ struct attribute *attr; ++ struct cleanup *cleanups; ++ struct die_info *comp_unit_die; ++ gdb_byte *beg_of_comp_unit, *info_ptr, *buffer; ++ int has_children, i; ++ struct dwarf2_cu cu; ++ unsigned int bytes_read, buffer_size; ++ struct die_reader_specs reader_specs; ++ char *name, *comp_dir; ++ ++ if (this_cu->v.quick->read_lines) ++ return; ++ this_cu->v.quick->read_lines = 1; ++ ++ memset (&cu, 0, sizeof (cu)); ++ cu.objfile = objfile; ++ obstack_init (&cu.comp_unit_obstack); ++ ++ cleanups = make_cleanup (free_stack_comp_unit, &cu); ++ ++ dwarf2_read_section (objfile, &dwarf2_per_objfile->info); ++ buffer_size = dwarf2_per_objfile->info.size; ++ buffer = dwarf2_per_objfile->info.buffer; ++ info_ptr = buffer + this_cu->offset; ++ beg_of_comp_unit = info_ptr; ++ ++ info_ptr = partial_read_comp_unit_head (&cu.header, info_ptr, ++ buffer, buffer_size, ++ abfd); ++ ++ /* Complete the cu_header. */ ++ cu.header.offset = beg_of_comp_unit - buffer; ++ cu.header.first_die_offset = info_ptr - beg_of_comp_unit; ++ ++ this_cu->cu = &cu; ++ cu.per_cu = this_cu; ++ ++ dwarf2_read_abbrevs (abfd, &cu); ++ make_cleanup (dwarf2_free_abbrev_table, &cu); ++ ++ if (this_cu->from_debug_types) ++ info_ptr += 8 /*signature*/ + cu.header.offset_size; ++ init_cu_die_reader (&reader_specs, &cu); ++ info_ptr = read_full_die (&reader_specs, &comp_unit_die, info_ptr, ++ &has_children); ++ ++ attr = dwarf2_attr (comp_unit_die, DW_AT_stmt_list, &cu); ++ if (attr) ++ { ++ unsigned int line_offset = DW_UNSND (attr); ++ lh = dwarf_decode_line_header (line_offset, abfd, &cu); ++ } ++ if (lh == NULL) ++ { ++ do_cleanups (cleanups); ++ return; ++ } ++ ++ find_file_and_directory (comp_unit_die, &cu, &name, &comp_dir); ++ ++ this_cu->v.quick->lines = lh; ++ ++ this_cu->v.quick->file_names ++ = obstack_alloc (&objfile->objfile_obstack, ++ lh->num_file_names * sizeof (char *)); ++ for (i = 0; i < lh->num_file_names; ++i) ++ this_cu->v.quick->file_names[i] = file_full_name (i + 1, lh, comp_dir); ++ ++ do_cleanups (cleanups); ++} ++ ++/* A helper for the "quick" functions which computes and caches the ++ real path for a given file name from the line table. ++ dw2_require_line_header must have been called before this is ++ invoked. */ ++static const char * ++dw2_require_full_path (struct objfile *objfile, ++ struct dwarf2_per_cu_data *cu, ++ int index) ++{ ++ if (!cu->v.quick->full_names) ++ cu->v.quick->full_names ++ = OBSTACK_CALLOC (&objfile->objfile_obstack, ++ cu->v.quick->lines->num_file_names, ++ sizeof (char *)); ++ ++ if (!cu->v.quick->full_names[index]) ++ cu->v.quick->full_names[index] ++ = gdb_realpath (cu->v.quick->file_names[index]); ++ ++ return cu->v.quick->full_names[index]; ++} ++ ++static struct symtab * ++dw2_find_last_source_symtab (struct objfile *objfile) ++{ ++ int index; ++ dw2_setup (objfile); ++ index = dwarf2_per_objfile->n_comp_units - 1; ++ return dw2_instantiate_symtab (objfile, ++ dwarf2_per_objfile->all_comp_units[index]); ++} ++ ++static void ++dw2_forget_cached_source_info (struct objfile *objfile) ++{ ++ int i; ++ ++ dw2_setup (objfile); ++ for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i) ++ { ++ struct dwarf2_per_cu_data *cu = dwarf2_per_objfile->all_comp_units[i]; ++ ++ if (cu->v.quick->full_names) ++ { ++ int j; ++ ++ for (j = 0; j < cu->v.quick->lines->num_file_names; ++j) ++ xfree ((void *) cu->v.quick->full_names[j]); ++ } ++ } ++} ++ ++static int ++dw2_lookup_symtab (struct objfile *objfile, const char *name, ++ const char *full_path, const char *real_path, ++ struct symtab **result) ++{ ++ int i; ++ int check_basename = lbasename (name) == name; ++ struct dwarf2_per_cu_data *base_cu = NULL; ++ ++ dw2_setup (objfile); ++ for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i) ++ { ++ int j; ++ struct dwarf2_per_cu_data *cu = dwarf2_per_objfile->all_comp_units[i]; ++ ++ if (cu->v.quick->symtab) ++ continue; ++ ++ dw2_require_line_header (objfile, cu); ++ if (!cu->v.quick->lines) ++ continue; ++ ++ for (j = 0; j < cu->v.quick->lines->num_file_names; ++j) ++ { ++ const char *this_name = cu->v.quick->file_names[j]; ++ ++ if (FILENAME_CMP (name, this_name) == 0) ++ { ++ *result = dw2_instantiate_symtab (objfile, cu); ++ return 1; ++ } ++ ++ if (check_basename && ! base_cu ++ && FILENAME_CMP (lbasename (this_name), name) == 0) ++ base_cu = cu; ++ ++ if (full_path != NULL) ++ { ++ const char *this_full_name = dw2_require_full_path (objfile, ++ cu, j); ++ ++ if (this_full_name ++ && FILENAME_CMP (full_path, this_full_name) == 0) ++ { ++ *result = dw2_instantiate_symtab (objfile, cu); ++ return 1; ++ } ++ } ++ ++ if (real_path != NULL) ++ { ++ const char *this_full_name = dw2_require_full_path (objfile, ++ cu, j); ++ ++ if (this_full_name != NULL) ++ { ++ char *rp = gdb_realpath (this_full_name); ++ if (rp != NULL && FILENAME_CMP (real_path, rp) == 0) ++ { ++ xfree (rp); ++ *result = dw2_instantiate_symtab (objfile, cu); ++ return 1; ++ } ++ xfree (rp); ++ } ++ } ++ } ++ } ++ ++ if (base_cu) ++ { ++ *result = dw2_instantiate_symtab (objfile, base_cu); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static struct symtab * ++dw2_lookup_symbol (struct objfile *objfile, int block_index, ++ const char *name, domain_enum domain) ++{ ++ /* We do all the work in the pre_expand_symtabs_matching hook ++ instead. */ ++ return NULL; ++} ++ ++/* A helper function that expands all symtabs that hold an object ++ named NAME. */ ++static void ++dw2_do_expand_symtabs_matching (struct objfile *objfile, const char *name) ++{ ++ dw2_setup (objfile); ++ ++ if (dwarf2_per_objfile->index_table) ++ { ++ offset_type *vec; ++ ++ if (find_slot_in_mapped_hash (dwarf2_per_objfile->index_table, ++ name, &vec)) ++ { ++ offset_type i, len = MAYBE_SWAP (*vec); ++ for (i = 0; i < len; ++i) ++ { ++ offset_type cu_index = MAYBE_SWAP (vec[i + 1]); ++ struct dwarf2_per_cu_data *cu; ++ cu = dwarf2_per_objfile->all_comp_units[cu_index]; ++ dw2_instantiate_symtab (objfile, cu); ++ } ++ } ++ } ++} ++ ++static void ++dw2_pre_expand_symtabs_matching (struct objfile *objfile, ++ int kind, const char *name, ++ domain_enum domain) ++{ ++ dw2_do_expand_symtabs_matching (objfile, name); ++} ++ ++static void ++dw2_print_stats (struct objfile *objfile) ++{ ++ int i, count; ++ ++ dw2_setup (objfile); ++ count = 0; ++ for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i) ++ { ++ struct dwarf2_per_cu_data *cu = dwarf2_per_objfile->all_comp_units[i]; ++ ++ if (!cu->v.quick->symtab) ++ ++count; ++ } ++ printf_filtered (_(" Number of unread CUs: %d\n"), count); ++} ++ ++static void ++dw2_dump (struct objfile *objfile) ++{ ++ /* Nothing worth printing. */ ++} ++ ++static void ++dw2_relocate (struct objfile *objfile, struct section_offsets *new_offsets, ++ struct section_offsets *delta) ++{ ++ /* There's nothing to relocate here. */ ++} ++ ++static void ++dw2_expand_symtabs_for_function (struct objfile *objfile, ++ const char *func_name) ++{ ++ dw2_do_expand_symtabs_matching (objfile, func_name); ++} ++ ++static void ++dw2_expand_all_symtabs (struct objfile *objfile) ++{ ++ int i; ++ ++ dw2_setup (objfile); ++ for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i) ++ { ++ struct dwarf2_per_cu_data *cu = dwarf2_per_objfile->all_comp_units[i]; ++ ++ dw2_instantiate_symtab (objfile, cu); ++ } ++} ++ ++static void ++dw2_expand_symtabs_with_filename (struct objfile *objfile, ++ const char *filename) ++{ ++ int i; ++ ++ dw2_setup (objfile); ++ for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i) ++ { ++ int j; ++ struct dwarf2_per_cu_data *cu = dwarf2_per_objfile->all_comp_units[i]; ++ ++ if (cu->v.quick->symtab) ++ continue; ++ ++ dw2_require_line_header (objfile, cu); ++ if (!cu->v.quick->lines) ++ continue; ++ ++ for (j = 0; j < cu->v.quick->lines->num_file_names; ++j) ++ { ++ const char *this_name = cu->v.quick->file_names[j]; ++ if (strcmp (this_name, filename) == 0) ++ { ++ dw2_instantiate_symtab (objfile, cu); ++ break; ++ } ++ } ++ } ++} ++ ++static const char * ++dw2_find_symbol_file (struct objfile *objfile, const char *name) ++{ ++ struct dwarf2_per_cu_data *cu; ++ offset_type *vec; ++ ++ dw2_setup (objfile); ++ ++ if (!dwarf2_per_objfile->index_table) ++ return NULL; ++ ++ if (!find_slot_in_mapped_hash (dwarf2_per_objfile->index_table, ++ name, &vec)) ++ return NULL; ++ ++ /* Note that this just looks at the very first one named NAME -- but ++ actually we are looking for a function. find_main_filename ++ should be rewritten so that it doesn't require a custom hook. It ++ could just use the ordinary symbol tables. */ ++ /* vec[0] is the length, which must always be >0. */ ++ cu = dwarf2_per_objfile->all_comp_units[MAYBE_SWAP (vec[1])]; ++ ++ dw2_require_line_header (objfile, cu); ++ if (!cu->v.quick->lines) ++ return NULL; ++ ++ return cu->v.quick->file_names[cu->v.quick->lines->num_file_names - 1]; ++} ++ ++static void ++dw2_map_ada_symtabs (struct objfile *objfile, ++ int (*wild_match) (const char *, int, const char *), ++ int (*is_name_suffix) (const char *), ++ void (*callback) (struct objfile *, ++ struct symtab *, void *), ++ const char *name, int global, ++ domain_enum namespace, int wild, ++ void *data) ++{ ++ /* For now, we don't support Ada, so this function can't be ++ reached. */ ++ internal_error (__FILE__, __LINE__, ++ _("map_ada_symtabs called via index method")); ++} ++ ++static void ++dw2_expand_symtabs_matching (struct objfile *objfile, ++ int (*file_matcher) (const char *, void *), ++ int (*name_matcher) (const char *, void *), ++ domain_enum kind, ++ void *data) ++{ ++ int i; ++ offset_type iter; ++ ++ dw2_setup (objfile); ++ if (!dwarf2_per_objfile->index_table) ++ return; ++ ++ for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i) ++ { ++ int j; ++ struct dwarf2_per_cu_data *cu = dwarf2_per_objfile->all_comp_units[i]; ++ ++ cu->v.quick->mark = 0; ++ if (cu->v.quick->symtab) ++ continue; ++ ++ dw2_require_line_header (objfile, cu); ++ if (!cu->v.quick->lines) ++ continue; ++ ++ for (j = 0; j < cu->v.quick->lines->num_file_names; ++j) ++ { ++ if (file_matcher (cu->v.quick->file_names[j], data)) ++ { ++ cu->v.quick->mark = 1; ++ break; ++ } ++ } ++ } ++ ++ for (iter = 0; ++ iter < dwarf2_per_objfile->index_table->index_table_slots; ++ ++iter) ++ { ++ offset_type idx = 2 * iter; ++ const char *name; ++ offset_type *vec, vec_len, vec_idx; ++ ++ if (dwarf2_per_objfile->index_table->index_table[idx] == 0 ++ && dwarf2_per_objfile->index_table->index_table[idx + 1] == 0) ++ continue; ++ ++ name = (dwarf2_per_objfile->index_table->constant_pool ++ + dwarf2_per_objfile->index_table->index_table[idx]); ++ ++ if (! (*name_matcher) (name, data)) ++ continue; ++ ++ /* The name was matched, now expand corresponding CUs that were ++ marked. */ ++ vec = (offset_type *) (dwarf2_per_objfile->index_table->constant_pool ++ + dwarf2_per_objfile->index_table->index_table[idx + 1]); ++ vec_len = MAYBE_SWAP (vec[0]); ++ for (vec_idx = 0; vec_idx < vec_len; ++vec_idx) ++ { ++ struct dwarf2_per_cu_data *cu ++ = dwarf2_per_objfile->all_comp_units[MAYBE_SWAP (vec[vec_idx + 1])]; ++ if (cu->v.quick->mark) ++ dw2_instantiate_symtab (objfile, cu); ++ } ++ } ++} ++ ++static struct symtab * ++dw2_find_pc_sect_symtab (struct objfile *objfile, ++ struct minimal_symbol *msymbol, ++ CORE_ADDR pc, ++ struct obj_section *section, ++ int warn_if_readin) ++{ ++ struct dwarf2_per_cu_data *data; ++ ++ dw2_setup (objfile); ++ ++ if (!objfile->psymtabs_addrmap) ++ return NULL; ++ ++ data = addrmap_find (objfile->psymtabs_addrmap, pc); ++ if (!data) ++ return NULL; ++ ++ if (warn_if_readin && data->v.quick->symtab) ++ warning (_("(Internal error: pc %s in read in CU, but not in symtab.)\n"), ++ paddress (get_objfile_arch (objfile), pc)); ++ ++ return dw2_instantiate_symtab (objfile, data); ++} ++ ++static void ++dw2_map_symbol_names (struct objfile *objfile, ++ void (*fun) (const char *, void *), ++ void *data) ++{ ++ offset_type iter; ++ dw2_setup (objfile); + +- /* Only try to mmap sections which are large enough: we don't want to +- waste space due to fragmentation. Also, only try mmap for sections +- without relocations. */ ++ if (!dwarf2_per_objfile->index_table) ++ return; + +- if (info->size > 4 * pagesize && (sectp->flags & SEC_RELOC) == 0) ++ for (iter = 0; ++ iter < dwarf2_per_objfile->index_table->index_table_slots; ++ ++iter) + { +- off_t pg_offset = sectp->filepos & ~(pagesize - 1); +- size_t map_length = info->size + sectp->filepos - pg_offset; +- caddr_t retbuf = bfd_mmap (abfd, 0, map_length, PROT_READ, +- MAP_PRIVATE, pg_offset); ++ offset_type idx = 2 * iter; ++ const char *name; ++ offset_type *vec, vec_len, vec_idx; + +- if (retbuf != MAP_FAILED) +- { +- info->was_mmapped = 1; +- info->buffer = retbuf + (sectp->filepos & (pagesize - 1)) ; +-#if HAVE_POSIX_MADVISE +- posix_madvise (retbuf, map_length, POSIX_MADV_WILLNEED); +-#endif +- return; +- } ++ if (dwarf2_per_objfile->index_table->index_table[idx] == 0 ++ && dwarf2_per_objfile->index_table->index_table[idx + 1] == 0) ++ continue; ++ ++ name = (dwarf2_per_objfile->index_table->constant_pool ++ + dwarf2_per_objfile->index_table->index_table[idx]); ++ ++ (*fun) (name, data); + } +-#endif ++} + +- /* If we get here, we are a normal, not-compressed section. */ +- info->buffer = buf +- = obstack_alloc (&objfile->objfile_obstack, info->size); ++static void ++dw2_map_symbol_filenames (struct objfile *objfile, ++ void (*fun) (const char *, const char *, void *), ++ void *data) ++{ ++ int i; + +- /* When debugging .o files, we may need to apply relocations; see +- http://sourceware.org/ml/gdb-patches/2002-04/msg00136.html . +- We never compress sections in .o files, so we only need to +- try this when the section is not compressed. */ +- retbuf = symfile_relocate_debug_section (objfile, sectp, buf); +- if (retbuf != NULL) ++ dw2_setup (objfile); ++ for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i) + { +- info->buffer = retbuf; +- return; ++ int j; ++ struct dwarf2_per_cu_data *cu = dwarf2_per_objfile->all_comp_units[i]; ++ ++ if (cu->v.quick->symtab) ++ continue; ++ ++ dw2_require_line_header (objfile, cu); ++ if (!cu->v.quick->lines) ++ continue; ++ ++ for (j = 0; j < cu->v.quick->lines->num_file_names; ++j) ++ { ++ const char *this_full_name = dw2_require_full_path (objfile, cu, j); ++ (*fun) (cu->v.quick->file_names[j], this_full_name, data); ++ } + } ++} + +- if (bfd_seek (abfd, sectp->filepos, SEEK_SET) != 0 +- || bfd_bread (buf, info->size, abfd) != info->size) +- error (_("Dwarf Error: Can't read DWARF data from '%s'"), +- bfd_get_filename (abfd)); ++static int ++dw2_has_symbols (struct objfile *objfile) ++{ ++ return 1; + } + +-/* Fill in SECTP, BUFP and SIZEP with section info, given OBJFILE and +- SECTION_NAME. */ ++const struct quick_symbol_functions dwarf2_gdb_index_functions = ++{ ++ dw2_has_symbols, ++ dw2_find_last_source_symtab, ++ dw2_forget_cached_source_info, ++ dw2_lookup_symtab, ++ dw2_lookup_symbol, ++ dw2_pre_expand_symtabs_matching, ++ dw2_print_stats, ++ dw2_dump, ++ dw2_relocate, ++ dw2_expand_symtabs_for_function, ++ dw2_expand_all_symtabs, ++ dw2_expand_symtabs_with_filename, ++ dw2_find_symbol_file, ++ dw2_map_ada_symtabs, ++ dw2_expand_symtabs_matching, ++ dw2_find_pc_sect_symtab, ++ dw2_map_symbol_names, ++ dw2_map_symbol_filenames ++}; + +-void +-dwarf2_get_section_info (struct objfile *objfile, const char *section_name, +- asection **sectp, gdb_byte **bufp, +- bfd_size_type *sizep) +-{ +- struct dwarf2_per_objfile *data +- = objfile_data (objfile, dwarf2_objfile_data_key); +- struct dwarf2_section_info *info; ++/* Initialize for reading DWARF for this objfile. Return 0 if this ++ file will use psymtabs, or 1 if using the GNU index. */ + +- /* We may see an objfile without any DWARF, in which case we just +- return nothing. */ +- if (data == NULL) ++int ++dwarf2_initialize_objfile (struct objfile *objfile) ++{ ++ /* If we're about to read full symbols, don't bother with the ++ indices. In this case we also don't care if some other debug ++ format is making psymtabs, because they are all about to be ++ expanded anyway. */ ++ if ((objfile->flags & OBJF_READNOW)) + { +- *sectp = NULL; +- *bufp = NULL; +- *sizep = 0; +- return; ++ int i; ++ ++ dwarf2_per_objfile->using_index = 1; ++ create_all_comp_units (objfile); ++ ++ for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i) ++ { ++ struct dwarf2_per_cu_data *cu = dwarf2_per_objfile->all_comp_units[i]; ++ ++ cu->v.quick = OBSTACK_ZALLOC (&objfile->objfile_obstack, ++ struct dwarf2_per_cu_quick_data); ++ } ++ ++ /* Return 1 so that gdb sees the "quick" functions. However, ++ these functions will be no-ops because we will have expanded ++ all symtabs. */ ++ return 1; + } +- if (section_is_p (section_name, EH_FRAME_SECTION)) +- info = &data->eh_frame; +- else if (section_is_p (section_name, FRAME_SECTION)) +- info = &data->frame; +- else +- gdb_assert (0); + +- if (info->asection != NULL && info->size != 0 && info->buffer == NULL) +- /* We haven't read this section in yet. Do it now. */ +- dwarf2_read_section (objfile, info); ++ if (dwarf2_read_index (objfile)) ++ return 1; + +- *sectp = info->asection; +- *bufp = info->buffer; +- *sizep = info->size; ++ dwarf2_build_psymtabs (objfile); ++ return 0; + } + ++ ++ + /* Build a partial symbol table. */ + + void +@@ -1897,7 +2885,7 @@ process_psymtab_comp_unit (struct objfile *objfile, + /* Store the function that reads in the rest of the symbol table */ + pst->read_symtab = dwarf2_psymtab_to_symtab; + +- this_cu->psymtab = pst; ++ this_cu->v.psymtab = pst; + + dwarf2_find_base_address (comp_unit_die, &cu); + +@@ -2182,6 +3170,7 @@ create_all_comp_units (struct objfile *objfile) + memset (this_cu, 0, sizeof (*this_cu)); + this_cu->offset = offset; + this_cu->length = length + initial_length_size; ++ this_cu->objfile = objfile; + + if (n_comp_units == n_allocated) + { +@@ -2613,7 +3602,7 @@ add_partial_subprogram (struct partial_die_info *pdi, + addrmap_set_empty (objfile->psymtabs_addrmap, + pdi->lowpc + baseaddr, + pdi->highpc - 1 + baseaddr, +- cu->per_cu->psymtab); ++ cu->per_cu->v.psymtab); + } + if (!pdi->is_declaration) + /* Ignore subprogram DIEs that do not have a name, they are +@@ -2885,7 +3874,6 @@ locate_pdi_sibling (struct partial_die_info *orig_pdi, + static void + dwarf2_psymtab_to_symtab (struct partial_symtab *pst) + { +- /* FIXME: This is barely more than a stub. */ + if (pst != NULL) + { + if (pst->readin) +@@ -2958,7 +3946,9 @@ process_queue (struct objfile *objfile) + may load a new CU, adding it to the end of the queue. */ + for (item = dwarf2_queue; item != NULL; dwarf2_queue = item = next_item) + { +- if (item->per_cu->psymtab && !item->per_cu->psymtab->readin) ++ if (dwarf2_per_objfile->using_index ++ ? !item->per_cu->v.quick->symtab ++ : (item->per_cu->v.psymtab && !item->per_cu->v.psymtab->readin)) + process_full_comp_unit (item->per_cu); + + item->per_cu->queued = 0; +@@ -3035,22 +4025,7 @@ psymtab_to_symtab_1 (struct partial_symtab *pst) + return; + } + +- back_to = make_cleanup (dwarf2_release_queue, NULL); +- +- queue_comp_unit (per_cu, pst->objfile); +- +- if (per_cu->from_debug_types) +- read_signatured_type_at_offset (pst->objfile, per_cu->offset); +- else +- load_full_comp_unit (per_cu, pst->objfile); +- +- process_queue (pst->objfile); +- +- /* Age the cache, releasing compilation units that have not +- been used recently. */ +- age_cached_comp_units (); +- +- do_cleanups (back_to); ++ dw2_do_instantiate_symtab (pst->objfile, per_cu); + } + + /* Load the DIEs associated with PER_CU into memory. */ +@@ -3130,9 +4105,8 @@ load_full_comp_unit (struct dwarf2_per_cu_data *per_cu, struct objfile *objfile) + static void + process_full_comp_unit (struct dwarf2_per_cu_data *per_cu) + { +- struct partial_symtab *pst = per_cu->psymtab; + struct dwarf2_cu *cu = per_cu->cu; +- struct objfile *objfile = pst->objfile; ++ struct objfile *objfile = per_cu->objfile; + CORE_ADDR lowpc, highpc; + struct symtab *symtab; + struct cleanup *back_to; +@@ -3165,8 +4139,15 @@ process_full_comp_unit (struct dwarf2_per_cu_data *per_cu) + { + symtab->language = cu->language; + } +- pst->symtab = symtab; +- pst->readin = 1; ++ ++ if (dwarf2_per_objfile->using_index) ++ per_cu->v.quick->symtab = symtab; ++ else ++ { ++ struct partial_symtab *pst = per_cu->v.psymtab; ++ pst->symtab = symtab; ++ pst->readin = 1; ++ } + + do_cleanups (back_to); + } +@@ -3559,6 +4540,46 @@ free_cu_line_header (void *arg) + } + + static void ++find_file_and_directory (struct die_info *die, struct dwarf2_cu *cu, ++ char **name, char **comp_dir) ++{ ++ struct attribute *attr; ++ ++ *name = NULL; ++ *comp_dir = NULL; ++ ++ /* Find the filename. Do not use dwarf2_name here, since the filename ++ is not a source language identifier. */ ++ attr = dwarf2_attr (die, DW_AT_name, cu); ++ if (attr) ++ { ++ *name = DW_STRING (attr); ++ } ++ ++ attr = dwarf2_attr (die, DW_AT_comp_dir, cu); ++ if (attr) ++ *comp_dir = DW_STRING (attr); ++ else if (*name != NULL && IS_ABSOLUTE_PATH (*name)) ++ { ++ *comp_dir = ldirname (*name); ++ if (*comp_dir != NULL) ++ make_cleanup (xfree, *comp_dir); ++ } ++ if (*comp_dir != NULL) ++ { ++ /* Irix 6.2 native cc prepends .: to the compilation ++ directory, get rid of it. */ ++ char *cp = strchr (*comp_dir, ':'); ++ ++ if (cp && cp != *comp_dir && cp[-1] == '.' && cp[1] == '/') ++ *comp_dir = cp + 1; ++ } ++ ++ if (*name == NULL) ++ *name = ""; ++} ++ ++static void + read_file_scope (struct die_info *die, struct dwarf2_cu *cu) + { + struct objfile *objfile = cu->objfile; +@@ -3584,35 +4605,7 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu) + lowpc += baseaddr; + highpc += baseaddr; + +- /* Find the filename. Do not use dwarf2_name here, since the filename +- is not a source language identifier. */ +- attr = dwarf2_attr (die, DW_AT_name, cu); +- if (attr) +- { +- name = DW_STRING (attr); +- } +- +- attr = dwarf2_attr (die, DW_AT_comp_dir, cu); +- if (attr) +- comp_dir = DW_STRING (attr); +- else if (name != NULL && IS_ABSOLUTE_PATH (name)) +- { +- comp_dir = ldirname (name); +- if (comp_dir != NULL) +- make_cleanup (xfree, comp_dir); +- } +- if (comp_dir != NULL) +- { +- /* Irix 6.2 native cc prepends .: to the compilation +- directory, get rid of it. */ +- char *cp = strchr (comp_dir, ':'); +- +- if (cp && cp != comp_dir && cp[-1] == '.' && cp[1] == '/') +- comp_dir = cp + 1; +- } +- +- if (name == NULL) +- name = ""; ++ find_file_and_directory (die, cu, &name, &comp_dir); + + attr = dwarf2_attr (die, DW_AT_language, cu); + if (attr) +@@ -5531,6 +6524,29 @@ process_enumeration_scope (struct die_info *die, struct dwarf2_cu *cu) new_symbol (die, this_type, cu); } @@ -1807,7 +3691,7 @@ index 16381de..ec31cf1 100644 /* Extract all information from a DW_TAG_array_type DIE and put it in the DIE's type field. For now, this only handles one dimensional arrays. */ -@@ -5544,7 +5576,7 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu) +@@ -5544,7 +6560,7 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu) struct type *element_type, *range_type, *index_type; struct type **range_types = NULL; struct attribute *attr; @@ -1816,7 +3700,7 @@ index 16381de..ec31cf1 100644 struct cleanup *back_to; char *name; -@@ -5597,17 +5629,11 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu) +@@ -5597,17 +6613,11 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu) type = element_type; if (read_array_order (die, cu) == DW_ORD_col_major) @@ -1839,7 +3723,7 @@ index 16381de..ec31cf1 100644 /* Understand Dwarf2 support for vector types (like they occur on the PowerPC w/ AltiVec). Gcc just adds another attribute to the -@@ -6061,29 +6087,114 @@ read_tag_string_type (struct die_info *die, struct dwarf2_cu *cu) +@@ -6061,29 +7071,114 @@ read_tag_string_type (struct die_info *die, struct dwarf2_cu *cu) struct gdbarch *gdbarch = get_objfile_arch (objfile); struct type *type, *range_type, *index_type, *char_type; struct attribute *attr; @@ -1968,7 +3852,7 @@ index 16381de..ec31cf1 100644 char_type = language_string_char_type (cu->language_defn, gdbarch); type = create_string_type (NULL, char_type, range_type); -@@ -6326,60 +6437,136 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu) +@@ -6326,60 +7421,136 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu) struct type *base_type; struct type *range_type; struct attribute *attr; @@ -2139,7 +4023,7 @@ index 16381de..ec31cf1 100644 } /* Dwarf-2 specifications explicitly allows to create subrange types -@@ -6421,20 +6608,41 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu) +@@ -6421,20 +7592,41 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu) } } @@ -2193,7 +4077,7 @@ index 16381de..ec31cf1 100644 name = dwarf2_name (die, cu); if (name) -@@ -8714,10 +8922,12 @@ var_decode_location (struct attribute *attr, struct symbol *sym, +@@ -8714,10 +9906,12 @@ var_decode_location (struct attribute *attr, struct symbol *sym, (i.e. when the value of a register or memory location is referenced, or a thread-local block, etc.). Then again, it might not be worthwhile. I'm assuming that it isn't unless performance @@ -2208,7 +4092,7 @@ index 16381de..ec31cf1 100644 } /* Given a pointer to a DWARF information entry, figure out if we need -@@ -8748,6 +8958,8 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu) +@@ -8748,6 +9942,8 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu) sizeof (struct symbol)); OBJSTAT (objfile, n_syms++); memset (sym, 0, sizeof (struct symbol)); @@ -2217,7 +4101,7 @@ index 16381de..ec31cf1 100644 /* Cache this symbol's name and the name's demangled form (if any). */ SYMBOL_LANGUAGE (sym) = cu->language; -@@ -9379,6 +9591,9 @@ read_type_die (struct die_info *die, struct dwarf2_cu *cu) +@@ -9379,6 +10575,9 @@ read_type_die (struct die_info *die, struct dwarf2_cu *cu) break; } @@ -2227,7 +4111,7 @@ index 16381de..ec31cf1 100644 return this_type; } -@@ -11983,67 +12198,102 @@ attr_form_is_constant (struct attribute *attr) +@@ -11983,67 +13182,102 @@ attr_form_is_constant (struct attribute *attr) } } @@ -2280,7 +4164,7 @@ index 16381de..ec31cf1 100644 + + return baton; +} - ++ +static struct dwarf2_loclist_baton * +dwarf2_attr_to_loclist_baton (struct attribute *attr, struct dwarf2_cu *cu) +{ @@ -2325,7 +4209,7 @@ index 16381de..ec31cf1 100644 + struct dwarf2_cu *cu) +{ + struct dwarf2_loclist_baton *loclist_baton; -+ + + loclist_baton = dwarf2_attr_to_loclist_baton (attr, cu); + if (loclist_baton) + { @@ -2379,7 +4263,74 @@ index 16381de..ec31cf1 100644 } } -@@ -12372,6 +12622,31 @@ offset_and_type_eq (const void *item_lhs, const void *item_rhs) +@@ -12054,7 +13288,7 @@ dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym, + struct objfile * + dwarf2_per_cu_objfile (struct dwarf2_per_cu_data *per_cu) + { +- struct objfile *objfile = per_cu->psymtab->objfile; ++ struct objfile *objfile = per_cu->objfile; + + /* Return the master objfile, so that we can report and look up the + correct file containing this variable. */ +@@ -12074,7 +13308,7 @@ dwarf2_per_cu_addr_size (struct dwarf2_per_cu_data *per_cu) + else + { + /* If the CU is not currently read in, we re-read its header. */ +- struct objfile *objfile = per_cu->psymtab->objfile; ++ struct objfile *objfile = per_cu->objfile; + struct dwarf2_per_objfile *per_objfile + = objfile_data (objfile, dwarf2_objfile_data_key); + gdb_byte *info_ptr = per_objfile->info.buffer + per_cu->offset; +@@ -12096,7 +13330,7 @@ dwarf2_per_cu_offset_size (struct dwarf2_per_cu_data *per_cu) + else + { + /* If the CU is not currently read in, we re-read its header. */ +- struct objfile *objfile = per_cu->psymtab->objfile; ++ struct objfile *objfile = per_cu->objfile; + struct dwarf2_per_objfile *per_objfile + = objfile_data (objfile, dwarf2_objfile_data_key); + gdb_byte *info_ptr = per_objfile->info.buffer + per_cu->offset; +@@ -12116,7 +13350,7 @@ dwarf2_per_cu_offset_size (struct dwarf2_per_cu_data *per_cu) + CORE_ADDR + dwarf2_per_cu_text_offset (struct dwarf2_per_cu_data *per_cu) + { +- struct objfile *objfile = per_cu->psymtab->objfile; ++ struct objfile *objfile = per_cu->objfile; + + return ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + } +@@ -12338,6 +13572,30 @@ dwarf2_free_objfile (struct objfile *objfile) + /* Cached DIE trees use xmalloc and the comp_unit_obstack. */ + free_cached_comp_units (NULL); + ++ if (dwarf2_per_objfile->using_index) ++ { ++ int i; ++ ++ for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i) ++ { ++ int j; ++ struct dwarf2_per_cu_data *cu = dwarf2_per_objfile->all_comp_units[i]; ++ ++ if (!cu->v.quick->lines) ++ continue; ++ ++ for (j = 0; j < cu->v.quick->lines->num_file_names; ++j) ++ { ++ if (cu->v.quick->file_names) ++ xfree ((void *) cu->v.quick->file_names[j]); ++ if (cu->v.quick->full_names) ++ xfree ((void *) cu->v.quick->full_names[j]); ++ } ++ ++ free_line_header (cu->v.quick->lines); ++ } ++ } ++ + /* Everything else should be on the objfile obstack. */ + } + +@@ -12372,6 +13630,31 @@ offset_and_type_eq (const void *item_lhs, const void *item_rhs) return ofs_lhs->offset == ofs_rhs->offset; } @@ -2411,7 +4362,7 @@ index 16381de..ec31cf1 100644 /* Set the type associated with DIE to TYPE. Save it in CU's hash table if necessary. For convenience, return TYPE. -@@ -12395,6 +12670,8 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu) +@@ -12395,6 +13678,8 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu) { struct dwarf2_offset_and_type **slot, ofs; @@ -2420,11 +4371,588 @@ index 16381de..ec31cf1 100644 /* For Ada types, make sure that the gnat-specific data is always initialized (if not already set). There are a few types where we should not be doing so, because the type-specific area is +@@ -12592,8 +13877,567 @@ dwarf2_per_objfile_free (struct objfile *objfile, void *d) + munmap_section_buffer (&data->loc); + munmap_section_buffer (&data->frame); + munmap_section_buffer (&data->eh_frame); ++ munmap_section_buffer (&data->gdb_index); ++} ++ ++ ++ ++/* The contents of the hash table we create when building the string ++ table. */ ++struct strtab_entry ++{ ++ offset_type offset; ++ const char *str; ++}; ++ ++/* Hash function for a strtab_entry. */ ++static hashval_t ++hash_strtab_entry (const void *e) ++{ ++ const struct strtab_entry *entry = e; ++ return mapped_index_string_hash (entry->str); ++} ++ ++/* Equality function for a strtab_entry. */ ++static int ++eq_strtab_entry (const void *a, const void *b) ++{ ++ const struct strtab_entry *ea = a; ++ const struct strtab_entry *eb = b; ++ return !strcmp (ea->str, eb->str); ++} ++ ++/* Create a strtab_entry hash table. */ ++static htab_t ++create_strtab (void) ++{ ++ return htab_create_alloc (100, hash_strtab_entry, eq_strtab_entry, ++ xfree, xcalloc, xfree); ++} ++ ++/* Add a string to the constant pool. Return the string's offset in ++ host order. */ ++static offset_type ++add_string (htab_t table, struct obstack *cpool, const char *str) ++{ ++ void **slot; ++ struct strtab_entry entry; ++ struct strtab_entry *result; ++ ++ entry.str = str; ++ slot = htab_find_slot (table, &entry, INSERT); ++ if (*slot) ++ result = *slot; ++ else ++ { ++ result = XNEW (struct strtab_entry); ++ result->offset = obstack_object_size (cpool); ++ result->str = str; ++ obstack_grow_str0 (cpool, str); ++ *slot = result; ++ } ++ return result->offset; ++} ++ ++/* An entry in the symbol table. */ ++struct symtab_index_entry ++{ ++ /* The name of the symbol. */ ++ const char *name; ++ /* The offset of the name in the constant pool. */ ++ offset_type index_offset; ++ /* A sorted vector of the indices of all the CUs that hold an object ++ of this name. */ ++ VEC (offset_type) *cu_indices; ++}; ++ ++/* The symbol table. This is a power-of-2-sized hash table. */ ++struct mapped_symtab ++{ ++ offset_type n_elements; ++ offset_type size; ++ struct symtab_index_entry **data; ++}; ++ ++/* Hash function for a symtab_index_entry. */ ++static hashval_t ++hash_symtab_entry (const void *e) ++{ ++ const struct symtab_index_entry *entry = e; ++ return iterative_hash (VEC_address (offset_type, entry->cu_indices), ++ sizeof (offset_type) * VEC_length (offset_type, ++ entry->cu_indices), ++ 0); ++} ++ ++/* Equality function for a symtab_index_entry. */ ++static int ++eq_symtab_entry (const void *a, const void *b) ++{ ++ const struct symtab_index_entry *ea = a; ++ const struct symtab_index_entry *eb = b; ++ int len = VEC_length (offset_type, ea->cu_indices); ++ if (len != VEC_length (offset_type, eb->cu_indices)) ++ return 0; ++ return !memcmp (VEC_address (offset_type, ea->cu_indices), ++ VEC_address (offset_type, eb->cu_indices), ++ sizeof (offset_type) * len); ++} ++ ++/* Destroy a symtab_index_entry. */ ++static void ++delete_symtab_entry (void *p) ++{ ++ struct symtab_index_entry *entry = p; ++ VEC_free (offset_type, entry->cu_indices); ++ xfree (entry); ++} ++ ++/* Create a hash table holding symtab_index_entry objects. */ ++static htab_t ++create_index_table (void) ++{ ++ return htab_create_alloc (100, hash_symtab_entry, eq_symtab_entry, ++ delete_symtab_entry, xcalloc, xfree); ++} ++ ++/* Create a new mapped symtab object. */ ++static struct mapped_symtab * ++create_mapped_symtab (void) ++{ ++ struct mapped_symtab *symtab = XNEW (struct mapped_symtab); ++ symtab->n_elements = 0; ++ symtab->size = 1024; ++ symtab->data = XCNEWVEC (struct symtab_index_entry *, symtab->size); ++ return symtab; ++} ++ ++/* Destroy a mapped_symtab. */ ++static void ++cleanup_mapped_symtab (void *p) ++{ ++ struct mapped_symtab *symtab = p; ++ /* The contents of the array are freed when the other hash table is ++ destroyed. */ ++ xfree (symtab->data); ++ xfree (symtab); ++} ++ ++/* Find a slot in SYMTAB for the symbol NAME. Returns a pointer to ++ the slot. */ ++static struct symtab_index_entry ** ++find_slot (struct mapped_symtab *symtab, const char *name) ++{ ++ offset_type index, step, hash = mapped_index_string_hash (name); ++ ++ index = hash & (symtab->size - 1); ++ step = ((hash * 17) & (symtab->size - 1)) | 1; ++ ++ for (;;) ++ { ++ if (!symtab->data[index] || !strcmp (name, symtab->data[index]->name)) ++ return &symtab->data[index]; ++ index = (index + step) & (symtab->size - 1); ++ } ++} ++ ++/* Expand SYMTAB's hash table. */ ++static void ++hash_expand (struct mapped_symtab *symtab) ++{ ++ offset_type old_size = symtab->size; ++ offset_type i; ++ struct symtab_index_entry **old_entries = symtab->data; ++ ++ symtab->size *= 2; ++ symtab->data = XCNEWVEC (struct symtab_index_entry *, symtab->size); ++ ++ for (i = 0; i < old_size; ++i) ++ { ++ if (old_entries[i]) ++ { ++ struct symtab_index_entry **slot = find_slot (symtab, ++ old_entries[i]->name); ++ *slot = old_entries[i]; ++ } ++ } ++ ++ xfree (old_entries); ++} ++ ++/* Add an entry to SYMTAB. NAME is the name of the symbol. CU_INDEX ++ is the index of the CU in which the symbol appears. */ ++static void ++add_index_entry (struct mapped_symtab *symtab, const char *name, ++ offset_type cu_index) ++{ ++ struct symtab_index_entry **slot; ++ ++ ++symtab->n_elements; ++ if (4 * symtab->n_elements / 3 >= symtab->size) ++ hash_expand (symtab); ++ ++ slot = find_slot (symtab, name); ++ if (!*slot) ++ { ++ *slot = XNEW (struct symtab_index_entry); ++ (*slot)->name = name; ++ (*slot)->cu_indices = NULL; ++ } ++ /* Don't push an index twice. Due to how we add entries we only ++ have to check the last one. */ ++ if (VEC_empty (offset_type, (*slot)->cu_indices) ++ || VEC_length (offset_type, (*slot)->cu_indices) != cu_index) ++ VEC_safe_push (offset_type, (*slot)->cu_indices, cu_index); ++} ++ ++/* Add a vector of indices to the constant pool. */ ++static offset_type ++add_indices_to_cpool (htab_t index_table, struct obstack *cpool, ++ struct symtab_index_entry *entry) ++{ ++ void **slot; ++ ++ slot = htab_find_slot (index_table, entry, INSERT); ++ if (!*slot) ++ { ++ offset_type len = VEC_length (offset_type, entry->cu_indices); ++ offset_type val = MAYBE_SWAP (len); ++ offset_type iter; ++ int i; ++ ++ *slot = entry; ++ entry->index_offset = obstack_object_size (cpool); ++ ++ obstack_grow (cpool, &val, sizeof (val)); ++ for (i = 0; ++ VEC_iterate (offset_type, entry->cu_indices, i, iter); ++ ++i) ++ { ++ val = MAYBE_SWAP (iter); ++ obstack_grow (cpool, &val, sizeof (val)); ++ } ++ } ++ else ++ { ++ struct symtab_index_entry *old_entry = *slot; ++ entry->index_offset = old_entry->index_offset; ++ entry = old_entry; ++ } ++ return entry->index_offset; ++} ++ ++/* Write the mapped hash table SYMTAB to the obstack OUTPUT, with ++ constant pool entries going into the obstack CPOOL. */ ++static void ++write_hash_table (struct mapped_symtab *symtab, ++ struct obstack *output, struct obstack *cpool) ++{ ++ offset_type i; ++ htab_t index_table; ++ htab_t str_table; ++ ++ index_table = create_index_table (); ++ str_table = create_strtab (); ++ /* We add all the index vectors to the constant pool first, to ++ ensure alignment is ok. */ ++ for (i = 0; i < symtab->size; ++i) ++ { ++ if (symtab->data[i]) ++ add_indices_to_cpool (index_table, cpool, symtab->data[i]); ++ } ++ ++ /* Now write out the hash table. */ ++ for (i = 0; i < symtab->size; ++i) ++ { ++ offset_type str_off, vec_off; ++ ++ if (symtab->data[i]) ++ { ++ str_off = add_string (str_table, cpool, symtab->data[i]->name); ++ vec_off = symtab->data[i]->index_offset; ++ } ++ else ++ { ++ /* While 0 is a valid constant pool index, it is not valid ++ to have 0 for both offsets. */ ++ str_off = 0; ++ vec_off = 0; ++ } ++ ++ str_off = MAYBE_SWAP (str_off); ++ vec_off = MAYBE_SWAP (vec_off); ++ ++ obstack_grow (output, &str_off, sizeof (str_off)); ++ obstack_grow (output, &vec_off, sizeof (vec_off)); ++ } ++ ++ htab_delete (str_table); ++ htab_delete (index_table); ++} ++ ++/* Write an address entry to ADDR_OBSTACK. The addresses are taken ++ from PST; CU_INDEX is the index of the CU in the vector of all ++ CUs. */ ++static void ++add_address_entry (struct objfile *objfile, ++ struct obstack *addr_obstack, struct partial_symtab *pst, ++ unsigned int cu_index) ++{ ++ offset_type offset; ++ char addr[8]; ++ CORE_ADDR baseaddr; ++ ++ baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); ++ ++ store_unsigned_integer (addr, 8, BFD_ENDIAN_LITTLE, pst->textlow - baseaddr); ++ obstack_grow (addr_obstack, addr, 8); ++ store_unsigned_integer (addr, 8, BFD_ENDIAN_LITTLE, pst->texthigh - baseaddr); ++ obstack_grow (addr_obstack, addr, 8); ++ offset = MAYBE_SWAP (cu_index); ++ obstack_grow (addr_obstack, &offset, sizeof (offset_type)); ++} ++ ++/* Add a list of partial symbols to SYMTAB. */ ++static void ++write_psymbols (struct mapped_symtab *symtab, ++ struct partial_symbol **psymp, ++ int count, ++ offset_type cu_index) ++{ ++ for (; count-- > 0; ++psymp) ++ { ++ if (SYMBOL_LANGUAGE (*psymp) == language_ada) ++ error (_("Ada is not currently supported by the index")); ++ add_index_entry (symtab, SYMBOL_NATURAL_NAME (*psymp), cu_index); ++ } ++} ++ ++/* Write the contents of an ("unfinished") obstack to FILE. Throw an ++ exception if there is an error. */ ++static void ++write_obstack (FILE *file, struct obstack *obstack) ++{ ++ if (fwrite (obstack_base (obstack), 1, obstack_object_size (obstack), ++ file) ++ != obstack_object_size (obstack)) ++ error (_("couldn't data write to file")); ++} ++ ++/* Unlink a file if the argument is not NULL. */ ++static void ++unlink_if_set (void *p) ++{ ++ char **filename = p; ++ if (*filename) ++ unlink (*filename); ++} ++ ++/* Create an index file for OBJFILE in the directory DIR. */ ++static void ++write_psymtabs_to_index (struct objfile *objfile, const char *dir) ++{ ++ struct cleanup *cleanup; ++ char *filename, *cleanup_filename; ++ struct obstack contents, addr_obstack, constant_pool, symtab_obstack, cu_list; ++ int i; ++ FILE *out_file; ++ struct mapped_symtab *symtab; ++ offset_type val, size_of_contents, total_len; ++ struct stat st; ++ char buf[8]; ++ ++ if (!objfile->psymtabs) ++ return; ++ if (dwarf2_per_objfile->using_index) ++ error (_("Cannot use an index to create the index")); ++ ++ if (stat (objfile->name, &st) < 0) ++ perror_with_name (_("Could not stat")); ++ ++ filename = concat (dir, SLASH_STRING, lbasename (objfile->name), ++ INDEX_SUFFIX, (char *) NULL); ++ cleanup = make_cleanup (xfree, filename); ++ ++ out_file = fopen (filename, "wb"); ++ if (!out_file) ++ error (_("Can't open `%s' for writing"), filename); ++ ++ cleanup_filename = filename; ++ make_cleanup (unlink_if_set, &cleanup_filename); ++ ++ symtab = create_mapped_symtab (); ++ make_cleanup (cleanup_mapped_symtab, symtab); ++ ++ obstack_init (&addr_obstack); ++ make_cleanup_obstack_free (&addr_obstack); ++ ++ obstack_init (&cu_list); ++ make_cleanup_obstack_free (&cu_list); ++ ++ for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i) ++ { ++ struct dwarf2_per_cu_data *cu = dwarf2_per_objfile->all_comp_units[i]; ++ struct partial_symtab *psymtab = cu->v.psymtab; ++ gdb_byte val[8]; ++ ++ write_psymbols (symtab, ++ objfile->global_psymbols.list + psymtab->globals_offset, ++ psymtab->n_global_syms, i); ++ write_psymbols (symtab, ++ objfile->static_psymbols.list + psymtab->statics_offset, ++ psymtab->n_static_syms, i); ++ ++ add_address_entry (objfile, &addr_obstack, psymtab, i); ++ ++ store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE, cu->offset); ++ obstack_grow (&cu_list, val, 8); ++ store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE, cu->length); ++ obstack_grow (&cu_list, val, 8); ++ } ++ ++ obstack_init (&constant_pool); ++ make_cleanup_obstack_free (&constant_pool); ++ obstack_init (&symtab_obstack); ++ make_cleanup_obstack_free (&symtab_obstack); ++ write_hash_table (symtab, &symtab_obstack, &constant_pool); ++ ++ obstack_init (&contents); ++ make_cleanup_obstack_free (&contents); ++ size_of_contents = 5 * sizeof (offset_type); ++ total_len = size_of_contents; ++ ++ /* The version number. */ ++ val = MAYBE_SWAP (1); ++ obstack_grow (&contents, &val, sizeof (val)); ++ ++ /* The offset of the CU list from the start of the file. */ ++ val = MAYBE_SWAP (total_len); ++ obstack_grow (&contents, &val, sizeof (val)); ++ total_len += obstack_object_size (&cu_list); ++ ++ /* The offset of the address table from the start of the file. */ ++ val = MAYBE_SWAP (total_len); ++ obstack_grow (&contents, &val, sizeof (val)); ++ total_len += obstack_object_size (&addr_obstack); ++ ++ /* The offset of the symbol table from the start of the file. */ ++ val = MAYBE_SWAP (total_len); ++ obstack_grow (&contents, &val, sizeof (val)); ++ total_len += obstack_object_size (&symtab_obstack); ++ ++ /* The offset of the constant pool from the start of the file. */ ++ val = MAYBE_SWAP (total_len); ++ obstack_grow (&contents, &val, sizeof (val)); ++ total_len += obstack_object_size (&constant_pool); ++ ++ gdb_assert (obstack_object_size (&contents) == size_of_contents); ++ ++ write_obstack (out_file, &contents); ++ write_obstack (out_file, &cu_list); ++ write_obstack (out_file, &addr_obstack); ++ write_obstack (out_file, &symtab_obstack); ++ write_obstack (out_file, &constant_pool); ++ ++ fclose (out_file); ++ ++ /* We want to keep the file, so we set cleanup_filename to NULL ++ here. See unlink_if_set. */ ++ cleanup_filename = NULL; ++ ++ do_cleanups (cleanup); ++} ++ ++/* The mapped index file format is designed to be directly mmap()able ++ on any architecture. In most cases, a datum is represented using a ++ little-endian 32-bit integer value, called an offset_type. Big ++ endian machines must byte-swap the values before using them. ++ Exceptions to this rule are noted. The data is laid out such that ++ alignment is always respected. ++ ++ A mapped index consists of several sections. ++ ++ 1. The file header. This is a sequence of values, of offset_type ++ unless otherwise noted: ++ [0] The version number. Currently 1. ++ [1] The offset, from the start of the file, of the CU list. ++ [2] The offset, from the start of the file, of the address section. ++ [3] The offset, from the start of the file, of the symbol table. ++ [4] The offset, from the start of the file, of the constant pool. ++ ++ 2. The CU list. This is a sequence of pairs of 64-bit ++ little-endian values. The first element in each pair is the offset ++ of a CU in the .debug_info section. The second element in each ++ pair is the length of that CU. References to a CU elsewhere in the ++ map are done using a CU index, which is just the 0-based index into ++ this table. ++ ++ 3. The address section. The address section consists of a sequence ++ of address entries. Each address entry has three elements. ++ [0] The low address. This is a 64-bit little-endian value. ++ [1] The high address. This is a 64-bit little-endian value. ++ [2] The CU index. This is an offset_type value. ++ ++ 4. The symbol table. This is a hash table. The size of the hash ++ table is always a power of 2. The initial hash and the step are ++ currently defined by the `find_slot' function. ++ ++ Each slot in the hash table consists of a pair of offset_type ++ values. The first value is the offset of the symbol's name in the ++ constant pool. The second value is the offset of the CU vector in ++ the constant pool. ++ ++ If both values are 0, then this slot in the hash table is empty. ++ This is ok because while 0 is a valid constant pool index, it ++ cannot be a valid index for both a string and a CU vector. ++ ++ A string in the constant pool is stored as a \0-terminated string, ++ as you'd expect. ++ ++ A CU vector in the constant pool is a sequence of offset_type ++ values. The first value is the number of CU indices in the vector. ++ Each subsequent value is the index of a CU in the CU list. This ++ element in the hash table is used to indicate which CUs define the ++ symbol. ++ ++ 5. The constant pool. This is simply a bunch of bytes. It is ++ organized so that alignment is correct: CU vectors are stored ++ first, followed by strings. */ ++static void ++save_gdb_index_command (char *arg, int from_tty) ++{ ++ struct objfile *objfile; ++ ++ if (!arg || !*arg) ++ error (_("usage: maintenance save-gdb-index DIRECTORY")); ++ ++ ALL_OBJFILES (objfile) ++ { ++ struct stat st; ++ ++ /* If the objfile does not correspond to an actual file, skip it. */ ++ if (stat (objfile->name, &st) < 0) ++ continue; ++ ++ dwarf2_per_objfile = objfile_data (objfile, dwarf2_objfile_data_key); ++ if (dwarf2_per_objfile) ++ { ++ volatile struct gdb_exception except; ++ ++ TRY_CATCH (except, RETURN_MASK_ERROR) ++ { ++ write_psymtabs_to_index (objfile, arg); ++ } ++ if (except.reason < 0) ++ exception_fprintf (gdb_stderr, except, ++ _("Error while writing index for `%s': "), ++ objfile->name); ++ } ++ } + } + ++ ++ + int dwarf2_always_disassemble; + + static void +@@ -12657,4 +14501,8 @@ The value is the maximum depth to print."), + NULL, + NULL, + &setdebuglist, &showdebuglist); ++ ++ add_cmd ("gdb-index", class_files, save_gdb_index_command, ++ _("Save a .gdb-index file"), ++ &save_cmdlist); + } diff --git a/gdb/elfread.c b/gdb/elfread.c -index 8c00938..4aa1f3f 100644 +index 8c00938..a250c58 100644 --- a/gdb/elfread.c +++ b/gdb/elfread.c -@@ -37,6 +37,7 @@ +@@ -37,9 +37,13 @@ #include "complaints.h" #include "demangle.h" #include "psympriv.h" @@ -2432,7 +4960,13 @@ index 8c00938..4aa1f3f 100644 extern void _initialize_elfread (void); -@@ -180,7 +181,8 @@ record_minimal_symbol (const char *name, int name_len, int copy_name, ++/* Forward declaration. */ ++static struct sym_fns elf_sym_fns_gdb_index; ++ + /* The struct elfinfo is available only during ELF symbol table and + psymtab reading. It is destroyed at the completion of psymtab-reading. + It's local to elf_symfile_read. */ +@@ -180,7 +184,8 @@ record_minimal_symbol (const char *name, int name_len, int copy_name, { struct gdbarch *gdbarch = get_objfile_arch (objfile); @@ -2442,7 +4976,7 @@ index 8c00938..4aa1f3f 100644 address = gdbarch_smash_text_address (gdbarch, address); return prim_record_minimal_symbol_full (name, name_len, copy_name, address, -@@ -388,7 +390,10 @@ elf_symtab_read (struct objfile *objfile, int type, +@@ -388,7 +393,10 @@ elf_symtab_read (struct objfile *objfile, int type, { if (sym->flags & (BSF_GLOBAL | BSF_WEAK)) { @@ -2454,7 +4988,7 @@ index 8c00938..4aa1f3f 100644 } else if ((sym->name[0] == '.' && sym->name[1] == 'L') || ((sym->flags & BSF_LOCAL) -@@ -569,6 +574,250 @@ elf_symtab_read (struct objfile *objfile, int type, +@@ -569,6 +577,250 @@ elf_symtab_read (struct objfile *objfile, int type, } } @@ -2705,7 +5239,7 @@ index 8c00938..4aa1f3f 100644 struct build_id { size_t size; -@@ -797,6 +1046,8 @@ elf_symfile_read (struct objfile *objfile, int symfile_flags) +@@ -797,6 +1049,8 @@ elf_symfile_read (struct objfile *objfile, int symfile_flags) bfd_errmsg (bfd_get_error ())); elf_symtab_read (objfile, ST_DYNAMIC, dynsymcount, dyn_symbol_table, 0); @@ -2714,6 +5248,46 @@ index 8c00938..4aa1f3f 100644 } /* Add synthetic symbols - for instance, names for any PLT entries. */ +@@ -869,11 +1123,9 @@ elf_symfile_read (struct objfile *objfile, int symfile_flags) + str_sect->filepos, + bfd_section_size (abfd, str_sect)); + } +- if (dwarf2_has_info (objfile)) +- { +- /* DWARF 2 sections */ +- dwarf2_build_psymtabs (objfile); +- } ++ ++ if (dwarf2_has_info (objfile) && dwarf2_initialize_objfile (objfile)) ++ objfile->sf = &elf_sym_fns_gdb_index; + + /* If the file has its own symbol tables it has no separate debug info. + `.dynsym'/`.symtab' go to MSYMBOLS, `.debug_info' goes to SYMTABS/PSYMTABS. +@@ -1049,6 +1301,24 @@ static struct sym_fns elf_sym_fns = + NULL /* next: pointer to next struct sym_fns */ + }; + ++/* The same as elf_sym_fns, but not registered and uses the ++ DWARF-specific GNU index rather than psymtab. */ ++static struct sym_fns elf_sym_fns_gdb_index = ++{ ++ bfd_target_elf_flavour, ++ elf_new_init, /* sym_new_init: init anything gbl to entire symab */ ++ elf_symfile_init, /* sym_init: read initial info, setup for sym_red() */ ++ elf_symfile_read, /* sym_read: read a symbol file into symtab */ ++ elf_symfile_finish, /* sym_finish: finished with file, cleanup */ ++ default_symfile_offsets, /* sym_offsets: Translate ext. to int. relocatin */ ++ elf_symfile_segments, /* sym_segments: Get segment information from ++ a file. */ ++ NULL, /* sym_read_linetable */ ++ default_symfile_relocate, /* sym_relocate: Relocate a debug section. */ ++ &dwarf2_gdb_index_functions, ++ NULL /* next: pointer to next struct sym_fns */ ++}; ++ + void + _initialize_elfread (void) + { diff --git a/gdb/eval.c b/gdb/eval.c index ff17c34..7b9e871 100644 --- a/gdb/eval.c @@ -3162,6 +5736,171 @@ index 85f698d..2f72b97 100644 CHECK_TYPEDEF (type); switch (TYPE_CODE (type)) { +diff --git a/gdb/findcmd.c b/gdb/findcmd.c +index ac63a9e..e9ba45c 100644 +--- a/gdb/findcmd.c ++++ b/gdb/findcmd.c +@@ -45,6 +45,41 @@ put_bits (bfd_uint64_t data, char *buf, int bits, bfd_boolean big_p) + } + } + ++/* Allocates a buffer in *PATTERN_BUF, with a hard-coded initial size which ++ will be returned in *PATTERN_BUF_SIZE. *PATTERN_BUF_END points to the same ++ place as *PATTERN_BUF, indicating that the buffer is initially empty. */ ++ ++void ++allocate_pattern_buffer (char **pattern_buf, char **pattern_buf_end, ++ ULONGEST *pattern_buf_size) ++{ ++#define INITIAL_PATTERN_BUF_SIZE 100 ++ *pattern_buf_size = INITIAL_PATTERN_BUF_SIZE; ++ *pattern_buf = xmalloc (*pattern_buf_size); ++ *pattern_buf_end = *pattern_buf; ++} ++ ++/* Grows *PATTERN_BUF by a factor of two if it's not large enough to hold ++ VAL_BYTES more bytes or a 64-bit value, whichever is larger. ++ *PATTERN_BUF_END is updated as necessary. */ ++ ++void ++increase_pattern_buffer (char **pattern_buf, char **pattern_buf_end, ++ ULONGEST *pattern_buf_size, int val_bytes) ++{ ++ /* Keep it simple and assume size == 'g' when watching for when we ++ need to grow the pattern buf. */ ++ if ((*pattern_buf_end - *pattern_buf + max (val_bytes, sizeof (int64_t))) ++ > *pattern_buf_size) ++ { ++ size_t current_offset = *pattern_buf_end - *pattern_buf; ++ ++ *pattern_buf_size *= 2; ++ *pattern_buf = xrealloc (*pattern_buf, *pattern_buf_size); ++ *pattern_buf_end = *pattern_buf + current_offset; ++ } ++} ++ + /* Subroutine of find_command to simplify it. + Parse the arguments of the "find" command. */ + +@@ -61,8 +96,7 @@ parse_find_args (char *args, ULONGEST *max_countp, + char *pattern_buf; + /* Current size of search pattern buffer. + We realloc space as needed. */ +-#define INITIAL_PATTERN_BUF_SIZE 100 +- ULONGEST pattern_buf_size = INITIAL_PATTERN_BUF_SIZE; ++ ULONGEST pattern_buf_size; + /* Pointer to one past the last in-use part of pattern_buf. */ + char *pattern_buf_end; + ULONGEST pattern_len; +@@ -75,8 +109,7 @@ parse_find_args (char *args, ULONGEST *max_countp, + if (args == NULL) + error (_("Missing search parameters.")); + +- pattern_buf = xmalloc (pattern_buf_size); +- pattern_buf_end = pattern_buf; ++ allocate_pattern_buffer (&pattern_buf, &pattern_buf_end, &pattern_buf_size); + old_cleanups = make_cleanup (free_current_contents, &pattern_buf); + + /* Get search granularity and/or max count if specified. +@@ -175,17 +208,9 @@ parse_find_args (char *args, ULONGEST *max_countp, + v = parse_to_comma_and_eval (&s); + val_bytes = TYPE_LENGTH (value_type (v)); + +- /* Keep it simple and assume size == 'g' when watching for when we +- need to grow the pattern buf. */ +- if ((pattern_buf_end - pattern_buf + max (val_bytes, sizeof (int64_t))) +- > pattern_buf_size) +- { +- size_t current_offset = pattern_buf_end - pattern_buf; ++ increase_pattern_buffer (&pattern_buf, &pattern_buf_end, ++ &pattern_buf_size, val_bytes); + +- pattern_buf_size *= 2; +- pattern_buf = xrealloc (pattern_buf, pattern_buf_size); +- pattern_buf_end = pattern_buf + current_offset; +- } + + if (size != '\0') + { +@@ -240,6 +265,45 @@ parse_find_args (char *args, ULONGEST *max_countp, + discard_cleanups (old_cleanups); + } + ++/* Drives target_search_memory to sweep through the specified search space, ++ possibly in several iterations (with one call to this function for each ++ iteration). *START_ADDR is the address where the search starts, and is ++ updated to the next starting address to continue the search. ++ *SEARCH_SPACE_LEN is the amount of bytes which will be searched, and is ++ updated for the next iteration. PATTERN_BUF holds the pattern to be searched ++ for, PATTERN_LEN is the size of the pattern in bytes. If a match is found, ++ it's address is put in *FOUND_ADDR. ++ ++ Returns 1 if found, 0 if not found, and -1 if there was an error requiring ++ halting of the search (e.g. memory read error). */ ++ ++int ++search_memory (CORE_ADDR *start_addr, ULONGEST *search_space_len, ++ const char *pattern_buf, ULONGEST pattern_len, ++ CORE_ADDR *found_addr) ++{ ++ /* Offset from start of this iteration to the next iteration. */ ++ ULONGEST next_iter_incr; ++ int found; ++ ++ found = target_search_memory (*start_addr, *search_space_len, ++ pattern_buf, pattern_len, found_addr); ++ if (found <= 0) ++ return found; ++ ++ /* Begin next iteration at one byte past this match. */ ++ next_iter_incr = (*found_addr - *start_addr) + 1; ++ ++ /* For robustness, we don't let search_space_len go -ve here. */ ++ if (*search_space_len >= next_iter_incr) ++ *search_space_len -= next_iter_incr; ++ else ++ *search_space_len = 0; ++ *start_addr += next_iter_incr; ++ ++ return found; ++} ++ + static void + find_command (char *args, int from_tty) + { +@@ -270,12 +334,11 @@ find_command (char *args, int from_tty) + while (search_space_len >= pattern_len + && found_count < max_count) + { +- /* Offset from start of this iteration to the next iteration. */ +- ULONGEST next_iter_incr; + CORE_ADDR found_addr; +- int found = target_search_memory (start_addr, search_space_len, +- pattern_buf, pattern_len, &found_addr); ++ int found; + ++ found = search_memory (&start_addr, &search_space_len, pattern_buf, ++ pattern_len, &found_addr); + if (found <= 0) + break; + +@@ -283,16 +346,6 @@ find_command (char *args, int from_tty) + printf_filtered ("\n"); + ++found_count; + last_found_addr = found_addr; +- +- /* Begin next iteration at one byte past this match. */ +- next_iter_incr = (found_addr - start_addr) + 1; +- +- /* For robustness, we don't let search_space_len go -ve here. */ +- if (search_space_len >= next_iter_incr) +- search_space_len -= next_iter_incr; +- else +- search_space_len = 0; +- start_addr += next_iter_incr; + } + + /* Record and print the results. */ diff --git a/gdb/findvar.c b/gdb/findvar.c index e0ca12c..de6311a 100644 --- a/gdb/findvar.c @@ -3373,6 +6112,41 @@ index e0ca12c..de6311a 100644 } else { +diff --git a/gdb/gdbcmd.h b/gdb/gdbcmd.h +index 6a230c0..d87a813 100644 +--- a/gdb/gdbcmd.h ++++ b/gdb/gdbcmd.h +@@ -124,6 +124,10 @@ extern struct cmd_list_element *setchecklist; + + extern struct cmd_list_element *showchecklist; + ++/* Chain containing all defined "save" subcommands. */ ++ ++extern struct cmd_list_element *save_cmdlist; ++ + extern void execute_command (char *, int); + + enum command_control_type execute_control_command (struct command_line *); +diff --git a/gdb/gdbinit.in b/gdb/gdbinit.in +index ffb7f53..a2e7e94 100644 +--- a/gdb/gdbinit.in ++++ b/gdb/gdbinit.in +@@ -1,5 +1,15 @@ + echo Setting up the environment for debugging gdb.\n + ++# Set up the Python library and "require" command. ++python ++from os.path import abspath ++gdb.datadir = abspath ('@srcdir@/python/lib') ++gdb.pythonlibdir = gdb.datadir ++gdb.__path__ = [gdb.datadir + '/gdb'] ++sys.path.insert(0, gdb.datadir) ++end ++source @srcdir@/python/lib/gdb/__init__.py ++ + set complaints 1 + + b internal_error diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h index cd24eaf..9638368 100644 --- a/gdb/gdbthread.h @@ -5310,6 +8084,174 @@ index 07fd67c..2524250 100644 /* This function is suitable for architectures that don't extend/override the standard siginfo structure. */ +diff --git a/gdb/main.c b/gdb/main.c +index bfd1213..72faabd 100644 +--- a/gdb/main.c ++++ b/gdb/main.c +@@ -39,6 +39,7 @@ + + #include "interps.h" + #include "main.h" ++#include "python/python.h" + #include "source.h" + #include "cli/cli-cmds.h" + #include "python/python.h" +@@ -259,6 +260,8 @@ captured_main (void *data) + char *cdarg = NULL; + char *ttyarg = NULL; + ++ int python_script = 0; ++ + /* These are static so that we can take their address in an initializer. */ + static int print_help; + static int print_version; +@@ -443,10 +446,14 @@ captured_main (void *data) + {"args", no_argument, &set_args, 1}, + {"l", required_argument, 0, 'l'}, + {"return-child-result", no_argument, &return_child_result, 1}, ++#if HAVE_PYTHON ++ {"python", no_argument, 0, 'P'}, ++ {"P", no_argument, 0, 'P'}, ++#endif + {0, no_argument, 0, 0} + }; + +- while (1) ++ while (!python_script) + { + int option_index; + +@@ -464,6 +471,9 @@ captured_main (void *data) + case 0: + /* Long option that just sets a flag. */ + break; ++ case 'P': ++ python_script = 1; ++ break; + case OPT_SE: + symarg = optarg; + execarg = optarg; +@@ -650,7 +660,31 @@ extern int gdbtk_test (char *); + + /* Now that gdb_init has created the initial inferior, we're in position + to set args for that inferior. */ +- if (set_args) ++ if (python_script) ++ { ++ /* The first argument is a python script to evaluate, and ++ subsequent arguments are passed to the script for ++ processing there. */ ++ if (optind >= argc) ++ { ++ fprintf_unfiltered (gdb_stderr, ++ _("%s: Python script file name required\n"), ++ argv[0]); ++ exit (1); ++ } ++ ++ /* FIXME: should handle inferior I/O intelligently here. ++ E.g., should be possible to run gdb in pipeline and have ++ Python (and gdb) output go to stderr or file; and if a ++ prompt is needed, open the tty. */ ++ quiet = 1; ++ /* FIXME: should read .gdbinit if, and only if, a prompt is ++ requested by the script. Though... maybe this is not ++ ideal? */ ++ /* FIXME: likewise, reading in history. */ ++ inhibit_gdbinit = 1; ++ } ++ else if (set_args) + { + /* The remaining options are the command-line options for the + inferior. The first one is the sym/exec file, and the rest +@@ -890,7 +924,8 @@ Can't attach to process and specify a core file at the same time.")); + xfree (cmdarg); + + /* Read in the old history after all the command files have been read. */ +- init_history (); ++ if (!python_script) ++ init_history (); + + if (batch_flag) + { +@@ -901,13 +936,25 @@ Can't attach to process and specify a core file at the same time.")); + /* Show time and/or space usage. */ + do_cleanups (pre_stat_chain); + +- /* 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 +- change - SET_TOP_LEVEL() - has been eliminated. */ +- while (1) ++#if HAVE_PYTHON ++ if (python_script) + { +- catch_errors (captured_command_loop, 0, "", RETURN_MASK_ALL); ++ extern int pagination_enabled; ++ pagination_enabled = 0; ++ run_python_script (argc - optind, &argv[optind]); ++ return 1; ++ } ++ else ++#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 ++ change - SET_TOP_LEVEL() - has been eliminated. */ ++ while (1) ++ { ++ catch_errors (captured_command_loop, 0, "", RETURN_MASK_ALL); ++ } + } + /* No exit -- exit is through quit_command. */ + } +@@ -939,7 +986,12 @@ print_gdb_help (struct ui_file *stream) + fputs_unfiltered (_("\ + This is the GNU debugger. Usage:\n\n\ + gdb [options] [executable-file [core-file or process-id]]\n\ +- gdb [options] --args executable-file [inferior-arguments ...]\n\n\ ++ gdb [options] --args executable-file [inferior-arguments ...]\n"), stream); ++#if HAVE_PYTHON ++ fputs_unfiltered (_("\ ++ gdb [options] [--python|-P] script-file [script-arguments ...]\n"), stream); ++#endif ++ fputs_unfiltered (_("\n\ + Options:\n\n\ + "), stream); + fputs_unfiltered (_("\ +@@ -977,7 +1029,13 @@ Options:\n\n\ + --nw Do not use a window interface.\n\ + --nx Do not read "), stream); + fputs_unfiltered (gdbinit, stream); +- fputs_unfiltered (_(" file.\n\ ++ fputs_unfiltered (_(" file.\n"), stream); ++#if HAVE_PYTHON ++ fputs_unfiltered (_("\ ++ --python, -P Following argument is Python script file; remaining\n\ ++ arguments are passed to script.\n"), stream); ++#endif ++ fputs_unfiltered (_("\ + --quiet Do not print version number on startup.\n\ + --readnow Fully read symbol files on first access.\n\ + "), stream); +diff --git a/gdb/maint.c b/gdb/maint.c +index 28fd610..4e21476 100644 +--- a/gdb/maint.c ++++ b/gdb/maint.c +@@ -909,4 +909,12 @@ When enabled GDB is profiled."), + show_maintenance_profile_p, + &maintenance_set_cmdlist, + &maintenance_show_cmdlist); ++ add_setshow_filename_cmd ("gdb_datadir", class_maintenance, ++ &gdb_datadir, _("Set GDB's datadir path."), ++ _("Show GDB's datadir path."), ++ _("\ ++When set, GDB uses the specified path to search for data files."), ++ NULL, NULL, ++ &maintenance_set_cmdlist, ++ &maintenance_show_cmdlist); + } diff --git a/gdb/mi/mi-cmd-var.c b/gdb/mi/mi-cmd-var.c index 310ade9..d8710a1 100644 --- a/gdb/mi/mi-cmd-var.c @@ -5732,6 +8674,1370 @@ index 5ffa099..58d9c79 100644 + + observer_attach_mark_used (print_types_mark_used); } +diff --git a/gdb/psymtab.c b/gdb/psymtab.c +index 367cf1e..c120894 100644 +--- a/gdb/psymtab.c ++++ b/gdb/psymtab.c +@@ -421,6 +421,14 @@ lookup_symbol_aux_psymtabs (struct objfile *objfile, + return NULL; + } + ++static void ++pre_expand_symtabs_matching_psymtabs (struct objfile *objfile, ++ int kind, const char *name, ++ domain_enum domain) ++{ ++ /* Nothing. */ ++} ++ + /* Look, in partial_symtab PST, for symbol whose natural name is NAME. + Check the global symbols if GLOBAL, the static symbols if not. */ + +@@ -941,7 +949,7 @@ psymtab_to_fullname (struct partial_symtab *ps) + return NULL; + } + +-static char * ++static const char * + find_symbol_file_from_partial (struct objfile *objfile, const char *name) + { + struct partial_symtab *pst; +@@ -1199,6 +1207,7 @@ const struct quick_symbol_functions psym_functions = + forget_cached_source_info_partial, + lookup_symtab_via_partial_symtab, + lookup_symbol_aux_psymtabs, ++ pre_expand_symtabs_matching_psymtabs, + print_psymtab_stats_for_objfile, + dump_psymtabs_for_objfile, + relocate_psymtabs, +diff --git a/gdb/psymtab.h b/gdb/psymtab.h +index 9b8c8df..de8b67e 100644 +--- a/gdb/psymtab.h ++++ b/gdb/psymtab.h +@@ -1,6 +1,6 @@ + /* Public partial symbol table definitions. + +- Copyright (C) 2009 Free Software Foundation, Inc. ++ Copyright (C) 2009, 2010 Free Software Foundation, Inc. + + This file is part of GDB. + +@@ -28,4 +28,6 @@ void map_partial_symbol_filenames (void (*) (const char *, const char *, + + extern const struct quick_symbol_functions psym_functions; + ++extern const struct quick_symbol_functions dwarf2_gdb_index_functions; ++ + #endif /* PSYMTAB_H */ +diff --git a/gdb/python/lib/gdb/FrameIterator.py b/gdb/python/lib/gdb/FrameIterator.py +new file mode 100644 +index 0000000..5654546 +--- /dev/null ++++ b/gdb/python/lib/gdb/FrameIterator.py +@@ -0,0 +1,33 @@ ++# Iterator over frames. ++ ++# Copyright (C) 2008, 2009 Free Software Foundation, Inc. ++ ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++ ++class FrameIterator: ++ """An iterator that iterates over frames.""" ++ ++ def __init__ (self, frame): ++ "Initialize a FrameIterator. FRAME is the starting frame." ++ self.frame = frame ++ ++ def __iter__ (self): ++ return self ++ ++ def next (self): ++ result = self.frame ++ if result is None: ++ raise StopIteration ++ self.frame = result.older () ++ return result +diff --git a/gdb/python/lib/gdb/FrameWrapper.py b/gdb/python/lib/gdb/FrameWrapper.py +new file mode 100644 +index 0000000..b790a54 +--- /dev/null ++++ b/gdb/python/lib/gdb/FrameWrapper.py +@@ -0,0 +1,112 @@ ++# Wrapper API for frames. ++ ++# Copyright (C) 2008, 2009 Free Software Foundation, Inc. ++ ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++ ++import gdb ++ ++# FIXME: arguably all this should be on Frame somehow. ++class FrameWrapper: ++ def __init__ (self, frame): ++ self.frame = frame; ++ ++ def write_symbol (self, stream, sym, block): ++ if len (sym.linkage_name): ++ nsym, is_field_of_this = gdb.lookup_symbol (sym.linkage_name, block) ++ if nsym.addr_class != gdb.SYMBOL_LOC_REGISTER: ++ sym = nsym ++ ++ stream.write (sym.print_name + "=") ++ try: ++ val = self.read_var (sym) ++ if val != None: ++ val = str (val) ++ # FIXME: would be nice to have a more precise exception here. ++ except RuntimeError, text: ++ val = text ++ if val == None: ++ stream.write ("???") ++ else: ++ stream.write (str (val)) ++ ++ def print_frame_locals (self, stream, func): ++ if not func: ++ return ++ ++ first = True ++ block = func.value ++ ++ for sym in block: ++ if sym.is_argument: ++ continue; ++ ++ self.write_symbol (stream, sym, block) ++ stream.write ('\n') ++ ++ def print_frame_args (self, stream, func): ++ if not func: ++ return ++ ++ first = True ++ block = func.value ++ ++ for sym in block: ++ if not sym.is_argument: ++ continue; ++ ++ if not first: ++ stream.write (", ") ++ ++ self.write_symbol (stream, sym, block) ++ first = False ++ ++ # FIXME: this should probably just be a method on gdb.Frame. ++ # But then we need stream wrappers. ++ def describe (self, stream, full): ++ if self.type () == gdb.DUMMY_FRAME: ++ stream.write (" \n") ++ elif self.type () == gdb.SIGTRAMP_FRAME: ++ stream.write (" \n") ++ else: ++ sal = self.find_sal () ++ pc = self.pc () ++ name = self.name () ++ if not name: ++ name = "??" ++ if pc != sal.pc or not sal.symtab: ++ stream.write (" 0x%08x in" % pc) ++ stream.write (" " + name + " (") ++ ++ func = self.function () ++ self.print_frame_args (stream, func) ++ ++ stream.write (")") ++ ++ if sal.symtab and sal.symtab.filename: ++ stream.write (" at " + sal.symtab.filename) ++ stream.write (":" + str (sal.line)) ++ ++ if not self.name () or (not sal.symtab or not sal.symtab.filename): ++ lib = gdb.solib_address (pc) ++ if lib: ++ stream.write (" from " + lib) ++ ++ stream.write ("\n") ++ ++ if full: ++ self.print_frame_locals (stream, func) ++ ++ def __getattr__ (self, name): ++ return getattr (self.frame, name) +diff --git a/gdb/python/lib/gdb/__init__.py b/gdb/python/lib/gdb/__init__.py +new file mode 100644 +index 0000000..b375c68 +--- /dev/null ++++ b/gdb/python/lib/gdb/__init__.py +@@ -0,0 +1,19 @@ ++# Startup code. ++ ++# Copyright (C) 2008 Free Software Foundation, Inc. ++ ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++ ++# Load the require command by default. ++import gdb.command.require +diff --git a/gdb/python/lib/gdb/backtrace.py b/gdb/python/lib/gdb/backtrace.py +new file mode 100644 +index 0000000..2baab5f +--- /dev/null ++++ b/gdb/python/lib/gdb/backtrace.py +@@ -0,0 +1,42 @@ ++# Filtering backtrace. ++ ++# Copyright (C) 2008 Free Software Foundation, Inc. ++ ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++ ++import gdb ++import itertools ++ ++# Our only exports. ++__all__ = ['push_frame_filter', 'create_frame_filter'] ++ ++frame_filter = None ++ ++def push_frame_filter (constructor): ++ """Register a new backtrace filter class with the 'backtrace' command. ++The filter will be passed an iterator as an argument. The iterator ++will return gdb.Frame-like objects. The filter should in turn act as ++an iterator returning such objects.""" ++ global frame_filter ++ if frame_filter == None: ++ frame_filter = constructor ++ else: ++ frame_filter = lambda iterator: constructor (frame_filter (iterator)) ++ ++def create_frame_filter (iter): ++ global frame_filter ++ if frame_filter is None: ++ return iter ++ return frame_filter (iter) ++ +diff --git a/gdb/python/lib/gdb/command/__init__.py b/gdb/python/lib/gdb/command/__init__.py +new file mode 100644 +index 0000000..8b13789 +--- /dev/null ++++ b/gdb/python/lib/gdb/command/__init__.py +@@ -0,0 +1 @@ ++ +diff --git a/gdb/python/lib/gdb/command/alias.py b/gdb/python/lib/gdb/command/alias.py +new file mode 100644 +index 0000000..96b6618 +--- /dev/null ++++ b/gdb/python/lib/gdb/command/alias.py +@@ -0,0 +1,59 @@ ++# Alias command. ++ ++# Copyright (C) 2008 Free Software Foundation, Inc. ++ ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++ ++import gdb ++ ++class AliasImplementation (gdb.Command): ++ def __init__ (self, name, real, doc): ++ # Have to set __doc__ before the super init call. ++ # It would be nice if gdb's help looked up __doc__ dynamically. ++ self.__doc__ = doc ++ # Note: no good way to complete :( ++ super (AliasImplementation, self).__init__ (name, gdb.COMMAND_NONE) ++ self.real = real ++ ++ def invoke(self, arg, from_tty): ++ gdb.execute (self.real + ' ' + arg, from_tty) ++ ++class AliasCommand (gdb.Command): ++ """Alias one command to another. ++In the simplest form, the first word is the name of the alias, and ++the remaining words are the the expansion. ++An '=' by itself can be used to define a multi-word alias; words ++before the '=' are the name of the new command.""" ++ ++ def __init__ (self): ++ # Completion is not quite right here. ++ super (AliasCommand, self).__init__ ("alias", gdb.COMMAND_NONE, ++ gdb.COMPLETE_COMMAND) ++ ++ def invoke (self, arg, from_tty): ++ self.dont_repeat () ++ # Without some form of quoting we can't alias a multi-word ++ # command to another command. ++ args = arg.split() ++ try: ++ start = args.index ('=') ++ end = start + 1 ++ except ValueError: ++ start = 1 ++ end = 1 ++ target = " ".join(args[end:]) ++ AliasImplementation (" ".join (args[0:start]), target, ++ "This command is an alias for '%s'." % target) ++ ++AliasCommand() +diff --git a/gdb/python/lib/gdb/command/backtrace.py b/gdb/python/lib/gdb/command/backtrace.py +new file mode 100644 +index 0000000..ec9a527 +--- /dev/null ++++ b/gdb/python/lib/gdb/command/backtrace.py +@@ -0,0 +1,106 @@ ++# New backtrace command. ++ ++# Copyright (C) 2008, 2009 Free Software Foundation, Inc. ++ ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++ ++import gdb ++import gdb.backtrace ++import itertools ++from gdb.FrameIterator import FrameIterator ++from gdb.FrameWrapper import FrameWrapper ++import sys ++ ++class ReverseBacktraceParameter (gdb.Parameter): ++ """The new-backtrace command can show backtraces in 'reverse' order. ++This means that the innermost frame will be printed last. ++Note that reverse backtraces are more expensive to compute.""" ++ ++ set_doc = "Enable or disable reverse backtraces." ++ show_doc = "Show whether backtraces will be printed in reverse order." ++ ++ def __init__(self): ++ gdb.Parameter.__init__ (self, "reverse-backtrace", ++ gdb.COMMAND_STACK, gdb.PARAM_BOOLEAN) ++ # Default to compatibility with gdb. ++ self.value = False ++ ++class FilteringBacktrace (gdb.Command): ++ """Print backtrace of all stack frames, or innermost COUNT frames. ++With a negative argument, print outermost -COUNT frames. ++Use of the 'full' qualifier also prints the values of the local variables. ++Use of the 'raw' qualifier avoids any filtering by loadable modules. ++""" ++ ++ def __init__ (self): ++ # FIXME: this is not working quite well enough to replace ++ # "backtrace" yet. ++ gdb.Command.__init__ (self, "new-backtrace", gdb.COMMAND_STACK) ++ self.reverse = ReverseBacktraceParameter() ++ ++ def reverse_iter (self, iter): ++ result = [] ++ for item in iter: ++ result.append (item) ++ result.reverse() ++ return result ++ ++ def final_n (self, iter, x): ++ result = [] ++ for item in iter: ++ result.append (item) ++ return result[x:] ++ ++ def invoke (self, arg, from_tty): ++ i = 0 ++ count = 0 ++ filter = True ++ full = False ++ ++ for word in arg.split (" "): ++ if word == '': ++ continue ++ elif word == 'raw': ++ filter = False ++ elif word == 'full': ++ full = True ++ else: ++ count = int (word) ++ ++ # FIXME: provide option to start at selected frame ++ # However, should still number as if starting from newest ++ newest_frame = gdb.selected_thread ().newest_frame () ++ iter = itertools.imap (FrameWrapper, ++ FrameIterator (newest_frame)) ++ if filter: ++ iter = gdb.backtrace.create_frame_filter (iter) ++ ++ # Now wrap in an iterator that numbers the frames. ++ iter = itertools.izip (itertools.count (0), iter) ++ ++ # Reverse if the user wanted that. ++ if self.reverse.value: ++ iter = self.reverse_iter (iter) ++ ++ # Extract sub-range user wants. ++ if count < 0: ++ iter = self.final_n (iter, count) ++ elif count > 0: ++ iter = itertools.islice (iter, 0, count) ++ ++ for pair in iter: ++ sys.stdout.write ("#%-2d" % pair[0]) ++ pair[1].describe (sys.stdout, full) ++ ++FilteringBacktrace() +diff --git a/gdb/python/lib/gdb/command/ignore_errors.py b/gdb/python/lib/gdb/command/ignore_errors.py +new file mode 100644 +index 0000000..6fa48ff +--- /dev/null ++++ b/gdb/python/lib/gdb/command/ignore_errors.py +@@ -0,0 +1,37 @@ ++# Ignore errors in user commands. ++ ++# Copyright (C) 2008 Free Software Foundation, Inc. ++ ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++ ++import gdb ++ ++class IgnoreErrorsCommand (gdb.Command): ++ """Execute a single command, ignoring all errors. ++Only one-line commands are supported. ++This is primarily useful in scripts.""" ++ ++ def __init__ (self): ++ super (IgnoreErrorsCommand, self).__init__ ("ignore-errors", ++ gdb.COMMAND_OBSCURE, ++ # FIXME... ++ gdb.COMPLETE_COMMAND) ++ ++ def invoke (self, arg, from_tty): ++ try: ++ gdb.execute (arg, from_tty) ++ except: ++ pass ++ ++IgnoreErrorsCommand () +diff --git a/gdb/python/lib/gdb/command/pahole.py b/gdb/python/lib/gdb/command/pahole.py +new file mode 100644 +index 0000000..21a0bf0 +--- /dev/null ++++ b/gdb/python/lib/gdb/command/pahole.py +@@ -0,0 +1,75 @@ ++# pahole command for gdb ++ ++# Copyright (C) 2008, 2009 Free Software Foundation, Inc. ++ ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++ ++import gdb ++ ++class Pahole (gdb.Command): ++ """Show the holes in a structure. ++This command takes a single argument, a type name. ++It prints the type and displays comments showing where holes are.""" ++ ++ def __init__ (self): ++ super (Pahole, self).__init__ ("pahole", gdb.COMMAND_NONE, ++ gdb.COMPLETE_SYMBOL) ++ ++ def pahole (self, type, level, name): ++ if name is None: ++ name = '' ++ tag = type.tag ++ if tag is None: ++ tag = '' ++ print '%sstruct %s {' % (' ' * (2 * level), tag) ++ bitpos = 0 ++ for field in type.fields (): ++ # Skip static fields. ++ if not hasattr (field, ('bitpos')): ++ continue ++ ++ ftype = field.type.strip_typedefs() ++ ++ if bitpos != field.bitpos: ++ hole = field.bitpos - bitpos ++ print ' /* XXX %d bit hole, try to pack */' % hole ++ bitpos = field.bitpos ++ if field.bitsize > 0: ++ fieldsize = field.bitsize ++ else: ++ # TARGET_CHAR_BIT here... ++ fieldsize = 8 * ftype.sizeof ++ ++ # TARGET_CHAR_BIT ++ print ' /* %3d %3d */' % (int (bitpos / 8), int (fieldsize / 8)), ++ bitpos = bitpos + fieldsize ++ ++ if ftype.code == gdb.TYPE_CODE_STRUCT: ++ self.pahole (ftype, level + 1, field.name) ++ else: ++ print ' ' * (2 + 2 * level), ++ print '%s %s' % (str (ftype), field.name) ++ ++ print ' ' * (14 + 2 * level), ++ print '} %s' % name ++ ++ def invoke (self, arg, from_tty): ++ type = gdb.lookup_type (arg) ++ type = type.strip_typedefs () ++ if type.code != gdb.TYPE_CODE_STRUCT: ++ raise TypeError, '%s is not a struct type' % arg ++ print ' ' * 14, ++ self.pahole (type, 0, '') ++ ++Pahole() +diff --git a/gdb/python/lib/gdb/command/require.py b/gdb/python/lib/gdb/command/require.py +new file mode 100644 +index 0000000..1fbc1e8 +--- /dev/null ++++ b/gdb/python/lib/gdb/command/require.py +@@ -0,0 +1,57 @@ ++# Demand-loading commands. ++ ++# Copyright (C) 2008, 2009 Free Software Foundation, Inc. ++ ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++ ++import gdb ++import os ++ ++class RequireCommand (gdb.Command): ++ """Prefix command for requiring features.""" ++ ++ def __init__ (self): ++ super (RequireCommand, self).__init__ ("require", ++ gdb.COMMAND_SUPPORT, ++ gdb.COMPLETE_NONE, ++ True) ++ ++class RequireSubcommand (gdb.Command): ++ """Demand-load a command by name.""" ++ ++ def __init__ (self, name): ++ self.__doc__ = "Demand-load a %s by name." % name ++ super (RequireSubcommand, self).__init__ ("require %s" % name, ++ gdb.COMMAND_SUPPORT) ++ self.name = name ++ ++ def invoke (self, arg, from_tty): ++ for cmd in arg.split(): ++ exec ('import gdb.' + self.name + '.' + cmd, globals ()) ++ ++ def complete (self, text, word): ++ dir = gdb.pythondir + '/gdb/' + self.name ++ result = [] ++ for file in os.listdir(dir): ++ if not file.startswith (word) or not file.endswith ('.py'): ++ continue ++ feature = file[0:-3] ++ if feature == 'require' or feature == '__init__': ++ continue ++ result.append (feature) ++ return result ++ ++RequireCommand() ++RequireSubcommand("command") ++RequireSubcommand("function") +diff --git a/gdb/python/lib/gdb/command/save_breakpoints.py b/gdb/python/lib/gdb/command/save_breakpoints.py +new file mode 100644 +index 0000000..6143187 +--- /dev/null ++++ b/gdb/python/lib/gdb/command/save_breakpoints.py +@@ -0,0 +1,65 @@ ++# Save breakpoints. ++ ++# Copyright (C) 2008, 2009 Free Software Foundation, Inc. ++ ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++ ++from __future__ import with_statement ++import gdb ++ ++class SavePrefixCommand (gdb.Command): ++ "Prefix command for saving things." ++ ++ def __init__ (self): ++ super (SavePrefixCommand, self).__init__ ("save", ++ gdb.COMMAND_SUPPORT, ++ gdb.COMPLETE_NONE, True) ++ ++class SaveBreakpointsCommand (gdb.Command): ++ """Save the current breakpoints to a file. ++This command takes a single argument, a file name. ++The breakpoints can be restored using the 'source' command.""" ++ ++ def __init__ (self): ++ super (SaveBreakpointsCommand, self).__init__ ("save breakpoints", ++ gdb.COMMAND_SUPPORT, ++ gdb.COMPLETE_FILENAME) ++ ++ def invoke (self, arg, from_tty): ++ self.dont_repeat () ++ bps = gdb.breakpoints () ++ if bps is None: ++ raise RuntimeError, 'No breakpoints to save' ++ with open (arg.strip (), 'w') as f: ++ for bp in bps: ++ print >> f, "break", bp.location, ++ if bp.thread is not None: ++ print >> f, " thread", bp.thread, ++ if bp.condition is not None: ++ print >> f, " if", bp.condition, ++ print >> f ++ if not bp.enabled: ++ print >> f, "disable $bpnum" ++ # Note: we don't save the ignore count; there doesn't ++ # seem to be much point. ++ commands = bp.commands ++ if commands is not None: ++ print >> f, "commands" ++ # Note that COMMANDS has a trailing newline. ++ print >> f, commands, ++ print >> f, "end" ++ print >> f ++ ++SavePrefixCommand () ++SaveBreakpointsCommand () +diff --git a/gdb/python/lib/gdb/command/upto.py b/gdb/python/lib/gdb/command/upto.py +new file mode 100644 +index 0000000..faf54ed +--- /dev/null ++++ b/gdb/python/lib/gdb/command/upto.py +@@ -0,0 +1,129 @@ ++# upto command. ++ ++# Copyright (C) 2009 Free Software Foundation, Inc. ++ ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++ ++import gdb ++import re ++from gdb.FrameIterator import FrameIterator ++from gdb.FrameWrapper import FrameWrapper ++ ++class UptoPrefix (gdb.Command): ++ def __init__ (self): ++ super (UptoPrefix, self).__init__ ("upto", gdb.COMMAND_STACK, ++ prefix = True) ++ ++class UptoImplementation (gdb.Command): ++ def __init__ (self, subcommand): ++ super (UptoImplementation, self).__init__ ("upto " + subcommand, ++ gdb.COMMAND_STACK) ++ ++ def search (self): ++ saved = gdb.selected_frame () ++ iter = FrameIterator (saved) ++ found = False ++ try: ++ for frame in iter: ++ frame.select () ++ try: ++ if self.filter (frame): ++ wrapper = FrameWrapper (frame) ++ wrapper.describe (sys.stdout, False) ++ return ++ except: ++ pass ++ except: ++ pass ++ saved.select () ++ raise RuntimeError, 'Could not find a matching frame' ++ ++ def invoke (self, arg, from_tty): ++ self.rx = re.compile (arg) ++ self.search () ++ ++class UptoSymbolCommand (UptoImplementation): ++ """Select and print some calling stack frame, based on symbol. ++The argument is a regular expression. This command moves up the ++stack, stopping at the first frame whose symbol matches the regular ++expression.""" ++ ++ def __init__ (self): ++ super (UptoSymbolCommand, self).__init__ ("symbol") ++ ++ def filter (self, frame): ++ name = frame.name () ++ if name is not None: ++ if self.rx.search (name) is not None: ++ return True ++ return False ++ ++class UptoSourceCommand (UptoImplementation): ++ """Select and print some calling stack frame, based on source file. ++The argument is a regular expression. This command moves up the ++stack, stopping at the first frame whose source file name matches the ++regular expression.""" ++ ++ def __init__ (self): ++ super (UptoSourceCommand, self).__init__ ("source") ++ ++ def filter (self, frame): ++ name = frame.find_sal ().symtab.filename ++ if name is not None: ++ if self.rx.search (name) is not None: ++ return True ++ return False ++ ++class UptoObjectCommand (UptoImplementation): ++ """Select and print some calling stack frame, based on object file. ++The argument is a regular expression. This command moves up the ++stack, stopping at the first frame whose object file name matches the ++regular expression.""" ++ ++ def __init__ (self): ++ super (UptoObjectCommand, self).__init__ ("object") ++ ++ def filter (self, frame): ++ name = frame.find_sal ().symtab.objfile.filename ++ if name is not None: ++ if self.rx.search (name) is not None: ++ return True ++ return False ++ ++class UptoWhereCommand (UptoImplementation): ++ """Select and print some calling stack frame, based on expression. ++The argument is an expression. This command moves up the stack, ++parsing and evaluating the expression in each frame. This stops when ++the expression evaluates to a non-zero (true) value.""" ++ ++ def __init__ (self): ++ super (UptoWhereCommand, self).__init__ ("where") ++ ++ def filter (self, frame): ++ try: ++ if gdb.parse_and_eval (self.expression): ++ return True ++ except: ++ pass ++ return False ++ ++ def invoke (self, arg, from_tty): ++ self.expression = arg ++ self.search () ++ ++UptoPrefix () ++UptoSymbolCommand () ++UptoSourceCommand () ++UptoObjectCommand () ++UptoWhereCommand () +diff --git a/gdb/python/lib/gdb/function/__init__.py b/gdb/python/lib/gdb/function/__init__.py +new file mode 100644 +index 0000000..8b13789 +--- /dev/null ++++ b/gdb/python/lib/gdb/function/__init__.py +@@ -0,0 +1 @@ ++ +diff --git a/gdb/python/lib/gdb/function/caller_is.py b/gdb/python/lib/gdb/function/caller_is.py +new file mode 100644 +index 0000000..2b9c5c7 +--- /dev/null ++++ b/gdb/python/lib/gdb/function/caller_is.py +@@ -0,0 +1,58 @@ ++# Caller-is functions. ++ ++# Copyright (C) 2008 Free Software Foundation, Inc. ++ ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++ ++import gdb ++import re ++ ++class CallerIs (gdb.Function): ++ """Return True if the calling function's name is equal to a string. ++This function takes one or two arguments. ++The first argument is the name of a function; if the calling function's ++name is equal to this argument, this function returns True. ++The optional second argument tells this function how many stack frames ++to traverse to find the calling function. The default is 1.""" ++ ++ def __init__ (self): ++ super (CallerIs, self).__init__ ("caller_is") ++ ++ def invoke (self, name, nframes = 1): ++ frame = gdb.selected_frame () ++ while nframes > 0: ++ frame = frame.older () ++ nframes = nframes - 1 ++ return frame.name () == name.string () ++ ++class CallerMatches (gdb.Function): ++ """Return True if the calling function's name matches a string. ++This function takes one or two arguments. ++The first argument is a regular expression; if the calling function's ++name is matched by this argument, this function returns True. ++The optional second argument tells this function how many stack frames ++to traverse to find the calling function. The default is 1.""" ++ ++ def __init__ (self): ++ super (CallerMatches, self).__init__ ("caller_matches") ++ ++ def invoke (self, name, nframes = 1): ++ frame = gdb.selected_frame () ++ while nframes > 0: ++ frame = frame.older () ++ nframes = nframes - 1 ++ return re.match (name.string (), frame.name ()) is not None ++ ++CallerIs() ++CallerMatches() +diff --git a/gdb/python/lib/gdb/function/in_scope.py b/gdb/python/lib/gdb/function/in_scope.py +new file mode 100644 +index 0000000..debb3bb +--- /dev/null ++++ b/gdb/python/lib/gdb/function/in_scope.py +@@ -0,0 +1,47 @@ ++# In-scope function. ++ ++# Copyright (C) 2008 Free Software Foundation, Inc. ++ ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++ ++import gdb ++ ++class InScope (gdb.Function): ++ """Return True if all the given variables or macros are in scope. ++Takes one argument for each variable name to be checked.""" ++ ++ def __init__ (self): ++ super (InScope, self).__init__ ("in_scope") ++ ++ def invoke (self, *vars): ++ if len (vars) == 0: ++ raise TypeError, "in_scope takes at least one argument" ++ ++ # gdb.Value isn't hashable so it can't be put in a map. ++ # Convert to string first. ++ wanted = set (map (lambda x: x.string (), vars)) ++ found = set () ++ block = gdb.selected_frame ().block () ++ while block: ++ for sym in block: ++ if (sym.is_argument or sym.is_constant ++ or sym.is_function or sym.is_variable): ++ if sym.name in wanted: ++ found.add (sym.name) ++ ++ block = block.superblock ++ ++ return wanted == found ++ ++InScope () +diff --git a/gdb/python/py-cmd.c b/gdb/python/py-cmd.c +index 2cff4ba..9255336 100644 +--- a/gdb/python/py-cmd.c ++++ b/gdb/python/py-cmd.c +@@ -49,8 +49,7 @@ static struct cmdpy_completer completers[] = + + #define N_COMPLETERS (sizeof (completers) / sizeof (completers[0])) + +-/* A gdb command. For the time being only ordinary commands (not +- set/show commands) are allowed. */ ++/* A gdb command. */ + struct cmdpy_object + { + PyObject_HEAD +diff --git a/gdb/python/py-hooks.c b/gdb/python/py-hooks.c +new file mode 100644 +index 0000000..a3140bc +--- /dev/null ++++ b/gdb/python/py-hooks.c +@@ -0,0 +1,50 @@ ++/* Notifications from gdb to Python ++ ++ Copyright (C) 2008 Free Software Foundation, Inc. ++ ++ This file is part of GDB. ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . */ ++ ++#include "defs.h" ++#include "cli/cli-decode.h" ++#include "charset.h" ++#include "python.h" ++#include "python-internal.h" ++#include "observer.h" ++ ++PyObject * ++gdbpy_get_hook_function (const char *name) ++{ ++ PyObject *hooks; ++ PyObject *result; ++ ++ if (! PyObject_HasAttrString (gdb_module, "hooks")) ++ return NULL; ++ hooks = PyObject_GetAttrString (gdb_module, "hooks"); ++ if (! hooks) ++ return NULL; ++ /* The cast is because the Python function doesn't declare const argument. ++ This is a problem in Python version 2.4, but not in 2.5. */ ++ if (! PyObject_HasAttrString (hooks, (char *) name)) ++ { ++ Py_DECREF (hooks); ++ return NULL; ++ } ++ /* The cast is because the Python function doesn't declare const argument. ++ This is a problem in Python version 2.4, but not in 2.5. */ ++ result = PyObject_GetAttrString (hooks, (char *) name); ++ Py_DECREF (hooks); ++ return result; ++} +diff --git a/gdb/python/py-membuf.c b/gdb/python/py-membuf.c +new file mode 100644 +index 0000000..7bc294c +--- /dev/null ++++ b/gdb/python/py-membuf.c +@@ -0,0 +1,268 @@ ++/* Python interface to the inferior memory. ++ ++ Copyright (C) 2008, 2009 Free Software Foundation, Inc. ++ ++ This file is part of GDB. ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . */ ++ ++#include "defs.h" ++#include "exceptions.h" ++#include "gdbcore.h" ++#include "python-internal.h" ++ ++typedef struct { ++ PyObject_HEAD ++ void *buffer; ++ ++ /* These are kept just for mbpy_str. */ ++ CORE_ADDR addr; ++ CORE_ADDR length; ++} membuf_object; ++ ++static PyTypeObject membuf_object_type; ++ ++/* Implementation of gdb.read_memory (address, length). ++ Returns a Python buffer object with LENGTH bytes of the inferior's memory ++ at ADDRESS. Both arguments are integers. */ ++ ++PyObject * ++gdbpy_read_memory (PyObject *self, PyObject *args) ++{ ++ int error = 0; ++ CORE_ADDR addr, length; ++ void *buffer = NULL; ++ membuf_object *membuf_obj; ++ PyObject *addr_obj, *length_obj; ++ struct cleanup *cleanups = NULL; ++ volatile struct gdb_exception except; ++ ++ if (! PyArg_ParseTuple (args, "OO", &addr_obj, &length_obj)) ++ return NULL; ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ if (!get_addr_from_python (addr_obj, &addr) ++ || !get_addr_from_python (length_obj, &length)) ++ { ++ error = 1; ++ break; ++ } ++ ++ buffer = xmalloc (length); ++ cleanups = make_cleanup (xfree, buffer); ++ ++ read_memory (addr, buffer, length); ++ } ++ GDB_PY_HANDLE_EXCEPTION (except); ++ ++ if (error) ++ return NULL; ++ ++ discard_cleanups (cleanups); ++ ++ membuf_obj = PyObject_New (membuf_object, &membuf_object_type); ++ if (membuf_obj == NULL) ++ { ++ xfree (buffer); ++ PyErr_SetString (PyExc_MemoryError, ++ "Could not allocate memory buffer object."); ++ return NULL; ++ } ++ ++ membuf_obj->buffer = buffer; ++ membuf_obj->addr = addr; ++ membuf_obj->length = length; ++ ++ return PyBuffer_FromReadWriteObject ((PyObject *) membuf_obj, 0, ++ Py_END_OF_BUFFER); ++} ++ ++/* Implementation of gdb.write_memory (address, buffer [, length]). ++ Writes the contents of BUFFER (a Python object supporting the read buffer ++ protocol) at ADDRESS in the inferior's memory. Write LENGTH bytes from ++ BUFFER, or its entire contents if the argument is not provided. The ++ function returns nothing. */ ++ ++PyObject * ++gdbpy_write_memory (PyObject *self, PyObject *args) ++{ ++ int buf_len, error = 0; ++ const char *buffer; ++ CORE_ADDR addr, length; ++ PyObject *addr_obj, *length_obj = NULL; ++ volatile struct gdb_exception except; ++ ++ if (! PyArg_ParseTuple (args, "Os#|O", &addr_obj, &buffer, &buf_len, ++ &length_obj)) ++ return NULL; ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ if (!get_addr_from_python (addr_obj, &addr)) ++ { ++ error = 1; ++ break; ++ } ++ ++ if (!length_obj) ++ length = buf_len; ++ else if (!get_addr_from_python (length_obj, &length)) ++ { ++ error = 1; ++ break; ++ } ++ ++ write_memory (addr, buffer, length); ++ } ++ GDB_PY_HANDLE_EXCEPTION (except); ++ ++ if (error) ++ return NULL; ++ ++ Py_RETURN_NONE; ++} ++ ++/* Destructor of Membuf objects. */ ++ ++static void ++mbpy_dealloc (PyObject *self) ++{ ++ xfree (((membuf_object *) self)->buffer); ++ self->ob_type->tp_free (self); ++} ++ ++/* Return a description of the Membuf object. */ ++ ++static PyObject * ++mbpy_str (PyObject *self) ++{ ++ membuf_object *membuf_obj = (membuf_object *) self; ++ ++ return PyString_FromFormat ("memory buffer for address %s, %s bytes long", ++ paddress (membuf_obj->addr), ++ pulongest (membuf_obj->length)); ++} ++ ++static Py_ssize_t ++get_read_buffer (PyObject *self, Py_ssize_t segment, void **ptrptr) ++{ ++ membuf_object *membuf_obj = (membuf_object *) self; ++ ++ if (segment) ++ { ++ PyErr_SetString (PyExc_SystemError, ++ "The memory buffer supports only one segment."); ++ return -1; ++ } ++ ++ *ptrptr = membuf_obj->buffer; ++ ++ return membuf_obj->length; ++} ++ ++static Py_ssize_t ++get_write_buffer (PyObject *self, Py_ssize_t segment, void **ptrptr) ++{ ++ return get_read_buffer (self, segment, ptrptr); ++} ++ ++static Py_ssize_t ++get_seg_count (PyObject *self, Py_ssize_t *lenp) ++{ ++ if (lenp) ++ *lenp = ((membuf_object *) self)->length; ++ ++ return 1; ++} ++ ++static Py_ssize_t ++get_char_buffer (PyObject *self, Py_ssize_t segment, char **ptrptr) ++{ ++ void *ptr = NULL; ++ Py_ssize_t ret; ++ ++ ret = get_read_buffer (self, segment, &ptr); ++ *ptrptr = (char *) ptr; ++ ++ return ret; ++} ++ ++/* Python doesn't provide a decent way to get compatibility here. */ ++#if HAVE_LIBPYTHON2_4 ++#define CHARBUFFERPROC_NAME getcharbufferproc ++#else ++#define CHARBUFFERPROC_NAME charbufferproc ++#endif ++ ++static PyBufferProcs buffer_procs = { ++ get_read_buffer, ++ get_write_buffer, ++ get_seg_count, ++ /* The cast here works around a difference between Python 2.4 and ++ Python 2.5. */ ++ (CHARBUFFERPROC_NAME) get_char_buffer ++}; ++ ++static PyTypeObject membuf_object_type = { ++ PyObject_HEAD_INIT (NULL) ++ 0, /*ob_size*/ ++ "gdb.Membuf", /*tp_name*/ ++ sizeof (membuf_object), /*tp_basicsize*/ ++ 0, /*tp_itemsize*/ ++ mbpy_dealloc, /*tp_dealloc*/ ++ 0, /*tp_print*/ ++ 0, /*tp_getattr*/ ++ 0, /*tp_setattr*/ ++ 0, /*tp_compare*/ ++ 0, /*tp_repr*/ ++ 0, /*tp_as_number*/ ++ 0, /*tp_as_sequence*/ ++ 0, /*tp_as_mapping*/ ++ 0, /*tp_hash */ ++ 0, /*tp_call*/ ++ mbpy_str, /*tp_str*/ ++ 0, /*tp_getattro*/ ++ 0, /*tp_setattro*/ ++ &buffer_procs, /*tp_as_buffer*/ ++ Py_TPFLAGS_DEFAULT, /*tp_flags*/ ++ "GDB memory buffer object", /*tp_doc*/ ++ 0, /* tp_traverse */ ++ 0, /* tp_clear */ ++ 0, /* tp_richcompare */ ++ 0, /* tp_weaklistoffset */ ++ 0, /* tp_iter */ ++ 0, /* tp_iternext */ ++ 0, /* tp_methods */ ++ 0, /* tp_members */ ++ 0, /* tp_getset */ ++ 0, /* tp_base */ ++ 0, /* tp_dict */ ++ 0, /* tp_descr_get */ ++ 0, /* tp_descr_set */ ++ 0, /* tp_dictoffset */ ++ 0, /* tp_init */ ++ 0, /* tp_alloc */ ++ PyType_GenericNew /* tp_new */ ++}; ++ ++void ++gdbpy_initialize_membuf (void) ++{ ++ if (PyType_Ready (&membuf_object_type) < 0) ++ return; ++ ++ Py_INCREF (&membuf_object_type); ++ PyModule_AddObject (gdb_module, "Membuf", (PyObject *) &membuf_object_type); ++} +diff --git a/gdb/python/py-prettyprint.c b/gdb/python/py-prettyprint.c +index 434c8a5..b22c557 100644 +--- a/gdb/python/py-prettyprint.c ++++ b/gdb/python/py-prettyprint.c +@@ -204,10 +204,10 @@ pretty_print_one_value (PyObject *printer, struct value **out_value) + && result != Py_None) + { + *out_value = convert_value_from_python (result); +- if (PyErr_Occurred ()) +- *out_value = NULL; +- Py_DECREF (result); +- result = NULL; ++ if (PyErr_Occurred ()) ++ *out_value = NULL; ++ Py_DECREF (result); ++ result = NULL; + } + } + } +@@ -700,14 +700,7 @@ gdbpy_get_varobj_pretty_printer (struct value *value) + { + PyObject *val_obj; + PyObject *pretty_printer = NULL; +- volatile struct gdb_exception except; + +- TRY_CATCH (except, RETURN_MASK_ALL) +- { +- value = value_copy (value); +- } +- GDB_PY_HANDLE_EXCEPTION (except); +- + val_obj = value_to_value_object (value); + if (! val_obj) + return NULL; diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c index b901255..4ff18e5 100644 --- a/gdb/python/py-type.c @@ -5957,6 +10263,440 @@ index 2024021..e8be12d 100644 } +diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h +index 2b8d301..0af99c8 100644 +--- a/gdb/python/python-internal.h ++++ b/gdb/python/python-internal.h +@@ -82,10 +82,11 @@ struct language_defn; + struct program_space; + + extern PyObject *gdb_module; +-extern PyTypeObject value_object_type; + extern PyTypeObject block_object_type; ++extern PyTypeObject value_object_type; + extern PyTypeObject symbol_object_type; + ++/* Used in python-inferior.c. */ + typedef struct + { + PyObject_HEAD +@@ -126,6 +127,10 @@ PyObject *block_to_block_object (struct block *block, struct objfile *objfile); + PyObject *value_to_value_object (struct value *v); + PyObject *type_to_type_object (struct type *); + PyObject *frame_info_to_frame_object (struct frame_info *frame); ++PyObject *frame_info_to_frame_object (struct frame_info *frame); ++thread_object *create_thread_object (struct thread_info *tp); ++thread_object *find_thread_object (ptid_t ptid); ++PyObject *find_inferior_object (int pid); + + PyObject *pspace_to_pspace_object (struct program_space *); + PyObject *pspy_get_printers (PyObject *, void *); +@@ -145,8 +150,11 @@ struct type *type_object_to_type (PyObject *obj); + struct symtab *symtab_object_to_symtab (PyObject *obj); + struct symtab_and_line *sal_object_to_symtab_and_line (PyObject *obj); + ++PyObject *gdbpy_get_hook_function (const char *); + void gdbpy_initialize_auto_load (void); ++ + void gdbpy_initialize_values (void); ++void gdbpy_initialize_breakpoints (void); + void gdbpy_initialize_frames (void); + void gdbpy_initialize_symtabs (void); + void gdbpy_initialize_commands (void); +@@ -154,6 +162,7 @@ void gdbpy_initialize_symbols (void); + void gdbpy_initialize_symtabs (void); + void gdbpy_initialize_blocks (void); + void gdbpy_initialize_types (void); ++void gdbpy_initialize_blocks (void); + void gdbpy_initialize_functions (void); + void gdbpy_initialize_pspace (void); + void gdbpy_initialize_objfile (void); +@@ -171,6 +180,12 @@ struct cleanup *ensure_python_env (struct gdbarch *gdbarch, + extern struct gdbarch *python_gdbarch; + extern const struct language_defn *python_language; + ++char *gdbpy_parse_command_name (char *text, ++ struct cmd_list_element ***base_list, ++ struct cmd_list_element **start_list); ++ ++PyObject *gdbpy_parameter_value (enum var_types, void *); ++ + /* Use this after a TRY_EXCEPT to throw the appropriate Python + exception. */ + #define GDB_PY_HANDLE_EXCEPTION(Exception) \ +@@ -221,13 +236,14 @@ int gdbpy_is_value_object (PyObject *obj); + PyObject *apply_varobj_pretty_printer (PyObject *print_obj, + struct value **replacement); + PyObject *gdbpy_get_varobj_pretty_printer (struct value *value); ++PyObject *gdbpy_instantiate_printer (PyObject *cons, PyObject *value); + char *gdbpy_get_display_hint (PyObject *printer); + PyObject *gdbpy_default_visualizer (PyObject *self, PyObject *args); + +-extern PyObject *gdbpy_doc_cst; + extern PyObject *gdbpy_children_cst; + extern PyObject *gdbpy_to_string_cst; + extern PyObject *gdbpy_display_hint_cst; ++extern PyObject *gdbpy_doc_cst; + extern PyObject *gdbpy_enabled_cst; + + extern PyObject *gdbpy_gdberror_exc; +diff --git a/gdb/python/python.c b/gdb/python/python.c +index 6680126..2eee31f 100644 +--- a/gdb/python/python.c ++++ b/gdb/python/python.c +@@ -28,6 +28,7 @@ + #include "value.h" + #include "language.h" + #include "exceptions.h" ++#include "event-loop.h" + + #include + +@@ -42,10 +43,17 @@ static int gdbpy_should_print_stack = 1; + #include "cli/cli-decode.h" + #include "charset.h" + #include "top.h" ++#include "solib.h" + #include "python-internal.h" ++#include "linespec.h" ++#include "symtab.h" ++#include "source.h" + #include "version.h" ++#include "inferior.h" ++#include "gdbthread.h" + #include "target.h" + #include "gdbthread.h" ++#include "event-top.h" + + static PyMethodDef GdbMethods[]; + +@@ -413,6 +421,105 @@ execute_gdb_command (PyObject *self, PyObject *args, PyObject *kw) + Py_RETURN_NONE; + } + ++/* Implementation of gdb.solib_address (Long) -> String. ++ Returns the name of the shared library holding a given address, or None. */ ++ ++static PyObject * ++gdbpy_solib_address (PyObject *self, PyObject *args) ++{ ++ unsigned long long pc; ++ char *soname; ++ PyObject *str_obj; ++ ++ if (!PyArg_ParseTuple (args, "K", &pc)) ++ return NULL; ++ ++ soname = solib_name_from_address (current_program_space, pc); ++ if (soname) ++ str_obj = PyString_Decode (soname, strlen (soname), host_charset (), NULL); ++ else ++ { ++ str_obj = Py_None; ++ Py_INCREF (Py_None); ++ } ++ ++ return str_obj; ++} ++ ++/* A Python function which is a wrapper for decode_line_1. */ ++ ++static PyObject * ++gdbpy_decode_line (PyObject *self, PyObject *args) ++{ ++ struct symtabs_and_lines sals = { NULL, 0 }; /* Initialize to appease gcc. */ ++ struct symtab_and_line sal; ++ char *arg = NULL; ++ int free_sals = 0, i; ++ PyObject *result = NULL; ++ volatile struct gdb_exception except; ++ ++ if (! PyArg_ParseTuple (args, "|s", &arg)) ++ return NULL; ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ if (arg) ++ { ++ char *copy; ++ ++ arg = strdup (arg); ++ copy = arg; ++ ++ sals = decode_line_1 (©, 0, 0, 0, 0, 0); ++ free_sals = 1; ++ } ++ else ++ { ++ set_default_source_symtab_and_line (); ++ sal = get_current_source_symtab_and_line (); ++ sals.sals = &sal; ++ sals.nelts = 1; ++ } ++ } ++ if (arg) ++ xfree (arg); ++ ++ if (except.reason < 0) ++ { ++ if (free_sals) ++ xfree (sals.sals); ++ /* We know this will always throw. */ ++ GDB_PY_HANDLE_EXCEPTION (except); ++ } ++ ++ if (sals.nelts) ++ { ++ result = PyTuple_New (sals.nelts); ++ for (i = 0; i < sals.nelts; ++i) ++ { ++ PyObject *obj; ++ char *str; ++ ++ obj = symtab_and_line_to_sal_object (sals.sals[i]); ++ if (! obj) ++ { ++ Py_DECREF (result); ++ result = NULL; ++ break; ++ } ++ ++ PyTuple_SetItem (result, i, obj); ++ } ++ } ++ ++ if (free_sals) ++ xfree (sals.sals); ++ ++ if (result) ++ return result; ++ Py_RETURN_NONE; ++} ++ + /* Parse a string and evaluate it as an expression. */ + static PyObject * + gdbpy_parse_and_eval (PyObject *self, PyObject *args) +@@ -453,6 +560,114 @@ source_python_script (FILE *stream, const char *file) + + + ++/* Posting and handling events. */ ++ ++/* A single event. */ ++struct gdbpy_event ++{ ++ /* The Python event. This is just a callable object. */ ++ PyObject *event; ++ /* The next event. */ ++ struct gdbpy_event *next; ++}; ++ ++/* All pending events. */ ++static struct gdbpy_event *gdbpy_event_list; ++/* The final link of the event list. */ ++static struct gdbpy_event **gdbpy_event_list_end; ++ ++/* We use a file handler, and not an async handler, so that we can ++ wake up the main thread even when it is blocked in poll(). */ ++static int gdbpy_event_fds[2]; ++ ++/* The file handler callback. This reads from the internal pipe, and ++ then processes the Python event queue. This will always be run in ++ the main gdb thread. */ ++static void ++gdbpy_run_events (int err, gdb_client_data ignore) ++{ ++ struct cleanup *cleanup; ++ char buffer[100]; ++ int r; ++ ++ cleanup = ensure_python_env (get_current_arch (), current_language); ++ ++ /* Just read whatever is available on the fd. It is relatively ++ harmless if there are any bytes left over. */ ++ r = read (gdbpy_event_fds[0], buffer, sizeof (buffer)); ++ ++ while (gdbpy_event_list) ++ { ++ /* Dispatching the event might push a new element onto the event ++ loop, so we update here "atomically enough". */ ++ struct gdbpy_event *item = gdbpy_event_list; ++ gdbpy_event_list = gdbpy_event_list->next; ++ if (gdbpy_event_list == NULL) ++ gdbpy_event_list_end = &gdbpy_event_list; ++ ++ /* Ignore errors. */ ++ PyObject_CallObject (item->event, NULL); ++ ++ Py_DECREF (item->event); ++ xfree (item); ++ } ++ ++ do_cleanups (cleanup); ++} ++ ++/* Submit an event to the gdb thread. */ ++static PyObject * ++gdbpy_post_event (PyObject *self, PyObject *args) ++{ ++ struct gdbpy_event *event; ++ PyObject *func; ++ int wakeup; ++ ++ if (!PyArg_ParseTuple (args, "O", &func)) ++ return NULL; ++ ++ if (!PyCallable_Check (func)) ++ { ++ PyErr_SetString (PyExc_RuntimeError, "Posted event is not callable"); ++ return NULL; ++ } ++ ++ Py_INCREF (func); ++ ++ /* From here until the end of the function, we have the GIL, so we ++ can operate on our global data structures without worrying. */ ++ wakeup = gdbpy_event_list == NULL; ++ ++ event = XNEW (struct gdbpy_event); ++ event->event = func; ++ event->next = NULL; ++ *gdbpy_event_list_end = event; ++ gdbpy_event_list_end = &event->next; ++ ++ /* Wake up gdb when needed. */ ++ if (wakeup) ++ { ++ char c = 'q'; /* Anything. */ ++ if (write (gdbpy_event_fds[1], &c, 1) != 1) ++ return PyErr_SetFromErrno (PyExc_IOError); ++ } ++ ++ Py_RETURN_NONE; ++} ++ ++/* Initialize the Python event handler. */ ++static void ++gdbpy_initialize_events (void) ++{ ++ if (!pipe (gdbpy_event_fds)) ++ { ++ gdbpy_event_list_end = &gdbpy_event_list; ++ add_file_handler (gdbpy_event_fds[0], gdbpy_run_events, NULL); ++ } ++} ++ ++ ++ + /* Printing. */ + + /* A python function to write a single string using gdb's filtered +@@ -498,6 +713,53 @@ gdbpy_print_stack (void) + + /* Return the current Progspace. + There always is one. */ ++/* True if 'gdb -P' was used, false otherwise. */ ++static int running_python_script; ++ ++/* True if we are currently in a call to 'gdb.cli', false otherwise. */ ++static int in_cli; ++ ++/* Enter the command loop. */ ++ ++static PyObject * ++gdbpy_cli (PyObject *unused1, PyObject *unused2) ++{ ++ if (! running_python_script || in_cli) ++ return PyErr_Format (PyExc_RuntimeError, "cannot invoke CLI recursively"); ++ ++ in_cli = 1; ++ cli_command_loop (); ++ in_cli = 0; ++ ++ Py_RETURN_NONE; ++} ++ ++/* Set up the Python argument vector and evaluate a script. This is ++ used to implement 'gdb -P'. */ ++ ++void ++run_python_script (int argc, char **argv) ++{ ++ FILE *input; ++ ++ /* We never free this, since we plan to exit at the end. */ ++ ensure_python_env (get_current_arch (), current_language); ++ ++ running_python_script = 1; ++ PySys_SetArgv (argc - 1, argv + 1); ++ input = fopen (argv[0], "r"); ++ if (! input) ++ { ++ fprintf (stderr, "could not open %s: %s\n", argv[0], strerror (errno)); ++ exit (1); ++ } ++ PyRun_SimpleFile (input, argv[0]); ++ fclose (input); ++ exit (0); ++} ++ ++ ++ + + static PyObject * + gdbpy_get_current_progspace (PyObject *unused1, PyObject *unused2) +@@ -759,6 +1021,7 @@ Enables or disables printing of Python stack traces."), + gdbpy_initialize_lazy_string (); + gdbpy_initialize_thread (); + gdbpy_initialize_inferior (); ++ gdbpy_initialize_events (); + + PyRun_SimpleString ("import gdb"); + PyRun_SimpleString ("gdb.pretty_printers = []"); +@@ -826,6 +1089,8 @@ static PyMethodDef GdbMethods[] = + "Get a value from history" }, + { "execute", (PyCFunction) execute_gdb_command, METH_VARARGS | METH_KEYWORDS, + "Execute a gdb command" }, ++ { "cli", gdbpy_cli, METH_NOARGS, ++ "Enter the gdb CLI" }, + { "parameter", gdbpy_parameter, METH_VARARGS, + "Return a gdb parameter's value" }, + +@@ -864,11 +1129,21 @@ a boolean indicating if name is a field of the current implied argument\n\ + `this' (when the current language is object-oriented)." }, + { "block_for_pc", gdbpy_block_for_pc, METH_VARARGS, + "Return the block containing the given pc value, or None." }, ++ { "solib_address (Long) -> String.\n\ ++Return the name of the shared library holding a given address, or None." }, ++ ++ { "decode_line", gdbpy_decode_line, METH_VARARGS, ++ "Decode a string argument the way that 'break' or 'edit' does.\n\ ++Return a tuple holding the file name (or None) and line number (or None).\n\ ++Note: may later change to return an object." }, + { "parse_and_eval", gdbpy_parse_and_eval, METH_VARARGS, + "parse_and_eval (String) -> Value.\n\ + Parse String as an expression, evaluate it, and return the result as a Value." + }, + ++ { "post_event", gdbpy_post_event, METH_VARARGS, ++ "Post an event into gdb's event loop." }, ++ + { "target_charset", gdbpy_target_charset, METH_NOARGS, + "target_charset () -> string.\n\ + Return the name of the current target charset." }, +diff --git a/gdb/python/python.h b/gdb/python/python.h +index affd4a4..5407878 100644 +--- a/gdb/python/python.h ++++ b/gdb/python/python.h +@@ -28,6 +28,8 @@ void eval_python_from_control_command (struct command_line *); + + void source_python_script (FILE *stream, const char *file); + ++void run_python_script (int argc, char **argv); ++ + int apply_val_pretty_printer (struct type *type, const gdb_byte *valaddr, + int embedded_offset, CORE_ADDR address, + struct ui_file *stream, int recurse, diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c index 1f135d4..489838d 100644 --- a/gdb/solib-svr4.c @@ -5971,6 +10711,84 @@ index 1f135d4..489838d 100644 } /* Given an executable's ABFD and target, compute the entry-point +diff --git a/gdb/symfile.c b/gdb/symfile.c +index ab51fa4..babe9cf 100644 +--- a/gdb/symfile.c ++++ b/gdb/symfile.c +@@ -1059,6 +1059,9 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd, + const char *name = bfd_get_filename (abfd); + const int from_tty = add_flags & SYMFILE_VERBOSE; + ++ if (readnow_symbol_files) ++ flags |= OBJF_READNOW; ++ + my_cleanups = make_cleanup_bfd_close (abfd); + + /* Give user a chance to burp if we'd be +@@ -1095,7 +1098,7 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd, + the gdb startup command line or on a per symbol file basis. Expand + all partial symbol tables for this objfile if so. */ + +- if ((flags & OBJF_READNOW) || readnow_symbol_files) ++ if ((flags & OBJF_READNOW)) + { + if (from_tty || info_verbose) + { +@@ -1535,7 +1538,7 @@ symbol_file_command (char *args, int from_tty) + void + set_initial_language (void) + { +- char *filename; ++ const char *filename; + enum language lang = language_unknown; + + filename = find_main_filename (); +@@ -2662,7 +2665,7 @@ init_filename_language_table (void) + } + + enum language +-deduce_language_from_filename (char *filename) ++deduce_language_from_filename (const char *filename) + { + int i; + char *cp; +diff --git a/gdb/symfile.h b/gdb/symfile.h +index d53c465..5815354 100644 +--- a/gdb/symfile.h ++++ b/gdb/symfile.h +@@ -171,6 +171,15 @@ struct quick_symbol_functions + int kind, const char *name, + domain_enum domain); + ++ /* This is called to expand symbol tables before looking up a ++ symbol. A backend can choose to implement this and then have its ++ `lookup_symbol' hook always return NULL, or the reverse. (It ++ doesn't make sense to implement both.) The arguments are as for ++ `lookup_symbol'. */ ++ void (*pre_expand_symtabs_matching) (struct objfile *objfile, ++ int kind, const char *name, ++ domain_enum domain); ++ + /* Print statistics about any indices loaded for OBJFILE. The + statistics should be printed to gdb_stdout. This is used for + "maint print statistics". */ +@@ -201,7 +210,7 @@ struct quick_symbol_functions + + /* Return the file name of the file holding the symbol in OBJFILE + named NAME. If no such symbol exists in OBJFILE, return NULL. */ +- char *(*find_symbol_file) (struct objfile *objfile, const char *name); ++ const char *(*find_symbol_file) (struct objfile *objfile, const char *name); + + /* This method is specific to Ada. It walks the partial symbol + tables of OBJFILE looking for a name match. WILD_MATCH and +@@ -566,6 +575,7 @@ extern struct cleanup *increment_reading_symtab (void); + + extern int dwarf2_has_info (struct objfile *); + ++extern int dwarf2_initialize_objfile (struct objfile *); + extern void dwarf2_build_psymtabs (struct objfile *); + extern void dwarf2_build_frame_info (struct objfile *); + diff --git a/gdb/symmisc.c b/gdb/symmisc.c index 62e6b97..00dc613 100644 --- a/gdb/symmisc.c @@ -5986,10 +10804,97 @@ index 62e6b97..00dc613 100644 ms_type = 'S'; break; diff --git a/gdb/symtab.c b/gdb/symtab.c -index 9472c24..561ee50 100644 +index 9472c24..c3b1792 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c -@@ -2914,7 +2914,7 @@ search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[], +@@ -1295,16 +1295,25 @@ lookup_symbol_aux_symtabs (int block_index, const char *name, + const struct block *block; + struct symtab *s; + +- ALL_PRIMARY_SYMTABS (objfile, s) ++ ALL_OBJFILES (objfile) + { +- bv = BLOCKVECTOR (s); +- block = BLOCKVECTOR_BLOCK (bv, block_index); +- sym = lookup_block_symbol (block, name, domain); +- if (sym) +- { +- block_found = block; +- return fixup_symbol_section (sym, objfile); +- } ++ if (objfile->sf) ++ objfile->sf->qf->pre_expand_symtabs_matching (objfile, ++ block_index, ++ name, domain); ++ ++ ALL_OBJFILE_SYMTABS (objfile, s) ++ if (s->primary) ++ { ++ bv = BLOCKVECTOR (s); ++ block = BLOCKVECTOR_BLOCK (bv, block_index); ++ sym = lookup_block_symbol (block, name, domain); ++ if (sym) ++ { ++ block_found = block; ++ return fixup_symbol_section (sym, objfile); ++ } ++ } + } + + return NULL; +@@ -1547,15 +1556,24 @@ basic_lookup_transparent_type (const char *name) + of the desired name as a global, then do psymtab-to-symtab + conversion on the fly and return the found symbol. */ + +- ALL_PRIMARY_SYMTABS (objfile, s) ++ ALL_OBJFILES (objfile) + { +- bv = BLOCKVECTOR (s); +- block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK); +- sym = lookup_block_symbol (block, name, STRUCT_DOMAIN); +- if (sym && !TYPE_IS_OPAQUE (SYMBOL_TYPE (sym))) +- { +- return SYMBOL_TYPE (sym); +- } ++ if (objfile->sf) ++ objfile->sf->qf->pre_expand_symtabs_matching (objfile, ++ GLOBAL_BLOCK, ++ name, STRUCT_DOMAIN); ++ ++ ALL_OBJFILE_SYMTABS (objfile, s) ++ if (s->primary) ++ { ++ bv = BLOCKVECTOR (s); ++ block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK); ++ sym = lookup_block_symbol (block, name, STRUCT_DOMAIN); ++ if (sym && !TYPE_IS_OPAQUE (SYMBOL_TYPE (sym))) ++ { ++ return SYMBOL_TYPE (sym); ++ } ++ } + } + + ALL_OBJFILES (objfile) +@@ -1599,14 +1617,16 @@ basic_lookup_transparent_type (const char *name) + /* FIXME: What about languages without main() or specially linked + executables that have no main() ? */ + +-char * ++const char * + find_main_filename (void) + { + struct objfile *objfile; +- char *result, *name = main_name (); ++ char *name = main_name (); + + ALL_OBJFILES (objfile) + { ++ const char *result; ++ + if (!objfile->sf) + continue; + result = objfile->sf->qf->find_symbol_file (objfile, name); +@@ -2914,7 +2934,7 @@ search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[], static enum minimal_symbol_type types3[] = {mst_file_data, mst_solib_trampoline, mst_abs, mst_unknown}; static enum minimal_symbol_type types4[] @@ -5999,7 +10904,7 @@ index 9472c24..561ee50 100644 enum minimal_symbol_type ourtype2; enum minimal_symbol_type ourtype3; diff --git a/gdb/symtab.h b/gdb/symtab.h -index bedc10a..f5ddcb1 100644 +index bedc10a..dc284e4 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -277,6 +277,9 @@ enum minimal_symbol_type @@ -6049,6 +10954,24 @@ index bedc10a..f5ddcb1 100644 extern struct minimal_symbol * lookup_minimal_symbol_and_objfile (const char *, struct objfile **); +@@ -1137,7 +1156,7 @@ extern char **make_source_files_completion_list (char *, char *); + + int matching_obj_sections (struct obj_section *, struct obj_section *); + +-extern char *find_main_filename (void); ++extern const char *find_main_filename (void); + + extern struct symtab *find_line_symtab (struct symtab *, int, int *, int *); + +@@ -1150,7 +1169,7 @@ extern void skip_prologue_sal (struct symtab_and_line *); + + extern void clear_symtab_users (void); + +-extern enum language deduce_language_from_filename (char *); ++extern enum language deduce_language_from_filename (const char *); + + /* symtab.c */ + diff --git a/gdb/target.c b/gdb/target.c index 862df4e..a8f1bdd 100644 --- a/gdb/target.c @@ -6109,7 +11032,7 @@ index 862df4e..a8f1bdd 100644 current_target.to_stopped_data_address = debug_to_stopped_data_address; current_target.to_watchpoint_addr_within_range = debug_to_watchpoint_addr_within_range; diff --git a/gdb/target.h b/gdb/target.h -index 3c8c017..e9503de 100644 +index 3c8c017..608a742 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -433,6 +433,7 @@ struct target_ops @@ -6136,6 +11059,25 @@ index 3c8c017..e9503de 100644 #define target_insert_hw_breakpoint(gdbarch, bp_tgt) \ (*current_target.to_insert_hw_breakpoint) (gdbarch, bp_tgt) +@@ -1369,6 +1379,18 @@ extern int target_search_memory (CORE_ADDR start_addr, + ULONGEST pattern_len, + CORE_ADDR *found_addrp); + ++/* Utility functions which can be used by search_memory implementations. */ ++ ++void allocate_pattern_buffer (char **pattern_bufp, char **pattern_buf_end, ++ ULONGEST *pattern_buf_size); ++ ++void increase_pattern_buffer (char **pattern_bufp, char **pattern_buf_end, ++ ULONGEST *pattern_buf_size, int val_bytes); ++ ++int search_memory (CORE_ADDR *start_addr, ULONGEST *search_space_len, ++ const char *pattern_buf, ULONGEST pattern_len, ++ CORE_ADDR *found_addr); ++ + /* Tracepoint-related operations. */ + + #define target_trace_init() \ diff --git a/gdb/testsuite/gdb.arch/x86_64-vla-pointer-foo.S b/gdb/testsuite/gdb.arch/x86_64-vla-pointer-foo.S new file mode 100644 index 0000000..83faaf6 @@ -9267,6 +14209,21 @@ index 0000000..226dc5d + h = 'h' + call foo (g, h) +end +diff --git a/gdb/testsuite/gdb.gdb/selftest.exp b/gdb/testsuite/gdb.gdb/selftest.exp +index 1aed252..593aa55 100644 +--- a/gdb/testsuite/gdb.gdb/selftest.exp ++++ b/gdb/testsuite/gdb.gdb/selftest.exp +@@ -92,6 +92,10 @@ proc do_steps_and_nexts {} { + set description "step over ttyarg initialization" + set command "step" + } ++ -re ".*python_script = 0.*$gdb_prompt $" { ++ set description "step over python_script initialization" ++ set command "step" ++ } + -re ".*pre_stat_chain = make_command_stats_cleanup.*$gdb_prompt $" { + set description "next over make_command_stats_cleanup and everything it calls" + set command "next" diff --git a/gdb/testsuite/gdb.java/jnpe.exp b/gdb/testsuite/gdb.java/jnpe.exp new file mode 100644 index 0000000..55aa80d @@ -9771,6 +14728,124 @@ index 0000000..295602d + s := 'test'#0'string'; + writeln(s); { set breakpoint 2 here } +end. +diff --git a/gdb/testsuite/gdb.python/py-cmd.exp b/gdb/testsuite/gdb.python/py-cmd.exp +index 0f250d2..84e5038 100644 +--- a/gdb/testsuite/gdb.python/py-cmd.exp ++++ b/gdb/testsuite/gdb.python/py-cmd.exp +@@ -20,24 +20,6 @@ if $tracelevel then { + strace $tracelevel + } + +-# Usage: gdb_py_test_multiple NAME INPUT RESULT {INPUT RESULT}... +-# Run a test named NAME, consisting of multiple lines of input. +-# After each input line INPUT, search for result line RESULT. +-# Succeed if all results are seen; fail otherwise. +-proc gdb_py_test_multiple {name args} { +- global gdb_prompt +- foreach {input result} $args { +- if {[gdb_test_multiple $input "$name - $input" { +- -re "\[\r\n\]*($result)\[\r\n\]+($gdb_prompt | *>)$" { +- pass "$name - $input" +- } +- }]} { +- return 1 +- } +- } +- return 0 +-} +- + # Start with a fresh gdb. + + gdb_exit +diff --git a/gdb/testsuite/gdb.python/py-frame.exp b/gdb/testsuite/gdb.python/py-frame.exp +index e1212d3..77f44f5 100644 +--- a/gdb/testsuite/gdb.python/py-frame.exp ++++ b/gdb/testsuite/gdb.python/py-frame.exp +@@ -89,8 +89,6 @@ gdb_py_test_silent_cmd "python f0 = f1.newer ()" "get first frame" 0 + + gdb_test "python print 'result =', f0 == f1" " = False" "test equality comparison (false)" + gdb_test "python print 'result =', f0 == f0" " = True" "test equality comparison (true)" +-gdb_test "python print 'result =', f0 != f1" " = True" "test inequality comparison (true)" +-gdb_test "python print 'result =', f0 != f0" " = False" "test inequality comparison (false)" + gdb_test "python print 'result =', f0.is_valid ()" " = True" "test Frame.is_valid" + gdb_test "python print 'result =', f0.name ()" " = f2" "test Frame.name" + gdb_test "python print 'result =', f0.type () == gdb.NORMAL_FRAME" " = True" "test Frame.type" +@@ -105,3 +103,5 @@ gdb_test "python print 'result =', f0.read_var ('variable_which_surely_doesnt_ex + gdb_test "python print 'result =', f0.read_var ('a')" " = 1" "test Frame.read_var - success" + + gdb_test "python print 'result =', gdb.selected_frame () == f1" " = True" "test gdb.selected_frame" ++ ++gdb_test "python print 'result =', f0.block ()" "" "test Frame.block" +diff --git a/gdb/testsuite/gdb.python/py-function.exp b/gdb/testsuite/gdb.python/py-function.exp +index 38c5693..e7f0037 100644 +--- a/gdb/testsuite/gdb.python/py-function.exp ++++ b/gdb/testsuite/gdb.python/py-function.exp +@@ -20,24 +20,6 @@ if $tracelevel then { + strace $tracelevel + } + +-# Usage: gdb_py_test_multiple NAME INPUT RESULT {INPUT RESULT}... +-# Run a test named NAME, consisting of multiple lines of input. +-# After each input line INPUT, search for result line RESULT. +-# Succeed if all results are seen; fail otherwise. +-proc gdb_py_test_multiple {name args} { +- global gdb_prompt +- foreach {input result} $args { +- if {[gdb_test_multiple $input "$name - $input" { +- -re "\[\r\n\]*($result)\[\r\n\]+($gdb_prompt | *>)$" { +- pass "$name - $input" +- } +- }]} { +- return 1 +- } +- } +- return 0 +-} +- + # Start with a fresh gdb. + + gdb_exit +diff --git a/gdb/testsuite/gdb.python/py-prettyprint.exp b/gdb/testsuite/gdb.python/py-prettyprint.exp +index 3b2aadd..03bbf3e 100644 +--- a/gdb/testsuite/gdb.python/py-prettyprint.exp ++++ b/gdb/testsuite/gdb.python/py-prettyprint.exp +@@ -102,6 +102,8 @@ proc run_lang_tests {lang} { + gdb_test "print estring" "\"embedded x\\\\201\\\\202\\\\203\\\\204\"" + gdb_test "print c" " = container \"container\" with 2 elements = {$nl *.0. = 23,$nl *.1. = 72$nl}" + ++ gdb_test "print nullstr" "RuntimeError: Error reading string from inferior.*" ++ + gdb_test "print nstype" " = {$nl *.0. = 7,$nl *.1. = 42$nl}" + gdb_test "continue" "Program exited normally\." + +diff --git a/gdb/testsuite/gdb.python/py-value.exp b/gdb/testsuite/gdb.python/py-value.exp +index a24bc11..e3043bc 100644 +--- a/gdb/testsuite/gdb.python/py-value.exp ++++ b/gdb/testsuite/gdb.python/py-value.exp +@@ -313,6 +313,15 @@ proc test_value_after_death {} { + "print value's type" + } + ++# Regression test for a cast failure. The bug was that if we cast a ++# value to its own type, gdb could crash. This happened because we ++# could end up double-freeing a struct value. ++proc test_cast_regression {} { ++ gdb_test "python v = gdb.Value(5)" "" "create value for cast test" ++ gdb_test "python v = v.cast(v.type)" "" "cast value for cast test" ++ gdb_test "python print v" "5" "print value for cast test" ++} ++ + # Regression test for invalid subscript operations. The bug was that + # the type of the value was not being checked before allowing a + # subscript operation to proceed. +@@ -437,6 +446,7 @@ if ![runto_main] then { + test_value_in_inferior + test_lazy_strings + test_value_after_death ++test_cast_regression + + # The following test recompiles the binary to test either C or C++ + # values. diff --git a/gdb/testsuite/gdb.threads/watchpoint-fork-forkoff.c b/gdb/testsuite/gdb.threads/watchpoint-fork-forkoff.c new file mode 100644 index 0000000..4dc308b @@ -10314,6 +15389,18 @@ index 0000000..1dc93ab +if {[istarget "*-*-linux*"]} { + test child FOLLOW_CHILD +} +diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp +index b5b3362..d916e94 100644 +--- a/gdb/testsuite/lib/gdb.exp ++++ b/gdb/testsuite/lib/gdb.exp +@@ -27,6 +27,7 @@ if {$tool == ""} { + } + + load_lib libgloss.exp ++load_lib python-support.exp + + global GDB + diff --git a/gdb/testsuite/lib/pascal.exp b/gdb/testsuite/lib/pascal.exp index 9691bc1..13ea8b5 100644 --- a/gdb/testsuite/lib/pascal.exp @@ -10349,6 +15436,65 @@ index 9691bc1..13ea8b5 100644 } set pascal_init_done 1 } +diff --git a/gdb/testsuite/lib/python-support.exp b/gdb/testsuite/lib/python-support.exp +new file mode 100644 +index 0000000..b8e9836 +--- /dev/null ++++ b/gdb/testsuite/lib/python-support.exp +@@ -0,0 +1,53 @@ ++global python_supported_saved ++ ++# Return 1 if Python scripting is supported in GDB, 0 if not. ++proc python_supported { } { ++ global gdb_prompt ++ global python_supported_saved ++ ++ if [info exists python_supported_saved] { ++ verbose "python_supported: returning saved $python_supported_saved" 2 ++ return $python_supported_saved ++ } ++ ++ gdb_test_multiple "python print 'hello, world!'" "verify python support" { ++ -re "not supported.*$gdb_prompt $" { ++ return [set python_supported_saved 0] ++ } ++ -re "$gdb_prompt $" { ++ return [set python_supported_saved 1] ++ } ++ } ++ ++ return [set python_supported_saved 0] ++} ++ ++# Run a command in GDB, and report a failure if a Python exception is thrown. ++# If report_pass is true, report a pass if no exception is thrown. ++proc gdb_py_test_silent_cmd {cmd name report_pass} { ++ global gdb_prompt ++ ++ gdb_test_multiple $cmd $name { ++ -re "Traceback.*$gdb_prompt $" { fail $name } ++ -re "$gdb_prompt $" { if $report_pass { pass $name } } ++ } ++} ++ ++# Usage: gdb_py_test_multiple NAME INPUT RESULT {INPUT RESULT}... ++# Run a test named NAME, consisting of multiple lines of input. ++# After each input line INPUT, search for result line RESULT. ++# Succeed if all results are seen; fail otherwise. ++proc gdb_py_test_multiple {name args} { ++ global gdb_prompt ++ ++ foreach {input result} $args { ++ if {[gdb_test_multiple $input "$name - $input" { ++ -re "\[\r\n\]*($result)\[\r\n\]+($gdb_prompt | *>)$" { ++ pass "$name - $input" ++ } ++ }]} { ++ return 1 ++ } ++ } ++ return 0 ++} diff --git a/gdb/thread.c b/gdb/thread.c index 2fdc7f9..2a5d0f1 100644 --- a/gdb/thread.c diff --git a/gdb-bz575292-delayed-physname.patch b/gdb-bz575292-delayed-physname.patch index 5e65974..e15391d 100644 --- a/gdb-bz575292-delayed-physname.patch +++ b/gdb-bz575292-delayed-physname.patch @@ -9,11 +9,11 @@ Neither its obstack-leak.patch nor http://sourceware.org/ml/gdb-patches/2010-05/msg00271.html is needed as the linked list is used instead. -Index: gdb-7.1.90.20100711/gdb/dwarf2read.c +Index: gdb-7.1.90.20100721/gdb/dwarf2read.c =================================================================== ---- gdb-7.1.90.20100711.orig/gdb/dwarf2read.c 2010-07-13 00:34:00.000000000 +0200 -+++ gdb-7.1.90.20100711/gdb/dwarf2read.c 2010-07-13 22:25:18.000000000 +0200 -@@ -216,6 +216,28 @@ struct comp_unit_head +--- gdb-7.1.90.20100721.orig/gdb/dwarf2read.c 2010-07-22 11:59:19.000000000 +0200 ++++ gdb-7.1.90.20100721/gdb/dwarf2read.c 2010-07-22 12:00:08.000000000 +0200 +@@ -253,6 +253,28 @@ struct comp_unit_head unsigned int first_die_offset; }; @@ -42,7 +42,7 @@ Index: gdb-7.1.90.20100711/gdb/dwarf2read.c /* Internal state when decoding a particular compilation unit. */ struct dwarf2_cu { -@@ -294,6 +316,10 @@ struct dwarf2_cu +@@ -331,6 +353,10 @@ struct dwarf2_cu /* Header data from the line table, during full symbol processing. */ struct line_header *line_header; @@ -53,17 +53,17 @@ Index: gdb-7.1.90.20100711/gdb/dwarf2read.c /* Mark used when releasing cached dies. */ unsigned int mark : 1; -@@ -1142,6 +1168,9 @@ static struct type *get_die_type (struct - static struct dwarf2_locexpr_baton *dwarf2_attr_to_locexpr_baton - (struct attribute *attr, struct dwarf2_cu *cu); +@@ -1239,6 +1265,9 @@ static gdb_byte *partial_read_comp_unit_ + static void init_cu_die_reader (struct die_reader_specs *reader, + struct dwarf2_cu *cu); +static const char *dwarf2_physname (char *name, struct die_info *die, + struct dwarf2_cu *cu); + - /* Try to locate the sections we need for DWARF 2 debugging - information and return true if we have enough to do something. */ + #if WORDS_BIGENDIAN -@@ -3137,6 +3166,58 @@ load_full_comp_unit (struct dwarf2_per_c + /* Convert VALUE between big- and little-endian. */ +@@ -4103,6 +4132,58 @@ load_full_comp_unit (struct dwarf2_per_c discard_cleanups (free_cu_cleanup); } @@ -122,8 +122,8 @@ Index: gdb-7.1.90.20100711/gdb/dwarf2read.c /* Generate full symbol information for PST and CU, whose DIEs have already been loaded into memory. */ -@@ -3148,7 +3229,7 @@ process_full_comp_unit (struct dwarf2_pe - struct objfile *objfile = pst->objfile; +@@ -4113,7 +4194,7 @@ process_full_comp_unit (struct dwarf2_pe + struct objfile *objfile = per_cu->objfile; CORE_ADDR lowpc, highpc; struct symtab *symtab; - struct cleanup *back_to; @@ -131,7 +131,7 @@ Index: gdb-7.1.90.20100711/gdb/dwarf2read.c CORE_ADDR baseaddr; baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); -@@ -3158,11 +3239,22 @@ process_full_comp_unit (struct dwarf2_pe +@@ -4123,11 +4204,22 @@ process_full_comp_unit (struct dwarf2_pe cu->list_in_scope = &file_symbols; @@ -154,7 +154,7 @@ Index: gdb-7.1.90.20100711/gdb/dwarf2read.c /* Some compilers don't define a DW_AT_high_pc attribute for the compilation unit. If the DW_AT_high_pc is missing, synthesize it, by scanning the DIE's below the compilation unit. */ -@@ -4854,7 +4946,6 @@ dwarf2_add_member_fn (struct field_info +@@ -5838,7 +5930,6 @@ dwarf2_add_member_fn (struct field_info int i; struct fn_field *fnp; char *fieldname; @@ -162,7 +162,7 @@ Index: gdb-7.1.90.20100711/gdb/dwarf2read.c struct nextfnfield *new_fnfield; struct type *this_type; -@@ -4866,9 +4957,6 @@ dwarf2_add_member_fn (struct field_info +@@ -5850,9 +5941,6 @@ dwarf2_add_member_fn (struct field_info if (fieldname == NULL) return; @@ -172,7 +172,7 @@ Index: gdb-7.1.90.20100711/gdb/dwarf2read.c /* Look up member function name in fieldlist. */ for (i = 0; i < fip->nfnfields; i++) { -@@ -4894,7 +4982,7 @@ dwarf2_add_member_fn (struct field_info +@@ -5878,7 +5966,7 @@ dwarf2_add_member_fn (struct field_info flp->name = fieldname; flp->length = 0; flp->head = NULL; @@ -181,7 +181,7 @@ Index: gdb-7.1.90.20100711/gdb/dwarf2read.c } /* Create a new member function field and chain it to the field list -@@ -4908,9 +4996,19 @@ dwarf2_add_member_fn (struct field_info +@@ -5892,9 +5980,19 @@ dwarf2_add_member_fn (struct field_info /* Fill in the member function field info. */ fnp = &new_fnfield->fnfield; @@ -204,7 +204,7 @@ Index: gdb-7.1.90.20100711/gdb/dwarf2read.c fnp->type = alloc_type (objfile); this_type = read_type_die (die, cu); if (this_type && TYPE_CODE (this_type) == TYPE_CODE_FUNC) -@@ -4936,7 +5034,7 @@ dwarf2_add_member_fn (struct field_info +@@ -5920,7 +6018,7 @@ dwarf2_add_member_fn (struct field_info } else complaint (&symfile_complaints, _("member function type missing for '%s'"), @@ -213,7 +213,7 @@ Index: gdb-7.1.90.20100711/gdb/dwarf2read.c /* Get fcontext from DW_AT_containing_type if present. */ if (dwarf2_attr (die, DW_AT_containing_type, cu) != NULL) -@@ -7315,7 +7413,9 @@ load_partial_dies (bfd *abfd, gdb_byte * +@@ -8299,7 +8397,9 @@ load_partial_dies (bfd *abfd, gdb_byte * || last_die->tag == DW_TAG_interface_type || last_die->tag == DW_TAG_structure_type || last_die->tag == DW_TAG_union_type)) @@ -224,10 +224,10 @@ Index: gdb-7.1.90.20100711/gdb/dwarf2read.c && (last_die->tag == DW_TAG_subprogram || last_die->tag == DW_TAG_lexical_block)))) { -Index: gdb-7.1.90.20100711/gdb/testsuite/gdb.dwarf2/pr11465.S +Index: gdb-7.1.90.20100721/gdb/testsuite/gdb.dwarf2/pr11465.S =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ gdb-7.1.90.20100711/gdb/testsuite/gdb.dwarf2/pr11465.S 2010-07-13 22:24:48.000000000 +0200 ++++ gdb-7.1.90.20100721/gdb/testsuite/gdb.dwarf2/pr11465.S 2010-07-22 11:59:29.000000000 +0200 @@ -0,0 +1,355 @@ +/* Copyright 2010 Free Software Foundation, Inc. + @@ -584,10 +584,10 @@ Index: gdb-7.1.90.20100711/gdb/testsuite/gdb.dwarf2/pr11465.S +.LASF4: + .string "GNU C++ 4.4.2" + .ident "GCC: (GNU) 4.4.2" -Index: gdb-7.1.90.20100711/gdb/testsuite/gdb.dwarf2/pr11465.exp +Index: gdb-7.1.90.20100721/gdb/testsuite/gdb.dwarf2/pr11465.exp =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ gdb-7.1.90.20100711/gdb/testsuite/gdb.dwarf2/pr11465.exp 2010-07-13 22:24:48.000000000 +0200 ++++ gdb-7.1.90.20100721/gdb/testsuite/gdb.dwarf2/pr11465.exp 2010-07-22 11:59:29.000000000 +0200 @@ -0,0 +1,39 @@ +# Copyright 2010 Free Software Foundation, Inc. + diff --git a/gdb-gdb-add-index-script.patch b/gdb-gdb-add-index-script.patch new file mode 100644 index 0000000..a22e37d --- /dev/null +++ b/gdb-gdb-add-index-script.patch @@ -0,0 +1,119 @@ +http://sourceware.org/ml/gdb-patches/2010-07/msg00184.html +Subject: Re: [0/4] RFC: add DWARF index support + +>>>>> "Tom" == Tom Tromey writes: + +Tom> This patch series adds support for a DWARF index to gdb. + +Roland suggested we wrap up the index-creation code into a helper +script. + +I'm not sure if this is something people would want in gdb proper, but I +figured I would send it here just in case. + +Tom + +2010-07-09 Tom Tromey + + * Makefile.in (install-only): Install gdb-add-index. + * gdb-add-index: New file. + +2010-07-09 Tom Tromey + + * gdb.texinfo (Index Files): Mention gdb-add-index. + +>From 30714fe719e61baea03d0dc5793eb0d564faebb7 Mon Sep 17 00:00:00 2001 +From: Tom Tromey +Date: Fri, 9 Jul 2010 11:17:54 -0600 +Subject: [PATCH 4/4] add gdb-add-index +Subject: [PATCH 4/4] add gdb-add-index + +--- + gdb/ChangeLog | 5 +++++ + gdb/Makefile.in | 11 ++++++++++- + gdb/doc/ChangeLog | 4 ++++ + gdb/doc/gdb.texinfo | 8 ++++++++ + gdb/gdb-add-index | 30 ++++++++++++++++++++++++++++++ + 5 files changed, 57 insertions(+), 1 deletions(-) + create mode 100755 gdb/gdb-add-index + +diff --git a/gdb/Makefile.in b/gdb/Makefile.in +index 6dbb284..8210a2c 100644 +--- a/gdb/Makefile.in ++++ b/gdb/Makefile.in +@@ -1018,7 +1018,16 @@ install-only: $(CONFIG_INSTALL) xml-syscall-install + $(SHELL) $(srcdir)/../mkinstalldirs \ + $(DESTDIR)$(man1dir) ; \ + $(INSTALL_DATA) $(srcdir)/gdb.1 \ +- $(DESTDIR)$(man1dir)/$$transformed_name.1 ++ $(DESTDIR)$(man1dir)/$$transformed_name.1; \ ++ transformed_name=`t='$(program_transform_name)'; \ ++ echo gdb-add-index | sed -e "$$t"` ; \ ++ if test "x$$transformed_name" = x; then \ ++ transformed_name=gdb-add-index ; \ ++ else \ ++ true ; \ ++ fi ; \ ++ $(INSTALL_PROGRAM) $(srcdir)/gdb-add-index \ ++ $(DESTDIR)$(bindir)/$$transformed_name$(EXEEXT) + @$(MAKE) DO=install "DODIRS=$(SUBDIRS)" $(FLAGS_TO_PASS) subdir_do + .PHONY: install-tui + install-tui: +diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo +index 69141e3..457e6b4 100644 +--- a/gdb/doc/gdb.texinfo ++++ b/gdb/doc/gdb.texinfo +@@ -15045,6 +15045,14 @@ There are currently some limitation on indices. They only work when + for DWARF debugging information, not stabs. And, they do not + currently work for programs using Ada. + ++@value{GDBN} comes with a program, @command{gdb-add-index}, which can ++be used to add the index to a symbol file. It takes the symbol file ++as its only argument: ++ ++@smallexample ++$ gdb-add-index symfile ++@end smallexample ++ + + @node Symbol Errors + @section Errors Reading Symbol Files +diff --git a/gdb/gdb-add-index b/gdb/gdb-add-index +new file mode 100755 +index 0000000..c9a03b0 +--- /dev/null ++++ b/gdb/gdb-add-index +@@ -0,0 +1,30 @@ ++#! /bin/sh ++ ++# Add a .gdb_index section to a file. ++ ++# Copyright (C) 2010 Free Software Foundation, Inc. ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++ ++file="$1" ++dir="${file%/*}" ++ ++# We don't care if gdb gives an error. ++gdb --batch-silent -ex "file $file" -ex "save gdb-index $d" > /dev/null 2>&1 ++ ++if test -f "${file}.gdb-index"; then ++ objcopy --add-section .gdb_index="${file}.gdb-index" --set-section-flags .gdb_index=readonly "$file" "$file" ++ rm -f "${file}.gdb-index" ++fi ++ ++exit 0 +-- +1.6.2.5 + diff --git a/gdb.spec b/gdb.spec index d4ecc0b..6ccb22f 100644 --- a/gdb.spec +++ b/gdb.spec @@ -36,7 +36,7 @@ Version: 7.1.90.20100721 # The release always contains a leading reserved number, start it at 1. # `upstream' is not a part of `name' to stay fully rpm dependencies compatible for the testing. -Release: 3%{?_with_upstream:.upstream}%{dist} +Release: 4%{?_with_upstream:.upstream}%{dist} License: GPLv3+ and GPLv3+ with exceptions and GPLv2+ and GPLv2+ with exceptions and GPL+ and LGPLv2+ and GFDL and BSD and Public Domain Group: Development/Debuggers @@ -417,6 +417,9 @@ Patch487: gdb-bz562763-pretty-print-2d-vectors-libstdcxx.patch # Fix prelinked executables with sepdebug and copy relocations (BZ 614659). Patch489: gdb-bz614659-prelink-dynbss.patch +# Provide /usr/bin/gdb-add-index for rpm-build (Tom Tromey). +Patch491: gdb-gdb-add-index-script.patch + BuildRequires: ncurses-devel%{?_isa} texinfo gettext flex bison expat-devel%{?_isa} Requires: readline%{?_isa} BuildRequires: readline-devel%{?_isa} @@ -667,6 +670,7 @@ rm -f gdb/jv-exp.c gdb/m2-exp.c gdb/objc-exp.c gdb/p-exp.c #patch487 -p1 %patch415 -p1 %patch489 -p1 +%patch491 -p1 %patch393 -p1 %patch335 -p1 @@ -972,6 +976,7 @@ fi %{_mandir}/*/gstack.1* %if 0%{!?el5:1} %{_bindir}/pstack +%{_bindir}/gdb-add-index %{_mandir}/*/pstack.1* %endif # 0%{!?el5:1} %endif # 0%{!?_with_upstream:1} @@ -994,7 +999,12 @@ fi %endif %changelog -* Thu Jul 22 2010 David Malcolm - 7.1.90.20100721-3 +* Thu Jul 22 2010 Jan Kratochvil - 7.1.90.20100721-4.fc14 +- Import archer-tromey-python. +- Import archer-tromey-optional-psymtab (as present in FSF GDB post-7.2). + - Provide /usr/bin/gdb-add-index for rpm-build (Tom Tromey). + +* Thu Jul 22 2010 David Malcolm - 7.1.90.20100721-3.fc14 - Rebuilt for https://fedoraproject.org/wiki/Features/Python_2.7/MassRebuild * Wed Jul 21 2010 Jan Kratochvil - 7.1.90.20100721-2.fc14