diff options
author | nobody <> | 2002-09-20 15:07:16 +0000 |
---|---|---|
committer | nobody <> | 2002-09-20 15:07:16 +0000 |
commit | 9dcc0b141cc6b94354177de13359f44691713b19 (patch) | |
tree | 4bf74b436a04aab8dafb5645a95ce289fc8c3173 | |
parent | 148ea30ef6e624235f31f27ee7a285c7529eb68a (diff) | |
download | gdb-9dcc0b141cc6b94354177de13359f44691713b19.zip gdb-9dcc0b141cc6b94354177de13359f44691713b19.tar.gz gdb-9dcc0b141cc6b94354177de13359f44691713b19.tar.bz2 |
This commit was manufactured by cvs2svn to create branch
'carlton_dictionary-branch'.
Cherrypick from master 2002-09-20 15:07:15 UTC Fernando Nasser <fnasser@redhat.com> ' From 2002-07-02 George Helffrich <george@gly.bris.ac.uk>':
gdb/ChangeLog
gdb/Makefile.in
gdb/ada-lang.c
gdb/c-lang.c
gdb/dbxread.c
gdb/mdebugread.c
gdb/symfile.c
gdb/symtab.c
gdb/symtab.h
Cherrypick from gdb_5_3-branch 2002-09-03 22:29:15 UTC nobody 'This commit was manufactured by cvs2svn to create branch 'gdb_5_3-branch'.':
gdb/coffread.c
gdb/dwarf2read.c
gdb/dwarfread.c
gdb/hpread.c
gdb/symfile.h
gdb/xcoffread.c
-rw-r--r-- | gdb/ChangeLog | 11415 | ||||
-rw-r--r-- | gdb/Makefile.in | 2595 | ||||
-rw-r--r-- | gdb/ada-lang.c | 8311 | ||||
-rw-r--r-- | gdb/c-lang.c | 652 | ||||
-rw-r--r-- | gdb/coffread.c | 2166 | ||||
-rw-r--r-- | gdb/dbxread.c | 3599 | ||||
-rw-r--r-- | gdb/dwarf2read.c | 6938 | ||||
-rw-r--r-- | gdb/dwarfread.c | 3788 | ||||
-rw-r--r-- | gdb/hpread.c | 6310 | ||||
-rw-r--r-- | gdb/mdebugread.c | 5021 | ||||
-rw-r--r-- | gdb/symfile.c | 3340 | ||||
-rw-r--r-- | gdb/symfile.h | 328 | ||||
-rw-r--r-- | gdb/symtab.c | 4063 | ||||
-rw-r--r-- | gdb/symtab.h | 1414 | ||||
-rw-r--r-- | gdb/xcoffread.c | 3049 |
15 files changed, 62989 insertions, 0 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog new file mode 100644 index 0000000..ec776f7 --- /dev/null +++ b/gdb/ChangeLog @@ -0,0 +1,11415 @@ +2002-09-20 Fernando Nasser <fnasser@redhat.com> + + From 2002-07-02 George Helffrich <george@gly.bris.ac.uk> + * cli/cli-cmds.c (list_command): New function. Implements the new + cli edit command. + (_init_cli_cmds): Add new command definition. + * gdb.1: Document edit command. + * doc/gdb.texinfo: Document edit command. + +2002-09-20 Fernando Nasser <fnasser@redhat.com> + + * source.c: Make global variables current_source_symtab and + current_source_line static. + (list_command): Moved to cli/cli-cmds.c. + (ambiguous_line_spec): Moved to cli/cli-cmds.c. + (get_first_line_listed): New accessor function. + (get_lines_to_list): New accessor function. + (get_current_source_symtab_and_line): New function. Retrieves the + position in the source code that we consider current. + (get_current_or_default_source_symtab_and_line): New function. + Like the above but attempts to determine a default position if one + is not currently defined. + (set_current_source_symtab_and_line): New function. Sets the source + code position considered current and returns the previously set one. + (clear_current_source_symtab_and_line): Reset stored information about + a current source line. + (_initialize_source): Remove registration for the "list" command and + its alias. + * source.h: Add declarations for the new functions above. + * symtab.h: Remove declarations for the global variables mentioned + above. + * breakpoint.c (parse_breakpoint_sals): Use accessor functions to + obtain current source line. + * linespec.c (decode_line_1): Ditto. + * macroscope.c (default_macro_scope): Ditto. + * scm-lang.c (scm_unpac): Ditto. + * stack.c (print_frame_info_base): Ditto. + * symfile.c (clear_symtab_users): Ditto. + * symtab.c (decode_line_spec): Ditto. + * cli/cli-cmds.c (list_command): Moved here from source.c. + (ambiguous_line_spec): Moved here from source.c. + (_init_cli_cmds): Add definition for "list" and its alias. + * Makefile.in: Update dependencies. + +2002-09-20 Corinna Vinschen <vinschen@redhat.com> + + * h8300-tdep.c (h8300_examine_prologue): Match saved regs location + with what gcc thinks is correct. + +2002-09-20 Corinna Vinschen <vinschen@redhat.com> + + * h8300-tdep.c (h8300_examine_prologue): Fix loop for saved regs in + multiple register push instruction. + +2002-09-19 Jim Blandy <jimb@redhat.com> + + Add support for distinct host and target character sets. + * charset.c, charset.h: New files. + * c-exp.y: #include "charset.h". + (yylex): Convert character and string literals to the target + character set, before returning them as the semantic value of the + token. + * c-lang.c: #include "charset.h". + (c_emit_char): Use charset-specific methods to recognize + characters with backslash escape forms, to decide which characters + to print literally and which to print using numeric escape + sequences, and to convert target characters to host characters + before printing. + * utils.c: #include "charset.h". + (no_control_char_error): New function. + (parse_escape): Use charset-specific methods to recognize + backslash escapes, parse `control character' notation, and convert + characters from the host character set to the target character set. + * configure.in: Set the default host character set. + Check where to find iconv, and what its argument types might be. + * acinclude.m4 (AM_ICONV): New macro, borrowed from GCC. + * Makefile.in (SFILES): List charset.c. + (COMMON_OBS): List charset.o. + (charset.o): New rule. + (charset_h): New header dependency variable. + (c-lang.o, utils.o, c-exp.tab.o): Note dependency on $(charset_h). + (LIBICONV): New variable, set by configure. + (CLIBS): Include $(LIBICONV) here. + * aclocal.m4, config.in, configure: Regenerated. + +2002-09-19 Joel Brobecker <brobecker@gnat.com> + + * ada-exp.y: Add missing semicolons to end rules. Fixes a + bison 1.35 warning. + +2002-09-19 Richard Earnshaw <rearnsha@arm.com> + + * gdb_mbuild.sh: New file. + +2002-09-19 Andrew Cagney <ac131313@redhat.com> + + * objc-exp.y, objc-lang.h, objc-lang.c: Fix copyright notice. + +2002-09-18 Andrew Cagney <ac131313@redhat.com> + + * breakpoint.c, c-exp.y, defs.h, elfread.c, expression.h, + jv-exp.y, language.c, language.h, p-exp.y, parse.c, parser-defs.h, + printcmd.c, source.c, stabsread.c, symfile.c, symtab.h, utils.c, + valops.c, value.h: Revert previous change. + +2002-09-18 Michael Snyder <msnyder@redhat.com> + + Preliminary support for Objective-C: + * defs.h (language_objc): New enum value. + (puts_filtered_tabular): Declaration only, exported from utils.c. + (skip_quoted): Delete, declared in completer.h. + * c-exp.y: Include completer.h. + * p-exp.y: Ditto. + * jv-exp.y: Ditto. + * expression.h (OP_MSGCALL, OP_SELECTOR, OP_SELF, OP_NSSTRING): + New operator enum values. + * language.h (CAST_IS_CONVERSION): Test for language_objc. + * language.c (binop_result_type): Handle language_objc case. + (integral_type, character_type, string_type, boolean_type, + structured_type, binop_type_check): Ditto. + * symtab.h (SYMBOL_OBJC_DEMANGLED_NAME): Define. + (struct objc_specific): Add to general_symbol_info. + (SYMBOL_INIT_LANGUAGE_SPECIFIC): Add objc initialization. + (SYMBOL_DEMANGLED_NAME): Handle objc case. + * parser-defs.h (struct objc_class_str): New struct type. + (start_msglist, end_msglist, add_msglist): Declaration only, + exported from objc-lang.c. + * value.h (value_of_local, value_nsstring, + call_function_by_hand_expecting_type): Exported from valops.c. + * valops.c (find_function_addr): Export. + (call_function_by_hand_expecting_type): New function. + (value_of_local): New function. + * symfile.c (init_filename_language_table): Add ".m" extension + for Objective-C. + * utils.c (puts_filtered_tabular): New function. + (fprintf_symbol_filtered): Add objc demangling support (disabled). + (set/show demangle): Extend help-string to refer to ObjC. + * elfread.c (elf_symtab_read): Skip Objective-C special symbols. + * stabsread.c (symbol_reference_defined): Objective-C symbols + may contain colons: make allowances when scanning stabs strings + for colons. + (objc_find_colon): New function. + * printcmd.c (address_info): If language == objc then print + "self" instead of "this". + * parse.c (length_of_subexp): Handle new operators OP_MSGCALL, + OP_NSSTRING, and OP_SELF. + (prefixify_subexp): Ditto. + * source.c (print_source_lines): Mention objc in comment. + * breakpoint.c (parse_breakpoint_sals): Recognize Objective-C + method names. + +2002-09-18 Andrew Cagney <ac131313@redhat.com> + + * complaints.h: Update copyright. + (struct complaints): Declare. + (struct complaint): Make `message' constant. + (internal_complaint): Declare. + (complaint): Declare. + (complaint_root): Delete declaration. + (symfile_complaints): Delete declaration. + (struct complaints): Add opaque declaration. + (clear_complaints): Add a complaints parameter. + * complaints.c: Update copyright. + (enum complaint_series): Define. + (complaint_root): Delete. + (struct complaints): Define. + (complaint_sentinel, symfile_complaint_book): New variables. + (symfile_explanations, symfile_complaints): New variables. + New variables. + (get_complaints): New function. + (vcomplaint): New function. + (complaint): New function. + (internal_complaint): New function. + (complain): Call vcomplain with symfile_complaint. + (clear_complaints): Rewrite. + (_initialize_complaints): Use add_setshow_command. + * Makefile.in (complaints.o): Update dependencies. + * symfile.c (syms_from_objfile): Add symfile_complaints parameter + to call to clear_complaints. + (new_symfile_objfile, reread_symbols): Ditto. + (oldsyms_complaint): Delete. + (empty_symtab_complaint, unknown_option_complaint): Delete. + (free_named_symtabs): Use complaint instead of complain. + +2002-09-18 Michael Snyder <msnyder@redhat.com> + + Contributed by Apple Computer, Inc. Merged with current sources + by Adam Fedor <fedor@doc.com> [cagney]. + + * objc-lang.c: First clean-up round: comments, indentation. + * objc-lang.h: Ditto. + * objc-lang.y: Ditto. + +2002-09-18 Andrew Cagney <ac131313@redhat.com> + + * maint.c (maintenance_internal_error): Print the parameter as the + error message. + (maintenance_internal_warning): New function. + (_initialize_maint_cmds): Add command `maint internal-warning'. + + * defs.h (internal_warning, internal_vwarning): Declare. + * utils.c (struct internal_problem): Define. + (internal_vproblem): New function. + (internal_warning): New function. + (internal_vwarning): New function. + (internal_warning_problem, internal_error_problem): New variables. + (internal_verror): Just call internal_vproblem. + +2002-09-18 Michael Snyder <msnyder@redhat.com> + + * objc-lang.c: New file, support for Objective-C. + Preliminary check-in, not yet integrated into gdb. + * objc-lang.h: New file. + * objc-exp.y: New file. + +2002-09-18 Andrew Cagney <ac131313@redhat.com> + + * infrun.c (signal_stop_update): Convert definition to ISO C. + (signal_print_update): Ditto. + (signal_pass_update): Ditto. + * inflow.c (terminal_save_ours): Ditto. + + * h8300-tdep.c (h8300_gdbarch_init): Use C instead of C++ + comments. + + * config/djgpp/fnchange.lst: Handle name clashes between + bfd/coff-tic30.c, bfd/coff-tic4x.c, bfd/coff-tic54x.c and + bfd/coff-tic80.c. + + * i386-linux-tdep.h: Fix tipo. + +2002-09-18 Adam Fedor <fedor@gnu.org> + + * MAINTAINERS: Add myself to the Write After Approval list. + +2002-09-18 Jim Blandy <jimb@redhat.com> + + * dbxread.c, mdebugread.c: Revert my change of 2001-10-23. Moving + texthigh and textlow to reader-specific structs caused + objfile_relocate to miss them. This is fixable, but the work that + the change was supposed to prepare GDB for never got done anyway. + +2002-09-18 David Carlton <carlton@math.stanford.edu> + + * MAINTAINERS: Alphabetize Write After Approval list. + +2002-09-18 Daniel Jacobowitz <drow@mvista.com> + + Fix PR gdb/709 + * values.c (value_static_field): Call read_var_value. + +2002-09-18 Andrew Cagney <ac131313@redhat.com> + + * valops.c (hand_function_call): Align the initial stack pointer + and STRUCT_ADDR using frame_align. When STRUCT_RETURN and + FRAME_ALIGN_P, use STRUCT_ADDR to obtain the called function's + return value. + * mips-tdep.c (mips_frame_align): New function. + (mips_gdbarch_init): Set frame_align. + * gdbarch.sh (FRAME_ALIGN): New method. + * gdbarch.h, gdbarch.c: Re-generate. + +2002-09-18 Michal Ludvig <mludvig@suse.cz> + + * x86-64-linux-nat.c (x86_64_regmap): Added CS and SS + registers. + +2002-09-17 Andrew Cagney <ac131313@redhat.com> + + * NEWS: Mention that MIPS $fp behavior changed. + * mipsnbsd-tdep.c (mipsnbsd_cannot_fetch_register): Delete + reference to FP_REGNUM. + (mipsnbsd_cannot_store_register): Ditto. + * mips-linux-nat.c: Update copyright. + (mips_linux_cannot_fetch_register): Delete reference to FP_REGNUM. + (mips_linux_cannot_store_register): Ditto. + * mips-linux-tdep.c (supply_gregset): Ditto. Update copyright. + * config/mips/tm-mips.h: Update copyright. + (FP_REGNUM): Delete macro. + (MIPS_REGISTER_NAMES): Replace "fp" with "". + * config/mips/tm-irix6.h (FP_REGNUM): Delete macro. + * mips-tdep.c (mips_gdbarch_init): Set read_fp to mips_read_sp. + (mips_r3041_reg_names, mips_r3051_reg_names) + (mips_r3081_reg_names): Replace "fp" with "". + Fix PR gdb/480. + +2002-09-17 Theodore A. Roth <troth@verinet.com> + + * gdb/avr-tdep.c(avr_scan_prologue): Fix bad call to + generic_read_register_dummy() (PR gdb/703). + (avr_push_return_address): #if 0 out unused vars. + (avr_gdbarch_init): Enable use of avr_push_return_address(). + +2002-09-17 Michael Snyder <msnyder@redhat.com> + + * m32r-stub.c (restore_and_return): Postpone restoring of PSW. + RTE will take care of it. + +2002-09-17 Andrew Cagney <ac131313@redhat.com> + + * arch-utils.c (legacy_virtual_frame_pointer): If FP_REGNUM is + invalid, return SP_REGNUM. + +2002-09-17 Michael Snyder <msnyder@redhat.com> + + * mips-tdep.c (mips_pop_frame): Read saved values of floating + point registers without sign extension. + +2002-09-17 Andrew Cagney <cagney@redhat.com> + + * blockframe.c (deprecated_read_register_dummy): Rename + generic_read_register_dummy. + * frame.c (frame_unwind_signed_register): New function. + (frame_unwind_unsigned_register): New function. + * frame.h (frame_unwind_signed_register): Declare. + (frame_unwind_unsigned_register): Declare. + (deprecated_read_register_dummy): Rename + generic_read_register_dummy. + + * h8300-tdep.c (h8300_frame_chain): Update. + (h8300_frame_saved_pc): Update. + * xstormy16-tdep.c (xstormy16_frame_saved_pc): Update. + * rs6000-tdep.c (rs6000_frame_saved_pc): Update. + * s390-tdep.c (s390_frame_saved_pc_nofix): Update. + (s390_frame_chain): Update. + * v850-tdep.c (v850_find_callers_reg): Update. + (v850_frame_saved_pc): Update. + * m32r-tdep.c (m32r_init_extra_frame_info): Update. + (m32r_find_callers_reg): Update. + (m32r_frame_saved_pc): Update. + * sh-tdep.c (sh_find_callers_reg): Update. + (sh64_get_saved_pr): Update. + (sh_init_extra_frame_info): Update. + (sh_init_extra_frame_info): Update. + (sh64_init_extra_frame_info): Update. + (sh64_init_extra_frame_info): Update. + * mcore-tdep.c (mcore_find_callers_reg): Update. + (mcore_frame_saved_pc): Update. + (mcore_init_extra_frame_info): Update. + * i386-tdep.c (i386_frame_saved_pc): Update. + * ia64-tdep.c (ia64_frame_saved_pc): Update. + (ia64_init_extra_frame_info): Update. + (ia64_init_extra_frame_info): Update. + * d10v-tdep.c (d10v_frame_saved_pc): Update. + * cris-tdep.c (cris_init_extra_frame_info): Update. + * avr-tdep.c (avr_frame_chain): Update. + (avr_init_extra_frame_info): Update. + (avr_frame_saved_pc): Update. + * arm-tdep.c (arm_find_callers_reg): Update. + (arm_init_extra_frame_info): Update. + (arm_frame_saved_pc): Update. + +2002-09-17 Tom Tromey <tromey@redhat.com> + + * c-lang.c (c_emit_char): Don't treat \0 specially unless quoter + is "'". + +2002-09-17 Corinna Vinschen <vinschen@redhat.com> + + * MAINTAINERS: Remove "non multi-arched" text from h8300. + * h8300-tdep.c (h8300_next_prologue_insn) Renamed from + NEXT_PROLOGUE_INSN. + (h8300_examine_prologue): Call h8300_next_prologue_insn instead of + NEXT_PROLOGUE_INSN. + +2002-09-16 Joel Brobecker <brobecker@gnat.com> + + * osfsolib.c: Remove file, replaced by solib-osf.c. + * Makefile.in: Remove compilation rules for osfsolib.c. + +2002-09-16 David Carlton <carlton@math.stanford.edu> + + * cp-valprint.c (cp_print_class_method): Correct args to + check_stub_method_group. + +2002-09-16 Corinna Vinschen <vinschen@redhat.com> + + * h8300-tdep.c: Multiarch. Drop `set machine' command in favor of + `set architecture'. Unify naming convention of functions. + (h8300_skip_prologue): Improve prologue analysis. + (h8300_push_arguments): Rewritten to more closely match GCC's + bizarre argument-passing behavior, along with the comment describing + said behavior. + * remote-hms.c (hms_regnames): Don't use NUM_REGS in definition. + * config/h8300/tm-h8300.h: Multiarch. Just keep stuff needed by + sim, remote-e7000.c, remote-hms.c and remote.c + +2002-09-15 Mark Kettenis <kettenis@gnu.org> + + * i386-tdep.c (gdb_print_insn_i386): Removed. + (i386_print_insn): New function. + (i386_gdbarch_init): Set print_insn to i386_print_insns. + (_initialize_i386_tdep): Don't initialize tm_print_insn and + tm_print_insn_info. + +2002-09-14 Mark Kettenis <kettenis@gnu.org> + + * gdbtypes.c (check_stub_method_group): Initialize found_stub to + zero. + +2002-09-14 Corinna Vinschen <vinschen@redhat.com> + + * arch-utils.c (legacy_pc_in_sigtramp): Move preprocessor expression + for IN_SIGTRAMP to here. Use IN_SIGTRAMP only if it's defined. + Guard usage of SIGTRAMP_START() by using SIGTRAMP_START_P. + +2002-09-13 Christopher Faylor <cgf@redhat.com> + + * win32-nat.c (child_create_inferior): Honor 'tty' command. + +2002-09-13 Daniel Jacobowitz <drow@mvista.com> + + * gdbtypes.c (check_stub_method): Make static. + (check_stub_method_group): New function. + * gdbtypes.h: Update prototypes. + * cp-support.c: New file. + * cp-support.h: New file. + + * stabsread.c: Include "cp-abi.h" and "cp-support.h". + (update_method_name_from_physname): New function. + (read_member_functions): Correct method names for operators + and v3 constructors/destructors. Separate v2 constructors and + destructors. + * Makefile.in (stabsread.o): Update dependencies. + (SFILES): Add cp-support.c. + (COMMON_OBS): Add cp-support.o. + (cp_support_h, cp-support.o): Add. + + * cp-valprint.c (cp_print_class_method): Call + check_stub_method_group instead of check_stub_method. Remove + extraneous QUITs. + * p-valprint.c (pascal_object_print_class_method): Likewise. + * valops.c (search_struct_method): Likewise. + (find_method_list, value_struct_elt_for_reference): Likewise. + +2002-09-13 Andrew Cagney <cagney@redhat.com> + + * gdbarch.sh (SIGTRAMP_END): Change to a predicate function. + * gdbarch.h, gdbarch.c: Regenerate. + +2002-09-13 Andrew Cagney <ac131313@redhat.com> + + * frame.c (find_saved_register): Delete function. + * frame.h (find_saved_register): Delete declaration. + Fix PR gdb/631. + +Fri Sep 13 14:59:55 2002 Andrew Cagney <cagney@redhat.com> + + * mips-tdep.c (read_next_frame_reg): Re-hack using + frame_register_unwind. + +Fri Sep 13 07:42:09 2002 Andrew Cagney <cagney@redhat.com> + + * mips-tdep.c (mips_get_saved_register): Re-hack using + frame_register_unwind. + +2002-09-12 Joel Brobecker <brobecker@gnat.com> + + * gdbarch.sh (NAME_OF_MALLOC): New variable in the architecture + vector. Will be useful for Interix. + * gdbarch.h, gdbarch.c: Regenerate. + + * valops.c (value_allocate_space_in_inferior): Replace hard-coded + name of the malloc function by NAME_OF_MALLOC. + +2002-09-12 Joel Brobecker <brobecker@gnat.com> + + * value.h (find_function_in_inferior): Add const keyword to + one of the parameters. Allows us to invoke this function with + a const char *. + * valops.c (find_function_in_inferior): Likewise. + +2002-09-12 Joel Brobecker <brobecker@gnat.com> + + * exec.c (xfer_memory): Fix compilation warning with old versions + of GCC. + * tracepoint.c (trace_find_tracepoint_command): Likewise. + +2002-09-12 David Carlton <carlton@math.stanford.edu> + + * symtab.h: Run through gdb_indent.h. + Add 2002 to Copyright year list. + +2002-09-12 Alan Modra <amodra@bigpond.net.au> + + * x86-64-tdep.c (_initialize_x86_64_tdep): Don't use hard-coded + mach constants. + * MAINTAINERS: Add myself to write after approval list. + +2002-09-11 J. Brobecker <brobecker@gnat.com> + + * osabi.c (gdb_osabi_name): Add entry for GDB_OSABI_INTERIX. + +2002-09-11 J. Brobecker <brobecker@gnat.com> + + * osabi.h (gdb_osabi): Add new GDB_OSABI_INTERIX enum value for + Interix. + +2002-06-05 Paul N. Hilfinger <hilfingr@otisco.mckusick.com> + + * procfs.c (do_detach): Clear current signal, not just fault. + Corrects problem with breakpoint trap signal leaking to detached + process on Tru64. + +2002-09-10 Michael Snyder <msnyder@redhat.com> + + * buildsym.c (finish_block): Protect against null pointer. + +2002-09-10 Andrew Cagney <cagney@redhat.com> + + * infcmd.c (default_print_registers_info): Send all output to + ``file'' instead of ``gdb_stdout''. + +2002-09-10 Michael Snyder <msnyder@redhat.com> + + * mips-tdep.c (mips_extract_struct_value_address): Make val a + LONGEST, and use signed register read (addresses are sign- + extended for mips). + +2002-09-10 Stephane Carrez <stcarrez@nerim.fr> + + * event-loop.c (gdb_do_one_event): Make public. + * event-loop.h (gdb_do_one_event): Declare. + +2002-09-10 Jeff Law <law@redhat.com> + + * infttrace.c (child_resume): Simplify and rework to avoid + TT_PROC_CONTINUE. + +2002-09-09 Fred Fish <fnf@intrinsity.com> + + * printcmd.c (print_scalar_formatted): "len" is the number of + target bytes, NOT the number of target bits. + +2002-09-09 Elena Zannoni <ezannoni@redhat.com> + + From: Emmanuel Thome' <thome@lix.polytechnique.fr> + * top.c (init_main): Set rl_terminal_name. + +2002-09-08 Aidan Skinner <aidan@velvet.net> + + * ada-lang.c (ada_array_bound, ada_type_match, + _initialize_ada_language): Fix K&R definitions. + * ada-tasks.c (get_current_task): Fix K&R definitions. + * ada-valprint.c (adjust_type_signedness): Fix K&R definitions. + +2002-09-07 Christopher Faylor <cgf@redhat.com> + + * MAINTAINERS: Remove CE from list of maintainership responsibilities. + Add XP. + +2002-09-06 Mark Kettenis <kettenis@gnu.org> + + * i386-tdep.c (i386_register_virtual_type, + i386_register_convertible, i386_register_convert_to_virtual, + i386_register_comvert_to_raw): Use FP_REGNUM_P and SSE_REGNUM_P + instead of IS_FP_REGNUM and IS_SSE_REGNUM. + (i386_gdbarch_init): Fix comment. Add comments on calls that set + sp_regnum, fp_regnum, pc_regnum, ps_regnum and fp0_regnum. + Don't set push_arguments twice. + + * i386bsd-tdep.c (i386bsd_init_abi): Set sigtramp_start and + sigtramp_end to i386bsd_sigtramp_start and i386bsd_sigtramp_end. + * i386nbsd-tdep.c (i386nbsd_init_abi): Set sigtramp_start and + sigtramp_end to NULL. + * config/i386/tm-fbsd.h (SIGTRAMP_START, SIGTRAMP_END): Remove + defines. + (i386bsd_sigtramp_start, i386_sigtramp_end): Remove prototypes. + + * i386nbsd-tdep.c (i386nbsd_pc_in_sigtramp): Remove spurious + whitespace. + + * gdbarch.sh (SIGTRAMP_START, SIGTRAMP_END): New methods. + * gdbarch.h, gdbarch.c: Re-generate. + * blockframe.c (find_pc_sect_partial_function): Convert to use + SIGTRAMP_START_P predicate. + +2002-09-05 Michael Snyder <msnyder@redhat.com> + + * arm-tdep.c (arm_init_extra_frame_info): Distinguish between + generic_dummy_frame method and old method. Also distinguish + between ARM_FP_REGNUM and THUMB_FP_REGNUM. + (arm_extract_return_value): Use new regcache method. + + * mips-tdep.c (mips_n32n64_push_arguments): Remove alignment + adjustment that doesn't conform to the ABI. + (mips_extract_struct_value_address): Retrieve V0_REGNUM from + saved regcache, not from current regcache. + +2002-09-05 Andrew Cagney <ac131313@redhat.com> + + * NEWS: Update for 5.3. Add new section ``Changes since 5.3''. + * README: Update. + +2002-09-04 Jason Thorpe <thorpej@wasabisystems.com> + + * arm-tdep.c (arm_addr_bits_remove): Don't check for Thumb mode + if arm_apcs_32 is false. + +2002-09-04 Andrew Cagney <ac131313@redhat.com> + + GDB 5.3 branch created. + +2002-09-03 Theodore A. Roth <troth@verinet.com> + + * gdb/avr-tdep.c (avr_gdbarch_init): Use + generic_unwind_get_saved_register. + +2002-09-03 David Carlton <carlton@math.stanford.edu> + + * dwarf2read.c (dwarf2_add_member_fn): Add the 'type' + argument (PR gdb/653). Update call to smash_to_method_type. + (read_structure_scope): Update call to dwarf2_add_member_fn. + +2002-09-03 Michal Ludvig <mludvig@suse.cz> + + * x86-64-linux-tdep.c: Include gdb_string.h + * x86-64-linux-nat.c: Ditto. + +2002-09-02 Jason Thorpe <thorpej@wasabisystems.com> + + * ada-exp.y (yyname, yyrule): Remap global variables that appear + when YYDEBUG is set to 1. + * c-exp.y: Likewise. + * f-exp.y: Likewise. + * jv-exp.y: Likewise. + * m2-exp.y: Likewise. + * p-exp.y: Likewise. + +2002-09-02 Jason Thorpe <thorpej@wasabisystems.com> + + * Makefile.in (i386nbsd-tdep.o): Add $(solib_svr4_h) to + dependency list. + * i386nbsd-tdep.c (i386nbsdelf_init_abi): Set + solib_svr4_fetch_link_map_offsets to + nbsd_ilp32_solib_svr4_fetch_link_map_offsets. + * config/i386/nbsd.mt (TDEPFILES): Add solib.o and solib-svr4.o. + * config/i386/nbsdaout.mh (NATDEPFILES): Remove solib.o. + * config/i386/nbsdelf.mh (NATDEPFILES): Remove solib.o, + solib-svr4.o, and solib-legacy.o. + * config/i386/tm-nbsd.h: Include solib.h. + +2002-09-02 Jason Thorpe <thorpej@wasabisystems.com> + + * configure.tgt (i[3456]86-*-netbsdelf*): Merge with... + (i[3456]86-*-netbsd*): ...this. Set gdb_target to nbsd. + (i[3456]86-*-openbsd*): Make this a separate entry. Add a + comment noting that this needs its own target configuration. + * config/i386/nbsd.mt: New file. + * config/i386/nbsdaout.mt: Remove. + * config/i386/nbsdelf.mt: Ditto. + * config/i386/tm-nbsdaout.h: Ditto. + +2002-09-02 Jason Thorpe <thorpej@wasabisystems.com> + + * i386nbsd-tdep.c (i386nbsd_sigtramp_offset): New function. + (i386nbsd_pc_in_sigtramp): Rewrite to use i386nbsd_sigtramp_offset. + (i386nbsd_init_abi): Don't initialize tdep->sigtramp_start or + tdep->sigtramp_end. + (i386nbsd_sigtramp_start, i386nbsd_sigtramp_end): Remove. + * config/i386/tm-nbsd.h (SIGTRAMP_START, SIGTRAMP_END) + (i386bsd_sigtramp_start, i386bsd_sigtramp_end): Remove. + +2002-09-02 Jason Thorpe <thorpej@wasabisystems.com> + + * Makefile.in (i386nbsd-tdep.o): Add $(arch_utils_h), + $(i386_tdep_h), and $(nbsd_tdep_h) to dependency list. + * i386-tdep.h (i386bsd_init_abi): New prototype. + * i386bsd-tdep.c (i386bsd_init_abi): Remove "static" from + function declaration. + (_initialize_i386bsd_tdep): Don't register OS ABI handlers + for NetBSD-a.out or NetBSD-ELF. + (i386nbsd_sigtramp_start, i386nbsd_sigtramp_end) + (i386nbsd_sc_pc_offset, i386nbsd_sc_sp_offset) + (i386nbsd_init_abi, i386nbsdelf_init_abi): Move to... + * i386nbsd-tdep.c: ...here. Include arch-utils.h, i386-tdep.h, + and nbsd-tdep.h. + (i386nbsd_pc_in_sigtramp): New function. + (i386nbsd_init_abi): Set gdbarch_pc_in_sigtramp to + i386nbsd_pc_in_sigtramp. + (_initialize_i386nbsd_tdep): Register i386nbsd_init_abi + and i386nbsdelf_init_abi OS ABI handlers. + * config/i386/nbsdaout.mt (TDEPFILES): Add nbsd-tdep.o. + * config/i386/nbsdelf.mt (TDEPFILES): Likewise. + +2002-09-02 Mark Kettenis <kettenis@gnu.org> + + * i386-linux-nat.c (dummy_sse_values): Only try to fill in the SSE + registers if the target really has them. + +2002-08-31 Jason Thorpe <thorpej@wasabisystems.com> + + * Makefile.in (mipsnbsd-tdep.o): Use $(nbsd_tdep_h) rather + than nbsd-tdep.h. + +2002-08-31 Jason Thorpe <thorpej@wasabisystems.com> + + * Makefile.in (alphanbsd-tdep.o): Add $(frame_h) to dependency + list. + * alphanbsd-tdep.c (alphanbsd_sigcontext_addr) + (alphanbsd_skip_sigtramp_frame): New functions. + (alphanbsd_init_abi): Set tdep->skip_sigtramp_frame to + alphanbsd_skip_sigtramp_frame. Set tdep->sigcontext_addr + to alphanbsd_sigcontext_addr. + +2002-08-31 Jason Thorpe <thorpej@wasabisystems.com> + + * Makefile.in (mipsnbsd-tdep.o): Add nbsd-tdep.h to dependency + list. + (nbsd-tdep.o): Add $(gdb_string_h) to dependency list. + * alphanbsd-tdep.c (alphanbsd_pc_in_sigtramp): Use + nbsd_pc_in_sigtramp. + * mipsnbsd-tdep.c: Include nbsd-tdep.h. + (mipsnbsd_pc_in_sigtramp): Use nbsd_pc_in_sigtramp. + * nbsd-tdep.c: Include gdb_string.h. + (nbsd_pc_in_sigtramp): New function. + * nbsd-tdep.h (nbsd_pc_in_sigtramp): New prototype. + * ppcnbsd-tdep.c (ppcnbsd_pc_in_sigtramp): New function. + (ppcnbsd_init_abi): Set gdbarch_pc_in_sigtramp to + ppcnbsd_pc_in_sigtramp. + * shnbsd-tdep.c (shnbsd_pc_in_sigtramp): New function. + (shnbsd_init_abi): Set gdbarch_pc_in_sigtramp to + shnbsd_pc_in_sigtramp. + * sparcnbsd-tdep.c (sparcnbsd_init_abi_elf): Set + gdbarch_pc_in_sigtramp to nbsd_pc_in_sigtramp. + * config/mips/nbsd.mt (TDEPFILES): Add nbsd-tdep.o. + +2002-08-30 Pierre Muller <muller@ics.u-strasbg.fr> + + * breakpoint.c (breakpoint_init_inferior): Reset the val field of + watchpoints to NULL. + (insert_breakpoints): set val field of watchpoints if NULL. + + +2002-08-29 Jim Blandy <jimb@redhat.com> + + * symtab.c (lookup_symbol_aux): In the cases where we find a + minimal symbol of an appropriate name and use its address to + select a symtab to read and search, use `name' (as passed to us) + as the demangled name when searching the symtab's global and + static blocks, not the minsym's name. + +2002-08-29 Keith Seitz <keiths@redhat.com> + + * stack.c (print_frame_info_base): Always set current_source_symtab + and current_source_line. + +2002-08-29 Donn Terry <donnte@microsoft.com> + + * proc-api.c (rw_table): Fix typo in #ifdef PCSHOLD (missing S). + +2002-08-28 Keith Seitz <keiths@redhat.com> + + * stack.c (select_frame): Add FIXME concerning selected-frame + events. + (select_frame_command): Send selected-frame-level-changed + event notification, but only if the level actually changed. + (up_silently_base): Add selected-frame-level-changed event + notification. + (down_silently_base): Likewise. + +2002-08-28 Andrew Cagney <ac131313@redhat.com> + + * Makefile.in: Update dependencies for all gdb/*.c files. + +2002-08-27 Tom Tromey <tromey@redhat.com> + + * Makefile.in (osabi.o, i387-tdep.o, i386-linux-nat.o, lin-lwp.o, + ax-gdb.o, signals.o, jv-valprint.o, c-valprint.o, cp-abi.o): + Update dependencies. + * i387-tdep.c: Include gdb_string.h. + * osabi.c: Likewise. + * i386-linux-nat.c: Likewise. + * lin-lwp.c: Likewise. + * ax-gdb.c: Likewise. + * signals/signals.c: Likewise. + * jv-valprint.c: Likewise. + * p-lang.c: Likewise. + * c-valprint.c: Likewise. + * cp-abi.c: Likewise. + +2002-08-27 Elena Zannoni <ezannoni@redhat.com> + + * cli/cli-script.h (copy_command_lines): Export. + * breakpoint.c: Include cli/cli-script.h. + * Makefile.in (breakpoint.o): Update dependencies. + +2002-08-26 Michael Snyder <msnyder@redhat.com> + + * breakpoint.c (insert_breakpoints): Protect all references + to 'process_warning'. Shorten long lines. + +2002-08-26 Joel Brobecker <brobecker@gnat.com> + + * cli/cli-script.c (copy_command_lines): New function. + * defs.h (copy_command_lines): Export. + * testsuite/gdb.base/commands.exp: New tests for commands + attached to a temporary breakpoint, and for commands that + delete the breakpoint they are attached to. + +2002-08-26 Michael Snyder <msnyder@redhat.com> + + * breakpoint.c (bpstat_stop_status): Instead of copying the + pointer to the breakpoint commands struct, make a new copy + of the struct and point to that. + (bpstat_clear): Free the commands struct. + (bpstat_clear_actions): Free the commands struct. + (bpstat_do_actions): Free the command actions. Also execute + the local cleanups, instead of deleting them. + (delete_breakpoint): Leave the commands field of the bpstat + chain alone -- it will be freed later. + +2002-08-26 Kevin Buettner <kevinb@redhat.com> + + * rs6000-tdep.c (altivec_register_p): Restore function inadvertently + deleted in 2002-08-20 commit. This function is still used by + ppc-linux-nat.c. + +2002-08-26 Keith Seitz <keiths@redhat.com> + + * gdb-events.sh: Add selected-frame-level-changed event. + * gdb-events.c: Regenerated. + * gdb-events.h: Regenerated. + +2002-08-26 Stephane Carrez <stcarrez@nerim.fr> + + Fix PR gdb/393: + * inflow.c (terminal_save_ours): New function to save terminal + settings. + * inferior.h (terminal_save_ours): Declare. + * target.c (debug_to_terminal_save_ours): New function. + (cleanup_target): Defaults to_terminal_save_ours. + (update_current_target): Inherit to_terminal_save_ours. + (setup_target_debug): Set to_terminal_save_ours. + * target.h (target_terminal_save_ours): New to save terminal settings. + (target_ops): New member to_terminal_save_ours. + * gnu-nat.c (init_gnu_ops): Set to_terminal_save_ours. + * hpux-thread.c (init_hpux_thread_ops): Likewise. + * inftarg.c (init_child_ops): Likewise. + * m3-nat.c (init_m3_ops): Likewise. + * procfs.c (init_procfs_ops): Likewise. + * wince.c (init_child_ops): Likewise. + * win32-nat.c (init_child_ops): Likewise. + * sol-thread.c (init_sol_thread_ops): Likewise. + +2002-08-26 Mark Kettenis <kettenis@gnu.org> + + * i386-tdep.c (i386_store_return_value): Undeprecate. Convert to + use regcache_* functions. + (i386_gdbarch_init): Set store_return_value instead of + deprecated_store_return_value. + + * regcache.c (regcache_raw_write_signed, + regcache_raw_write_unsigned): New functions. + * regcache.h (regcache_raw_write_signed, + regcache_raw_write_unsigned): New prototypes. + +2002-08-25 Andrew Cagney <ac131313@redhat.com> + + * Makefile.in (c-exp.tab.o, jv-exp.tab.o, f-exp.tab.o) + (m2-exp.tab.o, p-exp.tab.o, ada-exp.tab.o): Move to before the + source file dependencies. Cleanup corresponding generator rules. + +2002-08-25 Andrew Cagney <ac131313@redhat.com> + + * regcache.h (register_offset_hack): Declare. + (regcache_cooked_read_using_offset_hack): Declare. + (regcache_cooked_write_using_offset_hack): Declare. + + * regcache.c (register_offset_hack): New function. + (regcache_cooked_read_using_offset_hack): New function. + (regcache_cooked_write_using_offset_hack): New function. + (regcache_dump): Check that the registers, according to their + offset, are packed hard against each other. + (cooked_xfer_using_offset_hack): New function. + +2002-08-25 Andrew Cagney <ac131313@redhat.com> + + * regcache.c (struct regcache_descr): Add field register_type. + (init_legacy_regcache_descr): Pass a pre-allocated regcache_descr + in as a parameter + (init_regcache_descr): Initialize register_type. Pass the descr + to init_legacy_regcache_descr. Use register_type instead of + REGISTER_VIRTUAL_TYPE. + (register_type): New function. + (regcache_dump): Replace REGISTER_VIRTUAL_TYPE with register_type. + * regcache.h (register_type): Declare. + +2002-08-25 Andrew Cagney <ac131313@redhat.com> + + * rs6000-tdep.c (rs6000_gdbarch_init): Set store_struct_return + instead of deprecated_store_return_value. Fix fallout from + 2002-08-23 Andrew Cagney <cagney@redhat.com>. + +2002-08-25 Andrew Cagney <ac131313@redhat.com> + + * regcache.c (max_register_size): New function. + (init_legacy_regcache_descr): Ensure that max_register_size is + large enough for REGISTER_VIRTUAL_SIZE. + * regcache.h (max_register_size): Declare. + +2002-08-24 Andrew Cagney <ac131313@redhat.com> + + * rs6000-tdep.c (rs6000_gdbarch_init): Use deprecated version of + store_return_value. + (e500_extract_return_value): Change type of valbuf pointer to + void. + +2002-08-24 Mark Kettenis <kettenis@gnu.org> + + * PROBLEMS: Clarify problems with FreeBSD's compiler and suggest + workaround. + + * valprint.c (print_longest) [CC_HAS_LONG_LONG && + PRINTF_HAS_LONG_LONG]: Cast val_long to (long long) or (unsigned + long long) to prevent compiler warning on 64-bit systems. + +2002-08-23 Andrew Cagney <cagney@redhat.com> + + * gdbarch.sh (STORE_RETURN_VALUE): Add regcache parameter. + (DEPRECATED_STORE_RETURN_VALUE): New method. + (EXTRACT_RETURN_VALUE): Make buffer parameter a void pointer. + * gdbarch.h, gdbarch.c: Re-generate. + + * values.c (set_return_value): Pass current_regcache to + STORE_RETURN_VALUE. + * arch-utils.h (legacy_store_return_value): Declare. + * arch-utils.c (legacy_store_return_value): New function. + (legacy_extract_return_value): Update parameters. + + * config/pa/tm-hppa.h (DEPRECATED_STORE_RETURN_VALUE): Rename + STORE_RETURN_VALUE. + * config/pa/tm-hppa64.h (DEPRECATED_STORE_RETURN_VALUE): Ditto. + * config/sparc/tm-sparc.h (DEPRECATED_STORE_RETURN_VALUE): Ditto. + * config/z8k/tm-z8k.h (DEPRECATED_STORE_RETURN_VALUE): Ditto. + * config/sparc/tm-sparclet.h (DEPRECATED_STORE_RETURN_VALUE): Ditto. + * config/mn10200/tm-mn10200.h (DEPRECATED_STORE_RETURN_VALUE): Ditto. + * config/m68k/tm-linux.h (DEPRECATED_STORE_RETURN_VALUE): Ditto. + * config/m68k/tm-delta68.h (DEPRECATED_STORE_RETURN_VALUE): Ditto. + * config/m32r/tm-m32r.h (DEPRECATED_STORE_RETURN_VALUE): Ditto. + * config/h8500/tm-h8500.h (DEPRECATED_STORE_RETURN_VALUE): Ditto. + * config/h8300/tm-h8300.h (DEPRECATED_STORE_RETURN_VALUE): Ditto. + + * m68hc11-tdep.c (m68hc11_gdbarch_init): Update. + * i386-tdep.c (i386_extract_return_value): Update. + * arch-utils.c (legacy_extract_return_value): Update. + * frv-tdep.c (frv_gdbarch_init): Update. + * cris-tdep.c (cris_gdbarch_init): Update. + * d10v-tdep.c (d10v_gdbarch_init): Update. + * rs6000-tdep.c (rs6000_gdbarch_init): Update. + * m68k-tdep.c (m68k_gdbarch_init): Update. + * mcore-tdep.c (mcore_gdbarch_init): Update. + * mn10300-tdep.c (mn10300_gdbarch_init): Update. + * s390-tdep.c (s390_gdbarch_init): Update. + * sparc-tdep.c (sparc_gdbarch_init): Update. + * sh-tdep.c (sh_gdbarch_init): Update. + * x86-64-tdep.c (x86_64_gdbarch_init): Update. + * v850-tdep.c (v850_gdbarch_init): Update. + * avr-tdep.c (avr_gdbarch_init): Update. + * ia64-tdep.c (ia64_gdbarch_init): Update. + * ns32k-tdep.c (ns32k_gdbarch_init): Update. + * vax-tdep.c (vax_gdbarch_init): Update. + * alpha-tdep.c (alpha_gdbarch_init): Update. + * arm-tdep.c (arm_gdbarch_init): Update. + * mips-tdep.c (mips_gdbarch_init): Update. + * i386-tdep.c (i386_gdbarch_init): Update. + +2002-08-23 Andrew Cagney <ac131313@redhat.com> + + * config/djgpp/fnchange.lst: Add entries for bfd/elf32-ppcqnx.c, + bfd/elf32-ppc.c, bfd/elf32-sh.c and bfd/elf32-shqnx.c. + +2002-08-24 Mark Kettenis <kettenis@gnu.org> + + * PROBLEMS: Refer to GDB 5.3 instead of 5.2. Mention FreeBSD + problems. + +2002-08-23 Joel Brobecker <brobecker@gnat.com> + + * infrun.c (handle_inferior_event): Move a comment outside of a + function call, in order to avoid indent reformatting this part + of the code in an unreadable way. + +2002-08-23 Grace Sainsbury <graces@redhat.com> + + * infrun.c (normal_stop, proceed): Remove call to print_sys_errmsg + when breakpoints fail. Move general breakpoint error messages to + insert_breakpoints. + * breakpoint.c (insert_breakpoints): Change warnings when + breakpoints are nto inserted to specify the type. Remove call to + memory_error when hardware breakpoints can't be inserted. Remove + multiple calls to warning so all messages are sent to the user at + once. + (delete_breakpoints): Make insert error messsages more explicit. + +2002-08-23 Daniel Jacobowitz <drow@mvista.com> + + * ChangeLog: Move gdbserver entries after GDB 5.2 to + gdbserver/ChangeLog. + +2002-08-23 Mark Kettenis <kettenis@gnu.org> + + * i386-tdep.c: Include "objfiles.h". + (i386_svr4_init_abi): Set in_solib_call_trampoline and + skip_trampoline_code. + * config/i386/tm-i386v4.h: Don't include "config/tm-sysv4.h". + (CPLUS_MARKER): Define to '.'. + + * linux-proc.c (struct linux_corefile_thread_data): Add num_notes + member. + (linux_corefile_thread_callback): Increase args->num_notes. + (linux_make_note_section): Initialize thread_args.num_notes, and + use it to determine whether notes for any threads were created. + +2002-08-23 Donn Terry <donnte@microsoft.com> + + * proc-api.c (rw_table): Do not include a row for PCDSTOP if the + corresponding macro is not defined. Likewise for PCNICE, PCSHOLD + and PCUNKILL. + (write_with_trace): Conditionalize out the switch branch handling + PCSHOLD if the corresponding macro is not defined. Likewise for + PRSABORT and PRSTOP. + This change will be needed by the Interix port. + +2002-08-22 Elena Zannoni <ezannoni@redhat.com> + + * ppc-sysv-tdep.c (ppc_sysv_abi_push_arguments): use + write_register wherever possible instead of manipulating the + register bytes directly. + Assign VALUE_CONTENTS to a variable and use that. + The GPR numbers are now dependent on the architecture. + +2002-08-22 Elena Zannoni <ezannoni@redhat.com> + + * rs6000-tdep.c (struct rs6000_framedata): Add saved_ev and + ev_offset fields. + (skip_prologue): Add support for BookE/e500 instructions. + (e500_extract_return_value): New function. + (frame_get_saved_regs): Add support for saving ev registers and + pseudo gpr's. + (e500_store_return_value): New function. + (rs6000_gdbarch_init): Move up default intializations of + deprecated_extract_return_value and store_return_value. Overwrite + init of store_return_value with e500 specific version. + Set extract_return_value for e500. + +2002-08-22 Elena Zannoni <ezannoni@redhat.com> + + * blockframe.c (generic_call_dummy_register_unwind): Use + regcache_cooked_read to catch cases in which the variable is + stored in a pseudo register. + +2002-08-22 Andrew Cagney <cagney@redhat.com> + + * NEWS: Mention that the i960 has been made obsolete. + * Makefile.in (SFILES): Delete remote-nrom.c, remote-nindy.c and + i960-tdep.c + (remote-nrom.o): Obsolete target. + (remote-nindy.o, i960-tdep.o): Ditto. + * remote-nrom.c: Make file obsolete. + * remote-nindy.c, remote-vx960.c: Ditto. + * config/i960/vxworks960.mt, config/i960/nindy960.mt: Ditto. + * config/i960/mon960.mt, config/i960/tm-i960.h: Ditto. + * config/i960/tm-vx960.h, config/i960/tm-nindy960.h: Ditto. + * config/i960/tm-mon960.h, i960-tdep.c: Ditto. + * configure.tgt: Make i960-*-bout*, i960-nindy-coff*, + i960-*-coff*, i960-nindy-elf*, i960-*-elf*, i960-*-nindy* and + i960-*-vxworks* obsolete. + * MAINTAINERS: Note that the i960 is obsolete. + +2002-08-21 Corinna Vinschen <vinschen@redhat.com + + * aix-thread.c (aix_thread_detach): Disable thread debugging on + detach to allow reinitialization. + +2002-08-22 Andrew Cagney <ac131313@redhat.com> + + * MAINTAINERS: Change the s390 target to s390-linux-gnu (second + attempt). + +2002-08-22 Jim Blandy <jimb@redhat.com> + + * coffread.c (coff_symfile_read): Don't try to read the line + number table from disk if the image file doesn't have a symbol + table; we'll never actually look at the info anyway, and Windows + ships DLL's with bogus file offsets for the line number data. + +2002-08-21 Elena Zannoni <ezannoni@redhat.com> + + * rs6000-tdep.c (rs6000_gdbarch_init): Figure out whether we have + an e500 executable. + +2002-08-21 Michael Snyder <msnyder@redhat.com> + + * mips-tdep.c (MSYMBOL_IS_SPECIAL): Replace macro with function. + (MSYMBOL_SIZE): Replace macro with function. + (DEFAULT_MIPS_TYPE): Delete unused macro. + * config/mips/tm-mips.h (DEFAULT_MIPS_TYPE): Delete unused macro. + * config/mips/tm-embed.h (DEFAULT_MIPS_TYPE): Delete unused macro. + +2002-08-21 Jim Blandy <jimb@redhat.com> + + * valops.c (value_cast): Simplify and correct logic for doing a + static cast from a pointer to a base class to a pointer to a + derived class. + +2002-08-21 Andrew Cagney <ac131313@redhat.com> + + * infcmd.c (default_print_registers_info): Replace + do_registers_info. + (registers_info): Use gdbarch_print_registers_info instead of + DO_REGISTERS_INFO. + * inferior.h (default_print_registers_info): Replace + do_registers_info. + * gdbarch.sh (PRINT_REGISTERS_INFO): New method. + (DO_REGISTERS_INFO): Change to a predicate function. + * gdbarch.h, gdbarch.c: Regenerate. + +2002-08-21 Keith Seitz <keiths@redhat.com> + + * gdb-events.sh: Add target-changed event. + * gdb-events.c: Regenerated. + * gdb-events.c: Regenerated. + * valops.c (value_assign): Add target-changed event notification + to inlval_register, lval_memory, and lval_reg_frame_relative. + +2002-08-21 Joel Brobecker <brobecker@gnat.com> + + * NEWS: Add an entry regarding the improvement of the next/step + operation on Alpha Tru64 multi-processor machines. + +2002-08-21 Andrew Cagney <ac131313@redhat.com> + + * Makefile.in: Update dependencies for mi/ cli/ and tui/ + directores. + * Makefile.in: Update all _h macro definitions. + * Makefile.in (install-gdbtk): Move to install section. + (rdi-share/libangsd.a): Move to end of file. + +2002-08-19 Andrew Cagney <ac131313@redhat.com> + + * frame.c (frame_register_unwind): When a register, set addrp to + the register's byte. + +2002-08-20 Michael Snyder <msnyder@redhat.com> + + * mips-tdep.c (MSYMBOL_IS_SPECIAL, MSYMBOL_SIZE): These are only + used locally, so move them from the target machine header to here. + (mips_set_processor_type, mips_register_name, mips32_next_pc, + mips16_next_pc, cached_proc_desc, mips_set_processor_type): + Make static. + * config/mips/tm-mips.h (MSYMBOL_IS_SPECIAL, MSYMBOL_SIZE): Delete. + +2002-08-20 Andrew Cagney <cagney@redhat.com> + + * NEWS: Mention that the Apollo line was made obsolete. + * configure.tgt: Make m68*-apollo*-bsd*, m68*-hp-bsd*, and + m68*-hp-hpux* obsolete. + * configure.host: Make m68*-apollo*-sysv*, m68*-apollo*-bsd*, + m68*-hp-bsd* and m68*-hp-hpux* obsolete. + * buildsym.c (make_blockvector): Make static. + * buildsym.h (make_blockvector): Make extern declaration obsolete. + * Makefile.in (HFILES_NO_SRCDIR): Remove dst.h + (ALLDEPFILES): Remove dstread.c. + (dstread.o): Obsolete make rule. + * dstread.c: Makefile obsolete. + * dst.h: Ditto. + * config/m68k/hp300hpux.mt: Ditto. + * config/m68k/hp300hpux.mh: Ditto. + * config/m68k/hp300bsd.mt: Ditto. + * config/m68k/hp300bsd.mh: Ditto. + * config/m68k/apollo68b.mt: Ditto. + * config/m68k/apollo68v.mh: Ditto. + * config/m68k/apollo68b.mh: Ditto. + +2002-08-20 Michael Snyder <msnyder@redhat.com> + + * mips-tdep.c (mips_in_return_stub): Make static. + (mips_gdbarch_init): Set in_solib_return_trampoline. + * config/mips/tm-mips.h (IN_SOLIB_RETURN_TRAMPOLINE): Delete. + +2002-08-20 Michael Snyder <msnyder@redhat.com> + + * gdbarch.sh (IN_SOLIB_RETURN_TRAMPOLINE): Add. + * gdbarch.c, gdbarch.h: Regenerate. + * arch-utils.c, arch-utils.h (generic_in_solib_return_trampoline): + Add. + * infrun.c (IN_SOLIB_RETURN_TRAMPOLINE): Delete default definition. + +2002-08-20 Michael Snyder <msnyder@redhat.com> + + * mips-tdep.c (mips_skip_stub, mips_in_call_stub): Make static. + (mips_gdbarch_init): Set skip_trampoline_code, + in_solib_call_trampoline. + * config/mips/tm-mips.h (REGISTER_NAME): Delete. + (IN_SOLIB_CALL_TRAMPOLINE, SKIP_TRAMPOLINE_CODE): Delete. + +2002-08-20 Elena Zannoni <ezannoni@redhat.com> + + * ppc-tdep.h (struct gdbarch_tdep): Add ev registers. + + * rs6000-tdep.c (rs6000_register_virtual_type): Return 64 bit + vector type for ev registers. + (e500_pseudo_register_read): New function. + (e500_pseudo_register_write): New function. + (e500_dwarf2_reg_to_regnum): New function. + (PPC_UISA_NOFP_SPRS): New macro. + (PPC_EV_REGS): New macro. + (PPC_GPRS_PSEUDO_REGS): New macro. + (registers_e500): New register set for e500. + (variants): Add e500 variant. + (rs6000_gdbarch_init): Move setting of pc, sp, fp regnums to + before setting architectural dependent variations. Initialize ev + registers numbers. Add case for e500 architecture. Set the + number of pseudo registers. + +2002-08-20 Elena Zannoni <ezannoni@redhat.com> + + * rs6000-tdep.c: Clean up comments. + +2002-08-20 Andrew Cagney <cagney@redhat.com> + + * h8300-tdep.c: Re-indent file. + +2002-08-20 Jim Blandy <jimb@redhat.com> + + * Makefile.in (LDFLAGS): Allow the configure script to establish a + default for this. + +2002-08-20 Keith Seitz <keiths@redhat.com> + + * breakpoints.c (watch_command_1): Use internal breakpoint + when setting a watchpoint_scope breakpoint. + +2002-08-20 Elena Zannoni <ezannoni@redhat.com> + + * gdbtypes.c (build_builtin_type_vec64): Add name to type. + (build_builtin_type_vec64i): Ditto. + (build_builtin_type_vec128): Ditto. + (build_builtin_type_vec128i): Ditto. + +2002-08-19 Michael Snyder <msnyder@redhat.com> + + * config/mips/tm-mips.h (ELF_MAKE_MSYMBOL_SPECIAL): Delete. + (MSYMBOL_IS_SPECIAL, MSYMBOL_SIZE): Change into functions. + (FIX_CALL_DUMMY, PUSH_RETURN_ADDRESS, PUSH_DUMMY_FRAME, + POP_FRAME, INIT_EXTRA_FRAME_INFO): Delete. + (CALL_DUMMY_START_OFFSET, CALL_DUMMY_BREAKPOINT_OFFSET, + CALL_DUMMY_ADDRESS): Delete. + * mips-tdep.c (mips_elf_make_msymbol_special, mips_msymbol_size, + mips_msymbol_is_special, mips_fix_call_dummy): New functions. + (mips_gdbarch_init): Set elf_make_msymbol_special, pop_frame, + push_dummy_frame, fix_call_dummy, init_extra_frame_info, + push_return_address. + (mips_register_raw_size, mips_eabi_use_struct_convention, + mips_n32n64_use_struct_convention, mips_o32_use_struct_convention, + mips_o32_reg_struct_has_addr, mips_frame_saved_pc, mips_frame_chain, + mips_init_extra_frame_info, mips_eabi_push_arguments, + mips_n32n64_push_arguments, mips_push_return_address, + mips_push_dummy_frame, mips_pop_frame, mips_skip_prologue, + mips_breakpoint_from_pc, mips_call_dummy_address): Make static. + +2002-08-19 Michael Snyder <msnyder@redhat.com> + + * mips-tdep.c (mips_frame_num_args): New function. + (mips_gdbarch_init): Set frame_chain, frameless_function_invocation, + frame_saved_pc, frame_args_address, frame_locals_address, + frame_num_args, and frame_args_skip. + * config/mips/tm-mips.h (FRAME_CHAIN, FRAMELESS_FUNCTION_INVOCATION, + FRAME_SAVED_PC, FRAME_ARGS_ADDRESS, FRAME_LOCALS_ADDRESS, + FRAME_NUM_ARGS, FRAME_ARGS_SKIP): Delete. + * config/mips/tm-mipsv4.h (FRAME_CHAIN_VALID): Delete. + +2002-08-20 Michael Snyder <msnyder@redhat.com> + + * config/mips/tm-mips.h (STORE_STRUCT_RETURN): Delete. + (EXTRACT_STRUCT_VALUE_ADDRESS): Delete. + * mips-tdep.c (mips_store_struct_return): New function. + (mips_extract_struct_value_address): New function. + (mips_gdbarch_init): Set store_struct_return and + extract_struct_value_address. + +2002-08-20 David Carlton <carlton@math.stanford.edu> + + * dwarf2read.c (dwarf2_build_psymtabs): Check that + dwarf_line_offset is nonzero before creating dwarf_line_buffer. + (read_file_scope): Check that line_header is nonzero before + decoding macro information. + +2002-08-20 Mark Kettenis <kettenis@gnu.org> + + * i386-tdep.h (FP_REGNUM_P): Change such that we don't incorrectly + flag the general-purpose registers as floating-point on targets + that don't support the floating-point registers. + +2002-08-20 Elena Zannoni <ezannoni@redhat.com> + + * rs6000-tdep.c (altivec_register_p): Delete. + (rs6000_do_altivec_registers): Delete. + (rs6000_altivec_registers_info): Delete. + (rs6000_do_registers_info): Delete. + (_initialize_rs6000_tdep): Remove command 'info powerpc altivec'. + (rs6000_gdbarch_init): Remove setting of do_registers_info. + +2002-08-20 Elena Zannoni <ezannoni@redhat.com> + + * infcmd.c (do_registers_info): Print vector registers in hex + format only. + (print_vector_info): Check that printing registers + makes sense. + (print_float_info): Ditto. + +2002-08-20 Andrew Cagney <ac131313@redhat.com> + + * mips-tdep.c (mips_gdbarch_init): Update. + (mips_o32_extract_return_value): Rewrite. + (mips_o32_store_return_value): Rewrite. + (mips_o32_xfer_return_value): New function. + (mips_xfer_register): Tweak debug print message. Allow for + buf_offset when dumping the value transfered. + +2002-08-20 Andrew Cagney <ac131313@redhat.com> + + * config/mips/tm-nbsd.h (MIPS_DEFAULT_ABI): Delete. + * config/mips/tm-linux.h (MIPS_DEFAULT_ABI): Delete. + * config/mips/tm-irix5.h (MIPS_DEFAULT_ABI): Delete. + * config/mips/tm-irix6.h (MIPS_DEFAULT_ABI): Delete. + * mips-tdep.c (mips_gdbarch_init) [MIPS_DEFAULT_ABI]: Delete code. + +2002-08-14 Michael Snyder <msnyder@redhat.com> + + * mips-tdep.c (mips_frame_chain): Check for call-dummy frames. + +2002-08-19 Elena Zannoni <ezannoni@redhat.com> + + * rs6000-tdep.c (struct reg): Add field to indicate a pseudo + register. + (P): New macro to define a register as a pseudo register. + (R, R4, R8, R16, FR32, R64, R0): Updated. + (struct variant): Add new fields for number of pseudo registers + and number of total registers. + (tot_num_registers): New macro replacing.... + (num_registers): ...deleted macro. + (num_registers): New function. + (num_pseudo_registers): New function. + (variants): Update all variants to intialize new fields correctly. + Postpone initialization of number of pseudo regs and real regs. + (init_variants): New function. + (rs6000_gdbarch_init): Initialize variants. Update calculation of + registers offsets. + +2002-08-19 David Carlton <carlton@math.stanford.edu> + + * valops.c (search_struct_field): Change error message to treat + return value of 0 from value_static_field as meaning that field is + optimized out. + (value_struct_elt_for_reference): Ditto. + * values.c (value_static_field): Treat an unresolved location the + same as a nonexistent symbol. Fix PR gdb/635. + * gnu-v2-abi.c (gnuv2_value_rtti_type): Eliminate test for being + enclosed. Fix PR gdb/574. + * MAINTAINERS: Add self to Write After Approval list. + +2002-08-19 Andrew Cagney <ac131313@redhat.com> + + * mips-tdep.c (mips_xfer_register): New function. + (mips_n32n64_extract_return_value): Rewrite. + (mips_gdbarch_init): For N32 and N64, set extract_return_value + instead of deprecated_extract_return_value. + +2002-08-19 Elena Zannoni <ezannoni@redhat.com> + + * rs6000-tdep.c (TDEP): Delete macro. + (branch_dest): Replace use of TDEP macro with its body. + (rs6000_pop_frame): Ditto. + (rs6000_push_arguments): Ditto. + (rs6000_skip_trampoline_code): Ditto. + (rs6000_frame_saved_pc): Ditto. + (rs6000_frame_chain): Ditto. + (rs6000_register_name): Ditto. + (rs6000_register_byte): Ditto. + (rs6000_register_raw_size): Ditto. + (rs6000_register_virtual_type): Ditto. + (rs6000_register_convertible): Ditto. + (rs6000_convert_from_func_ptr_addr): Ditto. + +2002-08-19 Daniel Jacobowitz <drow@mvista.com> + + * config/mips/tm-linux.h (REALTIME_LO, REALTIME_HI): Define + conditionally. + (JB_PC, JB_ELEMENT_SIZE): Rename to MIPS_LINUX_JB_PC and + MIPS_LINUX_JB_ELEMENT_SIZE. + * mips-linux-tdep.c (supply_gregset, fill_gregset): Use alloca + for MAX_REGISTER_RAW_SIZE arrays. + (mips_linux_get_longjmp_target): Use MIPS_LINUX_JB_PC and + MIPS_LINUX_JB_ELEMENT_SIZE. + +2002-08-19 Pierre Muller <muller@ics.u-strasbg.fr> + + * i387-tdep.c (i387_print_float_info): Fix typo in comment. + +2002-08-19 Aidan Skinner <aidan@velvet.net> + + * Makefile.in (SFILES): Add ada-exp.y ada-lang.c ada-typeprint.c + ada-valprint.c ada-tasks.c. + (YYFILES): Add ada-exp.y. + (ada-exp.tab.c ada-lex.c ada-lang.o): New target. + (ada-tasks.o ada-typeprint.o ada-valprint.o): New target. + (ada-exp.tab.o): New target. + +2002-08-18 Andrew Cagney <ac131313@redhat.com> + + * regcache.c (regcache_xfer_part): New function. + (regcache_raw_read_part): New function. + (regcache_raw_write_part): New function. + (regcache_cooked_read_part): New function. + (regcache_cooked_write_part): New function. + * regcache.h (regcache_raw_read_part): Declare. + (regcache_raw_write_part): Declare. + (regcache_cooked_read_part): Declare. + (regcache_cooked_write_part): Declare. + +2002-08-18 Daniel Jacobowitz <drow@mvista.com> + + * remote.c (remote_open_1): Add async_p. + (remote_async_open_1): Delete. + (open_remote_target): Delete. + (remote_open, extended_remote_open): Update calls to remote_open_1. + (remote_async_open, extended_remote_async_open): Call + remote_open_1 instead of remote_async_open_1. + +2002-08-19 Mark Kettenis <kettenis@gnu.org> + + * blockframe.c: Fix a few coding standard violations. + +2002-08-19 Mark Kettenis <kettenis@gnu.org> + + * config/i386/nm-i386sco5.h (START_INFERIOR_TRAPS_EXPECTED): Moved + here from ... + * config/i386/tm-i386sco5.h: ... here. File removed. + * config/i386/i386sco5.mt (TM_FILE): Set to tm-i386v4.h. + + * config/i386/nm-i386v.h (START_INFERIOR_TRAPS_EXPECTED): New define. + * config/i386/i386aout.mt (TDEPFILES): Add i387-tdep.o + (TM_FILE): Set to tm-i386.h. + * config/i386/i386v.mt (TM_FILE): Set to tm-i386.h. + * config/i386/tm-i386v.h: Remove file. + * config/i386/tm-ptx.h [!SEQUENT_PTX4]: Include "i386/tm-i386.h" + instead of "i386/tm-i386v.h". + (START_INFERIOR_TRAPS_EXPECTED): Remove define. + * config/i386/tm-symmetry: Include "i386/tm-i386.h" instead of + "i386/tm-i386v.h". + (START_INFERIOR_TRAPS_EXPECTED): Remove define. + * config/i386/tm-vxworks.h: Include "i386/tm-i386.h" instead of + "i386/tm-i386.h". + +2002-08-18 Mark Kettenis <kettenis@gnu.org> + + * config/i386/nm-i386v.h: Add protection against + multiple-inclusion. + (i386_register_u_addr): Remove prototype. + (register_u_addr): New prototype. + (REGISTER_U_ADDR): Redefine accordingly. + * i386v-nat.c: Improve several comments. + (i386_register_u_addr): Change signature and rename to + register_u_addr. Use FP_REGNUM_P. Rewrite slightly to get rid of + ubase variable. + +2002-08-18 Andrew Cagney <ac131313@redhat.com> + + * config/mips/tm-mips.h (STORE_RETURN_VALUE): Delete macro. + (DEPRECATED_EXTRACT_RETURN_VALUE): Delete macro. + * mips-tdep.c (mips_gdbarch_init): Set store_return_value and + deprecated_extract_return_value. + (mips_o32_push_arguments, mips_o64_push_arguments): Clone and + rename mips_o32o64_push_arguments. + (mips_gdbarch_init): Update. + (mips_extract_return_value): Delete. + (mips_o32_extract_return_value): Clone mips_extract_return_value. + (mips_o64_extract_return_value): Clone mips_extract_return_value. + (mips_eabi_extract_return_value): Clone mips_extract_return_value. + (mips_n32n64_extract_return_value): Clone + mips_extract_return_value. + (mips_store_return_value): Delete. + (mips_o32_store_return_value): Clone mips_store_return_value. + (mips_o64_store_return_value): Clone mips_store_return_value. + (mips_eabi_store_return_value): Clone mips_store_return_value. + (mips_n32n64_store_return_value): Clone mips_store_return_value. + +2002-08-18 Aidan Skinner <aidan@velvet.net> + + * ada-lang.c: Use gdb_string.h instead of <string.h>. + * ada-typeprint.c: Use gdb_string.h instead of <string.h>. + +2002-08-18 Aidan Skinner <aidan@velvet.net> + + * ada-lang.c: Run through gdb_indent.sh. + * ada-lang.h: Run through gdb_indent.sh. + * ada-tasks.c: Run through gdb_indent.sh. + * ada-typeprint.c: Run through gdb_indent.sh. + * ada-valprint.c: Run through gdb_indent.sh. + +2002-08-18 Andrew Cagney <ac131313@redhat.com> + + * osabi.c (gdbarch_init_osabi): Don't complain about an unknown + ABI. + +2002-08-18 Mark Kettenis <kettenis@gnu.org> + + * i386b-nat.c [FETCH_INFERIOR_REGISTERS]: Remove dead code. + + * config/i386/nm-i386bsd.h (FLOAT_INFO): Remove redundant #undef. + * i386b-nat.c [FLOAT_INFO]: Remove dead code. + + * i386-tdep.c (i386_do_pop_frame, i386_store_return_value): Call + write_register_gen instead of write_register_bytes. + + * NEWS: Mention that the i[3456]-*mach3*, i[3456]-*-mach* and + i[3456]-*-osf1mk* configurations have been made obsolete. + * configure.host: Make i[3456]86-*-mach3*, i[3456]86-*mach* and + i[3456]86-*-osf1mk* hosts obsolete. + * confighure.tgt: Make i[3456]86-*-mach3*, i[3456]86-*-osf1mk* + targets obsolete. + * config/i386/i386mach.mh, config/i386/nm-i386mach.h, + config/i386/xm-i386mach.h, config/i386/i386m3.mh, + config/i386/i386m3.mt, config/i386/nm-m3.h, + config/i386/tm-i386m3.h, config/i386/xm-i386m3.h, + config/i386/i386mk.mh, config/i386/i386mk.mt, + config/i386/tm-i386mk.h, config/i386/xm-i386mk.h: Make files + obsolete. + * i386mach-nat.c, i386m3-nat.c: Make files obsolete. + * Makefile.in (ALLDEPFILES): Remove i386mach.c i386m3-nat.c + (i386mach-nat.o, i386m3-nat.o):Make targets obsolete. + +2002-08-18 Andrew Cagney <ac131313@redhat.com> + + * config/pa/tm-hppa.h (hppa_store_return_value): Declare. + (hppa_value_returned_from_stack): Declare. + (hppa_extract_return_value): Declare. + * config/pa/hppa.mt: New file. + * configure.tgt: Recognize hppa*-*-*. + * MAINTAINERS: Change HPPA target to hppa-elf. Still broken. + +2002-08-18 Mark Kettenis <kettenis@gnu.org> + + * i386-sol2-tdep.c (_initialize_i386_sol2_tdep): Fix typo in + comment. + +2002-08-17 Mark Kettenis <kettenis@gnu.org> + + * top.c (gdb_rl_operate_and_get_next): Make sure + operate-and-get-next functions correctly even when the history + list is completely filled. + +2002-08-18 Andrew Cagney <ac131313@redhat.com> + + * MAINTAINERS (Target Instruction Set Architectures): Rename + Target/Architectures. Replace vax-dec-vms5.5 with vax-netbsd. + Replace s390-linux with s390-linux-gnu. Remove i386-aout, + mcore-pe, mips64-elf, sparc64-elf. Remove i586-pc-msdosdjgpp, + already listed under Host/Native. + + * configure.tgt: Combine i[3456]86-*-coff*, i[3456]86-*-elf*, + i[3456]86-*-pe*, and i[3456]86-*-aout* into i[3456]86-*-*. Add + mips*-*-*. + +2002-08-17 Andrew Cagney <ac131313@redhat.com> + + * config/ia64/ia64.mt: New file. + * config/alpha/alpha.mt: New file. + * MAINTAINERS: Change the alpha target to alpha-elf and IA-64 to + ia64-linux-gnu. Mention that ia64-elf is broken. + * configure.tgt: Add alpha*-*-* and ia64*-*-* patterns. + +2002-08-17 Mark Kettenis <kettenis@elgar.kettenis.dyndns.org> + + * i386-tdep.c (i386_svr4_init_abi, i386_nw_init_abi): Use + generic_func_frame_valid instead of func_frame_valid. + +2002-08-16 Joel Brobecker <brobecker@gnat.com> + + * alpha-osf1-tdep.c (alpha_osf1_init_abi): Unfortunately, + procfs appears to be broken when debugging on multi-processor + machines. So enable software single stepping in order to avoid + using the procfs interface to do next/step operations, using + internal breakpoints instead. + + * infrun.c (handle_inferior_event): Readjust the stop_pc by + DECR_PC_AFTER_BREAK when hitting a single step breakpoint, to + make this pc address equal to the value it would have if the + system stepping capability was used. Also set a new flag used + to ensure that we don't readjust the PC one more time later. + + * breakpoint.c (bpstat_stop_status): Do not adjust the PC + address by DECR_PC_AFTER_BREAK when software single step is + in use for this architecture, as this has already been taken + care of in handle_inferior_event(). + +2002-08-16 Joel Brobecker <brobecker@gnat.com> + + * infrun.c (handle_inferior_event): Minor reformatting, to make + a rather long condition expression easier to read. + +2002-08-16 Andrew Cagney <ac131313@redhat.com> + + * Makefile.in (gdbtk.o): Move to end of file. + (gdbtk-bp.o, gdbtk-cmds.o): Ditto. + (gdbtk-hooks.o, gdbtk-register.o): Ditto. + (gdbtk-stack.o, gdbtk-varobj.o): Ditto. + (gdbtk-wrapper.o, gdbres.o): Ditto. + +2002-08-16 Andrew Cagney <ac131313@redhat.com> + + * Makefile.in (copying.o): Separate out compile rule. + (hpux-thread.o, procfs.o, signals.o): Ditto. + (v850ice.o, z8k-tdep.o): Ditto. + (tui-file.o): Move to TUI section. + (xdr_ptrace.o, xdr_rdb.o, xdr_ld.o): Move to separate section. + (nindy.o, Onindy.o, ttyflush.o): Move to separate section. + +2002-08-16 Joel Brobecker <brobecker@gnat.com> + + * i386-tdep.c (i386_pe_skip_trampoline_code): renamed from + skip_trampoline_code, for better namespace-proofing. + + * i386-tdep.h (i386_pe_skip_trampoline_code): Add declaration. + +2002-08-16 Joel Brobecker <brobecker@gnat.com> + + * config/i386/tm-cygwin.h: Remove some "#if 0"'ed macros. + +2002-08-16 Joel Brobecker <brobecker@gnat.com> + + * infrun.c (handle_inferior_event): When receiving a SIGTRAP + signal, check whether we hit a breakpoint before checking for a + single step breakpoint. Otherwise, GDB fails to notice that a + breakpoint has been hit when stepping onto a breakpoint. + +2002-08-16 Keith Seitz <keiths@redhat.com> + + * gdb-events.sh (clear_gdb_event_hooks): New function. + * gdb-events.c: Regenerate. + * gdb-events.h: Regenerate. + +2002-08-16 Andrew Cagney <ac131313@redhat.com> + + * breakpoint.c (bpstat_stop_status): Rename not_a_breakpoint to + not_a_sw_breakpoint. + * breakpoint.h (bpstat_stop_status): Add parameter names. + +2002-08-16 Grace Sainsbury <graces@redhat.com> + + * remote.c (remote_insert_hw_breakpoint) + (remote_remove_hw_breakpoint): Fix calculation of length field + for Z-packet. + +2002-08-15 Michael Snyder <msnyder@redhat.com> + + * irix5-nat.c (supply_gregset): Allocate plenty-big buffer + (32 bytes) instead of using MAX_REGISTER_RAW_SIZE. + (supply_fpregset): Ditto. + + * config/mips/tm-mips.h (REGISTER_CONVERT_TO_VIRTUAL, + REGISTER_CONVERT_TO_RAW, REGISTER_CONVERTIBLE, + MAX_REGISTER_RAW_SIZE, MAX_REGISTER_VIRTUAL_SIZE): Delete. + (TARGET_READ_SP): Delete. + (DO_REGISTERS_INFO): Delete. + (FUNCTION_START_OFFSET, IN_SIGTRAMP, REGISTER_VIRTUAL_SIZE): + Delete. + (REGISTER_CONVERT_FROM_TYPE, REGISTER_CONVERT_TO_TYPE): Convert + from macros to functions. + + * mips-tdep.c (mips_gdbarch_init): Set the above in the gdbarch. + (mips_register_convertible, mips_register_convert_to_virtual, + mips_register_convert_to_raw): Make static. + (mips_read_sp): New function. + (mips_gdbarch_init): Set gdbarch read_sp to mips_read_sp. + (mips_do_registers_info): Make static. + (mips_gdbarch_init): Insert mips_do_registers_info into gdbarch. + (in_sigtramp): Make static, rename to mips_pc_in_sigtramp. + (mips_register_convert_from_type, mips_register_convert_to_type): + New functions. + (mips_gdbarch_init): Set up function_start_offset, + register_virtual_size, pc_in_sigtramp. + +2002-08-15 Andrew Cagney <ac131313@redhat.com> + + * infcmd.c (vector_info): New function. + (_initialize_infcmd): Add command "info vector". + (print_vector_info): New function. + + * gdbarch.sh (PRINT_VECTOR_INFO): New method + * gdbarch.h, gdbarch.c: Regenerate. + +2002-08-15 Andrew Cagney <ac131313@redhat.com> + + * infcmd.c (do_registers_info): Rename parameter ``fpregs'' to + ``print_all''. Only print vector registers when ``print_all''. + +2002-08-15 Andrew Cagney <ac131313@redhat.com> + + * i387-tdep.h (i387_print_float_info): Add `args' parameter. + * i387-tdep.c (i387_print_float_info): Add `args' parameter. + + * gdbarch.sh (PRINT_FLOAT_INFO): Change to a predicate method. + Add `args' parameter. + * gdbarch.h, gdbarch.c: Regenerate. + + * arm-tdep.c (arm_print_float_info): Add the parameter `args'. + + * infcmd.c (float_info): Call print_float_info. + (print_float_info): New function. By default, print the + floating-point registers. + + * arch-utils.h (default_print_float_info): Delete declaration. + * arch-utils.c (default_print_float_info): Delete function. + +2002-08-16 Mark Kettenis <kettenis@gnu.org> + + * config/i386/nm-i386v.h (FLOAT_INFO): Remove already commented + out define. + + * i387-tdep.c (i387_print_float_info): Add comment about ignoring + FRAME. + + * NEWS: Mention that the i[3456]-*-aix target has been made obsolete. + * configure.host: Make i[3456]86-*-aix host obsolete. + * configure.tgt: Make i[3456]86-*-aix target obsolete. + * config/i386/i386aix.mh, config/i386/i386aix.mt, + config/i386/nm-i386aix.h, condig/i386/tm-i386aix.h, + config/i386/xm-i386aix.h: Make files obsolete. + * i386aix-nat.c: Make file obsolete. + * Makefile.in (ALLDEPFILES): Remove i386aix-nat.c. + (i386aix-nat.o): Make target obsolete. + + * config/i386/nm-gnu.h: Removed. + * config/i386/nm-i386gnu.h: New file. + (THREAD_STATE_FLAVOR, THREAD_STATE_SIZE, + THREAD_STATE_SET_TRACED, THREAD_STATE_CLEAR_STATE, ATTACH_DETACH): + Moved here from ... + * config/i386/tm-i386gnu.h: ... here. Removed. + * config/i386/xm-i386gnu.h: Removed. + * config/i386/i386gnu.mh (XM_FILE): Set to xm-i386.h. + (NAT_FILE): Set to nm-i386gnu.h. + * config/i386/i386gnu.mt (TDEPFILES): Add i386gnu-tdep.o. + * i386-tdep.c: New file. + * Makefile.in (ALLDEPFILES): Add i386gnu-nat.c and i386gnu-tdep.c. + (i386gnu-tdep.o): Specify dependencies. + +2002-08-15 Mark Kettenis <kettenis@gnu.org> + + * config/i386/tm-i386sco5.h: Include "i386/tm-i386v4.h" instead of + "i386/tm-i386.h", "i386/tm-i386v.h" and "config/tm-sysv.h". + Adjust a few comments to reflect reality a bit closer. + (KERNEL_U_SIZE, TARGET_HAS_HARDWARE_WATCHPOINTS, + TARGET_CAN_USE_HARDWARE_WATCHPOINT, HAVE_CONTINUEABLE_WATCHPOINT, + HAVE_STEPPABLE_WATCHPOINT, STOPPED_BY_WATCHPOINT, + target_insert_watchpoint, target_remove_watchpoint): + Move defines to ... + * config/i386/nm-i386sco5.h: ... here. + (kernel_u_size): Add prototype. Improve a few comments and add + protection against multiple inclusion. + + * config/i386/nm-i386sco.h (FLOAT_INFO): Remove already commented + out define. + + * uw-thread.c (SP_ARG0): Define if not already defined. + * config/i386/tm-i386.h (SO_ARG0): Remove define. + + * config/i386/tm-i386v4.h (HAVE_I387_REGS): Remove define. + + * config/i386/tm-i386.h: Don't include "regcache.h". + + * i387-tdep.h (i387_print_float_info): New prototype. + * i387-tdep.c (print_i387_value, print_i387_ext, + print_i387_status_word, print_i387_control_word): Add `struct + ui_file *' argument and use it for output. + (i387_print_float_info): Renamed from i387_float_info. Add + `struct gdbarch *' and `struct ui_file *' arguments and use the + latter for output. + * i386-tdep.c: Include "i387-tdep.h". + (i386_gdbarch_init): Set print_float_info. + * config/i386/tm-i386.h (i387_float_info): Remove prototype. + (FLOAT_INFO): Remove define. + +2002-08-13 Michael Snyder <msnyder@redhat.com> + + * mips-tdep.c (mips_push_arguments): Rename to + mips_eabi_push_arguments, and tune for EABI. + (MIPS_REGS_HAVE_HOME_P): Delete. + (struct gdbarch_tdep): Remove mips_regs_have_home_p field. + (mips_gdbarch_init): Set gdbarch push_arguments for eabi. + Delete references to mips_regs_have_home_p. + +2002-08-14 Keith Seitz <keiths@redhat.com> + + * Makefile.in (install-gdbtk): Create insight plugin directory. + Install plugins.tcl file. + +2002-08-14 Keith Seitz <keiths@redhat.com> + + * configure.in: Move SUBDIRS to near top of the file so that + --enable options may add things to it. + If gdbtk is enabled, add gdbtk directory to SUBDIRS and configdirs. + * configure: Regenerate. + +2002-08-13 Michael Snyder <msnyder@redhat.com> + + * mips-tdep.c (mips_o32o64_push_arguments): New function, + cloned from mips_push_arguments, tuned for o32/o64 ABI. + (mips_gdbarch_init): Set gdbarch_push_arguments to new func. + +2002-08-13 Andrew Cagney <ac131313@redhat.com> + + * vax-tdep.c (vax_get_saved_register): Delete function. + (vax_gdbarch_init): Update. + * ns32k-tdep.c (ns32k_get_saved_register): Delete function. + (ns32k_gdbarch_init): Update. + * alpha-tdep.c (alpha_get_saved_register): Delete function. + (alpha_gdbarch_init): Update. + +2002-08-13 Andrew Cagney <cagney@redhat.com> + + * regcache.c (init_regcache_descr): Overallocate the + raw_register_valid_p array including space for NUM_PSEUDO_REGS. + (registers_changed): Replace NUM_REGS+NUM_PSEUDO_REGS with + nr_raw_registers. + (set_register_cached): Add range checking assertions. Use + current_regcache. + +2002-08-13 Mark Kettenis <kettenis@gnu.org> + + * i386-tdep.c (i386_stab_reg_to_regnum): Return correct register + numbers for MMX registers. + +2002-08-13 Andrew Cagney <cagney@redhat.com> + + * i386-tdep.c (i386_gdbarch_init): Use + generic_unwind_get_saved_register. + +2002-08-13 Kevin Buettner <kevinb@redhat.com> + + * procfs.c (procfs_can_use_hw_breakpoint): New function. + (init_procfs_ops): Define ``to_can_use_hw_breakpoint'' for procfs + target vector. + * config/mips/nm-irix5.h (TARGET_CAN_USE_HARDWARE_WATCHPOINT): + Delete. Add comment regarding this now-deleted target method. + +2002-08-13 Stephane Carrez <stcarrez@nerim.fr> + + * m68hc11-tdep.c (M68HC12_NUM_PSEUDO_REGS): New define. + (M68HC12_HARD_PC_REGNUM): Define specific PC for 68HC12 (pseudo reg). + (m68hc11_pseudo_register_read): Compute the 68HC12 PC using the + real PC and the page number (if it's within the memory bank window). + (m68hc11_pseudo_register_write): Likewise when saving. + (m68hc11_register_name): Name the virtual pc 'pc' and the real one ppc. + (m68hc11_register_virtual_type): Return uint32 for virtual pc. + (m68hc11_register_raw_size): And use 32-bit for it. + (m68hc11_gdbarch_init): Use 32-bit address for 68HC12 if the + 16K memory bank is used by the prog; also use the virtual pc. + +2002-08-13 Stephane Carrez <stcarrez@nerim.fr> + + * m68hc11-tdep.c (m68hc11_elf_make_msymbol_special): New function. + (m68hc11_gdbarch_init): Install it in gdbarch. + (MSYMBOL_SET_RTC, MSYMBOL_SET_RTI): New to set symbol specific flags. + (MSYMBOL_IS_RTC, MSYMBOL_IS_RTI): New to test these flags. + (MSYMBOL_SIZE): New for documentation. + (insn_return_kind): Enum to specify how a function returns. + (frame_extra_info): Cleanup and record the return mode. + (gdbarch_tdep, USE_PAGE_REGISTER): New to control the use of page + register in address computation. + (m68hc11_get_return_insn): New to obtain the return instruction used + by the function. + (m68hc11_frame_init_saved_regs): Take into account the return + instruction used by the function for far and interrupt functions. + (m68hc11_init_extra_frame_info): Take into account page register. + (m68hc11_frame_args_address): Adjust according to the return mode. + (show_regs): Print page register only when it's used. + +2002-08-13 Stephane Carrez <stcarrez@nerim.fr> + + * m68hc11-tdep.c (HARD_PAGE_REGNUM): Define for 68HC12 page register. + (M68HC11_LAST_HARD_REG, m68hc11_register_names): Update. + (m68hc11_register_virtual_type): Return a 8-bit type for 8-bit + registers. + (m68hc11_register_raw_size): Likewise. + +2002-08-13 Andrew Cagney <cagney@redhat.com> + + * i386-tdep.c (i386_register_name): Handle mmx registers. + (mmx_regnum_p): New function. + (i386_mmx_names): New array. + (mmx_num_regs): New variable. + (i386_pseudo_register_read): New function. + (i386_pseudo_register_write): New function. + (mmx_regnum_to_fp_regnum): New function. Code from Fernando Nasser. + + * regcache.c (regcache_raw_read_unsigned): New function. + (regcache_raw_read_signed): New function. + * regcache.h (regcache_raw_read_unsigned): Declare. + (regcache_raw_read_signed): Declare. + +2002-08-13 Andrew Cagney <cagney@redhat.com> + + * regcache.c (regcache_raw_read_as_address): Delete function. + (regcache_cooked_read_signed): New function. + (regcache_cooked_read_unsigned): New function. + * regcache.h (regcache_cooked_read_signed): Declare. + (regcache_cooked_read_unsigned): Declare. + (regcache_raw_read_as_address): Delete declaration. + + * blockframe.c (generic_read_register_dummy): Use + regcache_cooked_read_unsigned. + * i386-tdep.c (i386_extract_struct_value_address): Use + regcache_cooked_read_unsigned. + +2002-08-13 Stephane Carrez <stcarrez@nerim.fr> + + * m68hc11-tdep.c (m68hc11_gdbarch_init): Set int, double and long + double sizes according to ELF ABI flags. + (gdbarch_tdep): Record elf_flags. + +2002-08-13 Stephane Carrez <stcarrez@nerim.fr> + + * m68hc11-tdep.c (M6812_OP_PSHX, M6812_OP_PSHY): New defines. + (m6812_prolog): They can appear in 68HC12 function prologue. + (m68hc11_frame_chain): Cleanup. + +2002-08-12 Andrew Cagney <cagney@redhat.com> + + * i386-tdep.h (i386_register_byte, i386_register_raw_size): Delete + declarations. + * i386-linux-tdep.c (i386_linux_register_byte): Delete function. + (i386_linux_register_raw_size): Delete function. + (i386_linux_init_abi): Update. + * i386-tdep.c (i386_register_raw_size): Delete function. + (i386_register_byte): Delete function. + (i386_gdbarch_init): Update. + (i386_register_size): Delete array. + (i386_register_offset): Delete array. + + * config/i386/tm-symmetry.h (REGISTER_BYTE): Delete macro. + (REGISTER_RAW_SIZE): Delete macro. + * config/i386/tm-ptx.h (REGISTER_RAW_SIZE): Delete macro. + (REGISTER_BYTE): Delete macro. + +2002-08-11 Aidan Skinner <aidan@velvet.net> + + * ada-lang.c (ada_lookup_partial_symbol) + (to_fixed_variant_branch_type) (find_line_in_linetable): Fix + prototype names so that grep ^func works properly. + + * ada-lang.c (ada_array_element_type) + (ada_lookup_partial_symbol): Fix typos in parameter list. + + * ada-valprint.c (val_print_packed_array_elements) (ada_val_print_1): + Fix prototype names so that grep ^func works properly. + +2002-08-10 Andrew Cagney <cagney@redhat.com> + Elena Zannoni <ezannoni@redhat.com> + Martin M. Hunt <hunt@redhat.com> + + * gdbtypes.c (build_builtin_type_vec128): Set the vector bit. + (build_builtin_type_vec128i): Set the vector bit. + * gdbtypes.h (builtin_type_vec64, builtin_type_vec64i): Declare. + * gdbtypes.c (builtin_type_vec64, builtin_type_vec64i): Define. + (build_builtin_type_vec64): New function. + (build_builtin_type_vec64i): New function. + (build_gdbtypes): Initialize builtin_type_vec64 and + builtin_type_vec64i. + +2002-08-09 Andrew Cagney <cagney@redhat.com> + + * regcache.c (regcache_dump): Compare the register offset + with REGISTER_BYTE. + * arch-utils.c (generic_register_byte): New function. + * arch-utils.h (generic_register_byte): Declare. + * gdbarch.sh (REGISTER_BYTE): Default to generic_register_byte. + * gdbarch.h, gdbarch.c: Regenerate. + +2002-08-09 Andrew Cagney <cagney@redhat.com> + + * regcache.c: Include "gdbcmd.h" + (_initialize_regcache): Add commands "maintenance print + registers", "maintenance print raw-registers" and "maintenance + print cooked-registers". + (enum regcache_dump_what): Define. + (dump_endian_bytes): New function. + (regcache_dump): New function. + (regcache_print): New function. + (maintenance_print_registers): New function. + (maintenance_print_raw_registers): New function. + (maintenance_print_cooked_registers): New function. + * Makefile.in (regcache.o): Update dependencies. + +2002-08-09 Michael Snyder <msnyder@redhat.com> + + * mips-tdep.c (ROUND_DOWN, ROUND_UP): Move to global scope. + (mips_push_arguments): Correct some comments. Use paddr_nz + for printing addresses in debug output. Replace static + allocation using MAX_REGISTER_RAW_SIZE with alloca. + (mips_n32n64_push_arguments): New function, cloned from + mips_push_arguments and tuned for the n32/n64 ABI. + (mips_push_register): Buffer needs dynamic allocation. + (mips_print_register): Ditto. + (do_gp_register_row): Ditto. + (mips_store_return_value): Ditto. + (mips_gdbarch_init): Set gdbarch_push_arguments per ABI. + +2002-08-09 Don Howard <dhoward@redhat.com> + + * memattr.c (mem_info_command): Print special case of upper bound + as max CORE_ADDR + 1. + +2002-08-08 Michael Snyder <msnyder@redhat.com> + + * mips-tdep.c (mips_n32n64_use_struct_convention): N32 only + returns structs by ref if they're too big to fit in two registers. + +2002-08-09 Kevin Buettner <kevinb@redhat.com> + + * mips-tdep.c (mips_init_extra_frame_info): Initialize SP_REGNUM's + saved regs value. + (read_next_frame_reg): Call FRAME_INIT_SAVED_REGS instead of + mips_find_saved_regs(). + (mips_pop_frame): Likewise. + +2002-08-09 Kevin Buettner <kevinb@redhat.com> + + * blockframe.c (frame_saved_regs_register_unwind): Revise + PC_IN_CALL_DUMMY assertion to only apply when generic dummy + frames are in use. + +2002-08-09 Grace Sainsbury <graces@redhat.com> + + * remote.c: (remote_wait, remote_async_wait): Add check for awatch + T-packets; the 'a' is not taken as a register number. + (remote_check_watch_resources, remote_stopped_by_watchpoint) + (remote_stopped_data_address): New functions; add to target + vector. + (remote_insert_hw_breakpoint, remote_remove_hw_breakpoint): Change + prototypes to match other implementations of this + function. replace integer argument with pointer -- the length + field in the Z-packet is the length of what is pointed to or 1 if + pointer is null. Add to target vector. + (remote_insert_watchpoint, remote_remove_watchpoint): Add to + target vector. + + From Mark Salter: + * remote.c (remote_wait): Add support to extract optional + watchpoint information from T-packet. Ignore unrecognized + optional info in T-packet. + (remote_async_wait): Ditto. + +2002-08-09 Corinna Vinschen <vinschen@redhat.com> + + * cli/cli-dump.c: Change fopen modes to use binary open modes + as defined in include/fopen-bin.h throughout. + +2002-08-08 Michael Snyder <msnyder@redhat.com> + + * mips-tdep.c: Minor whitespace and indentation clean-ups. + +2002-08-08 Kevin Buettner <kevinb@redhat.com> + + * doublest.c (store_floating): Avoid floatformat_from_doublest() + assertion failure by returning early after a warning. + +2002-08-08 Kevin Buettner <kevinb@redhat.com> + + * mips-tdep.c (mips_find_saved_regs): Make static. + (mips_frame_init_saved_regs): New function. + (mips_gdbarch_init): Setup FRAME_INIT_SAVED_REGS method. + * config/mips/tm-mips.h (FRAME_INIT_SAVED_REGS): Delete macro. + (mips_find_saved_regs): Delete declaration. + +2002-08-08 Grace Sainsbury <graces@redhat.com> + + * remote.c (remote_wait, remote_async_wait): Change + thread_num from int to ULONGEST. + (unpack_varlen_hex): Change result parameter from + int * to ULONGEST *. + +2002-08-08 Andrew Cagney <ac131313@redhat.com> + + * configure.tgt: Replace powerpc-*-sysv*, powerpc-*-elf*, + powerpcle-*-eabi*, powerpcle-*-sysv* and powerpcle-*-elf* with + powerpc*-*-*. + * MAINTAINERS: Remove redundant rs6000-ibm-aix4.1 target. + +2002-08-08 Andrew Cagney <cagney@redhat.com> + + * gcore.c (override_derive_stack_segment): Delete variable. + (preempt_derive_stack_segment): Delete function. + (derive_stack_segment): Delete function. + (default_derive_stack_segment): Renamed to derive_stack_segment. + (override_derive_heap_segment): Delete variable. + (preempt_derive_heap_segment): Delete function. + (derive_heap_segment): Delete function. + (default_derive_heap_segment): Rename to derive_heap_segment. + +2002-08-06 Michael Snyder <msnyder@redhat.com> + + * config/mips/tm-mips.h: Remove #define USE_STRUCT_CONVENTION. + * mips-tdep.c (mips_EABI_use_struct_convention, + mips_OABI_use_struct_convention, mips_NABI_use_struct_convention): + New functions. (mips_use_struct_convention): Delete. + (mips_gdbarch_init): set use_gdbarch_convention. + +2002-08-06 Michael Snyder <msnyder@redhat.com> + + * mips-tdep.c: gdbarch-ify reg_struct_has_addr. + (mips_eabi_reg_struct_has_addr, mips_n32n64_reg_struct_has_addr, + mips_o32_reg_struct_has_addr): New functions. + (mips_gdbarch_init): Set gdbarch reg_struct_has_addr. + +2002-08-07 Andrew Cagney <ac131313@redhat.com> + + * regcache.c (pseudo_register): Delete function. + (fetch_register): Delete function. + (store_register): Delete function. + (regcache_raw_read, legacy_read_register_gen): Use + target_fetch_registers instead of fetch_register. + (legacy_write_register_gen, regcache_raw_write): Use + target_store_register instead of store_register. + (write_register_bytes): Ditto. + + * gdbarch.sh (FETCH_PSEUDO_REGISTER): Delete. + (STORE_PSEUDO_REGISTER): Delete. + * gdbarch.h, gdbarch.c: Regenerate. + +2002-08-06 Corinna Vinschen <vinschen@redhat.com> + + * cli/cli-dump.c (add_dump_command): Explicitely use "b" flag to + write dump file binary. + +2002-08-05 Michael Snyder <msnyder@redhat.com> + + * mips-tdep.c (mips_find_saved_regs): Adjust stack according + to MIPS_SAVED_REGSIZE, not GDB_TARGET_IS_MIPS64. Enhance comment. + (mips_gdbarch_init): Set N32 target to be mips64. + +2002-08-06 Kevin Buettner <kevinb@redhat.com> + + * frame.c (find_saved_register): Break out of loop once saved + register address is found. Don't mention sparc in loop comment + anymore. + +2002-08-06 Kevin Buettner <kevinb@redhat.com> + + * mips-tdep.c (mips_gdbarch_init): For the N32 ABI, set + mips_default_saved_regsize to 8. + +2002-08-06 Andrew Cagney <ac131313@redhat.com> + + * gcore.c: Do not include <sys/procfs.h>. + * Makefile.in (gcore.o): Update dependencies. + +2002-08-06 Andrew Cagney <cagney@redhat.com> + + * configure.tgt: Make arc-*-* obsolete. + * NEWS: Mention that arc-*-* has been identifed as obsolete. + * MAINTAINERS: Make arc-elf obsolete. + * arc-tdep.c: Make file obsolete. + * config/arc/arc.mt: Ditto. + * config/arc/tm-arc.h: Ditto. + +2002-08-05 Theodore A. Roth <troth@verinet.com> + + * avr-tdep.c (avr_skip_prologue): Fix to return the correct pc. + +2002-08-05 Andrew Cagney <ac131313@redhat.com> + + * mcore-tdep.c (mcore_gdbarch_init): Use + generic_unwind_get_saved_register instead of + generic_get_saved_register. + * v850-tdep.c (v850_gdbarch_init): Ditto. + * frv-tdep.c (frv_gdbarch_init): Ditto. + * mn10300-tdep.c (mn10300_gdbarch_init): Ditto. + * s390-tdep.c (s390_gdbarch_init): Ditto. + * d10v-tdep.c (d10v_gdbarch_init): Ditto. + * config/mn10200/tm-mn10200.h (GET_SAVED_REGISTER): Ditto. + * config/h8300/tm-h8300.h (GET_SAVED_REGISTER): Ditto. + +2002-08-05 Joel Brobecker <brobecker@gnat.com> + + * objfiles.h: Add missing #include "symfile.h" + + * Makefile.in (objfiles_h): Add dependency on symfile.h and dependents. + +2002-08-04 Andrew Cagney <ac131313@redhat.com> + + From 2002-08-01 david carlton <carlton@math.stanford.edu>: + * hpread.c (hpread_read_struct_type): Deleted superfluous setting + of FIELD_BITSIZE. + +2002-08-04 Daniel Jacobowitz <drow@mvista.com> + + * NEWS: Cleanup and nitpick. + +2002-08-03 Andrew Cagney <ac131313@redhat.com> + + * NEWS: Cleanup. Use *-linux*-gnu*. Only use `*' for headings. + +2002-08-03 Andrew Cagney <ac131313@redhat.com> + + * Makefile.in (gdbtk-bp.o): Update dependencies. + (gdbtk-register.o): Ditto. + (gdbtk-varobj.o): Ditto. + +2002-08-03 Andrew Cagney <cagney@redhat.com> + + * m68hc11-tdep.c (m68hc11_pseudo_register_read): Replace + m68hc11_fetch_pseudo_register. + (m68hc11_pseudo_register_write): Replace + m68hc11_store_pseudo_register. + (m68hc11_gdbarch_init): Update. + +Fri Aug 2 15:53:50 2002 Andrew Cagney <cagney@redhat.com> + + * gdbarch.sh: Include "gdb_string.h". + * gdbarch.c: Regenerate. + + * regcache.c: Include "gdb_string.h". + * ax-general.c: Ditto. + * varobj.c: Ditto. + * std-regs.c: Ditto. + * fbsd-proc.c: Ditto. + * thread.c: Ditto. + + * Makefile.in (regcache.o): Update dependencies. + (thread.o, gdbarch.o): Ditto. + (ax-general.o, gdbarch.o): Ditto. + (varobj.o, std-regs.o): Ditto. + (fbsd-proc.o): Specify dependencies. + +2002-08-02 Andrew Cagney <cagney@redhat.com> + + * regcache.c (regcache_cooked_read): Rename rawnum parameter to + regnum. + (regcache_cooked_write): Ditto. + +2002-08-02 Andrew Cagney <ac131313@redhat.com> + + * regcache.c (regcache_cooked_read): New function. + (regcache_cooked_write): New function. + (read_register_gen): Rewrite using regcache_cooked_read. + (write_register_gen): Rewrite using regcache_cooked_write. + + * regcache.h (regcache_cooked_read, regcache_cooked_write): + Declare. + +2002-08-02 Andrew Cagney <cagney@redhat.com> + + * gdbarch.sh (pseudo_register_read, pseudo_register_write): + Replace the architecture methods register_read and register_write. + * gdbarch.h, gdbarch.c: Regenerate. + * regcache.c (init_regcache_descr): Update. + (read_register_gen): Update. + (write_register_gen): Update. + (supply_register): Update comment. + + * sh-tdep.c (sh_gdbarch_init): Update. + (sh_pseudo_register_read, sh64_pseudo_register_read): Add + `regcache' and `gdbarch' parameters. Make `buffer' a void + pointer. Update code. + (sh_pseudo_register_write, sh64_pseudo_register_write): Add + `regcache' and `gdbarch' parameters. Make `buffer' a constant + void pointer. Update code. + (sh64_register_write): Delete. + (sh4_register_read): Delete. + (sh64_register_read): Delete. + (sh4_register_write): Delete. + (sh_sh4_register_convert_to_raw): Make `from' parameter a constant + void pointer, `to' parameter a void pointer. + (sh_sh64_register_convert_to_raw): Ditto. + +2002-08-01 Kevin Buettner <kevinb@redhat.com> + + * mips-tdep.c (mips_register_virtual_type): Use architecture + invariant return values. + +2002-08-01 Andrew Cagney <cagney@redhat.com> + + * linux-proc.c: Include "gdb_string.h". + * Makefile.in (linux-proc.o): Update dependency list. + +2002-08-01 Kevin Buettner <kevinb@redhat.com> + + * mips-tdep.c (mips_gdbarch_init): Add comments. Fix typo in + comment. + +2002-08-01 Grace Sainsbury <graces@redhat.com> + + * target.h: Add to_insert_hw_breakpoint, to_remove_hw_breakpoint, + to_insert_watchpoint, to_remove_watchpoint, + to_stopped_by_watchpoint, to_stopped_data_address, + to_region_size_ok_for_hw_watchpoint, to_can_use_hw_breakpoint to + target vecctor. Define their corresponding macros so they call + them. + + * target.c: Add default and debug versions of for + to_insert_hw_breakpoint, to_remove_hw_breakpoint, + to_insert_watchpoint, to_remove_watchpoint, + to_stopped_by_watchpoint, to_stopped_data_address, + to_region_size_ok_for_hw_watchpoint, to_can_use_hw_breakpoint. + +2002-08-01 Kevin Buettner <kevinb@redhat.com> + + * mips-tdep.c (mips_register_virtual_type): New function. + (mips_gdbarch_init): Register mips_register_virtual_type() + with gdbarch machinery. + * config/mips/tm-irix6.h (mips/tm-bigmips64.h): Include + this file instead of tm-bigmips.h. + (MIPS_REGSIZE): Delete this macro. + (REGISTER_VIRTUAL_TYPE): Delete macro. Undef macro so that + multiarch version in mips-tdep.c will be found. + +2002-08-01 Andrew Cagney <cagney@redhat.com> + + * NEWS: Menion that CHILL has been made obsolete. + + * gdbtypes.c (chill_varying_type): Make chill references obsolete. + * stabsread.c (read_range_type): Ditto. + * gdbtypes.h: Ditto. + * language.c (binop_type_check): Ditto. + (binop_result_type): Ditto. + (integral_type): Ditto. + (character_type): Ditto. + (string_type): Ditto. + (boolean_type): Ditto. + (structured_type): Ditto. + (lang_bool_type): Ditto. + (binop_type_check): Ditto. + * language.h (_LANG_chill): Ditto. + * dwarfread.c (set_cu_language): Ditto. + * dwarfread.c (CHILL_PRODUCER): Ditto. + * dwarfread.c (handle_producer): Ditto. + * expression.h (enum exp_opcode): Ditto. + * eval.c: Ditto for comments. + * typeprint.c (typedef_print) [_LANG_chill]: Ditto. + * expprint.c (print_subexp): Ditto. + (print_subexp): Ditto. + * valops.c (value_cast): Ditto. + (search_struct_field): Ditto. + * value.h (COERCE_VARYING_ARRAY): Ditto. + * symfile.c (init_filename_language_table): Ditto. + (add_psymbol_with_dem_name_to_list): Ditto. + * valarith.c (value_binop): Ditto. + (value_neg): Ditto. + * valops.c (value_slice): Ditto. + * symtab.h (union language_specific): Ditto. + (SYMBOL_INIT_LANGUAGE_SPECIFIC): Ditto. + (SYMBOL_DEMANGLED_NAME): Ditto. + (SYMBOL_CHILL_DEMANGLED_NAME): Ditto. + * defs.h (enum language): Ditto. + * symtab.c (got_symtab): Ditto. + * utils.c (fprintf_symbol_filtered): Ditto. + + * ch-typeprint.c: Make file obsolete. + * ch-valprint.c: Make file obsolete. + * ch-lang.h: Make file obsolete. + * ch-exp.c: Make file obsolete. + * ch-lang.c: Make file obsolete. + + * Makefile.in (FLAGS_TO_PASS): Do not pass CHILL or CHILLFLAGS or + CHILL_LIB. + (TARGET_FLAGS_TO_PASS): Ditto. + (CHILLFLAGS): Obsolete. + (CHILL): Obsolete. + (CHILL_FOR_TARGET): Obsolete. + (CHILL_LIB): Obsolete. + (SFILES): Remove ch-exp.c, ch-lang.c, ch-typeprint.c and + ch-valprint.c. + (HFILES_NO_SRCDIR): Remove ch-lang.h. + (COMMON_OBS): Remove ch-valprint.o, ch-typeprint.o, ch-exp.o and + ch-lang.o. + (ch-exp.o, ch-lang.o, ch-typeprint.o, ch-valprint.o): Delete + targets. + +2002-07-31 Joel Brobecker <brobecker@gnat.com> + + * dwarf2read.c (set_cu_language): Add handler for LANG_Ada95. + This does not change anything at the moment, but will be helpful + later when full Ada support is integrated. + +2002-07-31 Kevin Buettner <kevinb@redhat.com> + + * mips-tdep.c (_initialize_mips_tdep): Add "n64" to "set mips abi" + help message. + +2002-07-31 Kevin Buettner <kevinb@redhat.com> + + * mips-tdep.c (mips_push_arguments): Fetch gdbarch_tdep struct + and save it in a local variable. Use variable in later test. + +2002-07-31 Kevin Buettner <kevinb@redhat.com> + + * mips-tdep.c (mips_find_abi_section): Add N64 ABI recognition + test. (Thanks to Daniel Jacobowitz.) + +2002-07-31 Kevin Buettner <kevinb@redhat.com> + + * mips-tdep.c (enum mips_abi): Add MIPS_ABI_N64. + (mips_abi_strings): Add "n64". + (mips_gdbarch_init): Add test for n64 abi. Add MIPS_ABI_N64 case. + +2002-07-31 Kevin Buettner <kevinb@redhat.com> + + * config/mips/tm-irix6.h (MIPS_REGSIZE): Define to be 8. + (REGISTER_VIRTUAL_TYPE): Some registers are now 64 bits wide. + +2002-07-31 Kevin Buettner <kevinb@redhat.com> + + * utils.c (host_pointer_to_address, address_to_host_pointer): + Use gdb_assert() instead of explicit call to internal_error(). + +2002-07-30 Kevin Buettner <kevinb@redhat.com> + + * Makefile.in (rs6000-nat.o): Update dependencies. + + From Nicholas Duffek: + * Makefile.in (ALLDEPFILES): Add aix-thread.c. + (aix-thread.o): New rule. + * configure.host (gdb_host): Set to aix432 on AIX 4.3.2+. + * config/powerpc/aix432.mh: New file. + +2002-07-30 Daniel Jacobowitz <drow@mvista.com> + + * ppc-linux-tdep.c (ELF_NGREG, ELF_NFPREG, ELF_NVRREG) + (ELF_FPREGSET_SIZE, ELF_GREGSET_SIZE): New enums. + (fetch_core_registers, ppc_linux_supply_gregset) + (ppc_linux_supply_fpregset): New functions. + (ppc_linux_regset_core_fns): New. + (_initialize_ppc_linux_tdep): Call add_core_fns. + * ppc-tdep.h: Add prototypes for ppc_linux_supply_fpregset + and ppc_linux_supply_gregset. + * ppc-linux-nat.c (supply_gregset): Call ppc_linux_supply_gregset. + (supply_fpregset): Call ppc_linux_supply_fpregset. + * config/powerpc/linux.mh (NATDEPFILES): Remove core-regset.o and + corelow.o. + * config/powerpc/linux.mt (TDEPFILES): Add corelow.o. + +2002-07-30 Daniel Jacobowitz <drow@mvista.com> + + * symtab.c (lookup_symbol): Demangle before lowercasing. + +2002-07-30 Andrew Cagney <ac131313@redhat.com> + + * symtab.h: Replace #include "gdb_obstack.h" with opaque + declaration. + * cli/cli-cmds.c, cli/cli-script.c: Include "gdb_string.h". + * gnu-v3-abi.c, arc-tdep.c, cli/cli-decode.c: Ditto. + * avr-tdep.c, mon960-rom.c, i960-tdep.c: Ditto. + * arch-utils.c, cli/cli-setshow.c: Unconditionally include + "gdb_string.h". + * Makefile.in (cli-script.o, cli-cmds.o): Update dependencies. + (gnu-v3-abi.o, cli-setshow.o, i960-tdep.o): Ditto. + (cli-decode.o, mi-cmd-var.o, mi-cmd-disas.o): Ditto. + (avr-tdep.o, mon960-rom.o): Ditto. + (aout_stabs_gnu_h): Define. + (symtab_h): Remove $(gdb_obstack_h). + +2002-07-30 Jim Blandy <jimb@redhat.com> + + Patch from David Carlton <carlton@math.stanford.edu>: + * gdbinit.in: Move the `dir' commands that add GDB's own source + directory to the search path to the end, so that the `gdb' source + directory will be searched first. + +2002-07-29 Andrew Cagney <ac131313@redhat.com> + + * gdb_obstack.h: New file. + * symtab.h: Include "gdb_obstack.h" instead of "obstack.h". + (obstack_chunk_alloc, obstack_chunk_free): Delete macros. + * objfiles.h: Include "gdb_obstack.h". + * Makefile.in (gdb_obstack_h): Define. + (symtab_h): Add $(gdb_obstack_h). + (objfiles_h): Add $(gdb_obstack_h). + + * objfiles.c: Include "gdb_obstack.h" instead of "obstack.h". + * macrotab.c, cp-valprint.c, dbxread.c: Ditto. + * ch-typeprint.c, ch-valprint.c, dstread.c: Ditto. + * macroexp.c, p-typeprint.c, stabsread.c: Ditto. + * symtab.c, f-typeprint.c, mdebugread.c: Ditto. + * p-valprint.c, symmisc.c, typeprint.c: Ditto. + * symfile.c, coffread.c, c-typeprint.c: Ditto. + * buildsym.c, bcache.c, ada-typeprint.c: Ditto. + + * Makefile.in (bcache.o): Update dependencies. + (buildsym.o, c-typeprint.o, ch-typeprint.o): Ditto. + (ch-valprint.o, coffread.o, cp-valprint.o): Ditto. + (dbxread.o, dstread.o, f-typeprint.o): Ditto. + (objfiles.o, p-typeprint.o, p-valprint.o): Ditto. + (stabsread.o, symfile.o, symmisc.o): Ditto. + (symtab.o, typeprint.o, macroexp.o): Ditto. + (macrotab.o, mdebugread.o): Ditto. + (f_lang_h, coff_sym_h, coff_symconst_h): Define. + (coff_ecoff_h, aout_aout64_h): Define. + (aout_stabs_gnu_h, libaout_h): Define. + +2002-07-29 Andrew Cagney <cagney@redhat.com> + + * regcache.c (struct regcache_descr): Rename nr_registers to + nr_cooked_registers. Revise comments describing the structure + member fields. + (init_regcache_descr): Update. + (init_legacy_regcache_descr): Update. + (read_register_gen, write_register_gen): When a cooked register in + the raw register range, directly access the value from the raw + register cache. + +2002-07-29 Andrew Cagney <ac131313@redhat.com> + + * z8k-tdep.c: Do not include "obstack.h". + * h8300-tdep.c, h8500-tdep.c: Ditto. + * m68hc11-tdep.c, sh-tdep.c: Ditto. + * valprint.c, v850-tdep.c: Ditto. + * d10v-tdep.c, mn10300-tdep.c: Ditto. + * mn10200-tdep.c: Ditto. + + * Makefile.in (z8k-tdep.o): Update dependencies. + (m68hc11-tdep.o, valprint.o): Ditto. + (v850-tdep.o, d10v-tdep.o): Ditto. + (mn10300-tdep.o, sparc-tdep.o): Ditto. + (sh-tdep.o, h8500-tdep.o, h8300-tdep.o): Ditto. + (m32r-tdep.o, mn10200-tdep.o): Specify dependencies. + (sh_opc_h, gdb_sim_sh_h): Define. + (elf_sh_h, elf_bfd_h): Define. + (opcode_m68hc11_h): Define. + (OPCODES_SRC, OPCODES_DIR): define. + (OPCODES): Use $(OPCODES_DIR). + (gdb_sim_d10v_h): Rename sim_d10v_h. + (gdb_sim_arm_h): Rename sim_arm_h. + +2002-07-26 Kevin Buettner <kevinb@redhat.com> + + * utils.c (host_pointer_to_address, address_to_host_pointer): + Change internal_error() message to indicate function responsible + for the error. + +2002-07-26 Kevin Buettner <kevinb@redhat.com> + + * ui-out.c (ui_out_field_core_addr): Remove unnecessary cast in + calls to local_hex_string_custom(). + +2002-07-26 Kevin Buettner <kevinb@redhat.com> + + * irix5-nat.c: Move IRIX shared library support from here... + * solib-irix.c: ...to here. Revised substantially to work with + generic solib framework. + + * osabi.h (gdb_osabi): Add new enum constant GDB_OSABI_IRIX. + * osabi.c (gdb_osabi_names): Add corresponding string for Irix. + * mips-irix-tdep.c: New file. + + * Makefile.in (ALLDEPFILES): Add mips-irix-tdep.c and solib-irix.c. + (mips-irix-tdep.o, solib-irix.o): New rules. + * config/mips/irix5.mt (TDEPFILES): Add mips-irix-tdep.o, solib.o, + solib-irix.o. + * config/mips/irix6.mt (TDEPFILES): Likewise. + * config/mips/irix6.mh (NATDEPFILES): Remove solib.o. + +2002-07-26 Kevin Buettner <kevinb@redhat.com> + + * aix-thread.c (coff/internal.h, bfd/libcoff.h, pthread.h): Remove + disabled (via ``#if 0'') includes. + +2002-07-26 Kevin Buettner <kevinb@redhat.com> + + * aix-thread.c (special_register_p, supply_sprs64, supply_sprs32) + (fetch_regs_user_thread, fetch_regs_kernel_thread, fill_sprs64) + (fill_sprs32, store_regs_user_thread, store_regs_kernel_thread): + Add support for the fpscr register. + * rs6000-nat.c (regmap, fetch_inferior_registers) + (store_inferior_registers, fetch_core_registers): Likewise. + +2002-07-26 Kevin Buettner <kevinb@redhat.com> + + * rs6000-nat.c (language.h): Include. + (special_regs): Delete this array. + (regmap): New function. + (fetch_register, store_register): Use regmap() to map gdb + register numbers to ptrace register numbers. Also, use + outputs from regmap() to make decisions regarding type of + ptrace() call to make. In particular, don't compare against + FIRST_UISA_SP_REGNUM or LAST_UISA_SP_REGNUM. + (fetch_inferior_registers, store_inferior_registers): Where + possible, obtain register numbers from tdep struct. Don't + refer to FIRST_UISA_SP_REGNUM or LAST_UISA_SP_REGNUM. + * config/rs6000/tm-rs6000.h (FIRST_UISA_SP_REGNUM) + (LAST_UISA_SP_REGNUM): Delete. + +2002-07-25 Kevin Buettner <kevinb@redhat.com> + + * rs6000-nat.c (ppc-tdep.h): Include. + (fetch_registers, store_register, fetch_core_registers): Don't + access registers[] directly. Instead, use supply_register() or + regcache_collect() as appropriate. + (find_toc_address): Format hex address with local_hex_string(). + +2002-07-25 Andrew Cagney <ac131313@redhat.com> + + * config/djgpp/fnchange.lst: Rename bfd/elf32-fr30.c and + bfd/elf32-frv.c. + +2002-07-24 Tom Tromey <tromey@redhat.com> + + * jv-exp.y: Marked all strings with _(). + (ClassInstanceCreationExpression, ArrayCreationExpression): Use + internal_error. + (MethodInvocation, CastExpression, parse_number, yyerror, + java_type_from_name, push_expression_name, yylex): Typo fixes. + +2002-07-24 Daniel Jacobowitz <drow@mvista.com> + + * ui-file.c (struct tee_file, tee_file_new, tee_file_delete) + (tee_file_flush, tee_file_write, tee_file_fputs) + (tee_file_isatty): New. + * ui-file.h (tee_file_new): Add prototype. + +2002-07-24 Aidan Skinner <aidan@velvet.net> + + * ada-lang.c: Change k&r style function definitions to prototyped + form. + * ada-typeprint.c: Change k&r style function definitions to prototyped + form. + * ada-valprint.c: Change k&r style function definitions to prototyped + form. + +2002-07-24 Andrew Cagney <cagney@redhat.com> + + * README: Remove reference to remote-bug. + * Makefile.in (ALLDEPFILES): Remove m88k-nat.c, m88k-tdep.c and + remote-bug.c. + (m88k-nat.o): Delete rule. + (m88k-tdep.o): Delete rule. + (remote-bug.o): Delete rule. + * MAINTAINERS: Mark as obsolete. + * elfread.c (elf_symtab_read): Mention that m88k is obsolete. + * m88k-tdep.c: Make file obsolete. + * config/m88k/m88k.mh: Ditto. + * config/m88k/delta88v4.mh: Ditto. + * config/m88k/delta88v4.mt: Ditto. + * config/m88k/delta88.mt: Ditto. + * config/m88k/delta88.mh: Ditto. + * remote-bug.c: Ditto. + * config/m88k/tm-delta88.h: Ditto. + * config/m88k/nm-delta88v4.h: Ditto. + * config/m88k/xm-delta88.h: Ditto. + * config/m88k/xm-dgux.h: Ditto. + * config/m88k/tm-m88k.h: Ditto. + * config/m88k/nm-m88k.h: Ditto. + * config/m88k/tm-delta88v4.h: Ditto. + * m88k-nat.c: Ditto. + * cxux-nat.c: Ditto. + * configure.host: Make m88*-motorola-sysv4*, m88*-motorola-sysv* + and m88*-*-* obsolete. + * configure.tgt: Make m88*-motorola-sysv4*, m88*-motorola-* and + m88*-*-* obsolete. + +2002-07-24 Andrew Cagney <cagney@redhat.com> + + * findvar.c (extract_unsigned_integer): Make `addr' parameter + constant. Same for local pointer variables. + (extract_signed_integer): Ditto. + * defs.h (extract_unsigned_integer): Update. + (extract_signed_integer): Update. + +2002-07-24 Andrew Cagney <cagney@redhat.com> + + * regcache.c (regcache_raw_write): Change buf parameter to a + constant void pointer. + (regcache_raw_read): Change buf parameter to a void pointer. + (legacy_write_register_gen): Change myaddr parameter a constant + void pointer. + (supply_register): Change val parameter to a const void pointer. + * regcache.h (regcache_raw_write): Update declaration. + (regcache_raw_read): Update declaration. + (supply_register): Update declaration. + +2002-07-24 Tom Tromey <tromey@redhat.com> + + * defs.h (gdb_readline_wrapper): Declare. + * utils.c (prompt_for_continue): Use gdb_readline_wrapper. + * tracepoint.c (read_actions): Use gdb_readline_wrapper. + * top.c (gdb_readline_wrapper): New function. + (command_line_input): Use it. + +2002-07-24 Andrew Cagney <cagney@redhat.com> + + * regcache.h (regcache_raw_read, regcache_raw_write): Replace + regcache_read and regcache_write. + (regcache_raw_read_as_address): Replace regcache_read_as_address. + * regcache.c: Update. + * sh-tdep.c (sh64_push_arguments): Update comment. + (sh_pseudo_register_read): Update. + (sh_pseudo_register_write): Update. + (sh4_register_read): Update. + (sh4_register_write): Update. + (sh64_pseudo_register_read): Update. + (sh64_pseudo_register_write): Update. + (sh64_register_read): Update. + (sh64_register_write): Update. + * i386-tdep.c (i386_extract_return_value): Update. + (i386_extract_struct_value_address): Update. + (i386_extract_return_value): Update. + * blockframe.c (generic_read_register_dummy): Update. + (generic_call_dummy_register_unwind): Update + * infrun.c (write_inferior_status_register): Update. + +2002-07-23 Jim Blandy <jimb@redhat.com> + + * parser-defs.h (expression_context_pc): Make this extern. + (Thanks to Michael Snyder.) + +2002-07-23 Andrew Cagney <ac131313@redhat.com> + + GDB 5.2.1 released from 5.2 branch. + * NEWS: Mention changes in 5.2.1 including addition of AVR target. + * README: Update to mention 5.2.1. + +2002-07-23 Mark Salter <msalter@redhat.com> + + * remote.c (remote_read_bytes): Fix check for error. + +2002-07-22 Kevin Buettner <kevinb@redhat.com> + + * aix-thread.c (language.h): Include. + (ptrace_check, pdc_symbol_addrs, pdc_read_regs, pdc_write_regs) + (pdc_read_data, pdc_write_data, pdc_alloc, pdc_realloc, pdc_dealloc): + Print newlines at end of debug messages. + (pdc_symbol_addrs, pdc_read_regs, pdc_write_regs, pdc_read_data) + (pdc_write_data): Use local_hex_string() instead of %llx formats. + +2002-07-22 Kevin Buettner <kevinb@redhat.com> + + * aix-thread.c (ppc-tdep.h): Include. + (special_register_p): New function. + (supply_sprs64, supply_sprs32, fill_sprs64, fill_sprs32) + (store_regs_user_thread): Use register number information from + gdbarch_tdep struct instead of hardcoded offsets relative to + FIRST_UISA_SP_REGNUM. + (fetch_regs_kernel_thread, store_regs_kernel_thread): Call + special_register_p() instead of using FPLAST_REGNUM and + LAST_UISA_SP_REGNUM as lower and upper bounds on the special + register numbers. Also, don't assume that LAST_UISA_SP_REGNUM + will be MQ's register number. + +2002-07-22 Michael Snyder <msnyder@redhat.com> + + * aix-thread.c (ops): Rename to aix_thread_ops. + (base_ops): Rename to base_target. + (ops_attach): Rename to aix_thread_attach. + (ops_detach): Rename to aix_thread_detach. + (ops_resume): Rename to aix_thread_detach. + (ops_wait): Rename to aix_thread_wait. + (ops_kill): Rename to aix_thread_kill. + (init_ops): Rename to init_aix_thread_ops. + (ops_fetch_register): Rename to aix_thread_fetch_register. + (ops_store_register): Rename to aix_thread_store_register. + (ops_mourn_inferior): Rename to aix_thread_mourn_inferior. + (ops_thread_alive): Rename to aix_thread_thread_alive. + (ops_extra_thread_info: Rename to aix_thread_extra_thread_info. + (ops_pid_to_str): Rename to aix_thread_pid_to_str. + (ops_xfer_memory): Rename to aix_thread_xfer_memory. + (fetch_regs_lib): Rename to fetch_regs_user_thread. + (fetch_regs_kern): Rename to fetch_regs_kernel_thread. + (store_regs_lib): Rename to store_regs_user_thread. + (store_regs_kern): Rename to store_regs_kernel_thread. + +2002-07-22 Michael Snyder <msnyder@redhat.com> + + * aix-thread.c (ops_prepare_to_store): Eliminate. + (init_ops): Don't initialize ops.prepare_to_store. + (store_regs_kern): Pre-fetch register buffers from child, + because some registers may not be in the cache. Copy + regs from register cache only if they are cached. + (store_regs_lib): Copy regs from register cache only + if they are cached. + (fill_sprs32, (fill_sprs64, fill_fprs, fill_gprs32, + fill_gprs64): Ditto. + +2002-07-22 Kevin Buettner <kevinb@redhat.com> + + * aix-thread.c (gdb_assert.h): Include. + (fill_sprs64, fill_sprs32): Add selected asserts to make sure that + register sizes (from register cache) match size of buffer holding + register data. + (fill_sprs32): Change parameter types to match those in the ptrace() + buffer. + (store_regs_lib): Likewise, but for 32-bit temporary variables. + (ops_prepare_to_store): Rename loop variable ``i'' to ``regno''. + +2002-07-22 Michael Snyder <msnyder@redhat.com> + + * aix-thread.c (supply_sprs64): Cosmetic change. + (supply_sprs32): Cosmetic change. + (fill_gprs64, fill_gprs32, fill_fprs, fill_sprs32): New funcs. + (fill_sprs64): Use regcache_collect instead of read_register. + (store_regs_lib): Use regcache_collect instead of + read_register. Use fill_sprs32 instead of fill_sprs64, + if debugging a 32-bit architecture. + (store_regs_kern): Use fill_gprs64 etc. to pull the values + out of the register cache, instead of passing a pointer into + the register cache directly to ptrace. Use regcache_collect + insteaad of read_register. + (ops_prepare_to_store): Use target_read_registers instead + of read_register_bytes. + +2002-07-20 Aidan Skinner <aidan@velvet.net> + + * MAINTAINERS: Add self under write after approval. + +2002-07-20 Aidan Skinner <aidan@velvet.net> + + * ada-tasks.c: Change k&r style function definitions to prototyped + form. + +2002-07-19 Andrew Cagney <ac131313@redhat.com> + + * Makefile.in (x86-64-tdep.o): Add $(objfiles_h). + * x86-64-tdep.c: Include "objfiles.h". + (x86_64_gdbarch_init): Set in_solib_call_trampoline to + in_plt_section. From 2002-07-18 Michal Ludvig <mludvig@suse.cz>. + +2002-07-17 Michal Ludvig <michal@suse.cz> + + * dwarf2cfi.c (execute_stack_op): Complain on unknown DW_OP_ value. + (update_context): Initialise cfa variable. + +2002-07-17 Michael Snyder <msnyder@redhat.com> + + * aix-thread.c: Shorten some long lines. + Bring comments into line with code spec. + +2002-07-18 Joel Brobecker <brobecker@gnat.com> + + * infrun.c: Re-indent using gdb_indent.sh. + +2002-07-18 Joel Brobecker <brobecker@gnat.com> + + * infrun.c (handle_inferior_event): Remove unneeded extra brace. + Leave the indentation temporarily untouched, to minimize the diffs. + +2002-07-18 Elena Zannoni <ezannoni@redhat.com> + + * stabsread.c: Make os9k sections of the code obsolete, + for real this time. + * stabsread.h: Make os9k sections of the code obsolete. + +2002-07-18 Michal Ludvig <mludvig@suse.cz> + + * linux-low.c (regsets_store_inferior_registers): Add free() + at the end of a loop to prevent memory leak. + * linux-x86-64-low.c (x86_64_regmap): Add CS, SS registers. + (X86_64_NUM_GREGS): Count it from the size of x86_64_regmap. + * config/sparc/tm-sp64linux.h: Make the rest of #endif + line a comment. + * Makefile.in (x86-64-linux-nat.o): Remove dependency on i387-tdep.h + +2002-07-17 Jim Blandy <jimb@redhat.com> + + * macrocmd.c (info_macro_command): Remove newline from error + message. + +2002-07-17 J"orn Rennecke <joern.rennecke@superh.com> + + * sh-tdep.c (sh_dsp_register_sim_regno): New function. + (sh_gdbarch_init): Use it for sh-dsp. + +2002-07-16 Kevin Buettner <kevinb@redhat.com> + + * dwarf2read.c (read_initial_length): Handle older, non-standard, + 64-bit DWARF2 format. + +2002-07-16 Joel Brobecker <brobecker@gnat.com> + + * proc-api.c: use HAVE_SYS_PROC_H macro to avoid including + <sys/proc.h> when not available. + +2002-07-16 Andrew Cagney <ac131313@redhat.com> + + * NEWS: Mention that the i[34]86-*-os9k has been made obsolete. + * stabsread.c: Make os9k sections of the code obsolete. + * configure.tgt: Make i[3456]86-*-os9k target obsolete. + * config/i386/i386os9k.mt: Make file obsolete. + * Makefile.in (ALLDEPFILES): Remove remote-os9k.c. + (COMMON_OBS): Remove os9kread.o + (SFILES): Remove os9kread.c. + (os9kread.o, remote-os9k.o): Make target obsolete. + * remote-os9k.c: Make file obsolete. + * os9kread.c: Make file obsolete. + * Makefile.in + +2002-07-16 Andrew Cagney <ac131313@redhat.com> + + * NEWS: Mention that the FR30 has been made obsolete. + * fr30-tdep.c: Make file obsolete. + * config/fr30/tm-fr30.h: Ditto. + * config/fr30/fr30.mt: Ditto. + * configure.tgt: Make fr30-*-elf obsolete. + * MAINTAINERS: Make fr30-elf obsolete. + +2002-07-16 Pierre Muller <muller@ics.u-strasbg.fr> + + * blockframe.c (get_pc_function_start): return 0 if the minimal symbol + found is not inside a section. + +2002-07-15 Kevin Buettner <kevinb@redhat.com> + + * aix-thread.c (ptrace_check): Use safe_strerror() instead of + strerror(). + (pdc_realloc): Use xrealloc() instead of realloc(). + +2002-07-15 Kevin Buettner <kevinb@redhat.com> + + * aix-thread.c (PD_ERROR, CALL_BASE): Delete. + (ops_resume, ops_wait, fetch_regs_lib, store_regs_lib) + (ops_xfer_memory, ops_kill): Don't use PD_ERROR or CALL_BASE + macros. + +2002-07-15 Kevin Buettner <kevinb@redhat.com> + + * aix-thread.c (ptrace_check): Eliminate goto. + (sync_threadlists): Eliminate gotos. Also, fix array overrun + problem. + +2002-07-15 Kevin Buettner <kevinb@redhat.com> + + * aix-thread.c (gdbcmd.h): Include. + (DEBUG, DBG, DBG2, dbg): Eliminate. + (debug_aix_thread): New static global. + (ptrace_check, pdc_symbol_addrs, pdc_read_regs, pdc_write_regs) + (pdc_read_data, pdc_write_data, pdc_alloc, pdc_realloc, pdc_dealloc) + (fetch_regs_lib, store_regs_lib, store_regs_kern): Rewrite + invocations to DBG and DBG2 macros to test against + ``debug_aix_thread'' and call fprintf_unfiltered(). + (_initialize_aix_thread): Add new command "set debug aix-thread". + +2002-07-15 Andrew Cagney <ac131313@redhat.com> + + From Gerhard Tonn <TON@de.ibm.com>: + * s390-nat.c (fill_fpregset, fill_gregset): Use regcache_collect + instead of supply_register. + +2002-07-15 Andrew Cagney <ac131313@redhat.com> + + * dwarf2cfi.c: Include "gdb_assert.h". + (frame_state_for): Use gdb_assert to check that fde->cie_ptr is + non-NULL. + (update_context): Do not use __func__. Add missing ``break''. + (update_context): Do not use __func__. + +2002-07-15 Elena Zannoni <ezannoni@redhat.com> + + * rs6000-tdep.c (rs6000_gdbarch_init): Remove variable print_insn + and its setting. Set gdbarch instruction printing functions + directly. For non-rs6000 case use new function + gdb_print_insn_powerpc. + (gdb_print_insn_powerpc): New function. + +2002-07-13 Andrew Cagney <ac131313@redhat.com> + + * NEWS: Mention that the d30v has been marked obsolete. + * MAINTAINERS: Note that d30v / d30v-elf has been made obsolete. + * configure.tgt: Mark d30v-*-* as obsolete. + * d30v-tdep.c: Mark file as obsolete. + * config/d30v/d30v.mt: Ditto. + * config/d30v/tm-d30v.h: Ditto. + +2002-07-13 Aidan Skinner <aidan@velvet.net> + + * ada-tasks.c (add_task_entry): replace calls to + malloc() with xmalloc + * ada-tasks.c (init_task_list): replace calls to free with xfree() + + * ada-lang.c (replace_operator_with_call, fill_in_ada_prototype, + ada_finish_decode_line_1, all_sals_for_line + ada_breakpoint_rewrite): replace calls to free() with xfree() + +2002-07-12 Kevin Buettner <kevinb@redhat.com> + + From Nicholas Duffek (with minor changes by Martin Hunt, + Louis Hamilton, and Kevin Buettner): + * aix-thread.c: New file. + +2002-07-12 Petr Sorfa <petrs@caldera.com> + + * dwarf2read.c (dwarf2_invalid_attrib_class): New + complaint for invalid attribute class or form. + (read_func_scope): DW_AT_frame_base + better handling of DW_AT_block*. + (dwarf2_add_member_fn): DW_AT_vtable_elem_location + better handling of DW_AT_block*. + (read_common_block): DW_AT_location + better handling of DW_AT_block*. + (read_partial_die): DW_AT_location better handling + of DW_AT_block*. + (new_symbol): DW_AT_external better handling of + DW_AT_block*. Proper initialization of variable + "addr". + (attr_form_is_block): New function that returns true + if the attribute's form is of DW_FORM_block*. + +2002-07-12 Peter Schauer <Peter.Schauer@Regent.E-Technik.TU-Muenchen.DE> + + * valops.c (find_method_list): Remove comment about + removed STATIC_MEMFUNCP argument. + (value_find_oload_method_list): Likewise. + +2002-07-12 Kevin Buettner <kevinb@redhat.com> + + From Nicholas Duffek: + * rs6000-nat.c (vmap_ldinfo, xcoff_relocate_core): Call + target_new_objfile_hook. + +2002-07-12 Kevin Buettner <kevinb@redhat.com> + + From Nicholas Duffek: + * xcoffread.c (scan_xcoff_symtab): Recognize XMC_TD as a data storage + csect. + +2002-07-12 Andrew Cagney <cagney@redhat.com> + + * MAINTAINERS: Mention --enable-sim-build-warnings. + (m68hc11-elf): Disable sim build warnings. + (m32r-elf): Mark as broken obsolete candidate. + (x86_64-linux-gnu): Mark as buildable with -Werror. + (arm-elf): Change -w to ``,'' which enables warnings but not + -Werror. + +2002-07-12 Andrew Cagney <ac131313@redhat.com> + + * bcache.h: Update copyright. + (struct bstring, struct bcache): Move definition to "bcache.c". + Replaced by opaque declaration. + (bcache_xfree): Replace free_bcache. + (bcache_xmalloc, bcache_memory_used): Declare. + + * bcache.c: Update copyright. + (struct bstring, struct bcache): Moved to here from "bcache.h". + Update comments. + (bcache_xmalloc, bcache_memory_used): New functions. + (bcache_xfree): Replace function free_bcache. + + * Makefile.in (objfiles.o): Add $(bcache_h). + (objfiles_h): Remove $(bcache_h). + (symfile.o): Add $(bcache_h). + + * symmisc.c: Update copyright. + (print_symbol_bcache_statistics): Pass psymbol_cache by value. + (print_objfile_statistics): Use bcache_memory_used. + + * symfile.c: Include "bcache.h". + (reread_symbols): Use bcache_xfree. + (reread_symbols): Use bcache_xmalloc and bcache_xfree. + (add_psymbol_to_list): Pass psymbol_cache by value. + (add_psymbol_with_dem_name_to_list): Ditto. + + * objfiles.h: Update copyright. + (struct bcache): Declare opaque. Do not include "bcache.h". + (struct objfile): Change psymbol_cache and macro_cache to ``struct + bcache'' pointers. + * dwarf2read.c (macro_start_file): Pass macro_cache by value. + + * objfiles.c: Include "bcache.h". Update copyright. + (allocate_objfile): Use bcache_xmalloc to create psymbol_cache and + macro_cache. + (free_objfile): Use bcache_xfree. + +2002-07-11 Grace Sainsbury <graces@redhat.com> + + * monitor.c (monitor_fetch_register): Make name a constant. + (monitor_store_register): Same. + +2002-07-11 Daniel Jacobowitz <drow@mvista.com> + + Based on patch from Daniel Berlin <dberlin@dberlin.org>. + * buildsym.c: Include "demangle.h" for SYMBOL_INIT_DEMANGLED_NAME. + (finish_block) For non-function blocks, hash the symbol table. For + function blocks, mark the symbol table as unhashed. + * minsyms.c (msymbol_hash): Return hash value without taking modulus. + (msymbol_hash_iw): Likewise. + (add_minsym_to_hash_table): Take modulus of msymbol_hash's return + value. + (add_minsym_to_demangled_hash_table): Likewise for msymbol_hash_iw. + (lookup_minimal_symbol): Likewise for both. + * symtab.h (struct block): Add `hashtable' flag. Comment the + hashtable. + (BLOCK_HASHTABLE, BLOCK_BUCKETS, BLOCK_BUCKET): New macro. + (ALL_BLOCK_SYMBOLS): Update. + (BLOCK_SHOULD_SORT): Do not sort hashed blocks. + (struct symbol): Add `hash_next' pointer. + * symtab.c (lookup_block_symbol): Search using the hash table when + possible. + (find_pc_sect_symtab): Use ALL_BLOCK_SYMBOLS. + (search_symbols, find_addr_symbol): Likewise. + + * dstread.c (process_dst_block): Clear hashtable bit for new block. + (read_dst_symtab): Likewise. + * jv-lang.c (get_java_class_symtab): Likewise. + * mdebugread.c: Include "gdb_assert.h". + (shrink_block): Assert that the block being modified is not hashed. + * coffread.c (patch_opaque_types): Use ALL_BLOCK_SYMBOLS. + * symmisc.c (free_symtab_block): Walk the hash table when freeing + symbols. + (dump_symtab): Recognize hashed blocks. + * printcmd.c (print_frame_args): Assert that function blocks do not + have hashed symbol tables. + * ada-lang.c (symtab_for_sym): Use ALL_BLOCK_SYMBOLS. + (fill_in_ada_prototype, debug_print_block): Likewise. + (ada_add_block_symbols): Use ALL_BLOCK_SYMBOLS. Handle hash tables. + +2002-07-11 Corinna Vinschen <vinschen@redhat.com> + + * stack.c (print_frame): Use result of frame_address_in_block() + instead of fi->pc when evaluating symbols. + (backtrace_command_1): Ditto. + +2002-07-11 Andrew Cagney <cagney@redhat.com> + + * cris-tdep.c (cris_saved_pc_after_call): Fix parameter type. + Make static. + + * arm-tdep.c (arm_register_name): Make return type constant. + +2002-07-10 Andrew Cagney <ac131313@redhat.com> + + * win32-nat.c (has_detach_ability): Convert to strict ISO C + prototype. + * top.c (gdb_rl_operate_and_get_next_completion): Ditto. + * s390-tdep.c (s390_fp_regnum): Ditto. + (s390_read_fp): Ditto. + (s390_pop_frame): Ditto. + (_initialize_s390_tdep): Ditto. + * remote.c (get_remote_state): Ditto. + * procfs.c (mappingflags): Ditto. + * memattr.c (_initialize_mem): Ditto. + * mcore-tdep.c (mcore_pop_frame): Ditto. + * m68klinux-nat.c (_initialize_m68k_linux_nat): Ditto. + * m68k-tdep.c (m68k_register_bytes_ok): Ditto. + * language.c (set_case_str): Ditto. + * gnu-v3-abi.c (vtable_address_point_offset): Ditto. + * frv-tdep.c (new_variant): Ditto. + (frv_stopped_data_address): Ditto. + * dwarf2cfi.c (fde_chunks_need_space): Ditto. + (context_alloc): Ditto. + (frame_state_alloc): Ditto. + (unwind_tmp_obstack_init): Ditto. + (unwind_tmp_obstack_free): Ditto. + (cfi_read_fp): Ditto. + * cris-tdep.c (cris_saved_pc_after_call): Ditto. + (cris_pop_frame): Ditto. + * c-lang.c (scanning_macro_expansion): Ditto. + (finished_macro_expansion): Ditto. + (c_preprocess_and_parse): Ditto. + * gdbarch.sh: Ditto. + * gdbarch.h, gdbarch.c: Regenerate. + * config/mn10200/tm-mn10200.h: Adjust indentation. + * target.c: Adjust indentation. + * symtab.h: Adjust indentation. + * stabsread.h: Adjust indentation. + * remote-es.c: Adjust indentation. + * os9kread.c: Adjust indentation. + +2002-07-10 Andrew Cagney <ac131313@redhat.com> + + * wince.c (_initialize_wince): Rename _initialize_inftarg. + * win32-nat.c (_initialize_win32_nat): Rename _initialize_inftarg. + +2002-07-10 Grace Sainsbury <graces@redhat.com> + + * NEWS: Mention m68k, mcore multi-arching. + * MAINTAINERS: Change status of m68k, mcore to reflect + multi-arching. + +2002-07-10 Daniel Jacobowitz <drow@mvista.com> + + * valops.c (find_overload_match): Free oload_syms. + +2002-07-09 Joel Brobecker <brobecker@gnat.com> + + Define HAVE_SYS_PROC_H if sys/proc.h exists + * configure.in: Add check for sys/proc.h + * config.in: Regenerate. + * configure: Regenerate. + +2002-07-09 Grace Sainsbury <graces@redhat.com> + + * config/m68k/tm-m68k.h: Remove macros wrapped in + #if !GDB_MULTI_ARCH. + +2002-07-08 Andrew Cagney <ac131313@redhat.com> + + * config.in, configure: Regenerate. + +2002-07-08 Mark Kettenis <kettenis@gnu.org> + + * dwarf2cfi.c: Include "gcore.h". + (execute_stack_op): Fix implementation of the + DW_OP_deref and DW_OP_deref_size operators by letting do their + lookup in the target. + +2002-07-07 Mark Kettenis <kettenis@gnu.org> + + From Peter Schauer <Peter.Schauer@regent.e-technik.tu-muenchen.de>: + * i386-sol2-tdep.c (i386_sol2_init_abi): Correct value for + tdep->sc_sp_offset. + +2002-07-05 Daniel Jacobowitz <drow@mvista.com> + + Fix PR gdb/595, gdb/602 + * gnu-v3-abi.c (gnuv3_baseclass_offset): Remove unused variables. + Don't call value_cast, just read the vtable pointer; update comments + to match. + +2002-07-05 Grace Sainsbury <graces@redhat.com> + + * config/mcore/tm-mcore.h: Remove file. + * config/mcore/mcore.mt: Remove definition of TM_FILE + * configure.tgt: Set gdb_multi_arch to yes for the mcore target. + +2002-07-05 Mark Kettenis <kettenis@gnu.org> + + * i386bsd-tdep.c: Include "gdb_string.h". + +2002-07-04 Grace Sainsbury <graces@redhat.com> + + * config/mcore/tm-mcore.h (GDB_MULTI_ARCH): Set to 2. + (PR_REGNUM, FIRST_ARGREG, LAST_ARGREG,RETVAL_REGNUM): Move to + mcore-tdep. + (REG_STRUCT_HAS_ADDR, USE_STRUCT_CONVENTION, GET_SAVED_REGISTER) + (TARGET_VIRTUAL_FRAME_POINTER, BELIEVE_PCC_PROMOTION): Remove. + * mcore-tdep.c (PR_REGNUM, FIRST_ARGREG, LAST_ARGREG) + (RETVAL_REGNUM): Move macros from tm-mcore.h + (mcore_reg_struct_has_addr): New function. + (mcore_gdbarch_init): Added initializations for the macros removed + from tm-mcore.h. + +2002-07-04 Mark Kettenis <kettenis@gnu.org> + + * osabi.c (generic_elf_osabi_sniffer): Add check for FreeBSD 3.x's + traditonal string branding within the ELF header. + +2002-07-04 Daniel Jacobowitz <drow@mvista.com> + + * symtab.c (remove_params): New function. + (make_symbol_overload_list): Use it instead of cplus_demangle. + (overload_list_add_symbol): Likewise. Reorder. Fix memory leak. + +2002-07-04 Mark Kettenis <kettenis@gnu.org> + + * i386obsd-nat.c (_initialize_i386obsd_nat): Fix typo in prototype. + + * i386bsd-tdep.c (i386nbsd_sigtramp_start, i386nbsd_sigtramp_end): + New variables. + (i386nbsd_init_abi): Use these to initialize tdep->sigtramp_start + and tdep->sigtramp_end. + * i386obsd-nat.c: New file. + * config/i386/obsd.mh (NATDEPFILES): Add i386obsd-nat.o. + + * dwarf2cfi.c (cfi_pop_frame): Use alloca() for regbuf. + Don't call get_current_frame(). + +2002-07-04 Pierre Muller <muller@ics.u-strasbg.fr> + + * i386-nat.c (child_post_startup_inferior): New function + calling i386_cleanup_dregs if + I386_USE_GENERIC_WATCHPOINTS is defined. + * config/i386/nm-i386.h: define CHILD_POST_STARTUP_INFERIOR + conditional to acknowledge that i386-nat.c has its + own child_post_startup_inferior function. + +2002-07-04 Mark Kettenis <kettenis@gnu.org> + + * i386-tdep.h (I386_MAX_REGISTER_SIZE): New define. + * i386-tdep.c (i386_do_pop_frame): Use I386_MAX_REGISTER_SIZE + instead of MAX_REGISTER_RAW_SIZE. + (i386_extract_return_value, i386_extract_struct_value_address): + Convert to use regcache. + (i386_gdbarch_init): Set max_register_raw_size and + max_register_virtual_size to I386_MAX_REGISTER_SIZE. + Set extract_return_value and extract_struct_value_address instead + of their deprecated variants. + + Convert i386 target to generic dummy frames. + * i386-tdep.c: Include "symfile.h". + (i386_frameless_signal_p): Consider a function to be frameless if + the pc points at the first instruction of the function. + (i386_frame_chain): Handle (generic) call dummies. + (i386_frame_saved_pc): Likewise. + (i386_frame_init_saved_regs): Remove code dealing with call + dummies on the stack. + (i386_push_dummy_frame): Removed. + (i386_call_dummy_words): Removed. + (i386_fix_call_dummy): Removed. + (i386_push_return_address): New function. + (i386_do_pop_frame): Renamed from i386_pop_frame. Add FRAME + parameter, and don't call get_current_frame. + (i386_pop_frame): New function. + (i386_gdbarch_init): Set use_generic_dummy_frames to 1, set + call_dummy_location to AT_ENTRY_POINT, set call_dummy_address to + entry_point_address, set call_dummy_breakpoint_offset to 0, set + call_dummy_length to 0, set call_dummy_words to NULL, set + sizeof_call_dummy_words to 0, set fix_call_dummy to + generic_fix_call_dummy, set pc_in_call_dummy to + pc_in_call_dummy_at_entry_point, set push_dummy_frame to + generic_push_dummy_frame, set push_return_address to + i386_push_return_address and set frame_chain_valid to + generic_file_frame_chain_valid. + +2002-07-03 Andrew Cagney <ac131313@redhat.com> + + * gdbarch.sh (struct regcache): Add opaque declaration. + (EXTRACT_RETURN_VALUE): New architecture method. + (EXTRACT_STRUCT_VALUE_ADDRESS): Ditto. + * gdbarch.h, gdbarch.c: Regenerate. + * arch-utils.c (legacy_extract_return_value): New function. + * arch-utils.h (legacy_extract_return_value): Declare. + * values.c (value_being_returned): Re-enable code handling + EXTRACT_STRUCT_VALUE_ADDRESS. Move + deprecated_grub_regcache_for_registers call to block handling + DEPRECATED_EXTRACT_STRUCT_VALUE_ADDRESS. + (EXTRACT_RETURN_VALUE): Do not define. + +2002-07-03 Grace Sainsbury <graces@redhat.com> + + * config/mcore/tm-mcore.h (REGISTER_BYTES, NUM_REGS, PC_REGNUM) + (SP_REGNUM, FP_REGNUM, FUNCTION_START_OFFSET, DECR_PC_AFTER_BREAK) + (BREAKPOINT_FROM_PC, INNER_THAN, SAVED_PC_AFTER_CALL) + (INIT_EXTRA_FRAME_INFO, FRAME_INIT_SAVED_REGS, INIT_FRAME_PC) + (FRAME_CHAIN, FRAME_CHAIN_VALID, FRAME_SAVED_PC) + (STORE_RETURN_VALUE, DEPRECATED_EXTRACT_RETURN_VALUE) + (STORE_STRUCT_RETURN, DEPRECATED_EXTRACT_STRUCT_VALUE_ADDRESS) + (SKIP_PROLOGUE, FRAME_ARGS_SKIP, FRAME_ARGS_ADDRESS) + (FRAME_LOCALS_ADDRESS, FRAME_NUM_ARGS, POP_FRAME) + (PUSH_RETURN_ADDRESS, PUSH_DUMMY_FRAME, PUSH_ARGUMENTS): Remove. + * mcore-tdep.c (mcore_init_extra_frame_info): Add fromleaf + argument so the function fits the prototype in the architecture + vector. + (mcore_pop_frame): Remove argument so the function fits the + prototype. Use get_current_frame instead of the argument. + (mcore_push_arguments): Change type of struct_return so the + function can be used in the architecture vector. + (mcore_store_struct_return): Add. + (mcore_frame_init_saved_regs): Add. + (mcore_gdbarch_init): Add function calls to replace the macros + removed from tm-mcore.h + +2002-07-03 Andrew Cagney <ac131313@redhat.com> + + * infcmd.c (print_return_value): Remove compatibility code calling + deprecated_grub_regcache_for_registers. + + * values.c: Include "regcache.h". + (value_being_returned): Update. Use + deprecated_grub_regcache_for_registers to extract the register + buffer address. + * value.h (value_being_returned): Change ``retbuf'' parameter to a + ``struct regcache''. + * Makefile.in (values.o): Add dependency on $(regcache_h). + + * inferior.h (run_stack_dummy): Change type of second parameter to + a ``struct regcache''. + * valops.c (hand_function_call): Change type of retbuf to ``struct + regcache''. Allocate using regcache_xmalloc, clean using + make_cleanup_regcache_xfree. + * infcmd.c (run_stack_dummy): Update. Use + regcache_cpu_no_passthrough instead of memcpy to copy the buffer. + + * regcache.c (do_regcache_xfree): New function. + (make_cleanup_regcache_xfree): New function. + * regcache.h (make_cleanup_regcache_xfree): Declare. + +2002-07-03 Martin M. Hunt <hunt@redhat.com> + + * event-top.c (command_line_handler): Don't read past + beginning of buffer. + +2002-07-03 Martin M. Hunt <hunt@redhat.com> + + * varobj.c (struct varobj_root): Change frame from CORE_ADDR to + struct frame_id. + (varobj_create): Store frame_id for root. + (varobj_gen_name): Use xasprintf. + (varobj_update): Save and restore frame using get_frame_id() and + frame_find_by_id(). + (create_child): Use xasprintf. + (new_root_variable): Initialize frame_id. + (c_name_of_child): Use xasprintf. Call find_frame_by_id(). + (c_value_of_variable): Use xasprintf. Move mem_fileopen call + to prevent memory leak. + +2002-07-03 Andrew Cagney <ac131313@redhat.com> + + * valops.c (hand_function_call): Move declaration of retbuf to + start of function, allocate using malloc, add a cleanup but before + the inf_status cleanup, cleanup the buffer. Rename local variable + old_chain to inf_status_cleanup. + +2002-07-03 Martin M. Hunt <hunt@redhat.com> + + * top.c (execute_command): Use cmd_func() and cmd_func_p(). + + * cli/cli-decode.c (cmd_func_p): New function. + (cmd_func): New function. + + * command.h: Add cmd_func() and cmd_func_p(). + +2002-07-03 Grace Sainsbury <graces@redhat.com> + + * config/mcore/tm-mcore.h (GDB_MULTI_ARCH): Add macro. Set to 0. + (REGISTER_SIZE): Remove. + (MAX_REGISTER_RAW_SIZE): Remove. + (REGISTER_VIRTUAL_TYPE): Remove. + (MAX_REGISTER_VIRTUAL_SIZE): Remove. + (REGISTER_NAME): Remove. + (USE_GENERIC_DUMMY_FRAMES): Remove. + (CALL_DUMMY): Remove. + (CALL_DUMMY_START_OFFSET): Remove. + (CALL_DUMMY_BREAKPOINT_OFFSET): Remove. + (CALL_DUMMY_LOCATION): Remove. + (FIX_CALL_DUMMY): Remove. + (CALL_DUMMY_ADDRESS): Remove. + (SIZEOF_CALL_DUMMY_WORDS): Remove. + (SAVE_DUMMY_FRAME_TOS): Remove. + * mcore-tdep.c (MCORE_REG_SIZE, MCORE_NUM_REGS): Add macros. + (mcore_register_virtual_type): New function. + (mcore_register_byte): New function. + (mcore_register_size): New function. + (mcore_register_name): New function. + (mcore_gdbarch_init): New function. Add set_gdbarch calls for + macros removed from tm-mcore.h. + (mcore_dump_tdep): Add. + (_initialize_mcore_tdep): Add gdbarch_register call. + +2002-07-03 Mark Kettenis <kettenis@gnu.org> + + * i386-tdep.c (i386_frameless_signal_p): Provide an argument in to + frameless_look_for_prologue, such that we actually call this + function. + +2002-07-02 Joel Brobecker <brobecker@gnat.com> + + * frame.h (frame_address_in_block): New function. + + * blockframe.c (frame_address_in_block): New function extracted + from get_frame_block(). + (get_frame_block): Use frame_address_in_block(). + (block_innermost_frame): Use frame_address_in_block() to match + the frame pc address against the block boundaries rather than + the frame pc directly. This prevents a failure when a frame pc + is actually a return-address pointing immediately after the end + of the given block. + +2002-07-02 Grace Sainsbury <graces@redhat.com> + + * MAINTAINERS: Add self under write after approval. + +2002-07-02 Grace Sainsbury <graces@redhat.com> + + * m68k-tdep.c (m68k_remote_breakpoint_from_pc): Add. Currently not + used in architecture vector. The default is + m68k_local_breakpoint_from_pc. + (m68k_local_breakpoint_from_pc): Add. + (enum): Add register numbers from tm-m68k.h. + (m68k_gdbarch_init): Add breakpoint_from_pc to architecture + vector. + * config/m68k/tm-m68k.h (GDB_MULTI_ARCH): Set to + GDB_MULTI_ARCH_PARTIAL. + (BPT_VECTOR, REGISTER_BYTES_FP, REGISTER_BYTES_NOFP) + (NUM_FREGS, SIG_PC_FP_OFFSET, SP_ARG0, REMOTE_BPT_VECTOR): Move to + m68k-tdep.c. + (BREAKPOINT, REMOTE_BREAKPOINT): Remove. + (A1_REGNUM, FP0_REGNUM, FPC_REGNUM, FPS_REGNUM, FPI_REGNUM): Move + to enum in m68k-tdep.c + +2002-07-02 Joel Brobecker <brobecker@gnat.com> + + * solib-osf.c (open_map): Compute the list of shared libraries + loaded by the inferior, rather than the list of libraries loaded + by GDB itself. Otherwise, GDB ends up reading the symbols from + the wrong shared libraries... + +2002-07-02 Mark Kettenis <kettenis@gnu.org> + + * i386-linux-tdep.c (i386_linux_sigcontext_addr): Make static. + (LINUX_SIGCONTEXT_PC_OFFSET, LINUX_SIGCONEXT_SP_OFFSET): Remove + macros. + (i386_linux_sigtramp_saved_pc, i386_linux_sigtramp_saved_sp): + Remove functions. + (FRAMELESS_SIGNAL): Remove function. + (i386_linux_frame_chain, i386_linux_frame_saved_pc, + i386_linux_saved_pc_after_call): Removed. + (i386_linux_init_abi): Initialize tdep->sigcontext_addr, + tdep->sc_pc_offset and tdep->sc_sp_offset. Don't override + frame_chain, frame_saved_pc and saved_pc_after_call any longer. + + * i386-tdep.c (i386_frameless_signal_p): New function. + (i386_frame_chain): Deal with frameless signals. + (i386_sigtramp_saved_sp): New function. + (i386_frame_saved_pc): Deal with frameless signals. + (i386_saved_pc_after_call): Make sure the correct value is + returned just after entry into a sigtramp. + * i386bsd-tdep.c (i386bsd_sc_sp_offset, i386nbsd_sc_sp_offset, + i386fbsd4_sc_sp_offset): New variables. + (i386bsd_init_abi, i386nbsd_init_abi, i386fbsd4_init_abi): Use + these variables to initialize tdep->sc_sp_offset. * i386bsd-nat.c + (_initialize_i386bsd_nat): Add sanity check for sc_sp_offset + similiar to what we already did for sc_pc_offset. + * i386-sol2-tdep.c (i386_sol2_init_abi): Initialize + tdep->sc_sp_offset. + + * i386nbsd-tdep.c (fetch_elfcore_registers): Wrap long line. + +2002-07-02 Michal Ludvig <mludvig@suse.cz> + + * config/i386/tm-x86-64linux.h: New. + * config/i386/x86-64linux.mt: Add GDB_MULTI_ARCH and TM_FILE + definitions. + * config/i386/nm-x86-64.h: Rename to ... + * config/i386/nm-x86-64linux.h: ... this one. + * config/i386/x86-64linux.mh: Reflect the above change. + +2002-07-01 Mark Kettenis <kettenis@gnu.org> + + * i386-tdep.h (struct gdbarch_tdep): Replace sigtramp_saved_pc + with sigcontext_addr. Add sc_sp_offset. + (i386bsd_sigtramp_saved_pc): Remove prototype. + (i386bsd_sicontext_addr): Add prototype. + * i386-tdep.c (i386_sigtramp_saved_pc): New function. + (i386_frame_saved_pc): Rewrite to call i386_sigtramp_saved_pc. + (i386_svr4_sigtramp_saved_pc): Removed. + (i386_svr4_sigcontext_addr): New function. + (i386_svr4_init_abi): Don't initialize tdep->sigtramp_saved_pc. + Initialize tdep->sigcontext_addr instead. Initialize + tdep->sc_pc_offset and tdep->sc_sp_offset. + (i386_gdbarch_init): Likewise. + * i386bsd-tdep.c (i386bsd_sigcontext_addr): Don't make it static + any more. + (i386bsd_sigtramp_saved_pc): Remove function. + (i386bsd_init_abi): Don't initialize tdep->sigtramp_saved_pc. + Initialize tdep->sigcontext_addr instead. Initialize + tdep->sc_pc_offset. + * i386-linux-tdep.c (i386_linux_init_abi): Remove initialization + of tdep->sigtramp_saved_pc. + * i386-sol2-tdep.c (i386_sol2_init_abi): Don't initialize + tdep->sigtramp_saved_pc. Initialize tdep->sigcontext_addr + instead. + + * i386-tdep.c (i386_frameless_function_invocation, + i386_frame_num_args, i386_frame_init_saved_regs, + i386_skip_prologue, i386_push_dummy_frame, i386_fix_call_dummy, + i386_pop_frame, i386_push_arguments, i386_store_struct_return, + i386_extract_return_value, i386_store_return_value, + i386_extract_struct_value_address, i386_register_virtual_type, + i386_register_convertible, i386_register_convert_to_virtual, + i386_register_convert_to_raw, i386_svr4_sigtramp_saved_pc, + i386_go32_init_abi, i386_nw_init_abi, i386_gdbarch_init): Make + static. + +2002-07-01 Mark Kettenis <kettenis@gnu.org> + + * i386bsd-tdep.c (i386bsd_frame_saved_pc): Removed. + + * config/i386/tm-i386sol2.h (COERCE_FLOAT_TO_DOUBLE): Removed. + * i386-sol2-tdep.c (i386_sol2_init_abi): Adjust for the removal of + this macro. Include "value.h". + +2002-06-30 Aidan Skinner <aidan@velvet.net> + + * ada-exp.tab.c: remove as it's a generated file + * ada-lex.c: remove as it's a generated file + +2002-06-30 Mark Kettenis <kettenis@gnu.org> + + * config/i386/tm-i386.h (struct frame_info, struct + frame_saved_regs, struct value, struct type): Remove forward + declarations. + + * config/i386/tm-linux.h [HAVE_PTRACE_GETFPXREGS] + (FILL_FPXREGSET, HAVE_SSE_REGS): Remove define. + * config/i386/nm-linux.h [HAVE_PTRACE_GETFPXREGS] + (FILL_FPXREGSET): Define. + + * config/i386/tm-nbsd.h (HAVE_SSE_REGS): Remove define. + + * configure.tgt (i[3456]86-*-openbsd*): Fold into + i[3456]86-*-netbsd* case. + * config/i386/tm-obsd.h: Removed. + * config/i386/obsd.mt: Removed. + * config/i386/obsd.mh (NATDEPFILES): Remove corelow.o and + core-aout.o. + (MH_CFLAGS): Add -DYYDEBUG=0. + + * i386bsd-nat.c (_initialize_i386bsd_nat): Define SC_PC_OFFSET to + i386nbsd_sc_pc_offset on OpenBSD too. + + * config/i386/tm-fbsd.h [!SVR4_SHARED_LIBS] + (IN_SOLIB_CALL_TRAMPOLINE): Remove define. + * config/i386/tm-nbsdaout.h (IN_SOLIB_CALL_TRAMPOLINE): Remove + define. + * i386bsd-tdep.c: Include "arch-utils.h". + (i386bsd_aout_in_solib_call_trampoline): New function. + (i386bsd_init_abi): Set in_solib_call_trampoline to + i386bsd_aout_in_solib_call_trampoline. + (i386nbsdelf_init_abi, i386fbsd_init_abi): Set + in_solib_call_trampoline to generic_in_solib_call_trampoline. + +2002-06-28 Andrew Cagney <ac131313@redhat.com> + + * macrotab.h: Do not include "obstack.h" or "bcache.h". + (struct obstack, struct bcache): Add opaque declarations. + * Makefile.in (macrotab_h): Update + +2002-06-28 Andrew Cagney <ac131313@redhat.com> + + * blockframe.c (generic_find_dummy_frame): Change return type to + ``struct regcache''. + (struct dummy_frame): Replace field ``registers'' with regcache, a + struct regcache object. + (generic_find_dummy_frame): Update. + (generic_push_dummy_frame): Update. Use regcache_xfree, + regcache_xmalloc and regcache_cpy. + (generic_pop_dummy_frame): Update. Use regcache_cpy and + regcache_xfree. + (deprecated_generic_find_dummy_frame): Update. + (generic_read_register_dummy): Update. Use + regcache_read_as_address. + (generic_call_dummy_register_unwind): Update. Use regcache_read. + (generic_get_saved_register): Update. Use regcache_read. + +2002-06-28 Andrew Cagney <ac131313@redhat.com> + + * Makefile.in (objfiles_h): Add $(bcache_h). + * objfiles.h: Include "bcache.h". + + * Makefile.in (symtab_h): Remove $(bcache_h). + * symtab.h: Do not include "bcache.h". + +2002-06-28 Andrew Cagney <ac131313@redhat.com> + + * ppcnbsd-tdep.c (ppcnbsd_init_abi): Set frame_chain_valid to + generic_func_frame_chain_valid. + +2002-06-28 David O'Brien <obrien@FreeBSD.org> + + * config/i386/nm-fbsd.h: Include <sys/param.h>. + * config/i386/tm-fbsd.h: Likewise. + +2002-06-28 Andrew Cagney <ac131313@redhat.com> + + * rs6000-tdep.c (rs6000_gdbarch_init): Use + generic_unwind_get_saved_register. + +2002-06-27 Andrew Cagney <ac131313@redhat.com> + + From 2002-06-27 John David Anglin <dave@hiauly1.hia.nrc.ca>: + * regcache.c (supply_register): Add missing argument to + register_buffer call. + +2002-06-27 Andrew Cagney <ac131313@redhat.com> + + * Makefile.in (init.c): Drop -e option to grep. Not necessary and + Solaris /bin/grep does not not like it. From Peter Schauer. + +2002-06-26 Tom Tromey <tromey@redhat.com> + + * command.h (add_setshow_cmd): Declare. + (add_setshow_cmd_full): Declare. + * cli/cli-decode.c (add_setshow_cmd): No longer static. Now + returns void. Use add_setshow_cmd_full. + (add_setshow_cmd_full): New function. + (add_setshow_auto_boolean_cmd): Use add_setshow_cmd_full. + (add_setshow_boolean_cmd): Likewise. + +2002-06-26 Jason Thorpe <thorpej@wasabisystems.com> + + * config/vax/tm-vax.h: Protect from multiple inclusion. + (TARGET_UPAGES, TARGET_NBPG, STACK_END_ADDR) + (SIGTRAMP_START, SIGTRAMP_END, SIGCONTEXT_PC_OFFSET): Move to... + * config/vax/tm-vaxbsd.h: ...here. New file. + * config/vax/vax.mt (TM_FILE): Set to tm-vaxbsd.h. + +2002-06-26 Jason Thorpe <thorpej@wasabisystems.com> + + * config/vax/tm-vax.h (BREAKPOINT): Remove. + (BELIEVE_PCC_PROMOTION): Remove. + (AP_REGNUM): Move to... + * config/vax/nm-vax.h: ...here. + * vax-tdep.c: Use VAX_AP_REGNUM instead of AP_REGNUM. + (vax_breakpoint_from_pc): New function. + (vax_gdbarch_init): Initialize gdbarch_breakpoint_from_pc + and gdbarch_believe_pcc_promotion. + +2002-06-26 Jason Thorpe <thorpej@wasabisystems.com> + + * Makefile.in (vax_tdep_h): Define. + (vax-tdep.o): Use $(vax_tdep_h). + * vax-tdep.c (vax_gdbarch_init): Use generic OS ABI framework. + (vax_dump_tdep): New function. + (_initialize_vax_tdep): Register vax_dump_tdep. + * vax-tdep.h: Include osabi.h. + (struct gdbarch_tdep): New. + +2002-06-26 Andrew Cagney <cagney@redhat.com> + + * frame.h (deprecated_generic_find_dummy_frame): Rename + generic_find_dummy_frame. + * blockframe.c (generic_find_dummy_frame): Make static. + (deprecated_generic_find_dummy_frame): New function. + * sh-tdep.c (sh_nofp_frame_init_saved_regs): Replace + generic_find_dummy_frame with deprecated_find_dummy_frame. + (sh64_nofp_frame_init_saved_regs): Ditto. + (sh_fp_frame_init_saved_regs): Ditto. + * s390-tdep.c (s390_frame_saved_pc_nofix): Ditto. + (s390_frame_chain): Ditto. + * cris-tdep.c (cris_frame_init_saved_regs): Ditto. + +2002-06-26 Grace Sainsbury <graces@redhat.com> + + * config/m68k/tm-m68k.h: Rearrange code so macros not in the + gdbarch vector are at the top. + (NUM_REGS): Remove. + (FP_REGNUM, SP_REGNUM, PS_REGNUM, PC_REGNUM, FP0_REGNUM): Remove. + (FRAME_ARGS_ADDRESS): Remove. + (FRAME_LOCALS_ADDRESS): Remove. + (FRAME_NUM_ARGS): Remove. + (FRAME_ARGS_SKIP): Remove. + * m68k-tdep.c (enum): Add eumeration of special register numbers. + (m68k_gdbarch_init): Add gdbarch initializations for macros + undefined in tm-m68k.h + +2002-06-26 Grace Sainsbury <graces@redhat.com> + + * monitor.h: Add the function regname to monitor_ops + structure. This way NUM_REGS does not have to be a constant. + * monitor.c (monitor_fetch_register): Added support for regname + function. The function is called if the array regnames is NULL. + (monitor_store_register): Same. + * cpu32bug-rom.c (cpu32bug_regname): Add function. Replaces + regnames array. + (init_cpu32bug_cmds): set cpu32bug_cmds.regnames to NULL, + cpu32bug_cmds.regname to point to new function. + * abug-rom.c (abug_regname): Same as above. + (init_abug_cmds): Same. + * dbug-rom.c (dbug_regname): Same as above. + (init_dbug_cmds): Same. + * remote-est.c (est_regname): Same. + (init_est_cmds): Same. + * rom68k-rom.c (rom68k_regname): Same. + (init_rom68k_cmds): Same. + +2002-06-25 Tom Tromey <tromey@redhat.com> + + * breakpoint.c (delete_command): Don't repeat `delete' commands. + +2002-06-25 Andrew Cagney <cagney@redhat.com> + + * infrun.c (stop_registers): Change variable's type to ``struct + regcache'''. + (xmalloc_inferior_status): Delete function. + (free_inferior_status): Delete function. + (normal_stop): Use regcache_cpy. + (struct inferior_status): Change type of fields ``stop_registers'' + and ``registers'' to ``struct regcache''. + (write_inferior_status_register): Use regcache_write. + (save_inferior_status): Instead of calling + xmalloc_inferior_status, allocate the inf_status buffer directly. + Use regcache_dup_no_passthrough and regcache_dup to save the + buffers. + (restore_inferior_status): Use regcache_xfree and regcache_cpy. + Replace the stop_registers regcache instead of overriding it. Use + regcache_xfree. Instead of calling free_inferior_status, xfree + the buffer directly. + (discard_inferior_status): Use regcache_xfree. Instead of calling + free_inferior_status, xfree the buffer directly. + (build_infrun): Use regcache_xmalloc. + (_initialize_infrun): Delete redundant call to build_infrun. + + * Makefile.in (infcmd.o): Add $(regcache_h). + + * infcmd.c: Include "regcache.h". + (run_stack_dummy): Use deprecated_grub_regcache_for_registers to + obtain the address of `stop_registers' register buffer. + (print_return_value): Ditto. + + * inferior.h (struct regcache): Add opaque declaration. + (stop_registers): Change variable's declared type to ``struct + regcache''. + +2002-06-24 Tom Tromey <tromey@redhat.com> + + * cli/cli-decode.c (add_show_from_set): Fixed typo in comment. + * target.c (initialize_targets): Fixed typo in + trust-readonly-sections `show' documentation. + + * main.c: Marked all strings with _(). + +2002-06-24 Don Howard <dhoward@redhat.com> + + * memattr.c (create_mem_region): Treat hi == 0 as a special case + that means max CORE_ADDR+1. + (lookup_mem_region): Ditto. + (mem_info_command): Ditto. + +2002-06-24 Grace Sainsbury <graces@redhat.com> + + * config/m68k/tm-m68k.h (DECR_PC_AFTER_BREAK): Remove. + (REGISTER_BYTES_OK): Remove. + (REGISTER_BYTES): Remove. + (STORE_STRUCT_RETURN): Remove. + (DEPRECATED_EXTRACT_RETURN_VALUE): Remove. + (STORE_RETURN_VALUE): Remove. + (DEPRECATED_EXTRACT_STRUCT_VALUE_ADDRESS): Remove. + (FRAME_CHAIN): Remove. + (FRAMELESS_FUNCTION_INVOCATION): Remove. + (FRAME_SAVED_PC): Remove. + * m68k-tdep.c (m68k_register_bytes_ok):Add. + (m68k_store_struct_return): Add. + (m68k_deprecated_extract_return_value): Add. + (m68k_deprecated_extract_struct_value_address): Add. + (m68k_store_return_value): Add. + (m68k_frame_chain): Add. + (m68k_frameless_function_invocation): Add. + (m68k_frame_saved_pc): Add. + (m68k_gdbarch_init): added set_gdbarch calls for new + functions and deleted macros. + +2002-06-23 Tom Tromey <tromey@redhat.com> + + * Makefile.in (HFILES_NO_SRCDIR): Remove old files. + (ALLDEPFILES): Likewise. + (udiheaders): Removed. + (udip2soc.o): Likewise. + (udi2go32.o): Likewise. + (udr.o): Likewise. + (HFILES_WITH_SRCDIR): Don't mention udiheaders. + +2002-06-22 Andrew Cagney <ac131313@redhat.com> + + * infrun.c (_initialize_infrun): Delete unnecessary call to + build_infrun. + + * regcache.h: Update comments describing the regcache_cpy family + of functions. + (regcache_save, regcache_restore): Delete declaration. + (regcache_save_no_passthrough): Delete declaration. + (regcache_restore_no_passthrough): Delete declaration. + * regcache.c (regcache_save): Delete function. + (regcache_save_no_passthrough): Delete function. + (regcache_restore): Delete function. + (regcache_restore_no_passthrough): Delete function. + +2002-06-21 Andrew Cagney <ac131313@redhat.com> + + * config/m68k/tm-m68k.h: Fix typo. + (FRAME_INIT_SAVED_REGS): Define when non-multi-arch. + (m68k_frame_init_saved_regs): Declare. + +2002-06-21 Jim Blandy <jimb@redhat.com> + + Remove some vestiges of Harris 88k support. + * dwarf2read.c (decode_locdesc): Remove `#if' block for Harris 88k + register numbering quirk. + * elfread.c (elf_symtab_read): Remove `#if' block for skipping + odd symbols occurring in Harris 88k ELF targets. + +2002-06-21 Tom Tromey <tromey@redhat.com> + + * gdb_locale.h: New file. + * Makefile.in (GDB_CFLAGS): Define LOCALEDIR. + (defs_h): Added gdb_locale.h. + * configure, config.in: Rebuilt. + * configure.in (PACKAGE): Define. + * defs.h: Include gdb_locale.h. + * main.c (captured_main): Call setlocale, bindtextdomain, + textdomain. + +2002-06-21 Dave Brolley <brolley@redhat.com> + + From Stan Shebs, Jim Blandy, Mark Salter, Kevin Buettner: + * config/frv/frv.mt: New file. + * config/frv/tm-frv.h: New file. + * configure.tgt: Support frv-*-*. + * Makefile.in (frv-tdep.o): New target. + * frv-tdep.c: New file. + * NEWS: Mention frv. + +2002-06-21 Dave Brolley <brolley@redhat.com> + + * MAINTAINERS: Add self to "Write After Approval" list. + +2002-06-21 Grace Sainsbury <graces@redhat.com> + + * config/m68k/tm-m68k.h (REGISTER_BYTE, REGISTER_RAW_SIZE) + (REGISTER_VIRTUAL_SIZE, MAX_REGISTER_RAW_SIZE) + (REGISTER_VIRTUAL_TYPE, REGISTER_NAMES, TARGET_LONG_DOUBLE_FORMAT) + (FUNCTION_START_OFFSET, SKIP_PROLOGUE, SAVED_PC_AFTER_CALL) + (INNER_THAN, STACK_ALIGN, REGISTER_SIZE): Remove macros. + + * m68k-tdep.c: Include arch-utils.h + (m68k_register_raw_size): Add. + (m68k_register_virtual_size): Add. + (m68k_register_virtual_type): Add. + (m68k_register_name): Add. + (m68k_stack_align): Add. + (m68k_register_byte): Add. + (m68k_gdbarch_init): Add set_gdbarch calls for macros removed in + tm-m68k.h. + +2002-06-21 Grace Sainsbury <graces@redhat.com> + + * m68k-tdep.c (m68k_frame_init_saved_regs): Replace + m68k_find_saved_regs. + (m68k_pop_frame): Removed saved_regs structure, and replaced + references to it with frame->saved_regs. + (m68k_gdbarch_init): Added function calls to initialize the + gdbarch structure. + (m68k_fix_call_dummy): Add. + * config/m68k/tm-m68k.h: (FRAME_FIND_SAVED_REGS): Remove. + (CALL_DUMMY): Remove. + (CALL_DUMMY_LENGTH): Remove. + (CALL_DUMMY_START_OFFSET): Remove. + (CALL_DUMMY_BREAKPOINT_OFFSET): Remove. + (FIX_CALL_DUMMY): Remove. + (PUSH_DUMMY_FRAME): Remove. + (POP_FRAME): Remove. + +2002-06-19 Pierre Muller <muller@ics.u-strasbg.fr> + + * parse.c (parse_fprintf): New function used to avoid calls to + fprintf in bison parser generated debug code. + * parser-defs.h: Declaration of new parse_fprintf function. + * ada-exp.y, c-exp.y, f-exp.y, jv-exp.y, m2-exp.y, p-exp.y: + Set YYDEBUG to 1 by default. + Set YYFPRINTF as parse_fprintf. + +2002-06-21 Michal Ludvig <mludvig@suse.cz> + + * dwarf2cfi.c (read_encoded_pointer): Don't handle pointer + encoding anymore. + (pointer_encoding, enum ptr_encoding): New. + (execute_cfa_program): Take care about pointer encoding. + (dwarf2_build_frame_info): Only call parse_frame_info for + .debug_frame and .eh_frame. + (parse_frame_info): New, derived from former dwarf2_build_frame_info. + fixed augmentation handling, added relative addressing, + ignore duplicate FDEs. Added comments. + * dwarf2cfi.c: Reindented. + +2002-06-20 Elena Zannoni <ezannoni@redhat.com> + + * event-top.c (command_handler): Don't use space_at_cmd_start + unless there is sbrk() on the host. Assign time and space data + to union fields of the appropriate length. + +2002-06-20 Michal Ludvig <mludvig@suse.cz> + + * x86-64-tdep.c (x86_64_register_nr2name): Rename to + x86_64_register_name. Return type changed to 'const char *'. + (x86_64_register_name2nr): Rename to x86_64_register_number. + (x86_64_gdbarch_init): Update to reflect the change. + * x86-64-tdep.h: Ditto. + * x86-64-linux-nat.c (x86_64_fxsave_offset) + (supply_fpregset): Ditto. + +2002-06-19 Andrew Cagney <cagney@redhat.com> + + * regcache.h: Update copyright. + (struct regcache, struct gdbarch): Add opaque declarations. + (current_regcache): Declare global variable. + (regcache_read, regcache_write): Add gdbarch parameter. + (regcache_save, regcache_save_no_passthrough) + (regcache_restore, regcache_restore_no_passthrough) + (regcache_dup, regcache_dup_no_passthrough) + (regcache_cpy, regcache_cpy_no_passthrough) + (deprecated_grub_regcache_for_registers) + (deprecated_grub_regcache_for_register_valid) + (regcache_valid_p): Add function declarations. + + * regcache.c: Update copyright. + (regcache_descr_handle): New global variable. + (struct regcache_descr): Define. + (init_legacy_regcache_descr, init_regcache_descr): New functions. + (regcache_descr, xfree_regcache_descr): New functions. + (struct regcache): Define. + (regcache_xmalloc, regcache_xfree): New functions. + (regcache_cpy, regcache_cpy_no_passthrough): New functions. + (regcache_dup, regcache_dup_no_passthrough): New functions. + (regcache_valid_p, regcache_read_as_address): New functions. + (deprecated_grub_regcache_for_registers): New function. + (deprecated_grub_regcache_for_register_valid): New function. + (current_regcache): New global variable. + (register_buffer): Add regcache parameter. Update calls. + (regcache_read, regcache_write): Add regcache parameter. Rewrite. + (read_register_gen, write_register_gen): Update register_buffer + call. Test for legacy_p instead of gdbarch_register_read_p or + gdbarch_register_write_p. + (regcache_collect): Update register_buffer call. + (build_regcache): Rewrite. Use deprecated grub functions. + (regcache_save, regcache_save_no_passthrough): New functions. + (regcache_restore, regcache_restore_no_passthrough): New + functions. + (_initialize_regcache): Create the regcache_data_handle. Swap + current_regcache global variable. + + * sh-tdep.c (sh_pseudo_register_read): Add current_regcache + parameter to regcache_read and regcache_write calls. + (sh4_register_read): Ditto. + (sh64_pseudo_register_read): Ditto. + (sh64_register_read): Ditto. + (sh_pseudo_register_write): Ditto. + (sh4_register_write): Ditto. + (sh64_pseudo_register_write): Ditto. + (sh64_register_write): Ditto. + + * defs.h (XCALLOC): Define. + +2002-06-19 Grace Sainsbury <graces@redhat.com> + + * config/m68k/tm-m68k.h (GDB_MULTI_ARCH): Added (set to 0). + * m68k-tdep.c (m68k_gdbarch_init): Added. + (m68k_dump_tdep): Added. + +2002-06-19 Daniel Jacobowitz <drow@mvista.com> + + * ada-lang.c (fill_in_ada_prototype): Update comment. + +2002-06-19 Daniel Jacobowitz <drow@mvista.com> + + * mips-tdep.c (enum mips_abi): Explicitly start at 0. Add + MIPS_ABI_LAST. + (mips_abi_string, mips_abi_strings): New. + (struct gdbarch_tdep): Remove mips_abi_string, add found_abi. + (mips_gdbarch_init): Set tdep->found_abi. Don't set + tdep->mips_abi_string. Honor mips_abi_string. Default to + O32 if no ABI is found. + (mips_dump_tdep): Use mips_abi_strings. + (mips_abi_update): New function. + (_initialize_mips_tdep): Initialize mips_abi_string. Add + ``set mips abi'' and ``show mips abi''. Check the size of + mips_abi_strings. + +2002-06-19 Andrew Cagney <cagney@redhat.com> + + * i386-linux-tdep.c (i386_linux_register_name): Make return type + constant. + +2002-06-18 Joel Brobecker <brobecker@gnat.com> + + * alpha-tdep.c (heuristic_proc_desc): Compute the size of the + current frame using only the first stack size adjustment. All + subsequent size adjustments are not considered to be part of + the "static" part of the current frame. + Compute the address of the saved registers relative to the + Frame Pointer ($fp) instead of the Stack Pointer if $fp is + in use in this frame. + +2002-06-18 Don Howard <dhoward@redhat.com> + + * valops.c (value_ind): Use value_at_lazy() when dereferencing + type int expressions. Thanks to Jim Blandy <jimb@redhat.com> for + suggesting this solution. + +2002-06-18 Andrew Cagney <ac131313@redhat.com> + + * config/romp/xm-rtbsd.h: Delete file. + * config/romp/rtbsd.mh: Delete file. + +2002-06-18 Keith Seitz <keiths@redhat.com> + + * breakpoint.c (condition_command): Post breakpoint_modify + when a condition is added to an existing breakpoint. + (commands_command): Likewise for commands. + (set_ignore_count): Likewise for ignore counts. + If no tty, do not simply return, still need to send event + notification. + (ignore_command): Only print a newline if the command came + from a tty. + Don't call breakpoints_changed, since this is now properly + handled by set_ignore_count. + +2002-06-18 Andrew Cagney <cagney@redhat.com> + + * MAINTAINERS: Note that cris-elf target can be compiled with + -Werror. + * cris-tdep.c (cris_register_name): Make return type constant. + (cris_breakpoint_from_pc): Ditto. + +2002-06-18 Michal Ludvig <mludvig@suse.cz> + + * frame.h (struct frame_info): Change type of context to + 'struct context'. + +2002-06-17 Andrew Cagney <cagney@redhat.com> + + * gdbarch.sh (REGISTER_NAME): Change return type a constant string + pointer. + * gdbarch.h, gdbarch.c: Regenerate. + * config/mips/tm-mips.h (mips_register_name): Update. + * i386-tdep.h (i386_register_name): Update. + * mips-tdep.c (mips_register_name): Update + * alpha-tdep.c (alpha_register_name): Update. + * arch-utils.c (legacy_register_name): Update. + * arch-utils.h (legacy_register_name): Update. + * avr-tdep.c (avr_register_name): Update. + * ia64-tdep.c (ia64_register_name): Update. + * i386-tdep.c (i386_register_name): Update. + * sparc-tdep.c (sparc32_register_name): Update. + (sparc64_register_name): Update. + (sparclite_register_name): Update. + (sparclet_register_name): Update. + * sh-tdep.c (sh_generic_register_name): Update. + (sh_sh_register_name): Update. + (sh_sh3_register_name): Update. + (sh_sh3e_register_name): Update. + (sh_sh_dsp_register_name): Update. + (sh_sh3_dsp_register_name): Update. + (sh_sh4_register_name): Update. + (sh_sh64_register_name): Update. + * s390-tdep.c (s390_register_name): Update. + * rs6000-tdep.c (rs6000_register_name): Update. + * ns32k-tdep.c (ns32k_register_name_32082): Update. + (ns32k_register_name_32382): Update. + * d10v-tdep.c (d10v_ts2_register_name): Update. + (d10v_ts3_register_name): Update. + * xstormy16-tdep.c (xstormy16_register_name): Update. + * vax-tdep.c (vax_register_name): Update. + * v850-tdep.c (v850_register_name): Update. + * m68hc11-tdep.c (m68hc11_register_name): Update. + * mn10300-tdep.c (mn10300_generic_register_name): Update. + (am33_register_name): Update. + +2002-06-17 Grace Sainsbury <graces@redhat.com> + + * m68k-tdep.c: Reindented. + +2002-06-17 Andrew Cagney <ac131313@redhat.com> + + * gdb_indent.sh: Add prgregset_t, fpregset_t, and gregset_t to the + list of predefined types. + +2002-06-16 Mark Kettenis <kettenis@gnu.org> + + * config/i386/tm-i386.h (REGISTER_VIRTUAL_TYPE, + REGISTER_CONVERTIBLE, REGISTER_CONVERT_TO_VIRTUAL, + REGISTER_CONVERT_TO_RAW): Remove defines. + (i386_register_virtual_type, i386_register_convertible, + i386_register_convert_to_virtual, i386_register_convert_to_raw): + Remove prototypes. + * i386-tdep.c (i386_gdbarch_init): Adjust for removal of the + macros mentioned above. + + * config/i386/tm-i386lynx.h (SAVED_PC_AFTER_CALL): Remove define. + (i386lynx_saved_pc_after_call): Remove prototype. + * i386ly-tdep.c: Include "i386-tdep.h". + (i386lynx_saved_pc_after_call): Make static. Use + read_memory_nobpt instead of read_memory. Use + read_memory_unsigned_integer instead of read_memory_integer. + (i386lynx_init_abi): New function. + (i386lynx_coff_osabi_sniffer): New function. + (_initialize_i386bsd_tdep): New function. + + * config/i386/tm-i386.h (PARM_BOUNDARY, CALL_DUMMY, + CALL_DUMMY_LENGTH, CALL_DUMMY_START_OFFSET, + CALL_DUMMY_BREAKPOINT_OFFSET, FIX_CALL_DUMMY): Remove defines. + (i386_fix_call_dummy): Remove prototype. + * i386-tdep.c (i386_call_dummy_words): New variable. + (i386_gdbarch_init): Adjust for removal of the + macros mentioned above. + +2002-06-15 Andrew Cagney <ac131313@redhat.com> + + * command.h (add_setshow_auto_boolean_cmd): Replace + add_set_auto_boolean_cmd. + * cli/cli-decode.c (add_setshow_auto_boolean_cmd): Replace + add_set_auto_boolean_cmd. + * cli/cli-decode.h (add_set_auto_boolean_cmd): Delete declaration. + * mips-tdep.c (_initialize_mips_tdep): Update ``set mips + mask-address'' command. + (show_mask_address): Add cmd parameter. + * remote.c (add_packet_config_cmd): Update. Change type of + set_func and show_func to cmd_sfunc_ftype. + (_initialize_remote): Update `set remote Z-packet' + (show_remote_protocol_qSymbol_packet_cmd): Add cmd parameter. + (show_remote_protocol_e_packet_cmd): Ditto. + (show_remote_protocol_E_packet_cmd): Ditto. + (show_remote_protocol_P_packet_cmd): Ditto. + (show_remote_protocol_Z_software_bp_packet_cmd): Ditto. + (show_remote_protocol_Z_hardware_bp_packet_cmd): Ditto. + (show_remote_protocol_Z_write_wp_packet_cmd): Ditto. + (show_remote_protocol_Z_read_wp_packet_cmd): Ditto. + (show_remote_protocol_Z_access_wp_packet_cmd): Ditto. + (show_remote_protocol_Z_packet_cmd): Ditto. + (show_remote_protocol_binary_download_cmd): Ditto. + (show_remote_cmd): Pass NULL to all of above. + +2002-06-15 Mark Kettenis <kettenis@gnu.org> + + * config/i386/tm-i386.h (PUSH_ARGUMENTS, STORE_STRUCT_RETURN, + DEPRECATED_EXTRACT_RETURN_VALUE, STORE_RETURN_VALUE, + DEPRECATED_EXTRACT_STRUCT_VALUE_ADDRESS, PUSH_DUMMY_FRAME, + POP_FRAME): Remove defines. + (i386_push_arguments, i386_store_struct_return, + i386_extract_return_value, i386_store_return_value, + i386_extract_struct_value_address, i386_push_dummy_frame, + i386_pop_frame): Renove prototypes. + * i386-tdep.c (i386_gdbarch_init): Adjust for removal of the + macros mentioned above. + +2002-06-15 Andrew Cagney <ac131313@redhat.com> + + * cli/cli-decode.c (add_setshow_boolean_cmd): Replace + add_set_boolean_cmd. + (add_setshow_cmd): New function. + * command.h (add_setshow_boolean_cmd): Replace + add_set_boolean_cmd. + * remote-rdi.c (_initialize_remote_rdi): Update ``set rdiheartbeat'' + and ``set rdiromatzero''. + * maint.c (_initialize_maint_cmds): Update commented out code. + * cli/cli-decode.h (add_set_boolean_cmd): Delete declaration. + * target.c (initialize_targets): Update `set + trust-readonly-sections'. + * remote.c (_initialize_remote): Update `set remotebreak'. + +2002-06-15 Mark Kettenis <kettenis@gnu.org> + + * config/i386/tm-i386.h (FUNCTION_START_OFFSET, INNER_THAN, + BREAKPOINT, DECR_PC_AFTER_BREAK): Removed. + * i386-tdep.c (i386_skip_prologue): Adjust function signature to + fit into multi-arch framework. + (i386_breakpoint_from_pc): New function. + (i386_gdbarch_init): Adjust for removal of the macros mentioned + above. + + * config/i386/tm-i386.h (FRAMELESS_FUNCTION_INVOCATION, + FRAME_ARGS_ADDRESS, FRAME_LOCALS_ADDRESS, FRAME_NUM_ARGS, + FRAME_ARGS_SKIP, FRAME_INIT_SAVED_REGS): Remove defines. + (i386_frameless_function_invocation, i386_frame_num_args, + i386_frame_init_saved_regs): Remove prototypes. + * i386-tdep.c (i386_gdbarch_init): Adjust for removal of the + macros mentioned above. + +2002-06-15 Andrew Cagney <ac131313@redhat.com> + + * cli/cli-decode.c (set_cmd_cfunc): Update. + (set_cmd_sfunc): Update. + * command.h (cmd_cfunc_ftype, cmd_sfunc_ftype): Declare. + (set_cmd_sfunc, set_cmd_cfunc): Update. + * cli/cli-decode.h: Update. + +2002-06-15 Mark Kettenis <kettenis@gnu.org> + + * i386-sol2-tdep.c (i386_sol2_osabi_sniffer): New function. + (_initialize_i386_sol2_tdep): Register i386_sol2_osabi_sniffer. + +2002-06-15 Andrew Cagney <ac131313@redhat.com> + + * defs.h (auto_boolean): Declare enum. + * command.h (cmd_auto_boolean): Delete enum. + * mips-tdep.c (mask_address_var): Update. + (mips_mask_address_p): Update. + (show_mask_address): Update. + * remote.c (struct packet_config): Update. + (update_packet_config): Update. + (show_packet_config_cmd): Update. + (packet_ok): Update. + (add_packet_config_cmd): Update. + (_initialize_remote): + * command.h: Update. + * cli/cli-setshow.c (parse_auto_binary_operation): Update. + (do_setshow_command): Update. + * cli/cli-decode.c (add_set_auto_boolean_cmd): Update. + * cli/cli-decode.h: Update. + +2002-06-15 Mark Kettenis <kettenis@gnu.org> + + * config/i386/tm-cygwin.h, config/i386/tm-fbsd.h, + config/i386/tm-go32.h, config/i386/tm-i386gnu.h, + config/i386/tm-i386sol2.h, config/i386/tm-i386v4.h, + config/i386/tm-linux.h, config/i386/tm-nbsd.h, + config/i386/tm-obsd.h (HAVE_I387_REGS): Remove define. + * config/i386/tm-i386.h: Unconditionally define FLOAT_INFO. + + * i386-tdep.c (i386_coff_osabi_sniffer): Add "coff-go32" to the + list of DJGPP COFF targets. + + * config/i386/tm-i386.h (REGISTER_SIZE): Remove define. + (NUM_GREGS, NUM_FREGS, NUM_SSE_REGS): Remove defines. + (FP_REGNUM, SP_REGNUM, PC_REGNUM, PS_REGNUM): Remove defines. + (FP0_REGNUM): Remove define. + (MAX_REGISTER_RAW_SIZE, MAX_REGISTER_VIRTUAL_SIZE, + MAX_REGISTER_VIRTUAL_SIZE): Remove define. + (i386_register_virtual_size): Remove protoype. + * i386-tdep.c (i386_register_virtual_size): Removed. + (i386_extract_return_value, i386_store_return_value): Use + FP0_REGNUM instead of NUM_FREGS to determine whether the + floating-point registers are available. + (i386_gdbarch_init): Tweak FIXME about FPU registers. + Adjust for removal of macros mentioned above. + +2002-06-15 Mark Kettenis <kettenis@gnu.org> + + * i386v4-nat.c: Include "i386-tdep.h". Reformat and tweak various + comments. + (fill_gregset, supply_gregset, supply_fpregset, fill_fpregset): + Remove prototypes. + (supply_gregset, fill_gregset): Remove use of register keyword and + remove declaration for regmap. Use I386_NUM_GREGS instead of + NUM_REGS and NUM_FREGS. + (FPREGSET_FSAVE_OFFSET): Remove. + (supply_fpregset, fill_fpregset): Use FPO_REGNUM instead of + NUM_FREGS to determine whether the floating-point registers are + available. + + * i386gnu-nat.c (supply_gregset, gnu_fetch_registers, + gnu_store_registers): Replace usage of NUM_GREGS with + I386_NUM_GREGS. + + * i386-linux-nat.c (OLD_CANNOT_FETCH_REGISTER, + OLD_CANNOT_STORE_REGISTER, supply_gregset, fill_gregset): Replace + usage of NUM_GREGS with I386_NUM_GREGS. + + * i386-linux-nat.c (fill_gregset): Remove redundant parentheses. + + * i386bsd-nat.c: Include "i386-tdep.h". + (supply_gregset, fill_gregset): Replace usage of NUM_GREGS with + I386_NUM_GREGS. + + * i386v-nat.c: Remove copnditional inclusion of <asm/debugreg.h>, + and associated comment. They no longer make any sense, since we + don't use this file anymore on Linux. + + * config/i386/tm-i386.h (MAX_NUM_REGS): Removed. + * i386-tdep.c (i386_register_offset, i386_register_size): Use + I386_SSE_NUM_REGS instead of MAX_NUM_REGS for the number of + elements in these arrays. + (_initialize_i386_tdep): Use I386_SSE_NUM_REGS instead of + MAX_NUM_REGS. + +2002-06-15 Mark Kettenis <kettenis@gnu.org> + + * osabi.h (gdb_osabi): Add GDB_OSABI_LYNXOS. + * osabi.c (gdb_osabi_names): Add entry for "LynxOS". + +2002-06-14 Andrew Cagney <cagney@redhat.com> + + * gdbarch.sh (DEPRECATED_EXTRACT_RETURN_VALUE): Rename + EXTRACT_RETURN_VALUE. + (DEPRECATED_EXTRACT_STRUCT_VALUE_ADDRESS): Rename + EXTRACT_STRUCT_VALUE_ADDRESS. + * gdbarch.h, gdbarch.c: Regenerate. + + * values.c (value_being_returned): Handle + DEPRECATED_EXTRACT_STRUCT_VALUE_ADDRESS. + (EXTRACT_RETURN_VALUE): Define as DEPRECATED_EXTRACT_RETURN_VALUE. + + * arm-linux-tdep.c (arm_linux_init_abi): Update. + * arm-tdep.c (arm_gdbarch_init): Update. + * avr-tdep.c (avr_gdbarch_init): Update. + * cris-tdep.c (cris_gdbarch_init): Update. + * d10v-tdep.c (d10v_gdbarch_init): Update. + * ia64-tdep.c (ia64_gdbarch_init): Update. + * m68hc11-tdep.c (m68hc11_gdbarch_init): Update. + * rs6000-tdep.c (rs6000_gdbarch_init): Update. + * s390-tdep.c (s390_gdbarch_init): Update. + * sh-tdep.c (sh_gdbarch_init): Update. + * s390-tdep.c (s390_gdbarch_init): Update. + * sparc-tdep.c (sparc_gdbarch_init): Update. + * ns32k-tdep.c (ns32k_gdbarch_init): Update. + * v850-tdep.c (v850_gdbarch_init): Update. + * vax-tdep.c (vax_gdbarch_init): Update. + * x86-64-tdep.c (x86_64_gdbarch_init): Update. + * xstormy16-tdep.c (xstormy16_gdbarch_init): Update. + + * config/arc/tm-arc.h: Update. + * config/d30v/tm-d30v.h: Update. + * config/fr30/tm-fr30.h: Update. + * config/h8300/tm-h8300.h: Update. + * config/h8500/tm-h8500.h: Update. + * config/i386/tm-i386.h: Update. + * config/i386/tm-ptx.h: Update. + * config/i386/tm-symmetry.h: Update. + * config/i960/tm-i960.h: Update. + * config/m32r/tm-m32r.h: Update. + * config/m68k/tm-delta68.h: Update. + * config/m68k/tm-linux.h: Update. + * config/m68k/tm-m68k.h: Update. + * config/m88k/tm-m88k.h: Update. + * config/mcore/tm-mcore.h: Update. + * config/mips/tm-mips.h: Update. + * config/mn10200/tm-mn10200.h: Update. + * config/pa/tm-hppa.h: Update. + * config/pa/tm-hppa64.h: Update. + * config/sparc/tm-sp64.h: Update. + * config/sparc/tm-sparc.h: Update. + * config/sparc/tm-sparclet.h: Update. + * config/z8k/tm-z8k.h: Update. + +2002-06-14 Andrew Cagney <cagney@redhat.com> + + * Makefile.in (i386_linux_tdep_h): Define. + (i386_tdep_h, i387_tdep_h): Define. + (i386-linux-nat.o): Add $(i386_linux_tdep_h), + $(i386_tdep_h) and $(i387_tdep_h). + * i386-linux-nat.c: Include "i386-linux-tdep.h". + +2002-06-14 Mark Kettenis <kettenis@gnu.org> + + * config/i386/tm-i386.h (START_INFERIOR_TRAPS_EXPECTED): Removed. + Already covered by the default. + + * config/i386/tm-i386.h (TARGET_LONG_DOUBLE_FORMAT, + TARGET_LONG_DOUBLE_BIT): Remove. * i386-tdep.c + (i386_gdbarch_init): Initialize long_double_format and long_double + bit. + + * config/i386/i386sol2.mt (TDEPFILES): Add i386-sol2-tdep.o and + i386bsd-tdep.o. Remove solib.o, solib-svr4.o and solib-legacy.o. + Move these to ... + * config/i386/i386sol2.mh: ... here. + * config/i386/tm-i386sol2.h (STAB_REG_TO_REGNUM): Remove define. + (sigtramp_saved_pc, I386V4_SIGTRAMP_SAVED_PC): Don't #undef. + (SIGCONTEXT_PC_OFFSET): Remove define. + (IN_SIGTRAMP): Remove define. + * i386-sol2-tdep.c: New file. + + * config/i386/i386nw.mt (TM_FILE): Change to tm-i386.h. + * config/i386/tm-i386nw.h: Removed. + + * config/i386/tm-fbsd.h (STAB_REG_TO_REGNUM, + USE_STRUCT_CONVENTION): Remove defines. + (JB_ELEMENT_SIZE, JB_PC, GET_LONGJMP_TARGET): Remove defines. + (get_longjmp_target): Remove prototype. + (IN_SIGTRAMP): Remove define. + (i386bsd_in_sigtramp): Remove prototype. + (i386bsd_sigtramp_start, i386bsd_sigtramp_end): Turn into a + function. Update comment accordingly + (SIGTRAMP_START, SIGTRAMP): Adjust definition accordingly. + (FRAME_SAVED_PC): Remove define. + (i386bsd_frame_saved_pc): Remove prototype. + * config/i386/tm-nbsd.h (JB_ELEMENT_SIZE, JB_PC, + GET_LONGJMP_TARGET): Remove defines. + (get_longjmp_target): Remove prototype. + (IN_SIGTRAMP): Remove define. + (i386bsd_in_sigtramp): Remove prototype. + (i386bsd_sigtramp_start, i386bsd_sigtramp_end): Turn into a + function. Update comment accordingly + (SIGTRAMP_START, SIGTRAMP): Adjust definition accordingly. + (FRAME_SAVED_PC): Remove define. + (i386bsd_frame_saved_pc): Remove prototype. + * config/i386/tm-nbsdaout.h (i386nbsd_aout_use_struct_convention): + Remove prototype. + (USE_STRUCT_CONVENTION): Remove prototype. + * i386bsd-nat.c (i386bsd_sigcontext_pc_offset): Remove + declaration. + (_initialize_i386bsd_nat): Revise logic to determine some + constants at compile time when compiling a native GDB. Warn if + things don't match up with what we expect. + * i386bsd-tdep.c (i386bsd_sigtramp_start, i386bsd_sigtramp_end): + Remove variables. + (i386bsd_in_sigtramp): Rename tp i386bsd_pc_in_sigtramp. Rewrite + to use date stored in `struct gdbarch_tdep'. + (i386bsd_sigcontext_offset): Remove varaible. + (i386bsd_sigtramp_saved_pc): Make public. Rewrite to use data + stored in `struct gdbarch_tdep'. + (i386bsd_frame_saved_pc): Make static. + (i386bsd_sigtramp_start, i386bsd_sigtramp_end): New functions. + (i386bsd_sc_pc_offset, i386nbsd_sc_pc_offset, + i386fbsd_sigtramp_start, i386fbsd_sigtramp_end, + i386fbsd4_sc_pc_offset): New variables. + (i386bsd_init_abi, i386nbsd_init_abi, i386nbsdelf_init_abi, + i386fbsdaout_init_abi, i386fbsd_init_abi, i386fbsd4_init_abi): New + functions. + (i386bsd_aout_osabi_sniffer, _initialize_i386bsd_tdep): New + functions. + * i386fbsd-nat.c (_initialize_i386fbsd_nat): Fix type in comment. + Modify the value of i386fbsd_sigtramp_start and + i386fbsd_sigtramp_end instead of i386bsd_sigtramp_start and + i386fbsd_sigtramp_end. + * i386nbsd-tdep.c: (i386nbsd_aout_use_struct_convention): Remove + function. + + * config/i386/tm-linux.h (I386_LINUX_ORIG_EAX_REGNUM): Move + define to i386-linux-tdep.h. + (NUM_REGS, MAX_NUM_REGS, REGISTER_BYTES, REGISTER_NAME, + REGISTER_BYTE, REGISTER_RAW_SIZE, STAB_REG_TO_REGNUM): Remove + defines. + (i386_linux_register_name, i386_linux_register_byte, + i386_linux_register_raw_size): Remove prototypes. + (i386_linux_svr4_fetch_link_map_offsets): Remove prototype. + (SVR4_FETCH_LINK_MAP_OFFSETS): Remove define. + (IN_SIGTRAMP, FRAME_CHAIN, FRAME_SAVED_PC, SAVED_PC_AFTER_CALL, + TARGET_WRITE_PC): Remove defines. + (i386_linux_in_sigtramp, i386_linux_frame_chain, + i386_linux_frame_saved_pc, i386_linux_saved_pc_after_call, + i386_linux_write_pc): Remove prototypes. + (JB_ELEMENT_SIZE, JB_PC, GET_LONGJMP_TARGET): Remove defines. + (get_longjmp_target): Remove prototype. + * i386-linux-tdep.h: New file. + * i386-linux-nat.c: Include "i386-linux-tdep.h". + * i386-linux-tdep.c: Include "i386-tdep.h" and + "i386-linux-tdep.h". + (i386_linux_register_name, i386_linux_register_byte, + i386_linux_register_raw_size, i386_linux_in_sigtramp, + i386_linux_write_pc, i386_linux_svr4_fetch_link_map_offsets): + Make static. + (i386_linux_init_abi): New function. + (_initialize_i386_linux_tdep): New function. + + * config/i386/tm-i386.h (SAVED_PC_AFTER_CALL): Remove define. + (i386_saved_pc_after_call): Remove prototype. + (MAX_NUM_REGS): Increase to deal with Linux's orig_eax "register". + (REGISTER_NAME, STAB_REG_TO_REGNUM, SDB_REG_TO_REGNUM, + DWARF_REG_TO_REGNUM, DWARF2_REG_TO_REGNUM): Remove defines. + (i386_register_name, i386_stab_reg_to_regnum, + i386_dwarf_reg_to_regnum): Remove prototypes. + (SIZEOF_GREGS, SIZEOF_FPU_REGS, SIZEOF_FPU_CTL_REGS, + SIZEOF_SSE_REGS): Remove defines. + (REGISTER_BYTES): Remove define. + (REGISTER_BYTE, REGISTER_RAW_SIZE): Remove defines. + (i386_register_byte, i386_register_raw_size): Remove prototypes. + (FRAME_CHAIN, FRAME_SAVED_PC): Remove defines. + (i386_frame_chain, i386_frame_saved_pc): Remove prototypes. + * config/i386/tm-i386v4.h (FRAME_CHAIN_VALID): Remove define. + (JB_ELEMENT_SIZE, JB_PC, JB_EBX, JB_ESI, JB_EDI, JB_EBP, JB_ESP, + JB_EDX, GET_LONGJMP_TARGET): Remove defines. + (get_longjmp_target): Remove prototype. + (I386V4_SIGTRAMP_SAVED_PC, IN_SIGTRAMP): Remove defines. + (sigtramp_saved_pc): Remove define. + (i386v4_sigtramp_saved_pc): Remove prototype. + * config/i386/tm-go32.h (FRAME_CHAIN, + FRAMELESS_FUNCTION_INVOCATION, FRAME_SAVED_PC): Remove defines. + (i386go32_frame_saved_pc): Remove prototype. + (JB_ELEMENT_SIZE, JB_PC, GET_LONGJMP_TARGET): Remove defines. + (get_longjmp_target): Remove prototype. + * i386-tdep.h: Include "osabi.h". + (enum i386_abi): Removed. + (enum struct_return): New enum. + (struct gdbarch_tdep): Remove abi member, add osabi, jb_pc_offset, + struct_return, sigtramp_saved_pc, sigtramp_start, sigtramp_end and + sc_pc_offset members. + (i386_gdbarch_register_os_abi): Remove prototype. + (I386_NUM_GREGS, I386_NUM_FREGS, I386_NUM_XREGS, + I386_SSE_NUM_REGS): New defines. + (I386_SIZEOF_GREGS, I386_SIZEOF_FREGS, I386_SIZEOF_XREGS, + I386_SSE_SIZEOF_REGS): New defines. + (i386_register_name, i386_register_byte, i386_register_raw_size): + New prototypes. + (i386_elf_init_abi, i386_svr4_init_abi): New prototypes. + (i386bsd_sigtramp_saved_pc): New prototype. + * i386-tdep.c: Don't include "elf-bfd.h". + (i386_stab_reg_to_regnum, i386_dwarf_reg_to_regnum, + i386_frame_chain, i386_saved_pc_after_call): Make static. + (i386_frame_saved_pc): Rewrite to call architecture dependent + function to deal with signal handlers. Make static. + (i386go32_frame_saved_pc): Removed. + [GET_LONGJMP_TARGET] (JB_PC, JB_ELEMENT_SIZE, get_longjmp_target): + Removed. + (i386_get_longjmp_target): New function. + (default_struct_convention, pcc_struct_convention, + reg_struct_convention, valid_conventions, struct_convention): New + variables. + (i386_use_struct_convention): New function. + (i386v4_sigtramp_saved_pc): Renamed to + i386_svr4_sigtramp_saved_pc. Made static. Moved. + (i386_pc_in_sigtramp): New function. + (i386_abi_names): Removed. + (ABI_TAG_OS_GNU_LINUX, ABI_TAG_OS_GNU_HURD, + ABI_TAG_OS_GNU_SOLARIS, ABI_TAG_OS_FREEBSD, ABI_TAG_OS_NETBSD): + Removed. + (process_note_sections, i386_elf_abi_from_note, i386_elf_abi, + i386_gdbarch_register_os_abi): Removed. + (struct i386_abi_handler): Removed. + (i386_abi_handler_list): Removed. + (i386_svr4_pc_in_sigtramp, i386_go32_pc_in_sigtramp): New + functions. + (i386_elf_init_abi, i386_svr4_init_abi, i386_go32_init_abi, + i386_nw_init_abi): New functions. + (i386_gdbarch_init): Rewritten to use generic OS ABI framework. + Use set_gdbarch_xxx() calls instead of relying on macros for a + number of calls. + (i386_coff_osabi_sniffer, i386_nlm_osabi_sniffer): New functions. + (_initialize_i386_tdep): Add new 'struct-convcention' command. + Register the various architecture variants defined in this file. + +2002-06-14 Daniel Jacobowitz <drow@mvista.com> + + * gdbtypes.h (TYPE_FLAG_VARARGS): Update comment. + (struct main_type): Remove arg_types member. Update comments for + struct field. + (TYPE_ARG_TYPES): Remove. + (TYPE_FN_FIELD_ARGS): Update. + (smash_to_method_type): Update prototype. + + * c-typeprint.c (cp_type_print_method_args): Take method type + instead of argument list. Use new argument layout. Simplify. + (c_type_print_args): Use new argument layout. Simplify. + (c_type_print_base): Update call to cp_type_print_method_args. + * dwarf2read.c (dwarf2_add_member_fn): Remove unneeded type + argument; use die->type instead. Update call to + smash_to_method_type. + (read_structure_scope): Update call to dwarf2_add_member_fn. + * gdbtypes.c (allocate_stub_method): Update comment. + (smash_to_method_type): Take new NARGS and VARARGS arguments. + Use new argument layout. + (check_stub_method): Use new argument layout. Don't count + void as an argument. + (print_arg_types): Update comments. Use new argument layout. + (recursive_dump_type): Don't print arg_types member. + * hpread.c (hpread_read_struct_type): Use new argument layout. + (fixup_class_method_type): Likewise. + (hpread_type_lookup): Likewise. + * stabsread.c (read_type): Update calls to read_args and + smash_to_method_type. + (read_args): Use new argument layout. Simplify. + * valops.c (typecmp): Use new argument layout. Update parameters + and comments. Simplify. + (hand_function_call): Use new argument layout. + (search_struct_method): Update call to typecmp. + (find_overload_match): Use new argument layout. + +2002-06-13 Daniel Jacobowitz <drow@mvista.com> + + * NEWS: Mention multithreaded debug support for gdbserver. + +2002-06-13 Daniel Jacobowitz <drow@mvista.com> + + * MAINTAINERS: Mention NEWS. + +2002-06-13 Daniel Jacobowitz <drow@mvista.com> + + * mips-tdep.c (PROC_SYMBOL): Add warning comment. + (struct mips_objfile_private, compare_pdr_entries): New. + (non_heuristic_proc_desc): Read the ".pdr" section if it + is present. + +2002-06-12 Andrew Cagney <ac131313@redhat.com> + + * arm-tdep.c (arm_push_arguments): Rewrite using a two-pass loop. + (arm_debug): New static variable. + (_initialize_arm_tdep): Add ``set debug arm'' command. + +2002-06-12 Andrew Cagney <ac131313@redhat.com> + + * Makefile.in (sim_arm_h): Define. + (arm-tdep.o): Add $(sim_arm_h) and $(gdb_assert_h). + * arm-tdep.c: Include "gdb/sim-arm.h" and "gdb_assert.h". + (arm_register_sim_regno): New function, map an internal REGNUM + onto a simulator register number. + (arm_gdbarch_init): Set register_sim_regno. + +2002-06-09 Aldy Hernandez <aldyh@redhat.com> + + * MAINTAINERS: Add self. + +2002-06-11 Jim Blandy <jimb@redhat.com> + + * source.c (source_info): Mention whether the symtab has + information about preprocessor macros. + + Call the command `info macro', not `show macro'. + * macrocmd.c (info_macro_command): Renamed from `show_macro_command'. + Fix error message. + (_initialize_macrocmd): Register `info_macro_command' in + `infolist', not `showlist'. + +2002-06-11 Daniel Jacobowitz <drow@mvista.com> + + * mips-tdep.c (MIPS_FPU_TYPE, FP_REGISTER_DOUBLE, MIPS_EABI) + (MIPS_LAST_FP_ARG_REGNUM, MIPS_LAST_ARG_REGNUM) + (MIPS_DEFAULT_SAVED_REGSIZE, MIPS_REGS_HAVE_HOME_P) + (MIPS_DEFAULT_STACK_ARGSIZE, GDB_TARGET_IS_MIPS64) + (MIPS_DEFAULT_MASK_ADDRESS_P): Remove obsolete definitions. Define + unconditionally. + (set_mipsfpu_single_command, set_mipsfpu_double_command) + (set_mipsfpu_none_command): Remove if (GDB_MULTI_ARCH). + (_initialize_mips_tdep): Remove dead code. + * config/mips/tm-irix5.h (MIPS_LAST_ARG_REGNUM) + (MIPS_DEFAULT_STACK_ARGSIZE, MIPS_REGS_HAVE_HOME_P): Remove. + * config/mips/tm-irix6.h (MIPS_LAST_ARG_REGNUM) + (MIPS_DEFAULT_STACK_ARGSIZE, MIPS_REGS_HAVE_HOME_P): Remove. + * config/mips/tm-mips.h (MIPS_EABI, MIPS_LAST_ARG_REGNUM, + MIPS_LAST_FP_ARG_REGNUM): Remove. + +2002-06-11 Michal Ludvig <mludvig@suse.cz> + + * dwarf2cfi.c (unwind_tmp_obstack_init): New. + (unwind_tmp_obstack_free, parse_frame_info) + (update_context, cfi_read_fp, cfi_write_fp) + (cfi_frame_chain, cfi_init_extra_frame_info) + (cfi_virtual_frame_pointer): Use the above function. + * dwarf2cfi.c: Reindented (using 'indent dwarf2cfi.c'). + +2002-06-11 Corinna Vinschen <vinschen@redhat.com> + + * v850-tdep.c (v850_type_is_scalar): New function. + (v850_use_struct_convention): Match current gcc implementation + as close as possible. + (v850_push_arguments): Fix stack_offset handling. Don't write + struct_addr into register. This is done by v850_store_struct_return. + (v850_extract_return_value): Care for structs. + (v850_store_return_value): Ditto. + (v850_store_struct_return): Actually write address. + +2002-06-11 Michal Ludvig <mludvig@suse.cz> + + * x86-64-tdep.c (x86_64_skip_prologue): Fix to work on functions + without debug information too. + +2002-06-10 Andrew Cagney <ac131313@redhat.com> + + * gdbarch.sh (PRINT_FLOAT_INFO): Add frame and ui_file parameters. + Make multi-arch pure. + * gdbarch.h, gdbarch.c: Re-generate. + * arm-tdep.c (arm_print_float_info): Update. + * arch-utils.h (default_print_float_info): Update. + * arch-utils.c (default_print_float_info): Update. + * infcmd.c (float_info): Update call. + +2002-06-10 Andrew Cagney <ac131313@redhat.com> + + * Makefile.in (init.c): Move the call to _initialize_gdbtypes to + the front of the initialize list. + +2002-06-10 Andrew Cagney <ac131313@redhat.com> + + * infrun.c (struct inferior_status): Replace fields + selected_frame_address and selected_level with field + selected_frame_id. + (save_inferior_status): Update. Use get_frame_id. + (struct restore_selected_frame_args): Delete. + (restore_selected_frame): Update. Use frame_find_by_id. + (restore_inferior_status): Update. + + * breakpoint.h (struct breakpoint): Change type of + watchpoint_frame to frame_id. + * breakpoint.c (insert_breakpoints): Use frame_find_by_id. Remove + call to get_current_frame. + (do_enable_breakpoint): Use frame_find_by_id. Remove call to + get_current_frame. + (watchpoint_check): Use frame_find_by_id. + + * frame.h (record_selected_frame): Delete declaration. + * stack.c (record_selected_frame): Delete function. + + * frame.h (struct frame_id): Define. + (get_frame_id): Declare. + (frame_find_by_id): Declare. + * frame.c (frame_find_by_id): New function. + (get_frame_id): New function. + +2002-06-10 Andrey Volkov <avolkov@transas.com> + + * ser-e7kpc.c: Fix duplicated define and call of + _initialize_ser_e7000pc + +2002-06-09 Daniel Jacobowitz <drow@mvista.com> + + * signals/signals.c (target_signal_from_host): Fix #ifdef + SIGRTMIN case. + (do_target_signal_to_host): Likewise. + +2002-06-09 Daniel Jacobowitz <drow@mvista.com> + + * mips-tdep.c (mips_find_abi_section): New function. + (mips_gdbarch_init): Call it. + +2002-06-09 Mark Kettenis <kettenis@gnu.org> + + * solib-svr4.c (init_fetch_link_map_offsets): Simply return + legacy_fetch_link_map_offsets. Adjust comment to reflect reality + after Andrew's 2002-06-08 gdbarch change. + +2002-06-09 Mark Kettenis <kettenis@gnu.org> + + * i386-linux-nat.c (suppy_gregset): Don't supply + I386_LINUX_ORIG_EAX_REGNUM if there isn't room for it in GDB's + register cache. + (fill_gregset): Don't fetch it under the same circumstances. + +2002-06-09 Andrew Cagney <cagney@redhat.com> + + * Makefile.in (callback_h): Define. + (remote_sim_h): Update path to remote-sim.h. + (remote-rdp.o): Add $(callback_h). + (remote-sim.o): Use $(callback_h). + * remote-sim.c: Include "gdb/callback.h" and "gdb/remote-sim.h". + * remote-rdp.c: Include "gdb/callback.h". + +2002-06-09 Mark Kettenis <kettenis@gnu.org> + + * osabi.h (gdb_osabi): Add GDB_OSABI_GO32 and GDB_OSABI_NETWARE. + * osabi.c (gdb_osabi_names): Add "DJGPP" and "NetWare". + +2002-06-08 Andrew Cagney <ac131313@redhat.com> + + * sparcl-tdep.c: Use __CYGWIN__ instead of __CYGWIN32__. + * rdi-share/serpardr.c: Ditto. + * rdi-share/unixcomm.c: Ditto. + * rdi-share/serdrv.c: Ditto. + * rdi-share/hostchan.h: Ditto. + * rdi-share/hostchan.c: Ditto. + * rdi-share/host.h: Ditto. + * rdi-share/devsw.c: Ditto. + + * objfiles.h: Change type of obj_private to void pointer. + * pa64solib.c: Update copyright. Don't include "assert.h", use + strcmp instead of STREQ, use LONGEST, do not use PTR + * somsolib.c: Ditto. + + * config/djgpp/fnchange.lst: Fix problems with bfd/elf32-i386.c, + bfd/elf32-i386qnx.c, bfd/elf32-sh.c, bfd/elf32-sh64-nbsd.c, + bfd/elf64-sh64-nbsd.c bfd/elf64-sh64.c. + +2002-06-08 Andrew Cagney <ac131313@redhat.com> + + * frame.c (GET_SAVED_REGISTER): Delete macro definition. + (default_get_saved_register): Delete function. + * gdbarch.sh (GET_SAVED_REGISTER): Set default to + generic_unwind_get_saved_register. + * gdbarch.h, gdbarch.c: Re-generate. + +2002-06-08 Andrew Cagney <ac131313@redhat.com> + + * gdbarch.sh (FRAME_CHAIN_VALID): Set default to + generic_func_frame_chain_valid. + * gdbarch.h, gdbarch.c: Re-generate. + * blockframe.c (generic_func_frame_chain_valid): Only check + PC_IN_CALL_DUMMY when generic dummy frames. Don't worry about + passing FP to PC_IN_CALL_DUMMY. + Fix PR gdb/360. + +2002-06-08 Andrew Cagney <ac131313@redhat.com> + + * gdbarch.sh (struct gdbarch_data): Add field init_p. + (register_gdbarch_data): Initialize init_p. + (gdbarch_data): Initialize data pointer using the init function. + (init_gdbarch_data): Delete function. + (gdbarch_update_p): Update. + (initialize_non_multiarch): Update. + (struct gdbarch): Add field initialized_p. + * gdbarch.h, gdbarch.c: Re-generate. + +2002-06-07 Michal Ludvig <mludvig@suse.cz> + + * x86-64-linux-nat.c (x86_64_fxsave_offset): New. + (supply_fpregset, fill_fpregset): Don't call i387_*_fxsave, + better do the things actually here. + * x86-64-tdep.c (x86_64_register_name2nr): New. + (x86_64_register_name): Renamed to x86_64_register_nr2name. + (x86_64_gdbarch_init): Respect the above change. + * x86-64-tdep.h (x86_64_register_name2nr) + (x86_64_register_nr2name): Add prototypes. + * config/i386/x86-64linux.mt (TDEPFILES): Remove i387-tdep.o. + +2002-06-06 Michael Snyder <msnyder@redhat.com> + + * d10v-tdep.c (d10v_push_arguments): Handle struct_return. + Delete extra braces and re-indent. + (d10v_store_return_value): Char return values + must be shifted over by one byte in R0. + (d10v_extract_return_value): Delete extra braces, re-indent. + +2002-06-06 Elena Zannoni <ezannoni@redhat.com> + + * d10v-tdep.c (d10v_read_sp, d10v_read_fp): Add prototype. + (d10v_register_virtual_type): Make $fp and $sp be pointer to data. + (d10v_integer_to_address): Rewrite. + (d10v_frame_init_saved_regs): When reading fp and sp registers use + the d10v specific functions which take care of converting to the + correct space. + +2002-06-06 Elena Zannoni <ezannoni@redhat.com> + + * config/djgpp/fnchange.lst: Add testsuite files altivec-abi.c, + altivec-abi.exp, altivec-regs.c, altivec-regs.exp. + +2002-06-02 Andrew Cagney <ac131313@redhat.com> + + * config/alpha/nm-linux.h: Add "config/" prefix to tm, nm and xm + includes. + * config/tm-linux.h: Ditto. + * config/alpha/tm-alphalinux.h: Ditto. + * config/arm/nm-linux.h, config/arm/tm-linux.h: Ditto. + * config/arm/xm-nbsd.h, config/i386/nm-gnu.h: Ditto. + * config/i386/nm-i386lynx.h, config/i386/nm-i386sol2.h: Ditto. + * config/i386/nm-i386v4.h, config/i386/nm-i386v42mp.h: Ditto. + * config/i386/nm-linux.h, config/i386/nm-m3.h: Ditto. + * config/i386/nm-ptx4.h, config/i386/nm-x86-64.h: Ditto. + * config/i386/tm-i386gnu.h, config/i386/tm-i386lynx.h: Ditto. + * config/i386/tm-i386m3.h, config/i386/tm-i386sco5.h: Ditto. + * config/i386/tm-i386v4.h, config/i386/tm-linux.h: Ditto. + * config/i386/tm-ptx4.h, config/i386/tm-vxworks.h: Ditto. + * config/i386/xm-i386v4.h, config/i386/xm-nbsd.h: Ditto. + * config/i386/xm-ptx.h, config/i386/xm-ptx4.h: Ditto. + * config/i960/tm-vx960.h, config/ia64/nm-aix.h: Ditto. + * config/ia64/nm-linux.h, config/ia64/tm-aix.h: Ditto. + * config/ia64/tm-linux.h, config/ia64/xm-aix.h: Ditto. + * config/m68k/nm-linux.h, config/m68k/nm-m68klynx.h: Ditto. + * config/m68k/nm-sysv4.h, config/m68k/tm-linux.h: Ditto. + * config/m68k/tm-m68klynx.h, config/m68k/tm-m68kv4.h: Ditto. + * config/m68k/tm-sun2os4.h, config/m68k/tm-sun3os4.h: Ditto. + * config/m68k/tm-vx68.h, config/m68k/xm-m68kv4.h: Ditto. + * config/m68k/xm-nbsd.h, config/m88k/nm-delta88v4.h: Ditto. + * config/m88k/tm-delta88v4.h, config/m88k/xm-delta88v4.h: Ditto. + * config/mips/nm-irix5.h, config/mips/nm-linux.h: Ditto. + * config/mips/tm-linux.h, config/mips/tm-mips64.h: Ditto. + * config/mips/tm-mipsm3.h, config/mips/tm-mipsv4.h: Ditto. + * config/mips/tm-vxmips.h, config/mips/xm-irix5.h: Ditto. + * config/mips/xm-mipsv4.h, config/ns32k/xm-nbsd.h: Ditto. + * config/pa/nm-hppao.h, config/powerpc/nm-linux.h: Ditto. + * config/powerpc/tm-linux.h, config/powerpc/tm-vxworks.h: Ditto. + * config/powerpc/xm-aix.h, config/rs6000/nm-rs6000ly.h: Ditto. + * config/rs6000/tm-rs6000ly.h, config/rs6000/xm-aix4.h: Ditto. + * config/sh/tm-linux.h, config/sparc/nm-linux.h: Ditto. + * config/sparc/nm-sparclynx.h, config/sparc/nm-sun4sol2.h: Ditto. + * config/sparc/tm-linux.h, config/sparc/tm-sp64linux.h: Ditto. + * config/sparc/tm-sp64sim.h, config/sparc/tm-sparclynx.h: Ditto. + * config/sparc/tm-sun4os4.h, config/sparc/tm-sun4sol2.h: Ditto. + * config/sparc/tm-vxsparc.h, config/sparc/xm-sun4sol2.h: Ditto. + +2002-05-04 Aidan Skinner <aidan@velvet.net> + + * ada-exp.tab.c: New file + * ada-exp.y: New file + * ada-lang.c: New file + * ada-lang.h: New file + * ada-lex.c: New file + * ada-lex.l: New file + * ada-tasks.c: New file + * ada-typeprint.c: New file + * ada-valprint.c: New file + +2002-06-02 Jason Thorpe <thorpej@wasabisystems.com> + + * ppcnbsd-tdep.c (ppcnbsd_init_abi): Don't set + use_struct_convention to ppc_sysv_abi_broken_use_struct_convention. + +2002-06-02 Jason Thorpe <thorpej@wasabisystems.com> + + * config/rs6000/aix4.mt (TDEPFILES): Use ppc-sysv-tdep.o + insetead of ppc-linux-tdep.o. + * config/rs6000/rs6000.mt (TDEPFILES): Likewise. + * config/rs6000/rs6000lynx.mt (TDEPFILES): Likewise. + +2002-06-02 Andrew Cagney <ac131313@redhat.com> + + 2002-05-07 Christian Groessler <chris@groessler.org> + * z8k-tdep.c (z8k_print_register_hook): Fix display of 32 and 64 + bit register contents for little endian hosts. + +2002-06-01 Andrew Cagney <ac131313@redhat.com> + + * MAINTAINERS: Mention that any `HP/UX reader' can be changed by + any maintainer. + +2002-06-01 Andrew Cagney <ac131313@redhat.com> + + * gdbarch.h: Regenerate. + +2002-06-01 Andrew Cagney <ac131313@redhat.com> + + * MAINTAINERS: Add everyone to write-after-approval list. + +2002-06-01 Andrew Cagney <ac131313@redhat.com> + + * stack.c (frame_info): Use frame_register_unwind instead of + saved_regs. Mention when the SP is on the stack or in a register. + + * frame.h (frame_register_unwind_ftype): Define. Document. + (struct frame_info): Add field register_unwind and + register_unwind_cache. + (frame_register_unwind): Declare. + (generic_unwind_get_saved_register): Declare. + + * frame.c (frame_register_unwind): New function. + (generic_unwind_get_saved_register): New function. + + * blockframe.c (generic_call_dummy_register_unwind): New function. + (frame_saved_regs_register_unwind): New function. + (set_unwind_by_pc): New function. + (create_new_frame): New function. + (get_prev_frame): New function. + +2002-05-30 Andrew Cagney <ac131313@redhat.com> + + * a29k-share/: Delete directory. + * remote-vx29k.c: Delete file. + +2002-05-30 Jason Thorpe <thorpej@wasabisystems.com> + + * config/djgpp/fnchange.lst: Add ns32knbsd-nat.c, ns32knbsd-tdep.c, + ppcnbsd-nat.c, ppcnbsd-tdep.c, sparcnbsd-nat.c, and sparcnbsd-tdep.c. + +2002-05-30 Jason Thorpe <thorpej@wasabisystems.com> + + * Makefile.in (ALLDEPFILES): Add sparc64nbsd-nat.c, + sparcnbsd-nat.c, and sparcnbsd-tdep.c. + (sparc64nbsd-nat.o) + (sparcnbsd-nat.o) + (sparcnbsd-tdep.o): New dependency lists. + * NEWS: Note new UltraSPARC NetBSD native configuration. + * configure.host (sparc64-*-netbsd*): New host. + * configure.tgt (sparc-*-netbsdelf*) + (sparc-*-netbsd*): Set gdb_target to nbsd. + (sparc64-*-netbsd*): New target. + * sparc64nbsd-nat.c: New file. + * sparcnbsd-nat.c: New file. + * sparcnbsd-tdep.c: New file. + * sparcnbsd-tdep.h: New file. + * config/sparc/nbsd.mt: New file. + * config/sparc/nbsd64.mh: New file. + * config/sparc/nbsd64.mt: New file. + * config/sparc/nbsdaout.mh (NATDEPFILES): Remove corelow.o, + sparc-nat.o, and solib.o. Add sparcnbsd-nat.o. + (HOST_IPC): Remove. + * config/sparc/nbsdaout.mt: Remove. + * config/sparc/nbsdelf.mh (NATDEPFILES): Remove corelow.o, + sparc-nat.o, and solib.o. Add sparcnbsd-nat.o. + (HOST_IPC): Remove. + * config/sparc/nbsdelf.mt: Remove. + * config/sparc/nm-nbsd.h: Update copyright years. Remove all + sparc-nat.c compatiblity defines. + * config/sparc/tm-nbsd.h: Update copyright years. Include solib.h. + (GDB_MULTI_ARCH): Set to GDB_MULTI_ARCH_PARTIAL. + * config/sparc/tm-nbsd64.h: New file. + * config/sparc/tm-nbsdaout.h: Remove. + * config/sparc/xm-nbsd.h: Remove. + +2002-05-30 Jason Thorpe <thorpej@wasabisystems.com> + + * Makefile.in (sparc-tdep.o): Add osabi.h to dependency list. + * sparc-tdep.c: Include osabi.h. + (gdbarch_tdep): Add osabi member. + (_initialize_sparc_tdep): Use gdbarch_register. + (sparc_gdbarch_init): Use generic OS ABI framework. + (sparc_dump_tdep): New function. + +2002-05-30 Kevin Buettner <kevinb@redhat.com> + + * corefile.c (do_captured_read_memory_integer): Return non-zero + result. + (safe_read_memory_integer): Copy result of memory read when + status is non-zero. Also, add comments. + +2002-05-20 Jason Thorpe <thorpej@wasabisystems.com> + + * Makefile.in (ppc_tdep_h): Define. + (ppc-linux-nat.o) + (ppc-linux-tdep.o) + (rs6000-tdep.o): Use $(ppc_tdep_h). + (ppc-sysv-tdep.o) + (ppcnbsd-nat.o) + (ppcnbsd-tdep.o): New dependency lists. + * ppc-tdep.h: Use generic OS ABI framework. + * ppc-linux-tdep.c (_initialize_ppc_linux_tdep) + (ppc_linux_init_abi): New functions. + (ppc_sysv_abi_broken_use_struct_convention) + (ppc_sysv_abi_use_struct_convention) + (ppc_sysv_abi_push_arguments): Move to... + * ppc-sysv-tdep.c: ...here. + * ppcnbsd-nat.c: Don't include gdbcore.h and regcache.h. + * rs6000-tdep.c (process_note_abi_tag_sections) + (get_elfosabi): Remove. + (rs6000_gdbarch_init): Use generic OS ABI framework. + (rs6000_dump_tdep): New function. + (_initialize_rs6000_tdep): Use gdbarch_register. + * config/powerpc/linux.mt (TDEPFILES): Add ppc-sysv-tdep.o. + * config/powerpc/nbsd.mh (NATDEPFILES): Remove solib-legacy.o. + * config/powerpc/aix.mt (TDEPFILES): Use ppc-sysv-tdep.o instead + of ppc-linux-tdep.o. + * config/powerpc/nbsd.mt (TDEPFILES): Likewise. + * config/powerpc/ppc-eabi.mt (TDEPFILES): Likewise. + * config/powerpc/ppc-sim.mt (TDEPFILES): Likewise. + * config/powerpc/ppcle-eabi.mt (TDEPFILES): Likewise. + * config/powerpc/ppcle-sim.mt (TDEPFILES): Likewise. + * config/powerpc/vxworks.mt (TDEPFILES): Likewise. + +2002-05-29 Jim Blandy <jimb@redhat.com> + + * macroscope.c (default_macro_scope): Put `void' in empty argument + list. + +2002-05-29 Andrew Cagney <ac131313@redhat.com> + + * Makefile.in (arch-utils.o): Add $(sim_regno_h). + * arch-utils.c: Include "sim-regno.h". + * gdbarch.sh: Don't include "sim-regno.h". + * gdbarch.h, gdbarch.c: Regenerate. + * sim-regno.h (legacy_register_sim_regno): Move declaration from + here. + * arch-utils.h (legacy_register_sim_regno): To here. + * remote-sim.c (legacy_register_sim_regno): Move function from + here. + * arch-utils.c (legacy_register_sim_regno): To here. + +2002-05-28 Andrew Cagney <ac131313@redhat.com> + + * sim-regno.h: New file. + * Makefile.in (sim_regno_h): Define. + (d10v-tdep.o, remote-sim.o): Add dependency on $(sim_regno_h). + * remote-sim.c: Include "sim-regno.h" and "gdb_assert.h". + (legacy_register_sim_regno): New function. + (one2one_register_sim_regno): New function. + (gdbsim_fetch_register): Rewrite. + (gdbsim_store_register): Only store a register when + REGISTER_SIM_REGNO is valid. + * d10v-tdep.c: Include "sim-regno.h". + (d10v_ts2_register_sim_regno): Add legacy_regiter_sim_regno check. + (d10v_ts3_register_sim_regno): Ditto. + * gdbarch.sh: Include "sim-regno.h". + (REGISTER_SIM_REGNO): Set default to legacy_register_sim_regno. + * gdbarch.h, gdbarch.c: Regenerate. + * arch-utils.h (default_register_sim_regno): Delete declaration. + * arch-utils.c (default_register_sim_regno): Delete function. + +2002-05-28 Jason Thorpe <thorpej@wasabisystems.com> + + * ppcnbsd-nat.c: Rewrite. + * ppcnbsd-tdep.c: New file. + * ppcnbsd-tdep.h: New file. + * config/powerpc/nbsd.mh (NATDEPFILES): Remove corelow.o, + solib.o, and solib-svr4.o. + * config/powerpc/nbsd.mt (TDEPFILES): Add ppcnbsd-tdep.o, + nbsd-tdep.o, and corelow.o. + +2002-05-28 Andrew Cagney <ac131313@redhat.com> + + * MAINTAINERS (--enable-gdb-build-warnings): Rewrite script to use + `tr' and `sed'. Mention that `broken' targets are not expected to + build. + +2002-05-27 Michal Ludvig <mludvig@suse.cz> + + * x86-64-tdep.c (x86_64_skip_prologue): Remove obsolete note. + Let PC point right after the prologue before looking up symbols. + +2002-05-27 Martin M. Hunt <hunt@redhat.com> + + * i386-tdep.c (i386_register_virtual_type): Return + builtin_type_vec128i for SSE registers. + + * gdbtypes.h (builtin_type_vec128i): Declare. + + * gdbtypes.c (build_builtin_type_vec128i): New function. + (builtin_type_v2_double, builtin_type_v4_int64): New types. + (builtin_type_vec128i): New type for SSE2 128-bit registers. + (build_gdbtypes): Initialize new builtin vector types. + (_initialize_gdbtypes): Register new vector types with gdbarch. + +2002-05-26 Jason Thorpe <thorpej@wasabisystems.com> + + * MAINTAINERS: ns32k is not longer an obsolete candidate, + since it has been multi-arch'd. + * NEWS: Note that ns32k-*-* is now partial multi-arch. + Move Alpha and VAX multi-arch news entries to same section + as other multi-arch news. + +2002-05-26 Jason Thorpe <thorpej@wasabisystems.com> + + * ns32k-tdep.c: include gdbtypes.h, inferior.h, regcache.h, + target.s, arch-utils.h, ns32k-tdep.h. Make many functions + static. Rename some register numbers to put them in ns32k-tdep + private namespace. + (ns32k_get_saved_register, ns32k_gdbarch_init_32082, + ns32k_gdbarch_init_32382, ns32k_gdbarch_init, ns32k_dump_tdep): New + functions. + (_initialize_ns32k_tdep): Use gdbarch_register. + * ns32k-tdep.h: New file. + * ns32knbsd-tdep.c: New file. + * config/ns32k/nbsdaout.mt (TDEPFILES): Add ns32knbsd-tdep.o. + * config/ns32k/tm-nbsd.h: Include "ns32k/tm-ns32k.h". + (IN_SOLIB_CALL_TRAMPOLINE, REGISTER_NAME, NUM_REGS, + REGISTER_BYTES, REGISTER_BYTE): Remove. + * config/ns32k/tm-ns32k.h: New file. + * config/ns32k/tm-umax.h: Remove. + +2002-05-26 Jason Thorpe <thorpej@wasabisystems.com> + + * ns32k-tdep.c (ns32k_saved_pc_after_call, + ns32k_store_struct_return, ns32k_extract_return_value, + ns32k_store_return_value, ns32k_extract_struct_value_address): New + functions. + * config/ns32k/tm-umax.h (SAVED_PC_AFTER_CALL): Define as + ns32k_saved_pc_after_call. + (STORE_STRUCT_RETURN): Define as ns32k_store_struct_return. + (EXTRACT_RETURN_VALUE): Define as ns32k_extract_return_value. + (STORE_RETURN_VALUE): Define as ns32k_store_return_value. + (EXTRACT_STRUCT_VALUE_ADDRESS): Define as + ns32k_extract_struct_value_address. + +2002-05-26 Jason Thorpe <thorpej@wasabisystems.com> + + * ns32k-tdep.c (ns32k_call_dummy_words, sizeof_ns32k_call_dummy_words, + ns32k_fix_call_dummy): New. + * config/ns32k/tm-umax.h (CALL_DUMMY_WORDS): Define as + ns32k_call_dummy_words. + (SIZEOF_CALL_DUMMY_WORDS): Define as sizeof_ns32k_call_dummy_words. + (CALL_DUMMY, CALL_DUMMY_LENGTH, CALL_DUMMY_ADDR, + CALL_DUMMY_NARGS): Remove. + (FIX_CALL_DUMMY): Define as ns32k_fix_call_dummy. + +2002-05-26 Jason Thorpe <thorpej@wasabisystems.com> + + * ns32k-tdep.c (ns32k_breakpoint_from_pc, ns32k_frame_chain, + ns32k_frame_saved_pc, ns32k_frame_args_address, + ns32k_frame_locals_address, ns32k_frame_init_saved_regs, + ns32k_push_dummy_frame, ns32k_pop_frame): New functions. + * config/ns32k/tm-nbsd.h (FRAME_SAVED_PC): Remove. + * config/ns32k/tm-umax.h (INNER_THAN): Define as core_addr_lessthan. + (BREAKPOINT_FROM_PC): Define as ns32k_breakpoint_from_pc. + (BREAKPOINT): Remove.. + (FRAME_CHAIN): Define as ns32k_frame_chain. + (FRAME_SAVED_PC): Define as ns32k_frame_saved_pc. + (FRAME_ARGS_ADDRESS): Define as ns32k_frame_args_address. + (FRAME_LOCALS_ADDRESS): Define as ns32k_frame_locals_address. + (FRAME_FIND_SAVED_REGS): Remove. + (FRAME_INIT_SAVED_REGS): Define as ns32k_frame_init_saved_regs. + (PUSH_DUMMY_FRAME): Define as ns32k_push_dummy_frame. + (POP_FRAME): Define as ns32k_pop_frame. + +2002-05-26 Jason Thorpe <thorpej@wasabisystems.com> + + * ns32k-tdep.c (ns32k_register_byte_32082, + ns32k_register_byte_32382, ns32k_register_raw_size, + ns32k_register_virtual_size, ns32k_register_virtual_type): New + functions. + * config/ns32k/tm-nbsd.h (REGISTER_BYTE): Define as + ns32k_register_byte_32382. + * config/ns32k/tm-umax.h: Update copyright years. + (REGISTER_BYTE): Define as ns32k_register_byte_32082. + (REGISTER_RAW_SIZE): Define as ns32k_register_raw_size. + (REGISTER_VIRTUAL_SIZE): Define as ns32k_register_virtual_size. + (REGISTER_VIRTUAL_TYPE): Define as ns32k_register_virtual_type. + (ns32k_get_enter_addr): Fix prototype. + +2002-05-26 Jason Thorpe <thorpej@wasabisystems.com> + + * ns32k-tdep.c: Update copyright years. + (ns32k_register_name_32082): New function. + (ns32k_register_name_32382): Ditto. + * config/ns32k/tm-nbsd.h (REGISTER_NAMES): Remove. + (REGISTER_NAME): Define as ns32k_register_name_32382. + * config/ns32k/tm-umax.h (REGISTER_NAMES): Remove. + (REGISTER_NAME): Define as ns32k_register_name_32082. + +2002-05-24 Jim Blandy <jimb@redhat.com> + + * dwarf2read.c (free_line_header): Use xfree, not free. + +2002-05-24 Jason Thorpe <thorpej@wasabisystems.com> + + * config/djgpp/fnchange.lst: Add alphabsd-nat.c, + alphabsd-tdep.c, mipsnbsd-nat.c, and mipsnbsd-tdep.c + +2002-05-23 Andrew Cagney <ac131313@redhat.com> + + * PROBLEMS: Mention s390 and FreeBSD 4.4 build problems. + +2002-05-23 Andrew Cagney <ac131313@redhat.com> + + From Ross Alexander at NEC Europe: + * config/pa/hpux11w.mh (NATDEPFILES): Add solib.o. + +2002-05-23 Michael Snyder <msnyder@redhat.com> + + * cli/cli-dump.c (restore_command): Use parse_and_eval_long + for input, rather than parse_and_eval_address. + +2002-05-23 Andrew Cagney <ac131313@redhat.com> + + * d10v-tdep.c: Include "gdb/sim-d10v.h" instead of "sim-d10v.h". + * Makefile.in (sim_d10v_h): Update definition. + +2002-05-24 Andrew Cagney <cagney@redhat.com> + + * d10v-tdep.c (d10v_gdbarch_init): Revert old code included in + change `2002-05-22 Michael Snyder' below. + (d10v_push_arguments): Ditto. + (d10v_extract_return_value): Ditto. + +2002-05-23 Jim Blandy <jimb@redhat.com> + + * macrotab.c (check_for_redefinition): Don't complain if the new + definition is the same as the previous one. Take more arguments + to allow the comparison. + (macro_define_object, macro_define_function): Pass more arguments + to check_for_redefinition. + +2002-05-22 Michael Snyder <msnyder@redhat.com> + + * d10v-tdep.c: Change a few macros to enums for ease of debugging. + (d10v_frame_chain_valid): Add PC_IN_CALL_DUMMY clause. + (d10v_frame_saved_pc): Add PC_IN_CALL_DUMMY clause. + (d10v_frame_chain): Bail immediately if PC_IN_CALL_DUMMY. + Don't bail if return_pc is PC_IN_CALL_DUMMY. + Add a temp variable to save a call (and a memory read). + (d10v_init_extra_frame_info): Get fi->pc from callee's return_pc + if possible (so that PC_IN_CALL_DUMMY will work). + +2002-05-22 Corinna Vinschen <vinschen@redhat.com> + + * MAINTAINERS: Remove status `OBSOLETE' from v850. + +2002-05-22 Michal Ludvig <mludvig@suse.cz> + + * dwarf2cfi.c (frame_state_for): Added safety check for a valid + fde->cie_ptr. + (dwarf2_build_frame_info): Corrected handling of eh_frame. + (dwarf2_build_frame_info): Add offset to fde->initial_location + so that frames of shared libraries are mapped correctly. + (execute_stack_op): Change type of 'result' from ULONGEST to + CORE_ADDR. + +2002-05-22 Jason Thorpe <thorpej@wasabisystems.com> + + * config/alpha/tm-nbsd.h: Include solib.h. + +2002-05-22 Jason Thorpe <thorpej@wasabisystems.com> + + * alphanbsd-tdep.c (alphanbsd_sigtramp_offset): Don't make + assumptions about the host's byte order. + +2002-05-22 Jason Thorpe <thorpej@wasabisystems.com> + + * Makefile.in (alphanbsd-tdep.o, shnbsd-tdep.o): Add solib-svr4.h + to dependency list. + * alphanbsd-tdep.c: Include solib-svr4.h. + * shnbsd-tdep.c: Ditto. + +2002-05-22 Jason Thorpe <thorpej@wasabisystems.com> + + * Makefile.in (armnbsd-tdep.o): Add solib-svr4.h and + nbsd-tdep.h to dependency list. + * configure.host (arm*-*-netbsdelf*, arm*-*-netbsd*, + i[3456]86-*-netbsdaout*, i[3456]86-*-netbsd*, m68*-*-netbsd*, + ns32k-*-netbsd*, sparc-*-netbsdaout*, sparc-*-netbsd*): Use + nbsdaout.mh and nbsdelf.mh consistently. + * configure.tgt (i[3456]86-*-netbsd*, m68*-*-netbsd*, + ns32k-*-netbsd*, sparc-*-netbsdelf*, sparc-*-netbsd*) Use + nbsdaout.mt and nbsdelf.mh consistently. + * armnbsd-tdep.c: Include nbsd-tdep.h and solib-svr4.h. + (arm_netbsd_elf_init_abi): Use set_solib_svr4_fetch_link_map_offsets + to set nbsd_ilp32_solib_svr4_fetch_link_map_offsets. + * config/nm-nbsd.h: Garbage-collect SVR4_SHARED_LIBS. Move + a.out shared library stuff from here... + * config/nm-nbsdaout.h: ...to here. + * config/tm-nbsd.h: Remove. + * config/alpha/nm-nbsd.h (SVR4_SHARED_LIBS): Remove. + * config/arm/nbsd.mh: Remove. + * config/arm/nbsd.mt (TDEPFILES): Remove solib-sunos.o, add + nbsd-tdep.o. + * config/arm/nbsdaout.mh: New file. + * config/arm/nbsdelf.mh: New file. + * config/arm/nm-nbsdaout.h: New file. + * config/i386/nbsd.mh: Remove. + * config/i386/nbsd.mt: Remove. + * config/i386/nbsdaout.mh: New file. + * config/i386/nbsdaout.mt: New file. + * config/i386/nbsdelf.mh (NAT_FILE): Use nm-nbsd.h. + * config/i386/nbsdelf.mt (TM_FILE): Use tm-nbsd.h. + * config/i386/nm-nbsd.h (REGISTER_U_ADDR, + i386_register_u_addr): Remove. + * config/i386/nm-nbsdaout.h: New file. + * config/i386/nm-nbsdelf.h: Remove. + * config/i386/tm-nbsd.h: Don't include config/tm-nbsd.h. + (USE_STRUCT_CONVENTION): Remove. + * config/i386/tm-nbsdaout.h: New file. + * config/i386/tm-nbsdelf.h: Remove. + * config/m68k/nbsd.mh: Remove. + * config/m68k/nbsd.mt: Remove. + * config/m68k/nbsdaout.mh: New file. + * config/m68k/nbsdaout.mt: New file. + * config/m68k/nm-nbsd.h: Use config/nm-nbsd.h. + * config/m68k/nm-nbsdaout.h: New file. + * config/m68k/tm-nbsd.h: Don't include config/tm-nbsd.h. + (IN_SOLIB_CALL_TRAMPOLINE): Define. + * config/ns32k/nbsd.mh: Remove. + * config/ns32k/nbsd.mt: Remove. + * config/ns32k/nbsdaout.mh: New file. + * config/ns32k/nbsdaout.mt: New file. + * config/ns32k/nm-nbsd.h: Include config/nm-nbsd.h. + * config/ns32k/nm-nbsdaout.h: New file. + * config/ns32k/tm-nbsd.h: Don't include config/tm-nbsd.h. + (IN_SOLIB_CALL_TRAMPOLINE): Define. + * config/powerpc/nm-nbsd.h: Include config/nm-nbsd.h. + (SVR4_SHARED_LIBS): Remove. + * config/powerpc/tm-nbsd.h: Dont' include config/tm-nbsd.h. + * config/sparc/nbsd.mh: Remove. + * config/sparc/nbsd.mt: Remove. + * config/sparc/nbsdaout.mh: New file. + * config/sparc/nbsdaout.mt: New file. + * config/sparc/nbsdelf.mh (NAT_FILE): Use nm-nbsd.h. + * config/sparc/nbsdelf.mt: New file. + * config/sparc/nm-nbsdaout.h: New file. + * config/sparc/nm-nbsdelf.h: Remove. + * config/sparc/tm-nbsd.h: Don't include config/tm-nbsd.h. + * config/sparc/tm-nbsdaout.h: New file. + +2002-05-21 Jason Thorpe <thorpej@wasabisystems.com> + + * Makefile.in (ALLDEPFILES): Add mipsnbsd-nat.c and + mipsnbsd-tdep.c + (mipsnbsd-nat.o, mipsnbsd-tdep.o): New dependency lists. + +2002-05-21 Jason Thorpe <thorpej@wasabisystems.com> + + * Makefile.in (ALLDEPFILES): Add shnbsd-tdep.c and + shnbsd-nat.c. + (shnbsd-tdep.o, shnbsd-nat.o): New dependency lists. + +2002-05-21 Jason Thorpe <thorpej@wasabisystems.com> + + * NEWS: Note new MIPS NetBSD native configuration. + * configure.host (mips*-*-netbsd*): New host. + * configure.tgt (mips*-*-netbsd*): New target. + * mipsnbsd-nat.c: New file. + * mipsnbsd-tdep.c: New file. + * mipsnbsd-tdep.h: New file. + * config/mips/nbsd.mh: New file. + * config/mips/nbsd.mt: New file. + * config/mips/nm-nbsd.h: New file. + * config/mips/tm-nbsd.h: New file. + +2002-05-21 Jason Thorpe <thorpej@wasabisystems.com> + + * Makefile.in (SFILES): Add osabi.c. + (COMMON_OBS): Add osabi.o. + (osabi.o): New dependency list. + * osabi.c: New file. + * osabi.h: New file. + * doc/gdbint.texinfo: Document new generic OS ABI framework. + + * Makefile.in (alpha_tdep_h): Define and use instead of + alpha-tdep.h. + * alpha-tdep.c (alpha_abi_names, process_note_abi_tag_sections, + get_elfosabi, alpha_abi_handler_list, alpha_gdbarch_register_os_abi): + Remove. + (alpha_gdbarch_init, alpha_dump_tdep): Use generic OS ABI framework. + * alpha-tdep.h: Include osabi.h. + (alpha_abi): Remove. + (gdbarch_tdep): Use generic OS ABI framework. + * alpha-linux-tdep.c (_initialize_alpha_linux_tdep): Use + gdbarch_register_osabi. + * alpha-osf1-tdep.c (_initialize_alpha_osf1_tdep): Likewise. + * alphafbsd-tdep.c (_initialize_alphafbsd_tdep): Likewise. + * alphanbsd-tdep.c (_initialize_alphanbsd_tdep): Likewise. + + * Makefile.in (sh_tdep_h): Add osabi.h. + * sh-tdep.h (sh_osabi): Remove. + (gdbarch_tdep): Use generic OS ABI framework. + * sh-tdep.c (sh_osabi_names, process_note_abi_tag_sections, + sh_osabi_handler_list, sh_gdbarch_register_os_abi): Remove. + (sh_gdbarch_init, sh_dump_tdep): Use generic OS ABI framework. + * shnbsd-tdep.c (_initialize_shnbsd_tdep): Use gdbarch_register_osabi. + + * Makefile.in (arm_tdep_h): Define and use instead of arm-tdep.h. + * arm-linux-tdep.c (_initialize_arm_linux_tdep): Use + gdbarch_register_osabi. + * arm-tdep.c (arm_abi_names, process_note_abi_tag_sections, + arm_abi_handler_list, arm_gdbarch_register_os_abi): Remove. + (get_elfosabi): Rename to... + (arm_elf_osabi_sniffer): ...this. Adjust to use generic OS + ABI framework support routines. + (arm_gdbarch_init): Use generic OS ABI framework. + (arm_dump_tdep): Likewise. + (_initialize_arm_tdep): Likewise. + * arm-tdep.h: Include osabi.h. + (arm_abi): Remove. + (gdbarch_tdep): Remove arm_abi and abi_name members. Add + osabi member. + (arm_gdbarch_register_os_abi): Remove prototype. + * armnbsd-tdep.c (arm_netbsd_aout_osabi_sniffer): New function. + (_initialize_arm_netbsd_tdep): Use gdbarch_register_osabi. + + * Makefile.in (mips-tdep.o): Add osabi.h to dependency list. + * mips-tdep.c: Include osabi.h. + (gdbarch_tdep, mips_gdbarch_init, mips_dump_tdep): Use generic + OS ABI framework. + +2002-05-20 Kazu Hirata <kazu@cs.umass.edu> + + * h8300-tdep.c: Fix formatting. + +2002-05-20 Elena Zannoni <ezannoni@redhat.com> + + * rs6000-tdep.c (rs6000_do_registers_info): Simplify code for + printing vector registers. + +2002-05-19 Andrew Cagney <ac131313@redhat.com> + + From Fernando Nasser: + * remote.c (remote_async_open_1): Re-throw the exception when the + connection fails. + (remote_cisco_open): Ditto. + (remote_open_1): Ditto. + +2002-05-19 Andrew Cagney <ac131313@redhat.com> + + * remote.c (remote_start_remote_dummy): Add uiout parameter. + (remote_start_remote): Add uiout parameter. Pass through to + remote_start_remote_dummy. + (remote_open_1): Use catch_exception instead of catch_errors. + (remote_async_open_1): Ditto. + (remote_cisco_open): Ditto. + +2002-05-19 Andrew Cagney <ac131313@redhat.com> + + * remote.c (remote_start_remote): Replace PTR with void pointer. + (sigint_remote_twice_token, sigint_remote_token): Ditto. Make + static. + +2002-05-18 Andrew Cagney <ac131313@redhat.com> + + * gdb_indent.sh: Allow the script to be run in the sim directory. + +2002-05-18 Mark Kettenis <kettenis@gnu.org> + + * config/i386/nm-cygwin.h (NO_PTRACE_H): Remove define. + * config/i386/nm-go32.h (NO_PTRACE_H): Remove define. + + * corelow.c (core_open): Only call set_gdbarch_from_file if + exec_bfd is NULL. + +2002-05-17 Andrey Volkov <avolkov@transas.com> + + * h8300-tdep.c: Add support of EXR register + * config/h8300/tm-h8300.h: Ditto. + +2002-05-17 Andrey Volkov <avolkov@transas.com> + + * h8300-tdep.c: Add additional CCR flags (I,UI,H,U) + +2002-05-17 Andrey Volkov <avolkov@transas.com> + + * h8300-tdep.c: Change literal regnums to REGNO. + +2002-05-17 Jim Blandy <jimb@redhat.com> + + * NEWS: Note addition of macro support. + + Expand preprocessor macros in C expressions. + * c-lang.h: #include "macroexp.h", for macro_lookup_ftype. + (scan_macro_expansion, scanning_macro_expansion, + finished_macro_expansion): New function declarations. + (expression_macro_lookup_func, expression_macro_lookup_baton): New + variable declarations. + * parser-defs.h (expression_context_pc): New declaration. + * parse.c (expression_context_pc): New variable. + (parse_exp_1): Set expression_context_pc, as well as + expression_context_block. + * c-exp.y (yylex): If we're not already reading the result of a + macro expansion, try to macro-expand the next token. When we're + done scanning a macro expansion, switch back to the mainline text. + Commas and `if's in a macro's expansion don't terminate the input. + * c-lang.c: #include "macroscope.h" and "gdb_assert.h". + (macro_original_text, macro_expanded_text, + expression_macro_lookup_func, expression_macro_lookup_baton): New + variables. + (scan_macro_expansion, scanning_macro_expansion, + finished_macro_expansion, scan_macro_cleanup, null_macro_lookup, + c_preprocess_and_parse): New functions. + (c_language_defn, cplus_language_defn, asm_language_defn): Call + c_preprocess_and_parse, instead of c_parse. + * Makefile.in (c_lang_h): Note that this #includes macroexp.h. + (c-lang.o): Note dependency on macroscope.h and gdb_assert.h. + +Fri May 17 14:26:19 2002 J"orn Rennecke <joern.rennecke@superh.com> + + * sh-tdep.c (gdb_print_insn_sh64): Delete. + (gdb_print_insn_sh): Just set info->endian and use print_insn_sh. + (sh_gdbarch_init): Always use gdb_print_insn_sh. + +2002-05-17 Corinna Vinschen <vinschen@redhat.com> + + * NEWS: Add section for multi-arched targets. Add v850 to that section. + +2002-05-17 Jason Thorpe <thorpej@wasabisystems.com> + + * Makefile.in (sh_tdep_h): Define and use. + * config/sh/tm-sh.h (sh_osabi, sh_abi, gdbarch_tdep, + register enum): Move to... + * * sh-tdep.h: ...here. + * sh-tdep.c: Include sh-tdep.h. + * sh3-rom.c: Likewise. + * shnbsd-tdep.c: Likewise. + +2002-05-16 Michael Snyder <msnyder@redhat.com> + + * arm-tdep.c: Spelling fix in comment. + +2002-05-16 Jim Blandy <jimb@redhat.com> + + Add commands for manually expanding macros and showing their + definitions. + * macrocmd.c, macroscope.c, macroscope.h: New files. + * Makefile.in (SFILES): Add macrocmd.c, macroscope.c. + (macroscope_h): New variable. + (HFILES_NO_SRCDIR): Add macroscope.h. + (COMMON_OBS): Add macrocmd.o, macroscope.o. + (macroscope.o, macrocmd.o): New rules. + + Teach the Dwarf 2 reader to read macro information. + * dwarf2read.c: #include "macrotab.h". + (dwarf_macinfo_buffer): New variable. + (struct dwarf2_pinfo): New members: dwarf_macinfo_buffer, and + dwarf_macinfo_size. + (DWARF_MACINFO_BUFFER, DWARF_MACINFO_SIZE): New macros. + (dwarf2_missing_macinfo_section, dwarf2_macros_too_long, + dwarf2_macros_not_terminated, dwarf2_macro_outside_file, + dwarf2_macro_unmatched_end_file, dwarf2_macro_malformed_definition, + dwarf2_macro_spaces_in_definition): New complaints. + (dwarf2_has_info): Initialize dwarf_macinfo_offset. + (dwarf2_build_psymtabs): Read the .dwarf_macinfo section. + (dwarf2_build_psymtabs_hard): Record the buffer and its size in + the partial symbol table. + (psymtab_to_symtab_1): Set the macinfo buffer and size globals + from what's recorded in the partial symbol table. + (read_file_scope): If the compilation unit has a + `DW_AT_macro_info' attribute, read its macro information. + * Makefile.in (dwarf2read.o): Depend on macrotab.h. + +2002-05-16 Daniel Jacobowitz <drow@mvista.com> + + Fix PR gdb/546 + * ser-tcp.c: Don't include <netinet/udp.h>. + +2002-05-16 Stephane Carrez <stcarrez@nerim.fr> + + * MAINTAINERS: Update my email address. + +2002-05-16 Richard Earnshaw <rearnsha@arm.com> + + * config/arm/nm-nbsd.h: Use "config/nm-nbsd.h" to include generic + include file of the same name. + +2002-05-16 Corinna Vinschen <vinschen@redhat.com> + + * configure.tgt: Mark v850 as multi-arched. + * config/v850/tm-v850.h: Remove file. + * config/v850/v850.mt: Eliminate TM_FILE. + +2002-05-16 Corinna Vinschen <vinschen@redhat.com> + + * v850-tdep.c: Full multi-arch. + * config/v850/tm-v850.h: Eliminate or move to v850-tdep.c everything. + Define GDB_MULTI_ARCH to 2. + +2002-05-16 Pierre Muller <muller@ics.u-strasbg.fr> + + * p-exp.y (current_type): New static variable. + Carries the type of the expression at the position that is parsed. + (push_current_type, pop_current_type): Two new functions. Used + to store/restore current_type in expression on specific tokens. + (search_field): New static variable. Set to one after parsing a point + as at that point only a FIELDNAME token should be searched. + (FIELDNAME): New token. After a point only a token belonging to + current_type type definition is allowed. + (all over token rules): reset and change current_type according + to rules. + (exp '[' rule): insert implicit array index field if + exp is a pascal string type. + +2002-05-16 Corinna Vinschen <vinschen@redhat.com> + + * v850-tdep.c: Fix comment for v850_scan_prologue. Remove extra + frame info. Use frame_info's saved_regs instead of matching member + in extra_frame_info throughout. + (v850_frame_init_saved_regs): New function. + (v850_init_extra_frame_info): Move most functionality into + v850_frame_init_saved_regs(). + * config/v850/tm-v850.h (EXTRA_FRAME_INFO): Remove definition. + (v850_frame_find_saved_regs): Remove declaration. + (FRAME_FIND_SAVED_REGS): Remove definition. + (v850_frame_init_saved_regs): Add declaration. + (FRAME_INIT_SAVED_REGS): Add definition. + +2002-05-16 Corinna Vinschen <vinschen@redhat.com> + + * v850-tdep.c: Begin multi-arch'ing v850. + (v850_target_architecture_hook): Remove function. + (v850_gdbarch_init): New function. Add code previously in + v850_target_architecture_hook(). + (_initialize_v850_tdep): Don't set target_architecture_hook. + Call register_gdbarch_init() instead. + +2002-05-16 Daniel Jacobowitz <drow@mvista.com> + + * gdbtypes.h (struct cplus_struct_type): Remove args field. + * hpread.c (hpread_read_struct_type): Remove assignments to args. + (fixup_class_method_type): Likewise. + +2002-05-15 Jim Blandy <jimb@redhat.com> + + Add macro structures to GDB's symbol tables. Nobody puts anything + in them yet. + * symtab.h (struct symtab): New member: `macro_table'. + * buildsym.h (pending_macros): New global variable. + * buildsym.c: #include "macrotab.h". + (buildsym_init): Initialize `pending_macros'. + (end_symtab): If we found macro information while reading a CU's + debugging info, do build a symtab structure for it. Make the + symtab point to the macro information, and clear the + `pending_macros' pointer which held it while we were reading the + debug info. + (really_free_pendings): Free any pending macro table. + * objfiles.h (struct objfile): New member: `macro_cache'. + * objfiles.c (allocate_objfile): Set allocate and free functions + for the macro cache's objstack. + (free_objfile): Empty the macro cache's obstack. + * symfile.c (reread_symbols): Empty the macro cache's obstack, and + set new allocate and free functions for it. + * solib-sunos.c (allocate_rt_common_objfile): Set allocate and + free functions for the macro cache's objstack. (Why is this + function building its own objfile?) + * symmisc.c (print_objfile_statistics): Print statistics on the + macro bcache. + * Makefile.in: Note that buildsym.o depends on macrotab.h. + +2002-05-15 Richard Earnshaw <rearnsha@arm.com> + + * config/arm/nm-nbsd.h: Use <> for include of config/nm-nbsd.h. + (REGISTER_U_ADDR): Delete definition. + (arm_register_u_addr): Delete declaration. + +2002-05-15 Richard Earnshaw <rearnsha@arm.com> + + * arm-linux-tdep.c (ARM_LINUX_JB_PC): Renamed from JB_PC. + (ARM_LINUX_JB_ELEMENT_SIZE): Likewise. + +2002-05-14 Andrew Cagney <ac131313@redhat.com> + + * regcache.c (register_valid): Revise comments refering to "Not + available" and "unavailable". + * frame.c (frame_register_read): Ditto. + * findvar.c (value_of_register): Ditto. + +2002-05-15 Andrew Cagney <cagney@redhat.com> + + * Makefile.in (remote_sim_h): Replace remote-sim_h. + (remote-sim.o): Update dependencies. + (d10v-tdep.o): Specify dependencies. + (sim_d10v_h): Define. + +2002-05-14 Jim Blandy <jimb@redhat.com> + + * macroexp.c (init_buffer, gather_arguments, expand): Use NULL, not 0. + * macrotab.c (macro_lookup_inclusion, find_definition, + new_macro_table): Same. + + * macroexp.c (currently_rescanning, expand): Use `strcmp () == 0', + not `! strcmp ()'. This is a dubious improvement. + * macrotab.c (macro_lookup_inclusion, find_definition): Same. + + * macrotab.c (macro_lookup_inclusion): Initialize `best_depth', + although it's not necessary, to avoid a warning. + +2002-05-14 Daniel Jacobowitz <drow@mvista.com> + + * gdbtypes.h: Update accessor macros to use TYPE_MAIN_TYPE. + (TYPE_CONST, TYPE_VOLATILE, TYPE_CODE_SPACE, TYPE_DATA_SPACE): Use + TYPE_INSTANCE_FLAGS. + (struct main_type): New. + (struct type): Move most members to struct main_type. Change + cv_type and as_type to new type_chain member. Add instance_flags. + (TYPE_MAIN_TYPE, TYPE_CHAIN, TYPE_INSTANCE_FLAGS): New macros. + (TYPE_CV_TYPE, TYPE_AS_TYPE): Remove. + (finish_cv_type): Remove prototype. + * gdbtypes.c (alloc_type): Update comment. Allocate TYPE_MAIN_TYPE. + Set TYPE_CHAIN. + (alloc_type_instance): New function. + (smash_type): New function. + (make_pointer_type, make_reference_type, make_function_type) + (smash_to_member_type, smash_to_method_type): Call smash_type. + (make_qualified_type): New function. + (make_type_with_address_space): Call make_qualified_type. + (make_cv_type): Likewise. + (finish_cv_type): Remove unnecessary function. + (replace_type): Update comment. Copy TYPE_MAIN_TYPE. + (recursive_dump_type): Dump TYPE_CHAIN and TYPE_INSTANCE_FLAGS; + remove TYPE_CV_TYPE and TYPE_AS_TYPE. + * c-typeprint.c (c_type_print_modifier): Use TYPE_INSTANCE_FLAGS. + * dwarf2read.c (read_structure_scope): Don't call finish_cv_type. + * hpread.c (hpread_read_struct_type): Likewise. + * stabsread.c (read_struct_type): Likewise. + +2002-05-14 Elena Zannoni <ezannoni@redhat.com> + + * configure.tgt: Add a catch all sh* target, for cases like + sh[2,3,4]-elf and sh-hms. + +2002-05-14 Keith Seitz <keiths@redhat.com> + + * event-loop.c (create_file_handler): Don't do anything but + update data when we are given a fd which we are already + monitoring. + +2002-05-14 Michal Ludvig <mludvig@suse.cz> + + * dwarf2cfi.c (context_cpy): Copy registers correctly. + (update_context): Use __func__ in warnings. + +2002-05-14 Daniel Jacobowitz <drow@mvista.com> + + * ser-tcp.c: Include <netinet/udp.h>. Rename tcp_open + and tcp_close to net_open and net_close. + (net_open): Accept "udp:" and "tcp:" specifications. Connect + using UDP if requested. Don't try to disable Nagle on UDP + sockets. + * remote.c (remote_serial_open): New function. Warn about UDP. + (remote_open_1, remote_async_open_1, remote_cisco_open): Call it. + +2002-05-13 Elena Zannoni <ezannoni@redhat.com> + + * MAINTAINERS: List sh-elf as buildable with ,-Werror. + +2002-05-13 Elena Zannoni <ezannoni@redhat.com> + + * configure.tgt: Remove sh-hms target. + * MAINTAINERS: Don't list sh-hms as a separate target. + +2002-05-13 Jim Blandy <jimb@redhat.com> + + Add first preprocessor macro-expansion files. + * macroexp.c, macroexp.h, macrotab.c, macrotab.h: New files. + * Makefile.in (SFILES): Add macrotab.c, macroexp.c. + (splay_tree_h, macroexp_h, macrotab_h): New variable. + (HFILES_NO_SRCDIR): Add macrotab.h, macroexp.h. + (COMMON_OBS): Add macrotab.o, macroexp.o. + (macroexp.o, macrotab.o): New rules. + +2002-05-13 Andrew Cagney <ac131313@redhat.com> + + * config/m88k/tm-m88k.h: Update copyright. + (m88k_target_write_pc): Declare + (TARGET_WRITE_PC): Redefine using m88k_target_write_pc. + (M88K_NNPC_REGNUM): Rename NNPC_REGNUM. + (SHIFT_INST_REGS): Update definition. + * m88k-tdep.c (m88k_target_write_pc): New function. Implement + using old definition of TARGET_WRITE_PC. + * regcache.c (generic_target_write_pc): Delete code handling + NNPC_REGNUM. + * gdbarch.sh (NNPC_REGNUM): Delete. + * gdbarch.h, gdbarch.c: Regenerate. + +2002-05-13 Richard Earnshaw <rearnsha@arm.com> + + * builtin-regs.c (value_of_builtin_reg): Correctly calculate the + builtin reg number. + +2002-05-13 Daniel Jacobowitz <drow@mvista.com> + + * ax-gdb.c (gen_sign_extend, gen_fetch, gen_usual_unary) + (gen_cast, gen_scale, gen_add, gen_sub, gen_binop, gen_deref) + (gen_address_of, gen_struct_ref, gen_repeat): Use type + access macros. + * c-typeprint.c (cp_type_print_method_args): Likewise. + (c_type_print_args): Likewise. + * d10v-tdep.c (d10v_push_arguments): Likewise. + (d10v_extract_return_value): Likewise. + * expprint.c (print_subexp): Likewise. + * gdbtypes.c (lookup_primitive_typename): Likewise. + (lookup_template_type, add_mangled_type, print_arg_types): Likewise. + * gdbtypes.h (TYPE_UNSIGNED, TYPE_NOSIGN, TYPE_STUB) + (TYPE_TARGET_STUB, TYPE_STATIC, TYPE_CONST, TYPE_VOLATILE) + (TYPE_PROTOTYPED, TYPE_INCOMPLETE, TYPE_CODE_SPACE, TYPE_VARARGS) + (TYPE_VECTOR): Likewise. + * hpread.c (hpread_read_struct_type) + (fix_static_member_physnames, fixup_class_method_type) + (hpread_type_lookup): Likewise. + * mdebugread.c (parse_symbol, parse_type): Likewise. + * p-lang.c (is_pascal_string_type): Likewise. + * valops.c (hand_function_call): Likewise. + * x86-64-tdep.c (classify_argument): Likewise. + + * hpread.c (hpread_read_function_type) + (hpread_read_doc_function_type): Call replace_type. + * dstread.c (create_new_type): Delete. + (decode_dst_structure, process_dst_function): Call alloc_type. + Use type access macros. + +2002-05-12 Mark Kettenis <kettenis@gnu.org> + + * i387-tdep.c (i387_supply_fxsave): Skip the SSE registers if + the're not supported by the current architecture. + (i387_fill_fxsave): Likewise. + +2002-05-12 Fred Fish <fnf@redhat.com> + + * symfile.c (default_symfile_offsets): Arrange for uninitialized + sect_index_xxx members to index the first slot in section_offsets + if all of the section_offsets are zero. + +2002-05-12 Mark Kettenis <kettenis@gnu.org> + + * configure.tgt (sparc-*openbsd): Remove entry accidentially + checked in with last change. + +2002-05-12 Mark Kettenis <kettenis@gnu.org> + + * configure.tgt (i[3456]86-*-unixware*, i[3456]86-*-unixware2*): + Remove targets. These are canonicalized to i386-*-sysv4.2uw by + config.sub. + +2002-05-12 Daniel Jacobowitz <drow@mvista.com> + + * Makefile.in: Update dependencies. + +2002-05-11 Andrew Cagney <ac131313@redhat.com> + + * language.c (local_hex_string_custom): Simplify. Do not depend + on PRINTF_HAS_LONG_LONG or CC_HAS_LONG_LONG. + + * memattr.c (mem_info_command): Replace calls to + longest_local_hex_string and longest_local_hex_string_custom. + * buildsym.c (make_blockvector): Ditto. + * solib.c (info_sharedlibrary_command): Ditto. + * tracepoint.c (tracepoints_info): Ditto. + * symtab.c (print_msymbol_info): Ditto. + + * language.c (local_hex_string): Delete. + (local_hex_string_custom): Delete. + (longest_local_hex_string): Rename to local_hex_string. + (longest_local_hex_string_custom): Rename to + local_hex_string_custom. + * language.h (local_hex_string): Change parameter type to LONGEST. + (local_hex_string_custom): Ditto. + (longest_local_hex_string): Delete declaration. + (longest_local_hex_string_custom): Ditto. + + * solib.c: Update copyright. + * memattr.c: Update copyright. + +2002-05-11 Andrew Cagney <ac131313@redhat.com> + + * arch-utils.h (legacy_register_to_value): Declare. + (legacy_value_to_register): Declare. + (legacy_convert_register_p): Declare. + * arch-utils.c (legacy_register_to_value): New function. + (legacy_value_to_register): New function. + (legacy_convert_register_p): New function. + + * gdbarch.sh (REGISTER_TO_VALUE): Define. + (VALUE_TO_REGISTER): Define. + (CONVERT_REGISTER_P): Define. + * gdbarch.h, gdbarch.c: Regenerate. + + * valops.c (value_assign): Use CONVERT_REGISTER_P and + VALUE_TO_REGISTER. + * findvar.c (value_from_register): Use REGISTER_TO_VALUE and + CONVERT_REGISTER_P. + +2005-05-11 Daniel Jacobowitz <drow@mvista.com> + Peter Schauer <pes@regent.e-technik.tu-muenchen.de> + + * Makefile.in: Update dependencies for valops.c. + * valops.c: Include "gdb_assert.h". + (typecmp): Skip THIS parameter to methods. + (find_method_list): Remove static_memfuncp argument, + update callers. Check for stub methods. + (find_value_oload_method_list): Don't set *static_memfuncp. + (find_overload_match): Don't check for stub methods. Assert + that methods are not stubbed. Handle static methods. + (value_find_oload_method_list): Remove static_memfuncp argument. + * gdbtypes.c (check_stub_method): Do not add THIS pointer + to the argument list for static stub methods. + * value.h (value_find_oload_method_list): Update prototype. + +2002-05-11 Andrew Cagney <ac131313@redhat.com> + + * arch-utils.h (generic_register_size): Declare. + (generic_register_raw_size, generic_register_virtual_size): Delete + declarations. + * arch-utils.c (generic_register_raw_size): Delete. + (generic_register_size): New function. + (generic_register_virtual_size): Delete. + + * gdbarch.sh (REGISTER_RAW_SIZE, REGISTER_VIRTUAL_SIZE): Make + default generic_register_size. + * gdbarch.h, gdbarch.c: Re-generate. + + * d10v-tdep.c (d10v_gdbarch_init): Use generic_register_size for + register_virtual_size. + * x86-64-tdep.c (x86_64_gdbarch_init): Ditto. + * rs6000-tdep.c (rs6000_gdbarch_init): Ditto. + +2002-05-11 Andrew Cagney <ac131313@redhat.com> + + * gdbarch.sh (gdbarch_data): Add gdbarch parameter. + * gdbarch.h, gdbarch.c: Regenerate. + * gnu-v3-abi.c: Update copyright. + (vtable_address_point_offset): Update. + (gnuv3_rtti_type): Update. + (gnuv3_baseclass_offset): Update. + * solib-svr4.c (svr4_fetch_link_map_offsets): Update. + (init_fetch_link_map_offsets): Update. + * remote.c (get_remote_state): Update. + +2002-05-11 Daniel Jacobowitz <drow@mvista.com> + + * TODO: Remove value_headof/value_from_vtable_info comment. + * printcmd.c (print_command_1): Don't call value_from_vtable_info. + * values.c (value_headof, value_from_vtable_info): Delete. + * value.h (value_from_vtable_info): Delete prototype. + +2002-05-11 Andrew Cagney <ac131313@redhat.com> + + * Makefile.in: Replace gdb_assert.h with $(gdb_assert_h), + gdb_string.h with $(gdb_string_h) and gdb_regex.h with + $(gdb_regex_h). + (gdb_assert_h): Define. + (gdb_wait_h): Define. + (gdb_regex_h): Define. + +2002-05-11 Daniel Jacobowitz <drow@mvista.com> + + From Peter Schauer <Peter.Schauer@Regent.E-Technik.TU-Muenchen.DE>: + * linespec.c (find_methods): Handle GCC 3.x template constructors. + +2002-05-11 Jason Thorpe <thorpej@wasabisystems.com> + + * nbsd-tdep.c: Fix comment. + +2002-05-11 Jason Thorpe <thorpej@wasabisystems.com> + + * Makefile.in (ALLDEPFILES): Add nbsd-tdep.c. + (alphanbsd-tdep.o): Add nbsd-tdep.h to dependency list. + (nbsd-tdep.o): New dependency list. + * alphanbsd-tdep.c: Don't include solib-svr4.h. Include + nbsd-tdep.h. + (alphanbsd_solib_svr4_fetch_link_map_offsets): Remove. + (alphanbsd_init_abi): Use nbsd_lp64_solib_svr4_fetch_link_map_offsets. + * nbsd-tdep.c: New file. + * nbsd-tdep.h: New file. + * shnbsd-tdep.c: Don't include solib-svr4.h. Include + nbsd-tdep.h. + (shnbsd_solib_svr4_fetch_link_map_offsets): Remove. + (shnbsd_init_abi): Use nbsd_ilp32_solib_svr4_fetch_link_map_offsets. + * config/alpha/nbsd.mt (TDEPFILES): Add nbsd-tdep.o. + * config/sh/nbsd.mt (TDEPFILES): Ditto. + +2002-05-11 Jason Thorpe <thorpej@wasabisystems.com> + + * config/alpha/nbsd.mh (NATDEPFILES): Remove corelow.o. + * config/alpha/nbsd.mt (TDEPFILES): Add corelow.o. + * config/i386/nbsd.mh (NATDEPFILES): Remove corelow.o. + * config/i386/nbsd.mt (TDEPFILES): Add corelow.o. + * config/i386/nbsdelf.mh (NATDEPFILES): Remove corelow.o. + * config/i386/nbsdelf.mt (TDEPFILES): Add corelow.o. + +2002-05-11 Jason Thorpe <thorpej@wasabisystems.com> + + * config/i386/nbsd.mh (NATDEPFILES): Use line continuations. + * config/i386/nbsdelf.mh (NATDEPFILES): Likewise. + * config/m68k/nbsd.mh (NATDEPFILES): Likewise. + * config/ns32k/nbsd.mh (NATDEPFILES): Likewise. + * config/powerpc/nbsd.mh (NATDEPFILES): Likewise. + * config/sparc/nbsd.mh (NATDEPFILES): Likewise. + * config/sparc/nbsdelf.mh (NATDEPFILES): Likewise. + +2002-05-11 Jason Thorpe <thorpej@wasabisystems.com> + + * i386nbsd-nat.c: Delete file. Move fetch_core_registers and + fetch_elfcore_registers to... + * i386nbsd-tdep.c: ...here. + (i386nbsd_use_struct_convention): Rename to... + (i386nbsd_aout_use_struct_convention): ...this. + (i386nbsd_supply_reg): New function. + (i386nbsd_fill_reg): New function. + (fetch_core_registers): Use i386nbsd_supply_reg. + (fetch_elfcore_registers): Likewise. + (_initialize_i386nbsd_tdep): New function. + * config/i386/nbsd.mh (NATDEPFILES): Remove i386nbsd-nat.o. + * config/i386/nbsdelf.mh (NATDEPFILES): Likewise. + * config/i386/nbsdelf.mt (TDEPFILES): Add i386nbsd-tdep.o. + * config/i386/tm-nbsd.h (i386nbsd_use_struct_convention): Rename to... + (i386nbsd_aout_use_struct_convention): ...this. + +2002-05-11 Jason Thorpe <thorpej@wasabisystems.com> + + * shnbsd-nat.c (fetch_inferior_registers): Use shnbsd_supply_reg. + (store_inferior_registers): Use shnbsd_fill_reg. + * shnbsd-tdep.c (sh_nbsd_supply_registers, + sh_nbsd_supply_register): Collapse into... + (shnbsd_supply_reg): ...this. + (sh_nbsd_fill_registers, sh_nbsd_fill_register): Collapse into... + (shnbsd_fill_reg): ...this. + (sh_nbsd_solib_svr4_fetch_link_map_offsets): Rename to... + (shnbsd_solib_svr4_fetch_link_map_offsets): ...this. + (fetch_core_registers): Use shnbsd_supply_reg. + (fetch_elfcore_registers): Use shnbsd_supply_reg. + (sh_nbsd_core_fns): Rename to... + (shnbsd_core_fns): ...this. + (sh_nbsd_elfcore_fns): Rename to... + (shnbsd_elfcore_fns): ...this. + (sh_nbsd_init_abi): Rename to... + (shnbsd_init_abi): ...this. + (_initialize_sh_nbsd_tdep): Rename to... + (_initialize_shnbsd_tdep): ...this. + * shnbsd-tdep.h (sh_nbsd_supply_registers, + sh_nbsd_supply_register, sh_nbsd_fill_registers, + sh_nbsd_fill_register): Remove prototypes. + (shnbsd_supply_reg, shnbsd_fill_reg): Add prototypes. + +2002-05-11 Jason Thorpe <thorpej@wasabisystems.com> + + * Makefile.in (ALLDEPFILES): Remove i387-nat.c. + (i387-nat.o): Delete dependency list. + (go32-nat.o): Change i387-nat.h to i387-tdep.h. + (x86-64-linux-nat.o): Likewise. + * i387-nat.c: Delete file, moving contents to... + * i387-tdep.c: ...here. + * i387-nat.h: Rename... + * i387-tdep.h: ...to this. + * go32-nat.c: Include i387-tdep.h instead of i387-nat.h. + * i386-linux-nat.c: Likewise. + * i386bsd-nat.c: Likewise. + * i386gnu-nat.c: Likewise. + * i386nbsd-nat.c: Likewise. + * i386v4-nat.c: Likewise. + * x86-64-linux-nat.c: Likewise. + * config/i386/fbsd.mh (NATDEPFILES): Remove i387-nat.o. + * config/i386/go32.mh (NATDEPFILES): Likewise. + * config/i386/i386gnu.mh (NATDEPFILES): Likewise. + * config/i386/i386sol2.mh (NATDEPFILES): Likewise. + * config/i386/i386v42mp.mh (NATDEPFILES): Likewise. + * config/i386/linux.mh (NATDEPFILES): Likewise. + * config/i386/nbsd.mh (NATDEPFILES): Likewise. + * config/i386/nbsdelf.mh (NATDEPFILES): Likewise. + * config/i386/obsd.mh (NATDEPFILES): Likewise. + * config/i386/x86-64linux.mh (NATDEPFILES): Likewise. + +2002-05-11 Jason Thorpe <thorpej@wasabisystems.com> + + * Makefile.in (ALLDEPFILES): Remove alphanbsd-nat.c. + (alphanbsd-nat.o): Remove dependency list. + (alphanbsd-tdep.o): Add $(regcache_h) to dependency list. + * alphanbsd-nat.c: Delete. Contents moved to... + * alphanbsd-tdep.c: ...here. + (_initialize_alphanbsd_tdep): Register core functions. + * config/alpha/nbsd.mh (NATDEPFILES): Remove alphanbsd-nat.o. + +2002-05-11 Jason Thorpe <thorpej@wasabisystems.com> + + * Makefile.in (ALLDEPFILES): Add alphabsd-tdep.c. + (alphabsd-nat.o): Depend on alphabsd-tdep.h. + (alphanbsd-nat.o): Likewise. + (alphabsd-tdep.o): New dependency list. + * alphabsd-nat.c (supply_gregset): Use alphabsd_supply_reg. + (fill_gregset): Use alphabsd_fill_reg. + (supply_fpregset): Use alphabsd_supply_fpreg. + (fill_fpregset): Use alphabsd_fill_fpreg. + (fetch_inferior_registers): Use struct reg and struct fpreg + rather than gregset_t and fpregset_t. Use alphabsd_supply_reg + and alphabsd_supply_fpreg. + (store_inferior_registers): Use struct reg and struct fpreg + rather than gregset_t and fpregset_t. Use alphabsd_fill_reg + and alphabsd_fill_fpreg. + * alphabsd-tdep.c: New file. + * alphabsd-tdep.h: New file. + * alphanbsd-nat.c (fetch_core_registers): Use alphabsd_supply_fpreg. + (fetch_elfcore_registers): Use alphabsd_supply_reg and + alphabsd_supply_fpreg. + * config/alpha/fbsd.mt (TDEPFILES): Add alphabsd-tdep.o. + * config/alpha/nbsd.mt (TDEPFILES): Likewise. + +2002-05-11 Eric Christopher <echristo@redhat.com> + + * mips-tdep.c (mips_double_register_type): Fix thinko. + (mips_single_register_type): Ditto. + * MAINTAINERS: Add self. + +2002-05-11 Mark Kettenis <kettenis@gnu.org> + + * i387-nat.c (i387_supply_register, i387_fill_fsave, + i387_supply_fxsave, i387_fill_fxsave): Rewrite in order to do the + right thing on architectures with different endianness and/or + integer sizes. + +2002-05-10 Jason Thorpe <thorpej@wasabisystems.com> + + From Christian Limpach <chris@Pin.LU> + * configure.in: Change sed expression which comments out + NATDEPFILES to also comment out continuation lines. + * configure: Regenerate. + +2002-05-10 Elena Zannoni <ezannoni@redhat.com> + + * sh-tdep.c: Clean up code erroneously reintroduced by previous + big patch. + +2002-05-10 Elena Zannoni <ezannoni@redhat.com> + + * sh-tdep.c: Include correct file. + +2002-05-10 Elena Zannoni <ezannoni@redhat.com> + + New support for sh64-elf (sh5) target. + + * configure.tgt: For sh64-elf target, default to sh-elf. + + * config/sh/tm-sh.h (enum sh-abi): Possible ABI's. + (struct gdbarch_tdep): Add new fields for new registers and ABI + info. + + * sh-tdep.c: Include elf-bfd.h, elf/sh.h, gdb/sim-sh.h. + (NUM_PSEUDO_REGS_SH_MEDIA, NUM_PSEUDO_REGS_SH_COMPACT, + MSYMBOL_IS_SPECIAL, IS_ISA32_ADDR, MAKE_ISA32_ADDR, + UNMAKE_ISA32_ADDR, IS_PTABSL_R18, IS_STS_R0, IS_STS_PR, + IS_MOV_TO_R15, IS_MOV_R14, IS_STQ_R18_R14, IS_STQ_R18_R15, + IS_STL_R18_R15, IS_STQ_R14_R15, IS_STL_R14_R15, IS_ADDIL_SP_MEDIA, + IS_ADDI_SP_MEDIA, IS_ADDL_SP_FP_MEDIA, IS_ADD_SP_FP_MEDIA, + IS_MOV_SP_FP_MEDIA, IS_MOV_R0, IS_MOVL_R0, IS_ADD_SP_R0, + IS_MOV_R14_R0, IS_MEDIA_IND_ARG_MOV, IS_MEDIA_ARG_MOV, + IS_MEDIA_MOV_TO_R14, IS_COMPACT_IND_ARG_MOV, IS_COMPACT_ARG_MOV, + IS_COMPACT_MOV_TO_R14, IS_JSR_R0, IS_NOP): New macros. + (sh_sh64_register_name, sh64_elf_make_msymbol_special, + pc_is_isa32, sh_sh64_breakpoint_from_pc, look_for_args_moves, + sh64_skip_prologue_hard_way, sh64_use_struct_convention, + gdb_print_insn_sh64, translate_insn_rn, sh64_frame_chain, + sh64_get_saved_pr, fpp_reg_base_num, is_media_pseudo, + sh64_get_gdb_regnum, sh64_media_reg_base_num, + sh64_compact_reg_base_num, translate_rn_to_arch_reg_num, + sign_extend, sh64_nofp_frame_init_saved_regs, + sh64_init_extra_frame_info, sh64_get_saved_register, + sh64_extract_struct_value_address, sh64_pop_frame, + sh64_push_arguments, sh64_extract_return_value, + sh64_store_return_value, sh64_show_media_regs, + sh64_show_compact_regs, sh64_show_regs, sh_sh64_register_byte, + sh_sh64_register_raw_size, sh_sh64_register_virtual_size, + sh_sh64_register_virtual_type, + sh_sh64_register_convert_to_virtual, + sh_sh64_register_convert_to_raw, sh64_pseudo_register_read, + sh64_register_read, sh64_pseudo_register_write, + sh64_register_write, do_fv_c_register_info, do_dr_c_register_info, + do_r_c_register_info, do_fpp_register_info, do_cr_c_register_info, + sh64_do_pseudo_register, sh_compact_do_registers_info, + sh64_do_registers_info, sh_gdbarch_init): New functions. + +2002-05-10 Elena Zannoni <ezannoni@redhat.com> + + * sh-tdep.c (sh_breakpoint_from_pc): Add 'const' to return type. + +2002-05-10 Daniel Jacobowitz <drow@mvista.com> + + * linespec.c (decode_line_1): Check for a double quote after + a filename correctly. + +2002-05-10 Jim Blandy <jimb@redhat.com> + + Properly track the size of the current objfile's .debug_line section. + * dwarf2read.c (struct dwarf2_pinfo): New member: dwarf_line_size. + (DWARF_LINE_SIZE): New macro. + (dwarf2_build_psymtabs_hard): Record the line section's size in + the partial symbol table. + (psymtab_to_symtab_1): Restore dwarf_line_size from the partial + symbol table. + +2002-05-10 Petr Sorfa <petrs@caldera.com> + + * ia64-tdep.c: Handle breakpoints on L instruction type + in MLX instruction bundle by moving the breakpoint to + the third slot (X instruction type) as L holds only data. + +2002-05-10 Kevin Buettner <kevinb@redhat.com> + + * dbxread.c (discarding_local_symbols_complaint): New complaint. + (process_one_symbol): Complain about discarding local symbols + due to a misplaced N_LBRAC entry. + +2002-05-09 Elena Zannoni <ezannoni@redhat.com> + + From Daniel Berlin <dan@cgsoftware.com> + * linespec.c (find_toplevel_char): '<' and '>' also increase and + decrease the depth we are at, in the case of templates. + +2002-05-09 Daniel Jacobowitz <drow@mvista.com> + + * mips-tdep.c (mips_float_register_type): New function. + (mips_double_register_type): New function. + (mips_print_register): Use them. + (do_fp_register_row): Likewise. + +2002-05-09 Daniel Jacobowitz <drow@mvista.com> + + * signals/signals.c (signals): Remove conditional compilation around + Mach-specific signals. Move them to after TARGET_SIGNAL_DEFAULT. + (target_signal_from_name): Loop until TARGET_SIGNAL_LAST. + +2002-05-09 Michael Snyder <msnyder@redhat.com> + + * remote-rdp.c (remote_rdp_can_run): Remove. + +2002-05-09 Tom Tromey <tromey@redhat.com> + + * jv-valprint.c (java_val_print): Handle `char' as a special case + of TYPE_CODE_INT. + +2002-05-09 Michael Snyder <msnyder@redhat.com> + + * arm-tdep.c (arm_scan_prologue): Accept strb r(0123),[r11,#-nn], + strh r(0123),[r11,#-nn], str r(0123),[r11,#-nn], as well as + strb r(0123),[sp,#nn], strh r(0123),[sp,#nn] and + str r(0123),[sp,#nn]. + (arm_skip_prologue): Ditto. Also make disassembly + order-independent by placing it in a loop. + +2002-05-06 Michael Snyder <msnyder@redhat.com> + + * stabsread.c (read_type): Add recognition for new attribute: + "@V;" means that an array type is actually a vector. + This is analogous to the vector flag that's been added to dwarf2. + +2002-05-09 Mark Kettenis <kettenis@gnu.org> + + * i386-tdep.h (i386_abi): New enum. + (struct gdbarch_tdep): Replace os_ident member with abi. + (i386_gdbarch_register_os_abi): New prototype. + * i386-tdep.c (i386_abi_names): New array. + (process_note_abi_tag_sections): Removed. + (process_note_sections): New function. + (i386_elf_abi_from_note, i386_elf_abi): New functions. + (struct i386_abi_handler): New struct. + (i386_abi_handler_list): New variable. + (i386_gdbarch_register_os_abi): New function. + (i386_gdbarch_init): Adapt for the changes given above. + +2002-05-08 Daniel Jacobowitz <drow@mvista.com> + + * gregset.h: Say "GNU/Linux". + +2002-05-08 Elena Zannoni <ezannoni@redhat.com> + + * gdbtypes.c : Add new builtin type for 64 bit vectors. + (build_gdbtypes): Build builtin_type_v2_float. + (_initialize_gdbtypes): Register new builtin type. + +2002-05-08 Andrew Cagney <ac131313@redhat.com> + + * gdbarch.sh (init_gdbarch_swap): Do not clear the swap section. + (clear_gdbarch_swap): New function. + (initialize_non_multiarch): Call. + (gdbarch_update_p): Before calling init(), swap out and clear the + existing architecture. + * gdbarch.c: Regenerate. + +2002-05-08 Jason Thorpe <thorpej@wasabisystems.com> + + * config/djgpp/fnchange.lst: Add alphanbsd-nat.c and + alphanbsd-tdep.c. + +2002-05-08 Jason Thorpe <thorpej@wasabisystems.com> + + * sh-nbsd-nat.c: Rename to... + * shnbsd-nat.c: ...this. + * sh-nbsd-tdep.c: Rename to... + * shnbsd-tdep.c: ...this. + * sh-nbsd-tdep.h: Rename to... + * shnbsd-tdep.h: ...this. + * config/sh/nbsd.mh: Use shnbsd-nat.o. + * config/sh/nbsd.mt: Use shnbsd-tdep.o. + +2002-05-08 Richard Earnshaw <rearnsha@arm.com> + + * remote-rdi.c (_initializie_remote_rdi): Use ANSI-style string + concatenation for command help messages. + +2002-05-08 Jason Thorpe <thorpej@wasabisystems.com> + + * NEWS: Note new sh*-*-netbsdelf* configuration. + * configure.host: Set gdb_host_cpu to sh for all sh*. + (sh*-*-netbsdelf*): New host. + * configure.tgt: Set gdb_target_cpu to sh for all sh*. + (sh*-*-netbsdelf*): New target. + * sh-nbsd-nat.c: New file. + * sh-nbsd-tdep.c: New file. + * sh-nbsd-tdep.h: New file. + * config/sh/nbsd.mh: New file. + * config/sh/nbsd.mt: New file. + * config/sh/nm-nbsd.h: New file. + * config/sh/tm-nbsd.h: New file. + +2002-05-08 Jason Thorpe <thorpej@wasabisystems.com> + + * sh-tdep.c (sh_osabi_names): Declare. + (process_note_abi_tag_sections): New function. + (get_elfosabi): Ditto. + (sh_gdbarch_register_os_abi): Ditto. + (sh_dump_tdep): Ditto. + _initialize_sh_tdep): Use gdbarch_register to register + sh_gdbarch_init and sh_dump_tdep. + * config/sh/tm-sh.h (sh_osabi): Declare. + (gdbarch_tdep): Add sh_osabi and osabi_name members. + +2002-05-07 Andrew Cagney <ac131313@redhat.com> + + * arm-tdep.c (arm_skip_prologue): Handle generic dummy frames. + (thumb_scan_prologue): Ditto. + (arm_find_callers_reg): Ditto. + (arm_frame_chain): Ditto. + (arm_init_extra_frame_info): Ditto. + (arm_frame_saved_pc): Ditto. + (arm_pop_frame): Ditto. + (arm_push_return_address): New function. + (arm_gdbarch_init): Initialize use_generic_dummy_frames, + call_dummy_location, call_dummy_breakpoint_offset_p, + call_dummy_breakpoint_offset, call_dummy_p, + call_dummy_stack_adjust_p, call_dummy_words, + sizeof_call_dummy_words, call_dummy_start_offset, + call_dummy_length, fix_call_dummy, pc_in_call_dummy, + call_dummy_address, push_return_address and push_dummy_frame for + generic dummy frames. + +2002-05-07 Jason Thorpe <thorpej@wasabisystems.com> + + * sh-tdep.c (sh_nofp_frame_init_saved_regs): Fix error in + size computation for alloca. + (sh_fp_frame_init_saved_regs): Likewise. + +2002-05-07 Richard Earnshaw <rearnsha@arm.com> + + * arm-tdep.h (ARM_MAX_REGISTER_RAW_SIZE): Define. + (ARM_MAX_REGISTER_VIRTUAL_SIZE): Define. + * arm-tdep.c (arm_store_return_value): Use them. + Use FP_REGISTER_RAW_SIZE when setting the FPA return value. + * remote-rdp.c (remote_rdp_fetch_register): Use + ARM_MAX_REGISTER_RAW_SIZE. + (remote_rdp_store_register): Likewise. + +2002-05-07 Michal Ludvig <mludvig@suse.cz> + + * dwarf2cfi.c: Code cleanup, removed unused variables, + added default labels to switch {} statements. + * x86-64-tdep.c: Ditto. + * x86-64-linux-nat.c: Ditto. + +2002-05-07 Jason Thorpe <thorpej@wasabisystems.com> + + * solib.h: Protect against multiple inclusion. + +2002-05-06 Jim Blandy <jimb@redhat.com> + + Add first preprocessor macro-expansion files. + * macroexp.c, macroexp.h, macrotab.c, macrotab.h: New files. + * Makefile.in (SFILES): Add macrotab.c, macroexp.c. + (splay_tree_h, macroexp_h, macrotab_h): New variable. + (HFILES_NO_SRCDIR): Add macrotab.h, macroexp.h. + (COMMON_OBS): Add macrotab.o, macroexp.o. + (macroexp.o, macrotab.o): New rules. + + Separate the job of reading the line number info statement program + header (...expialidocious) out into its own function. + * dwarf2read.c (struct line_head, struct filenames, struct + directories): Replace with... + (struct line_header): New structure, containing the full + contents of the statement program header, including the + include directory and file name tables. + (read_file_scope): If we have line number info, instead of just + calling dwarf_decode_lines to do all the work, call + dwarf_decode_line_header first to get a `struct line_header' + containing the data in the statement program header, and then + pass that to dwarf_decode_lines, which will pick up where that + left off. Be sure to clean up the `struct line_header' object. + (dwarf_decode_line_header, free_line_header, add_include_dir, + add_file_name): New functions. + (dwarf_decode_lines): Move all the code to read the statement + program header into dwarf_decode_line_header. Take the line + header it built as the first argument, instead of the offset to + the compilation unit's line number info. Use the new `struct + line_header' type instead of the old structures. No need to do + cleanups here now, since we don't allocate anything. + (dwarf2_statement_list_fits_in_line_number_section, + dwarf2_line_header_too_long): New complaints. + +2002-05-06 Elena Zannoni <ezannoni@redhat.com> + + * gdbtypes.c (init_vector_type): New function. + (build_builtin_type_vec128): Simplify the representation of SIMD + registers. + (build_gdbtypes): Initialize new builtin vector types. + (_initialize_gdbtypes): Register new vector types with gdbarch. + (builtin_type_v4_float, builtin_type_v4_int32, + builtin_type_v8_int16, builtin_type_v16_int8, + builtin_type_v2_int32, builtin_type_v4_int16, + builtin_type_v8_int8): New (renamed) SIMD types. + +2002-05-06 Mark Kettenis <kettenis@gnu.org> + + * i387-nat.c (i387_fill_fsave): Use regcache_collect. + (i387_fill_fxsave): Likewise. + +2002-05-05 Alexandre Oliva <aoliva@redhat.com> + + * alpha-tdep.c (alpha_extract_return_value): Don't use + non-constant array size in prototype. + +2002-05-04 Andrew Cagney <ac131313@redhat.com> + + From Brian Taylor <briant at model dot com>: + * ui-out.c (ui_out_field_core_addr): Use the function + longest_local_hex_string_custom'to format addresses > 32 bits + wide. + + * ui-out.c (ui_out_field_core_addr): Update comment. + +2002-05-04 Andrew Cagney <ac131313@redhat.com> + + * stack.c (select_and_print_frame): Make static. Delete the + parameter `level'. + (func_command): Update call. + (select_frame_command): Delete code computing the frame level. + * frame.h (select_and_print_frame): Delete declaration. + +2002-05-04 Andrew Cagney <ac131313@redhat.com> + + * sparc-tdep.c (sparc_get_saved_register): Comment why + get_prev_frame call is safe. + +2002-05-04 Andrew Cagney <ac131313@redhat.com> + + * frame.h (select_frame): Delete level parameter. + * stack.c (select_frame): Update. Use frame_relative_level to + obtain the frame's level. + (select_and_print_frame): Update call. + (select_frame_command): Ditto. + (up_silently_base): Ditto. + (down_silently_base): Ditto. + * ocd.c (ocd_start_remote): Ditto. + * remote-rdp.c (remote_rdp_open): Ditto. + * remote-mips.c (mips_initialize): Ditto. + (common_open): Ditto. + * remote-e7000.c (e7000_start_remote): Ditto. + * m3-nat.c (select_thread): Ditto. + * hppa-tdep.c (child_get_current_exception_event): Ditto. + (child_get_current_exception_event): Ditto. + * varobj.c (varobj_create): Ditto. + (varobj_update): Ditto. + (c_value_of_root): Ditto. + * tracepoint.c (finish_tfind_command): Ditto. + * corelow.c (core_open): Ditto. + * arch-utils.c (generic_prepare_to_proceed): Ditto. + * thread.c (info_threads_command): Ditto. + (switch_to_thread): Ditto. + * infrun.c (normal_stop): Ditto. + (restore_selected_frame): Ditto. + (restore_inferior_status): Ditto. + * breakpoint.c (insert_breakpoints): Ditto. + (watchpoint_check): Ditto. + (bpstat_stop_status): Ditto. + (do_enable_breakpoint): Ditto. + * blockframe.c (flush_cached_frames): Ditto. + (reinit_frame_cache): Ditto. + +2002-05-04 Andrew Cagney <ac131313@redhat.com> + + * MAINTAINERS (Host/Native): Add Jason Thorpe as NetBSD + maintainer. + +2002-05-04 Jim Blandy <jimb@redhat.com> + + * gdbtypes.c (replace_type): Doc fix. + +2002-05-04 Andrew Cagney <ac131313@redhat.com> + + * valprint.c (strcat_longest): Delete commented out function. + Update copyright. + +2002-05-04 Andrew Cagney <ac131313@redhat.com> + + * MAINTAINERS: Mark a29k as deleted. + * NEWS: Mention that a29k was removed. Add OBSOLETE section. + Move new configurations to the top. + * configure.tgt: Remove a29k. + * config/a29k/tm-vx29k.h: Delete. + * config/a29k/vx29k.mt: Delete. + * config/a29k/tm-a29k.h: Delete. + * config/a29k/a29k-udi.mt: Delete. + * config/a29k/a29k.mt: Delete. + * a29k-tdep.c: Delete. + * remote-udi.c: Delete. + * remote-mm.c: Delete. + * remote-eb.c: Delete. + * remote-adapt.c: Delete. + * Makefile.in: Remove obsolete code. + * config/s390/s390x.mt: Ditto. + * config/s390/s390.mt: Ditto. + * config/sparc/sparclynx.mh: Ditto. + * config/sparc/linux.mh: Ditto. + * config/pa/hppaosf.mh: Ditto. + * config/pa/hppabsd.mh: Ditto. + * config/ns32k/nbsd.mt: Ditto. + * config/mips/vr5000.mt: Ditto. + * config/m68k/sun3os4.mh: Ditto. + * config/m68k/nbsd.mt: Ditto. + * config/m68k/m68klynx.mh: Ditto. + * config/m32r/m32r.mt: Ditto. + * config/i386/x86-64linux.mt: Ditto. + * config/i386/nbsdelf.mt: Ditto. + * config/i386/nbsd.mt: Ditto. + * config/i386/i386lynx.mh: Ditto. + +2002-05-04 Andrew Cagney <ac131313@redhat.com> + + * target.c (debug_print_register): New function. Handle oversize + registers. + (debug_to_fetch_registers): Call. + (debug_to_store_registers): Call. + +2002-05-03 Jim Blandy <jimb@redhat.com> + + * stabsread.c (cleanup_undefined_types): Use replace_type, not memcpy. + (read_type): Doc fix. + * gdbtypes.c (replace_type): Doc fix. + + * stabsread.c (multiply_defined_struct): New complaint. + (read_struct_type): If the type we were passed isn't empty, or + incomplete, don't read the new struct type into it; complain, + and return the original type unchanged. Take a new `type_code' + argument, which is the type code for the new type. + (read_type): Rather than storing the type's type code here, pass + it as an argument to read_struct_type, and let that take care of + storing it. That way, we don't overwrite the original type code, + so read_struct_type can use it to decide whether we're overwriting + something we shouldn't. + (complain_about_struct_wipeout): New function. + +2002-05-03 Andrew Cagney <ac131313@redhat.com> + + * gdbarch.sh: Assert that gdbarch is non-NULL. + * gdbarch.c: Regenerate. + +2002-05-03 Jason Merrill <jason@redhat.com> + + * gnu-v3-abi.c (gnuv3_rtti_type): If we get confused, just warn + and return NULL. + +2002-05-03 Michal Ludvig <mludvig@suse.cz> + + * x86-64-tdep.c (x86_64_dwarf2gdb_regno_map), + (x86_64_dwarf2gdb_regno_map_length), + (x86_64_dwarf2_reg_to_regnum): Added. + (x86_64_gdbarch_init): Added registration of x86_64_dwarf2_reg_to_regnum. + (x86_64_gdbarch_init): Renamed from i386_gdbarch_init. + (_initialize_x86_64_tdep): Synced with the change above. + (x86_64_skip_prologue): Reformulated message. + +2002-05-03 Pierre Muller <muller@ics.u-strasbg.fr> + + * f-exp.y: Also use new prev_lexptr variable + to improve error reporting. Based on Michael Snyder + 2002-04-24 dated patch to c-exp.y. + * jv-exp.y: Likewise. + * m2-exp.y: Likewise. + +2002-05-02 Elena Zannoni <ezannoni@redhat.com> + + * valops.c (value_arg_coerce): Don't coerce arrays to pointers if + we are dealing with vectors. + +2002-05-02 Pierre Muller <muller@ics.u-strasbg.fr> + + * config/m68k/tm-nbsd.h: Obvious fix, + correct machine name. + +2002-05-02 Pierre Muller <muller@ics.u-strasbg.fr> + + * p-typeprint.c (pascal_type_print_base): Add support + for TYPE_CODE_STRING and TYPE_CODE_BITSTRING. + +2002-05-02 Pierre Muller <muller@ics.u-strasbg.fr> + + * p-lang.c (pascal_create_fundamental_type): Use TYPE_CODE_CHAR + for fondamental pascal 'char' type. + +2002-05-02 Pierre Muller <muller@ics.u-strasbg.fr> + + * p-lang.h (is_pascal_string_type): Declaration changed, + new sixth argument of type char ** added. + * p-lang.c (is_pascal_string_type): Implementation + changed. Args length_pos, length_size, string_pos, char_size + can now be NULL. New argument arrayname set to the field + name of the char array. Return value set to char array + field index plus one. + * p-valprint.c (pascal_val_print): Adapt to new declaration of + is_pascal_string_type function. + +2002-05-02 Andrew Cagney <cagney@redhat.com> + + * gdbarch.sh (gdbarch_update_p): Revert 2002-05-02 Andrew Cagney + <cagney@redhat.com> change. + * gdbarch.c: Regenerate. + +2002-05-02 Andrew Cagney <cagney@redhat.com> + + * gdbarch.sh (gdbarch_update_p): Swap out the old architecture + before probing for a new one. Detect errorenous gdbarch_init + functions. + * gdbarch.c: Regenerate. + +2002-05-01 Andrew Cagney <cagney@redhat.com> + + * config/mn10200/tm-mn10200.h: Include "symfile.h" and "symtab.h". + * config/mcore/tm-mcore.h: Ditto. Update copyright. + * config/v850/tm-v850.h: Ditto. Update copyright. + +2002-04-30 Andrew Cagney <ac131313@redhat.com> + + * cris-tdep.c (cris_gdbarch_init): Use arches instead of + current_gdbarch. + +2002-04-30 Michael Snyder <msnyder@redhat.com> + + * arm-tdep.c: Whitespace clean-ups. + (arm_skip_prologue): Fix thinko; two lines + should have been removed as part of 4/24 change. + +2002-04-30 Kevin Buettner <kevinb@redhat.com> + + * rs6000-tdep.c: Added comment describing how fpscr register + numbers were chosen. + +2002-04-30 Michael Snyder <msnyder@redhat.com> + + * gnu-nat.c (gnu_find_memory_regions): Fix merge botch. + +2002-04-29 Elena Zannoni <ezannoni@redhat.com> + + * hpread.c (DNTT_TYPE_VECTOR): Rename from TYPE_VECTOR. + (DNTT_TYPE_VECTOR_LENGTH): Rename from TYPE_VECTOR_LENGTH. + (hpread_symfile_init, hpread_lookup_type): Substitute throughout. + +2002-04-29 Kevin Buettner <kevinb@redhat.com> + + From Louis Hamilton <hamilton@redhat.com>: + * rs6000-tdep.c (coff/xcoff.h, libxcoff.h): Include. + * xcoffread.c (coff/xcoff.h, libxcoff.h): Likewise. + * rs6000-tdep.c (rs6000_gdbarch_init): Use bfd_xcoff_is_xcoff64(), + not bfd-private xcoff data, to determine wordsize. + * xcoffread.c (read_xcoff_xymtab, read_symbol_lineno): Likewise. + +2002-04-29 Andrew Cagney <ac131313@redhat.com> + + GDB 5.2 released from 5.2 branch. + +2002-04-29 Michal Ludvig <mludvig@suse.cz> + + * x86-64-linux-nat.c (fill_gregset): Explicit cast to avoid warning. + * x86-64-tdep.c (i386_gdbarch_init): Ditto. + (x86_64_register_info_table): Added comments with register numbers. + +2002-04-29 Elena Zannoni <ezannoni@redhat.com> + + * rs6000-tdep.c (rs6000_extract_return_value, + rs6000_store_return_value): Handle returning vectors. + (rs6000_gdbarch_init): Use + ppc_sysv_abi_broken_use_struct_convention for native sysv cases. + * ppc-linux-tdep.c (ppc_sysv_abi_broken_use_struct_convention): + New function. + (ppc_sysv_abi_use_struct_convention): Deal with functions returning + vectors. + (ppc_sysv_abi_push_arguments): Handle vector parameters. + * ppc-tdep.h (ppc_sysv_abi_broken_use_struct_convention): Export. + +2002-04-24 Pierre Muller <ics.u-strasbg.fr> + + * hpread.c (hpread_psymtab_to_symtab_1, + hpread_psymtab_to_symtab): Replace fprintf tab_to_s...) + with fprintf_unfiltered (gdb_stderr,...). + +2002-04-24 Pierre Muller <ics.u-strasbg.fr> + + * remote-array.c (printf_monitor, write_monitor, + array_insert_breakpoint, array_remove_breakpoint ): + Replace fprintf (stderr,... + with fprintf_unfiltered (gdb_stderr,.... + * remote-es.c: Likewise. + * remote-os9k.c: Likewise. + * remote-st.c: Likewise. + +2002-04-28 Andreas Schwab <schwab@suse.de> + + * config/s390/s390.mh (NATDEPFILES): Remove solib.o, add + linux-proc.o and gcore.o. + +2002-04-26 Michal Ludvig <mludvig@suse.cz> + + * x86-64-tdep.c (x86_64_skip_prologue): Print note when debugging + code without frame pointers. + +2002-04-26 Andrew Cagney <ac131313@redhat.com> + + * sparc-tdep.c (sparc_gdbarch_init): Add comment explaining why + ON_STACK is needed. + +2002-04-26 Ben Elliston <bje@redhat.com> + + * target.c (do_xfer_memory): Correct reference to the new option + "trust-readonly-sections". + +2002-04-26 Elena Zannoni <ezannoni@redhat.com> + + * gdbtypes.h (TYPE_FLAG_VECTOR, TYPE_VECTOR): Define. + * gdbtypes.c (recursive_dump_type): Output the vector flag. + * dwarf2read.c (dwarf_attr_name): Handle new attribute for + vectors. + (read_array_type): Record the fact that this array type is really a + vector (i.e. are passed in by value). + +2002-04-26 Jason Thorpe <thorpej@wasabisystems.com> + + * alpha-tdep.h (gdbarch_tdep): Add sigcontext_addr member. + * alpha-tdep.c (alpha_sigcontext_addr): New function. + (alpha_find_saved_regs): Use alpha_sigcontext_addr. + (alpha_gdbarch_init): Initialize tdep->sigcontext_addr. + * alpha-linux-tdep.c: Include frame.h. + (alpha_linux_sigcontext_addr): New function. + (alpha_linux_init_abi): Set tdep->sigcontext_addr to + alpha_linux_sigcontext_addr. + * alpha-osf1-tdep.c: Include gdbcore.h. + (alpha_osf1_sigcontext_addr): New function. + (alpha_osf1_init_abi): Set tdep->sigcontext_addr to + alpha_osf1_sigcontext_addr. + * config/alpha/tm-alpha.h (SIGCONTEXT_ADDR): Remove. + * config/alpha/tm-alphalinux.h (SIGCONTEXT_ADDR): Remove. + +2002-04-26 Andrew Cagney <ac131313@redhat.com> + + * stack.c (selected_frame_level): + (select_frame): Do not set selected_frame_level. + * frame.h (selected_frame_level): Delete declaration. + +2002-04-26 Andrew Cagney <ac131313@redhat.com> + + * rs6000-tdep.c (rs6000_gdbarch_init): Only set + convert_from_func_ptr-addr when AIX / PowerOpen. + +2002-04-25 Andrew Cagney <ac131313@redhat.com> + + * valops.c (hand_function_call): Call + generic_save_call_dummy_addr. + * frame.h (generic_save_call_dummy_addr): Declare. + * blockframe.c (struct dummy_frame): Add fields call_lo and + call_hi. + (generic_find_dummy_frame): Check for PC in range call_lo to + call_hi instead of entry_point_address. + (generic_pc_in_call_dummy): Search the dummy frames for a PC in + the call_lo to call_hi range. Allow for DECR_PC_AFTER_BREAK. + (generic_save_call_dummy_addr): New function. + +2002-04-24 David S. Miller <davem@redhat.com> + + * sparc-tdep.c (sparc_gdbarch_skip_prologue): Kill, duplicates + sparc_skip_prologue. + (sparc_skip_prologue): Kill frameless_p arg, and use line number + information to find prologue when possible. + (sparc_prologue_frameless_p): Call examine_prologue directly. + (sparc_gdbarch_init): Update set_gdbarch_skip_prologue call. + * config/sparc/tm-sparc.h (sparc_skip_prologue): Update for killed + second argument. + (SKIP_PROLOGUE): Likewise. + +2002-04-25 Jason Thorpe <thorpej@wasabisystems.com> + + * alpha-tdep.c (alpha_skip_prologue_internal): Remove + GDB_TARGET_HAS_SHARED_LIBS #ifdef and update comment to + indicate that the condition it was testing is always true. + * config/alpha/nm-linux.h (GDB_TARGET_HAS_SHARED_LIBS): Remove. + * config/alpha/nm-nbsd.h (GDB_TARGET_HAS_SHARED_LIBS): Ditto. + * config/alpha/nm-osf.h (GDB_TARGET_HAS_SHARED_LIBS): Ditto. + +2002-04-25 Jason Thorpe <thorpej@wasabisystems.com> + + * alpha-tdep.h (gdbarch_tdep): Add jb_pc and jb_elt_size members. + * alpha-linux-tdep.c (alpha_linux_init_abi): Initialize + tdep->jb_pc and tdep->jb_elt_size. + * alpha-osf1-tdep.c (alpha_osf1_init_abi): Likewise. + * alphafbsd-tdep.c (alphafbsd_init_abi): Likewise. + * alphanbsd-tdep.c (alphanbsd_init_abi): Likewise. + * alpha-nat.c (get_longjmp_target): Remove. + (JB_ELEMENT_SIZE): Ditto. + (JB_PC): Ditto. + * alpha-tdep.c (alpha_get_longjmp_target): New function. + (alpha_gdbarch_init): Default tdep->jb_pc to -1. If the + OS ABI sets jb_pc to a valid value, set gdbarch_get_longjmp_target + to alpha_get_longjmp_target. + (alpha_dump_tdep): Report tdep->jb_pc and tdep->jb_elt_size. + * config/alpha/nm-linux.h (GET_LONGJMP_TARGET): Remove. + * config/alpha/nm-osf.h (GET_LONGJMP_TARGET): Remove. + +2002-04-25 Andrew Cagney <ac131313@redhat.com> + + * README: Update to GDB 5.2. + +2002-04-25 Andrew Cagney <ac131313@redhat.com> + + * gdbarch.sh (LC_ALL): Set to `c'. + +2002-04-25 Theodore A. Roth <troth@verinet.com> + + * avr-tdep.c: Ran through gdb_indent.sh. + +2002-04-25 Theodore A. Roth <troth@verinet.com> + + * MAINTAINERS: Add myself as AVR maintainer. + * NEWS: Note new target avr. + +2002-04-25 Theodore A. Roth <troth@verinet.com> + + * Makefile.in: Add support for AVR target. + * configure.tgt: Add support for AVR target. + * avr-tdep.c: New file + * config/avr/avr.mt: New file. + +2002-04-25 Theodore A. Roth <troth@verinet.com> + + * MAINTAINERS: Add myself to write-after-approval. + +2002-04-24 Pierre Muller <ics.u-strasbg.fr> + + * f-lang.c (get_bf_for_fcn): Replace fprintf (stderr,... + with fprintf_unfiltered (gdb_stderr,.... + +2002-04-25 Pierre Muller <muller@ics.u-strasbg.fr> + + Fix PR gdb/508. + * symfile.c (add_filename_language): Fix wrong xrealloc size argument. + +2002-04-25 Pierre Muller <muller@ics.u-strasbg.fr> + + * p-exp.y: Also use new prev_lexptr variable + to improve error reporting. Based on Michael Snyder + 2002-04-24 dated patch to c-exp.y. + +2002-04-25 Jason Thorpe <thorpej@wasabisystems.com> + + * alpha-tdep.c (alpha_breakpoint_from_pc): New function. + (alpha_gdbarch_init): Set gdbarch_breakpoint_from_pc to + alpha_breakpoint_from_pc. Set gdbarch_function_start_offset + to 0. + * config/alpha/tm-alpha.h: Remove forward decls of struct type + and struct value. + (FUNCTION_START_OFFSET): Remove. + (BREAKPOINT): Ditto. + +2002-04-25 Jason Thorpe <thorpej@wasabisystems.com> + + * MAINTAINERS: Reflect that multi-arch is enabled for VAX. + * NEWS: Ditto. + +2002-04-24 Jason Thorpe <thorpej@wasabisystems.com> + + * alpha-linux-tdep.c (alpha_linux_pc_in_sigtramp): New function. + (alpha_linux_init_abi): Set gdbarch_pc_in_sigtramp to + alpha_linux_pc_in_sigtramp. + * alpha-osf1-tdep.c (alpha_osf1_pc_in_sigtramp): New function. + (alpha_osf1_init_abi): Set gdbarch_pc_in_sigtramp to + alpha_osf1_pc_in_sigtramp. + * alpha-tdep.c (alpha_osf_in_sigtramp): Remove. + * alphafbsd-tdep.c (alphafbsd_pc_in_sigtramp): New function. + (alphafbsd_init_abi): Set gdbarch_pc_in_sigtramp to + alphafbsd_pc_in_sigtramp. + * alphanbsd-tdep.c (alphanbsd_pc_in_sigtramp): New function. + (alphanbsd_init_abi): Set gdbarch_pc_in_sigtramp to + alphanbsd_pc_in_sigtramp. + * config/alpha/tm-alpha.h (IN_SIGTRAMP): Remove. + * config/alpha/tm-alphalinux.h (IN_SIGTRAMP): Remove. + +2002-04-24 Jason Thorpe <thorpej@wasabisystems.com> + + * config/alpha/nbsd.mh (NATDEPFILES): Remove solib-legacy.o. + +2002-04-24 Jason Thorpe <thorpej@wasabisystems.com> + + * Makefile.in (ALLDEPFILES): Add alphanbsd-nat.c and + alphanbsd-tdep.c. + (alphanbsd-nat.o): New dependency list. + (alphanbsd-tdep.o): Ditto. + * NEWS: Note new native NetBSD/alpha configuration. + * alphanbsd-nat.c: New file. + * alphanbsd-tdep.c: Ditto. + * configure.host (alpha*-*-netbsd*): New host. + * configure.tgt (alpha*-*-netbsd*): New target. + * config/alpha/nbsd.mh: New file. + * config/alpha/nbsd.mt: Ditto. + * config/alpha/nm-nbsd.h: Ditto. + * config/alpha/tm-nbsd.h: Ditto. + +2002-04-24 Jason Thorpe <thorpej@wasabisystems.com> + + * Makefile.in (ALLDEPFILES): Add alpha-osf1-tdep.c. + (alpha-osf1-tdep.o): New dependency list. + * alpha-tdep.h (gdbarch_tdep): Add dynamic_sigtramp_offset + and skip_sigtramp_frame members. + * alpha-linux-tdep.c: Include gdbcore.h. + (alpha_linux_sigtramp_offset): Change return type to LONGEST. + (alpha_linux_init_abi): Initialize tdep->dynamic_sigtramp_offset. + * alpha-osf1-tdep.c: New file. + * alpha-tdep.c (alpha_osf_skip_sigtramp_frame): Moved to + alpha-osf1-dep.c. + (alpha_frame_past_sigtramp_frame): New function. + (alpha_dynamic_sigtramp_offset): Ditto. + (alpha_proc_desc_is_dyn_sigtramp): Ditto. + (alpha_set_proc_desc_is_dyn_sigtramp): Ditto. + (ALPHA_PROC_SIGTRAMP_MAGIC): Define. + (push_sigtramp_desc): Use alpha_set_proc_desc_is_dyn_sigtramp. + (after_prologue): Use alpha_proc_desc_is_dyn_sigtramp. + (find_proc_desc): Use alpha_dynamic_sigtramp_offset. + (alpha_frame_chain): Use alpha_frame_past_sigtramp_frame. + (alpha_init_extra_frame_info): Use alpha_proc_desc_is_dyn_sigtramp. + (alpha_pop_frame): Use alpha_proc_desc_is_dyn_sigtramp. + (alpha_gdbarch_init): Initialize tdep->dynamic_sigtramp_offset + and tdep->skip_sigtramp_frame. Set gdbarch_skip_trampoline_code + to find_solib_trampoline_target. + * config/alpha/alpha-osf1.mt (TDEPFILES): Add alpha-osf1-tdep.o. + * config/alpha/tm-alpha.h: Remove inclusion of regcache.h. + (SKIP_TRAMPOLINE_CODE): Remove. + (PROC_DESC_IS_DYN_SIGTRAMP): Ditto. + (SET_PROC_DESC_IS_DYN_SIGTRAMP): Ditto. + (DYNAMIC_SIGTRAMP_OFFSET): Ditto. + (FRAME_PAST_SIGTRAMP_FRAME): Ditto. + * config/alpha/tm-alphalinux.h (PROC_DESC_IS_DYN_SIGTRAMP): Remove. + (PROC_SIGTRAMP_MAGIC): Ditto. + (PROC_DESC_IS_DYN_SIGTRAMP): Ditto. + (SET_PROC_DESC_IS_DYN_SIGTRAMP): Ditto. + (SET_PROC_DESC_IS_DYN_SIGTRAMP): Ditto. + (DYNAMIC_SIGTRAMP_OFFSET): Ditto. + (FRAME_PAST_SIGTRAMP_FRAME): Ditto. + +2002-04-24 Jason Thorpe <thorpej@wasabisystems.com> + + * NEWS: Note that Alpha targets are now multi-arch. + +2002-04-24 Michael Snyder <msnyder@redhat.com> + + * parser-defs.h (prev_lexptr): New external variable. + * parse.c (parse_exp_1): Set prev_lexptr to null before + calling the language-specific parser. + * c-exp.y (yylex): Set prev_lexptr to start of current token. + (yyerror): Use prev_lexptr in error reporting. + +2002-04-24 Daniel Jacobowitz <drow@mvista.com> + + * config/i386/tm-linux.h: Define FILL_FPXREGSET. + * gregset.h: If FILL_FPXREGSET is defined, provide + gdb_fpxregset_t, supply_fpxregset, and fill_fpxregset. + * linux-proc.c (linux_do_thread_registers): If FILL_FPXREGSET + is defined, call fill_fpxregset. + +2002-04-24 Roland McGrath <roland@frob.com> + + * config/i386/i386gnu.mh (NATDEPFILES): Add core-regset.o here. + * i386gnu-nat.c [HAVE_SYS_PROCFS_H] + (supply_gregset, supply_fpregset): New functions. + + * gnu-nat.c (gnu_find_memory_regions): New function. + (init_gnu_ops): Set `to_find_memory_regions' hook to that. + (gnu_xfer_memory): Add a cast. + +2002-04-24 Michael Snyder <msnyder@redhat.com> + + * arm-tdep.c (arm_scan_prologue): Move "mov ip, sp" into the + loop. Add handling for "str lr, [sp, #-4]!" and for saves + of argument regs ("str r(0123), [r11, #-nn"]). + (arm_skip_prologue): Better handling for frameless functions. + Treat "mov ip, sp" as optional. Recognize "str lr, [sp, #-4]". + (arm_skip_prologue): Recognize str r(0123), [r11, #-nn]. + +Wed Apr 24 14:22:21 2002 Andrew Cagney <cagney@redhat.com> + + * arm-tdep.c (arm_gdbarch_init): Add comment that NUM_REGS nor + NUM_PSEUDO_REGS can be used. + +2002-04-24 Andrew Cagney <ac131313@redhat.com> + + * arch-utils.h: Update copyright. + + * gdbarch.sh (PC_IN_SIGTRAMP): Add. + * gdbarch.h, gdbarch.c: Re-generate. + + * inferior.h (IN_SIGTRAMP): Delete definition. + * arch-utils.c (legacy_pc_in_sigtramp): New function. + * arch-utils.h (legacy_pc_in_sigtramp): Declare. + + * mips-tdep.c (mips_init_extra_frame_info): Use PC_IN_SIGTRAMP. + (mips_dump_tdep): Do not print value of IN_SIGTRAMP. + * hppa-tdep.c (pc_in_interrupt_handler): Use PC_IN_SIGTRAMP. + (find_proc_framesize): Ditto. + * alpha-tdep.c (alpha_osf_skip_sigtramp_frame): Ditto. + (alpha_init_extra_frame_info): Ditto. + * infrun.c (handle_inferior_event): Ditto. + (handle_inferior_event): Ditto. + (check_sigtramp2): Ditto. + * blockframe.c (create_new_frame): Ditto. + (get_prev_frame): Ditto. + * ppc-linux-tdep.c: Update comments. + * i386-linux-tdep.c: Update comments. + * breakpoint.c (bpstat_what): Update comment. + +2002-04-24 David S. Miller <davem@redhat.com> + + * i960-tdep.c (register_in_window_p): New function. + (i960_find_saved_register): Use it instead of + REGISTER_IN_WINDOW_P. + * config/i960/tm-i960.h (REGISTER_IN_WINDOW): Delete. + + * symtab.h (find_stab_function_addr): Kill extern. + * minsyms.c (find_stab_function_addr): Remove from here... + * dbxread.c: ... to here, and mark it static. + +2002-04-20 David S. Miller <davem@redhat.com> + + * sparc-tdep.c (sparc_pop_frame): Only need to allocate + SPARC_INTREG_SIZE * 16 bytes for reg_temp. + +2002-04-21 David S. Miller <davem@redhat.com> + + * remote-vxsparc.c (vx_read_register): Fix typo, we want + REGISTER_RAW_SIZE of SP_REGNUM not CORE_ADDR. + (vx_write_register): Likewise. + +2002-04-23 J. Brobecker <brobecker@gnat.com> + + * source.c (is_regular_file): New function. + (openp): Check wether file to open is a regular file + to avoid opening directories. + +2002-04-22 Jason Thorpe <thorpej@wasabisystems.com> + + * findvar.c (extract_signed_integer): Cast printf argument + to suppress format warning. + (extract_unsigned_integer): Likewise. + * infcmd.c (registers_info): Likewise. + * top.c (get_prompt_1): Likewise. + * valops.c (value_assign): Likewise. + * valprint.c (print_decimal): Likewise. + +2002-04-22 H.J. Lu (hjl@gnu.org) + + * c-exp.y (typebase): Support + + [long|long long|short] [signed|unsigned] [int|] + + and + + signed [long|long long|short] int + +2002-04-22 Jason Thorpe <thorpej@wasabisystems.com> + + * Makefile.in (vax-tdep.o): Add $(arch_utils_h), $(inferior_h), + and vax-tdep.h. + * vax-tdep.h: New file. + * vax-tdep.c: Include inferior.h, arch-utils.h, and vax-tdep.h. + Make several routines static. + (vax_get_saved_register): New function. + (vax_gdbarch_init): New function. + (_initialize_vax_tdep): Register vax_gdbarch_init. + * config/vax/tm-vax.h: Set GDB_MULTI_ARCH to GDB_MULTI_ARCH_PARTIAL. + Remove macros now under the control of gdbarch. + +2002-04-22 Michael Snyder <msnyder@redhat.com> + + * arm-tdep.c (arm_skip_prologue): Recognize "sub sp, sp, #nn". + Some whitespace and coding standards tweaks. + +2002-04-22 Jason Thorpe <thorpej@wasabisystems.com> + + * vax-tdep.c: Include regcache.h. + (vax_call_dummy_words): New. + (sizeof_vax_call_dummy_words): New. + (vax_fix_call_dummy): New function. + (vax_saved_pc_after_call): Ditto. + * config/vax/tm-vax.h: Don't include regcache.h. + (SAVED_PC_AFTER_CALL): Use vax_saved_pc_after_call. + (CALL_DUMMY): Remove. + (CALL_DUMMY_WORDS): Define. + (SIZEOF_CALL_DUMMY_WORDS): Define. + (FIX_CALL_DUMMY): Use vax_fix_call_dummy. + +2002-04-18 Michael Snyder <msnyder@redhat.com> + + * arm-tdep.h: Change regnum defines to enums for ease of debugging. + +2002-04-22 Jason Thorpe <thorpej@wasabisystems.com> + + * vax-tdep.c (vax_frame_chain): New function. + (vax_push_dummy_frame): Ditto. + (vax_pop_frame): Ditto. + * config/vax/tm-vax.h (FRAME_CHAIN): vax_frame_chain. + (FRAMELESS_FUNCTION_INVOCATION): Use + generic_frameless_function_invocation_not. + (PUSH_DUMMY_FRAME): Use vax_push_dummy_frame. + (POP_FRAME): Use vax_pop_frame. + +2002-04-22 Jason Thorpe <thorpej@wasabisystems.com> + + * vax-tdep.c (vax_store_struct_return): New function. + (vax_extract_return_value): Ditto. + (vax_store_return_value): Ditto. + (vax_extract_struct_value_address): Ditto. + * config/vax/tm-vax.h (STORE_STRUCT_RETURN): Use + vax_store_struct_return. + (EXTRACT_RETURN_VALUE): Use vax_extract_return_value. + (STORE_RETURN_VALUE): Use vax_store_return_value. + (EXTRACT_STRUCT_VALUE_ADDRESS): Use vax_extract_struct_value_address. + +2002-04-22 Jason Thorpe <thorpej@wasabisystems.com> + + * vax-tdep.c (vax_frame_saved_pc): New function. + (vax_frame_args_address_correct): Ditto. + (vax_frame_args_address): Ditto. + (vax_frame_locals_address): Ditto. + (vax_frame_num_args): Move code to be in proximity to + other frame-related functions. + * config/vax/tm-vax.h (INNER_THAN): Use core_addr_lessthan. + (FRAME_SAVED_PC): Use vax_frame_saved_pc. + (FRAME_ARGS_ADDRESS_CORRECT): Use vax_frame_args_address_correct. + (FRAME_ARGS_ADDRESS): Use vax_frame_args_address. + (FRAME_LOCALS_ADDRESS): Use vax_frame_locals_address. + +2002-04-22 H.J. Lu (hjl@gnu.org) + + * Makefile.in (FLAGS_TO_PASS): Add libdir, mandir, datadir and + includedir. + +2002-04-22 Jason Thorpe <thorpej@wasabisystems.com> + + * vax-tdep.c (vax_frame_init_saved_regs): New function. + * config/vax/tm-vax.h (FRAME_FIND_SAVED_REGS): Remove. + (FRAME_INIT_SAVED_REGS): New macro. + +2002-04-22 Jason Thorpe <thorpej@wasabisystems.com> + + * MAINTAINERS: Reflect that the Alpha target has been multi-arch'd. + +2002-04-22 Jason Thorpe <thorpej@wasabisystems.com> + + * alpha-nat.c (get_longjmp_target): Use ALPHA_* constants + where needed. + (fetch_osf_core_registers): Likewise. + (supply_gregset): Likewise. + +2002-04-22 J. Brobecker <brobecker@gnat.com> + + * symfile.h (get_section_index): Define. + * symfile.c (get_section_index): New function. + * mdebugread.c (SC_IS_SBSS): New macro. + (SC_IS_BSS): Return true for the scBss storage class only, as + the scSBss storage class refers to the .sbss section. + (parse_partial_symbols): Discard the symbols which associated + section does not exist. + Make sure to use the .sbss section index for symbols which + storage class is scBss, rather than using the .bss section index. + +2002-04-22 Jason Thorpe <thorpej@wasabisystems.com> + + * vax-tdep.c: Update copyright years. + (vax_register_name): New function. + (vax_register_byte): Ditto. + (vax_register_raw_size): Ditto. + (vax_register_virtual_size): Ditto. + (vax_register_virtual_type): Ditto. + * config/vax/tm-vax.h: Update copyright years. + (REGISTER_NAMES): Remove. + (REGISTER_NAME): Define. + (REGISTER_BYTE): Use vax_register_byte. + (REGISTER_RAW_SIZE): Use vax_register_raw_size. + (REGISTER_VIRTUAL_SIZE): Use vax_register_virtual_size. + (REGISTER_VIRTUAL_TYPE): Use vax_register_virtual_type. + +2002-04-21 Andrew Cagney <ac131313@redhat.com> + + * config/sparc/tm-sparc.h (sparc_skip_prologue): Restore + declaration + * arc-tdep.c (arc_prologue_frameless_p): Fix syntax error. + +2002-04-21 David S. Miller <davem@redhat.com> + + * arch-utils.c (generic_prologue_frameless_p): Kill + SKIP_PROLOGUE_FRAMELESS_P code. + * config/arc/tm-arc.h (SKIP_PROLOGUE_FRAMELESS_P): Delete + references. + (PROLOGUE_FRAMELESS_P, arc_prologue_frameless_p): New. + * arc-tdep.c (arc_prologue_frameless_p): Implement. + * config/arc/tm-sparc.h (SKIP_PROLOGUE_FRAMELESS_P): Delete + references. + (PROLOGUE_FRAMELESS_P, sparc_prologue_frameless_p): New. + * sparc-tdep.c (sparc_prologue_frameless_p): Implement. + (sparc_gdbarch_init): Pass it to + set_gdbarch_prologue_frameless_p. + +2002-04-21 Jason Thorpe <thorpej@wasabisystems.com> + + * Makefile.in (ALLDEPFILES): Add alphabsd-nat.c. + (alphabsd-nat.o): New dependency list. + +2002-04-21 Jason Thorpe <thorpej@wasabisystems.com> + + * Makefile.in (ALLDEPFILES): Add alpha-linux-tdep.c and + alphafbsd-tdep.c. + (alpha-linux-tdep.o): New dependency list. + (alphafbsd-tdep.o): Likewise. + +2002-04-21 Jason Thorpe <thorpej@wasabisystems.com> + + * alpha-linux-tdep.c: New file. Move alpha_linux_sigtramp_offset + to here... + * alpha-tdep.c: ...from here. + * config/alpha/alpha-linux.mt (TDEPFILES): Add alpha-linux-tdep.o. + +2002-04-21 Jason Thorpe <thorpej@wasabisystems.com> + + * config/alpha/tm-alpha.h: Move alpha_software_single_step + prototype from here... + * alpha-tdep.h: ...to here. + +2002-04-21 Andrew Cagney <ac131313@redhat.com> + + * frame.h (selected_frame_level): Document as deprecated. + (frame_relative_level): Declare. + * stack.c (frame_relative_level): New function. + (selected_frame_level): Document as deprecated. + (select_frame): Do not set the selected_frame_level. + + * stack.c (frame_info, record_selected_frame): Update. + (frame_command, current_frame_command): Update. + (up_silently_base, up_command, down_silently_base): Update. + (down_command): Update. + * inflow.c (kill_command): Update. + * tracepoint.c (finish_tfind_command): Update. + * corelow.c (core_open): Update. + * thread.c (info_threads_command): Update. + (do_captured_thread_select): Update. + * infcmd.c (finish_command): Update. + * breakpoint.c (insert_breakpoints, do_enable_breakpoint): Update. + +2002-04-21 Jason Thorpe <thorpej@wasabisystems.com> + + * config/alpha/tm-fbsd.h (FRAME_CHAIN_VALID): Remove. + +2002-04-21 Andrew Cagney <ac131313@redhat.com> + + * arm-tdep.c (arm_breakpoint_from_pc): Make static. Make return + type const. + +2002-04-21 Jason Thorpe <thorpej@wasabisystems.com> + + * alphafbsd-tdep.c: Update copyright years. Include + alpha-tdep.h. + (alphafbsd_use_struct_convention): Make static. + (alphafbsd_init_abi): New function. + (_initialize_alphafbsd_tdep): New function. + * config/alpha/tm-fbsd.h: Update copyright years. + (USE_STRUCT_CONVENTION): Remove. + +2002-04-21 Jason Thorpe <thorpej@wasabisystems.com> + + * alpha-tdep.c (alpha_abi_handler): New structure to describe + an Alpha ABI variant. + (alpha_abi_handler_list): Declare. + (alpha_gdbarch_register_os_abi): New function. + (alpha_gdbarch_init): Give registered ABI variant handlers a + chance to tweak the gdbarch once we have set up defaults. + * alpha-tdep.h: Prototype alpha_gdbarch_register_os_abi. + +2002-04-21 Jason Thorpe <thorpej@wasabisystems.com> + + * alpha-tdep.c (alpha_gdbarch_init): Set coerce_float_to_double + to standard_coerce_float_to_double. + * config/alpha/tm-alpha.h (COERCE_FLOAT_TO_DOUBLE): Remove. + +2002-04-21 Jason Thorpe <thorpej@wasabisystems.com> + + * alpha-tdep.h (gdbarch_tdep): Add vm_min_address member. + * alpha-tdep.c (heuristic_proc_start): Use vm_min_address + from gdbarch_tdep rather than a constant. + (alpha_gdbarch_init): Initialize tdep->vm_min_address to + the default text address for all Alpha Unix ABIs. + (alpha_dump_tdep): Report the value of tdep->vm_min_address. + * config/alpha/tm-alpha.h (VM_MIN_ADDRESS): Delete. + +2002-04-21 Jason Thorpe <thorpej@wasabisystems.com> + + * alpha-tdep.h: New file. Includes several Alpha target constants + taken from... + * config/alpha/tm-alpha.h: ...here. Remove macros that we now + let gdbarch deal with. + (GDB_MULTI_ARCH): Define as GDB_MULTI_ARCH_PARTIAL. + * Makefile.in (alpha-nat.o): Add alpha-tdep.h and $(BFD_SRC)/elf-bfd + to dependency list. + * alpha-nat.c: Include alpha-tdep.h. Update for adjusted + Alpha target register names. + * alphabsd-nat.c: Likewise. + * alpha-tdep.c: Include alpha-tdep.h. Update for adjusted + Alpha target register names. Make serveral routines static. + (alpha_get_saved_register): New function. + (alpha_abi_names): New. + (process_note_abi_tag_sections): New function. + (get_elfosabi): New function. + (alpha_gdbarch_init): New function. + (alpha_dump_tdep): New function. + (_initialize_alpha_tdep): Register alpha_gdbarch_init. + +2002-04-21 Andrew Cagney <ac131313@redhat.com> + + * frame.c (find_saved_register): Delete #ifdef + HAVE_REGISTER_WINDOWS code. + * config/sparc/tm-sparc.h: Update comments. + * config/i960/tm-i960.h (HAVE_REGISTER_WINDOWS): Delete macro. + +2002-04-21 Andrew Cagney <ac131313@redhat.com> + + * i960-tdep.c (i960_find_saved_register): New function. + (i960_get_saved_register): New function. + * config/i960/tm-i960.h (GET_SAVED_REGISTER): Define. + (i960_get_saved_register): Declare. + * config/i960/tm-i960.h, i960-tdep.c: Update copyright. + +2002-04-20 David S. Miller <davem@redhat.com> + + * sparc-nat.c (store-inferior_registers): Fix ambiguous else. + +2002-04-20 Andrew Cagney <ac131313@redhat.com> + + * arm-tdep.c (arm_gdbarch_init): Use gdbarch_num_pseudo_regs + instead of NUM_PSEUDO_REGS. + +2002-04-20 David S. Miller <davem@redhat.com> + + * config/sparc/tm-linux.h (GDB_MULTI_ARCH): Define to + GDB_MULTI_ARCH_PARTIAL + * config/sparc/tm-sp64linux.h (GDB_MULTI_ARCH): Do not + define, let tm-sp64.h do it. + +2002-04-20 Jason Thorpe <thorpej@wasabisystems.com> + + * frame.c (find_saved_register): Avoid a NULL pointer + dereference and actually walk the frame list. + +2002-04-20 Andrew Cagney <ac131313@redhat.com> + + * gdbarch.sh (gdbarch_update_p): Keep the list of architectures + sorted in most most-recent-used order. Document. + * gdbarch.h, gdbarch.c: Regenerate. + +2002-04-19 Andrew Cagney <ac131313@redhat.com> + + * sparc-tdep.c (sparc_get_saved_register): Use get_prev_frame + instead of ->prev. + * z8k-tdep.c (z8k_frame_chain): Do not use ->prev. + * s390-tdep.c (s390_frame_chain): Do not use ->prev. + * rs6000-tdep.c (frame_get_saved_regs): Use rs6000_frame_chain() + instead of ->prev. + +2002-04-19 Elena Zannoni <ezannoni@redhat.com> + + Fix PR gdb/471. + * gdbtypes.c (init_simd_type): Rewrite using new functions. + (build_builtin_type_vec128): Ditto. + (append_composite_type_field): Fix calculation of type length in + union case. + +2002-04-19 Eli Zaretskii <eliz@is.elta.co.il> + + * config/djgpp/README: Update. + + * go32-nat.c (store_register): Cast &a_tss to `char *' to avoid a + compiler warnings. + +2002-04-19 Jason Thorpe <thorpej@wasabisystems.com> + + * alpha-tdep.c (setup_arbitrary_frame): Rename... + (alpha_setup_arbitrary_frame): ...to this. + * config/alpha/tm-alpha.h (SETUP_ARBITRARY_FRAME): Update + for alpha_setup_arbitrary_frame. + +2002-04-18 Andrew Cagney <cagney@redhat.com> + + * gdbarch.sh (BREAKPOINT_FROM_PC): Return a const buffer. + * gdbarch.h, gdbarch.c: Regenerate. + + * defs.h (breakpoint_from_pc_fn): Delete type definition. + * target.h (memory_breakpoint_from_pc): Update declaration. + * config/mcore/tm-mcore.h (mcore_breakpoint_from_p): Ditto. + + * arch-utils.c (legacy_breakpoint_from_pc): Update return type. + * mcore-tdep.c (mcore_breakpoint_from_pc): Ditto. + * mem-break.c (memory_breakpoint_from_pc): Ditto. + * rs6000-tdep.c (rs6000_breakpoint_from_pc): Ditto. + * s390-tdep.c (s390_breakpoint_from_pc): Ditto + * xstormy16-tdep.c (xstormy16_breakpoint_from_pc): Ditto. + * mn10300-tdep.c (mn10300_breakpoint_from_pc): Ditto. + * mips-tdep.c (mips_breakpoint_from_pc): Ditto. + * m68hc11-tdep.c (m68hc11_breakpoint_from_pc): Ditto. + * ia64-tdep.c (ia64_breakpoint_from_pc): Ditto. + * d10v-tdep.c (d10v_breakpoint_from_pc): Ditto. + * arch-utils.c (legacy_breakpoint_from_pc): Ditto.. + + * mem-break.c (default_memory_insert_breakpoint): Make `bp' a + const pointer. + * monitor.c (monitor_insert_breakpoint): Ditto. + * rs6000-tdep.c (rs6000_software_single_step): Ditto for `breakp'. + + * config/mcore/tm-mcore.h: Update copyright. + * mem-break.c: Ditto. + * xstormy16-tdep.c: Ditto. + +2002-04-18 Pierre Muller <muller@ics.u-strasbg.fr> + + * p-exp.y: Add precedence rule for '^' token. + This removes the shift/reduce conflicts. + Remove the comment concerning these shift/reduce conflicts. + +2002-04-18 Elena Zannoni <ezannoni@redhat.com> + + * rs6000-tdep.c (COMMON_UISA_NOFP_REGS): New macro. + (registers_powerpc_nofp): New register set for processors + without floating point unit. + +2002-04-18 David S. Miller <davem@redhat.com> + + * MAINTAINERS: Add myself to write-after-approval. + +2002-04-17 Michael Snyder <msnyder@redhat.com> + + * MAINTAINERS: Add myself as co-maintainer of testsuite/gdb.asm. + +2002-04-17 Andrew Cagney <ac131313@redhat.com> + + * rs6000-tdep.c (frame_initial_stack_address): Use + frame_register_read to read the alloca_reg. + +2002-04-17 Andrew Cagney <ac131313@redhat.com> + + * frame.c (find_saved_register): Find saved registers in the next + not prev frame. + Fix PR gdb/365. + +2002-04-17 Andrew Cagney <ac131313@redhat.com> + + * gdbarch.sh (LANG): Set to ``c''. + +2002-04-15 Andrew Cagney <ac131313@redhat.com> + + * PROBLEMS: Mention hppa2.0-hp-hpux10.20 compile problems. + +2002-04-15 Andrew Cagney <ac131313@redhat.com> + + * bcache.c: Include <stddef.h> and <stdlib.h> after "defs.h". + Update copyright. + + * hpread.c (hpread_get_lntt): Add declaration. + Also fix PR gdb/391. + +2002-04-14 Andrew Cagney <ac131313@redhat.com> + + * acinclude.m4 (AM_PROG_CC_STDC): Import from automake 1.6. + * aclocal.m4, configure: Re-generate. + Fix PR gdb/391. + +2002-04-14 Elena Zannoni <ezannoni@redhat.com> + + * mi/mi-cmd-disas.c (dump_insns): Use TARGET_PRINT_INSN + instead of tm_print_insn. + +2002-04-14 Elena Zannoni <ezannoni@redhat.com> + + * ppc-bdm.c (bdm_ppc_fetch_registers): Fix typo. + +2002-04-14 Andrew Cagney <ac131313@redhat.com> + + * config/pa/tm-hppa.h (FRAME_CHAIN_COMBINE): Delete macro. + * blockframe.c (FRAME_CHAIN_COMBINE): Delete macro. + (get_prev_frame): Do not call FRAME_CHAIN_COMBINE. + +2002-04-12 Don Howard <dhoward@redhat.com> + + * cli/cli-cmds.c (init_cli_cmds): Add new user settable value: + max_user_call_depth. + (init_cmd_lists): Initialize the new value; + * cli/cli-script.c (execute_user_command): Limit the call depth of + user defined commands. This avoids a core-dump when user commands + are infinitly recursive. + +2002-04-12 Kevin Buettner <kevinb@redhat.com> + + * ppc-tdep.h (struct gdbarch_tdep): Add new member ``lr_frame_offset''. + * rs6000-tdep.c (rs6000_frame_saved_pc): Use ``lr_frame_offset'' + from tdep struct instead of DEFAULT_LR_SAVE. + (rs6000_gdbarch_init): Initialize ``lr_frame_offset''. + * config/powerpc/tm-ppc-eabi.h (DEFAULT_LR_SAVE): Delete. + * config/rs6000/tm-rs6000.h (DEFAULT_LR_SAVE): Delete. + +2002-04-12 Michael Snyder <msnyder@redhat.com> + + * Remote.c: Spelling fix. + * gcore.c (default_derive_heap_segment): Use bfd_section_name. + If no symbol found for "sbrk", try "_sbrk". + (make_output_phdrs): Use bfd_section_name. + (gcore_copy_callback): Use bfd_section_name. + * eval.c: Indentation fix-ups. + * d10v-tdep.c (d10v_make_iaddr): Make it idempotent, + in case it gets applied to an address that is already + in the instruction space. + * cli/cli-decode.c (help_list): Allow long lines to wrap. + * symfile.c: Fix indentation, long lines. + * source.c: White space fix-up. + +2002-04-12 Andrew Cagney <cagney@redhat.com> + + * defs.h (read_relative_register_raw_bytes): Delete declaration. + * frame.c (frame_register_read): New function. Return non-zero on + success. + (read_relative_register_raw_bytes_for_frame): Delete. + (read_relative_register_raw_bytes): Delete. + * frame.h (frame_register_read): Declare. + * d30v-tdep.c: Update Copyright. Use frame_register_read. + * sh-tdep.c: Ditto. + * infcmd.c (do_registers_info): Ditto. + * hppa-tdep.c: Ditto. + * rs6000-tdep.c: Ditto. + * h8500-tdep.c: Ditto. + * mips-tdep.c: Ditto. + * h8300-tdep.c: Ditto. + * z8k-tdep.c: Ditto. + +2002-04-12 Kevin Buettner <kevinb@redhat.com> + + From Jimi X <jimix@watson.ibm.com>: + * rs6000-tdep.c (rs6000_gdbarch_init): Use rs6000_* methods for + 64-bit SysV ABI. + +2002-04-12 Kevin Buettner <kevinb@redhat.com> + + From Jimi X <jimix@watson.ibm.com>: + * rs6000-tdep.c (rs6000_gdbarch_init): Compute ``wordsize'' from + bfd info. + +2002-04-12 Kevin Buettner <kevinb@redhat.com> + + From Jimi X <jimix@watson.ibm.com>: + * rs6000-tdep.c (powerpc64, 630, rs64ii, rs64iii): Define + register sets for these processor variants. + +2002-04-11 Daniel Jacobowitz <drow@mvista.com> + + * regformats/reg-ppc.dat: Support FPSCR. + +2002-04-11 Kevin Buettner <kevinb@redhat.com> + + * ppc-tdep.h (struct gdbarch_tdep): Add new field ``ppc_fpscr_regnum''. + * ppc-bdm.c (bdm_ppc_fetch_registers, bdm_ppc_store_registers): + Add fpscr as an invalid/unfetchable register. + * ppc-linux-nat.c (ppc_register_u_addr, store_register) + (fetch_ppc_registers, store_ppc_registers, supply_fpregset) + (fill_fpregset): Add support for register fpscr. + (fetch_ppc_registers, store_ppc_registers, supply_gregset) + (fill_gregset): Account for the fact that register ``mq'' might + not exist. + * rs6000-tdep.c (PPC_UISA_SPRS): Use (unused) slot 70 for fpscr. + (registers_power): Add fpscr to register set at slot 71. + (rs6000_gdbarch_init): Account for the fact that ``mq'' doesn't + exist on most PPC architectures. Initialize ppc_fpscr_regnum. + +2002-04-11 Michael Snyder <msnyder@redhat.com> + + * configure.in: Autoconfiscate _SYSCALL32 define for solaris. + * configure: Regenerate. + * config.in: Regenerate. + * acconfig.h: Add define for _SYSCALL32. + * core-sol2.c: Remove #define _SYSCALL32. + * solib-legacy.c: Remove #define _SYSCALL32. + +2002-04-10 Andrew Cagney <ac131313@redhat.com> + + * stack.c (select_frame): Cleanup internal error message, do not + use %p. + +2002-04-10 Andrew Cagney <ac131313@redhat.com> + + * stack.c (select_frame): Check that selected_frame and the + specified level are as expected. + * blockframe.c (get_prev_frame): Set the `level' from next_frame. + Update copyright. + * frame.h (struct frame_info): Add field `level'. Update + copyright. + Work-in-progress PR gdb/464. + +2002-04-10 Andrew Cagney <ac131313@redhat.com> + + * maint.c (maint_print_section_info): Rename print_section_info. + (print_bfd_section_info, print_objfile_section_info): Update. + * inferior.h (struct gdbarch): Add opaque declaration. + * gdbarch.sh: Add include of "inferior.h" to gdbarch.sh. + * gdbarch.h: Regenerate. + +2002-04-10 Michal Ludvig <mludvig@suse.cz> + + * x86-64-linux-nat.c (child_resume, child_xfer_memory): Delete. + (PTRACE_XFER_TYPE): Moved to config/i386/nm-x86-64.h. + (kernel_u_size): Added. + * config/i386/nm-x86-64.h (CHILD_XFER_MEMORY, CHILD_RESUME): Delete. + (PTRACE_XFER_TYPE): Moved here from config/i386/nm-x86-64.h. + +2002-04-04 Jim Ingham <jingham@apple.com> + + * valarith.c (find_size_for_pointer_math): New function, either returns + the size for a pointer's target, returns 1 for void *, or errors for + incomplete types. + (value_add, value_sub): use find_size_for_pointer_math. + +2002-04-09 Daniel Jacobowitz <drow@mvista.com> + + * linux-low.c (linux_look_up_symbols): New hook. + (linux_target_ops): Add linux_look_up_symbols. + * remote-utils.c (decode_address): New function. + (look_up_one_symbol): New function. + * server.c (handle_query): Call target look_up_symbols hook. + * server.h (look_up_one_symbol): Add prototype. + * target.h (struct target_ops): Add look_up_symbols hook. + +2002-04-09 Andrew Cagney <ac131313@redhat.com> + + * frame.c (read_relative_register_raw_bytes_for_frame): Do not + override FP_REGNUM with frame->fp. Update copyright. + * parse.c (num_std_regs, std_regs): Delete. + (target_map_name_to_register): Do not search std_regs. Update + function description. + * parser-defs.h (num_std_regs, std_regs, struct std_regs): Delete + declarations. Update copyright. + Fix PR gdb/251. + +2002-04-09 Daniel Jacobowitz <drow@mvista.com> + + * symtab.h (ALL_BLOCK_SYMBOLS): Don't dereference the pointer + after the last symbol in a block. + +2002-04-09 Pierre Muller <muller@ics.u-strasbg.fr> + + * p-exp.y (yylex): Handle also the fact that is_a_field_of_this + is non zero as a found symbol. + +2002-04-08 Andrew Cagney <ac131313@redhat.com> + + * findvar.c: Include "builtin-regs.h". + (value_of_register): Call value_of_builtin_reg when applicable. + * parse.c: Include "builtin-regs.h" and "gdb_assert.h". + (target_map_name_to_register): Call + builtin_reg_map_name_to_regnum. + * Makefile.in (SFILES): Add builtin-regs.c and std-regs.c. + (COMMON_OBS): Add builtin-regs.o and std-regs.o. + (builtin_regs_h): Define. + (builtin-regs.o): New target. + (findvar.o): Add $(builtin_regs_h). + * builtin-regs.c, builtin-regs.h: New files. + * std-regs.c: New file. + Partial fix for PR gdb/251. + +2002-04-08 Kevin Buettner <kevinb@redhat.com> + + * rs6000-tdep.c (rs6000_gdbarch_init): Don't set tm_print_insn; + it's no longer required. + +2002-04-08 Andrew Cagney <ac131313@redhat.com> + + * Makefile.in (gdbtk-wrapper.o): Add missing dependencies. + +2002-04-08 Kevin Buettner <kevinb@redhat.com> + + From Jimi X <jimix@watson.ibm.com>: + * rs6000-tdep.c (rs6000_software_single_step): Use + rs6000_breakpoint_from_pc() to fetch breakpoint instruction + and size. Use target_insert_breakpoint() and + target_remove_breakpoint() to insert and remove breakpoints + instead of explicit memory reads and writes. + +2002-04-08 Kevin Buettner <kevinb@redhat.com> + + * config/powerpc/tm-ppc-eabi.h (ELF_OBJECT_FORMAT): Delete. + * rs6000-tdep.c (rs6000_push_arguments): Eliminate + ELF_OBJECT_FORMAT ifdef. + +2002-04-08 Kevin Buettner <kevinb@redhat.com> + + From Jimi X <jimix@watson.ibm.com>: + * rs6000-tdep.c (rs6000_gdbarch_init): Use set_gdbarch_print_insn(). + +2002-04-08 Kevin Buettner <kevinb@redhat.com> + + From Jimi X <jimix@watson.ibm.com>: + * rs6000-tdep.c (rs6000_fix_call_dummy): Delete unused macro + definitions for TOC_ADDR_OFFSET and TARGET_ADDR_OFFSET. + +2002-04-07 Mark Kettenis <kettenis@gnu.org> + + * fbsd-proc.c (child_pid_to_exec_file, fbsd_find_memory_regions): + s/asprintf/xasprintf/. + (fbsd_make_corefile_notes): s/strdup/xstrdup/. + +2002-04-07 Andrew Cagney <ac131313@redhat.com> + + I believe Jeff Law denies responsability for this one: + * config/pa/hpux11w.mh (MH_CFLAGS): Add -Dvfork=fork. + * config/pa/hpux11.mh (MH_CFLAGS): Add -Dvfork=fork. + * config/pa/hpux1020.mh (MH_CFLAGS): Add -Dvfork=fork. + Work-around for PR gdb/366. + +2002-04-07 Elena Zannoni <ezannoni@redhat.com> + + * remote-e7000.c (write_small, e7000_read_inferior_memory, + e7000_read_inferior_memory_large, e7000_insert_breakpoint, + e7000_remove_breakpoint): Use paddr_nz() to print addresses. + +2002-04-07 Elena Zannoni <ezannoni@redhat.com> + + * sh-tdep.c (sh_fp_frame_init_saved_regs, + sh_nofp_frame_init_saved_regs): Use alloca() for 'where' + information. + +2002-04-07 Andrew Cagney <ac131313@redhat.com> + + * MAINTAINERS (Misc): List Daniel Jacobowitz as the GDBSERVER + maintainer. + +2002-04-07 Andrew Cagney <ac131313@redhat.com> + + * README (Reporting Bugs in GDB): Document the bug web page as the + prefered way of submitting bugs. + Fix PR gdb/402. + +2002-04-06 Andrew Cagney <ac131313@redhat.com> + + * gdbarch.sh (FP_REGNUM, PC_REGNUM, SP_REGNUM): Allow default of + -1. Update comment. + * gdbarch.h, gdbarch.c: Re-generate. + +2002-04-07 Andreas Schwab <schwab@suse.de> + + * m68klinux-nat.c (fill_fpregset): Properly pass address of + buffer to regcache_collect. + +2002-04-06 Andrew Cagney <ac131313@redhat.com> + + * gdbarch.sh (PS_REGNUM): Add. Document. Default to -1. + * gdbarch.c, gdbarch.h: Re-generate. + +2002-04-06 Andrew Cagney <ac131313@redhat.com> + + * symtab.c (lookup_symtab): Remove ``const'' from ``rp'' + declaration. Fix -Werror. + +2002-04-05 Daniel Jacobowitz <drow@mvista.com> + + * gdbarch.sh (initialize_non_multiarch): Call init_gdbarch_swap. + * gdbarch.c: Regenerate. + +2002-04-05 Michael Snyder <msnyder@redhat.com> + + * breakpoint.c (clear_command): Rewrite middle section to + combine two loops with identical control conditions. + Add a cleanup to eliminate a memory leak. + * cli/cli-dump.c (restore_section_callback): Use paddr_nz. + +2002-04-05 H.J. Lu (hjl@gnu.org) + + * solib-svr4.c (bkpt_names): Add "__start". + +2002-04-04 Andrew Cagney <ac131313@redhat.com> + + * sparc-tdep.c (sparc_push_dummy_frame): Use GDB_TARGET_IS_SPARC64 + as test for 64 bit target. + +2002-04-05 Andrew Cagney <ac131313@redhat.com> + + * h8500-tdep.c (h8500_write_fp): Delete function. + * dwarf2cfi.c (cfi_write_fp): Document as not used. + * mips-tdep.c (mips_gdbarch_init): Do not set write_fp. + * ia64-tdep.c (ia64_gdbarch_init): Do not set write_fp. + * m68hc11-tdep.c (m68hc11_gdbarch_init): Do not set write_fp. + * rs6000-tdep.c (rs6000_gdbarch_init): Do not set write_fp. + * s390-tdep.c (s390_gdbarch_init): Do not set write_fp. + (s390_write_fp): + * sh-tdep.c (sh_gdbarch_init): Do not set write_fp. + * x86-64-tdep.c (i386_gdbarch_init): Do not set write_fp. + * d10v-tdep.c (d10v_gdbarch_init): Do not set write_fp. + (d10v_write_fp): Delete function. + * inferior.h (write_fp, generic_target_write_fp): Delete + declarations. + * regcache.c (generic_target_write_fp): Delete function. + (write_fp): Delete function. + * gdbarch.sh (TARGET_WRITE_FP): Delete. + * gdbarch.h, gdbarch.c: Regenerate. + * config/v850/tm-v850.h (TARGET_WRITE_FP): Delete macro. + * config/sparc/tm-sp64.h (TARGET_WRITE_FP): Delete macro. + (sparc64_write_fp): Delete declaration. + * config/h8500/tm-h8500.h (TARGET_WRITE_FP): Delete macro. + (h8500_write_fp): Delete declaration. + +2002-04-04 Andrew Cagney <ac131313@redhat.com> + + * sparc-tdep.c (sparc64_write_fp): Delete. + (sparc_push_dummy_frame): Replace write_fp call with code to store + the FP directly. + (sparc_gdbarch_init): Do not initialize write_fp. + +2002-04-05 Kevin Buettner <kevinb@redhat.com> + + * rs6000-tdep.c (skip_prologue): Eliminate unused/unreachable + clause. + +2002-03-29 Jim Blandy <jimb@redhat.com> + + * stack.c (get_selected_block): Add new argument `addr_in_block', + used to return the exact code address we used to select the block, + not just the block. + * blockframe.c (get_frame_block, get_current_block): Same. + * frame.h (get_frame_block, get_current_block, + get_selected_block): Update declarations. + * linespec.c, stack.c, blockframe.c, breakpoint.c, findvar.c, + linespec.c, varobj.c, printcmd.c, symtab.c: Callers changed. + +2002-04-05 Michael Snyder <msnyder@redhat.com> + + * breakpoint.c (insert_breakpoints): Change 'hw' to 'hardware in + warning message. + +2002-04-05 J. Brobecker <brobecker@gnat.com> + + * utils.c (xfullpath): New function. + * defs.h (xfullpath): Add declaration. + * source.c (openp): Use xfullpath in place of gdb_realpath to + avoid resolving the basename part of filenames when the + associated file is a symbolic link. This fixes a potential + inconsistency between the filenames known to GDB and the + filenames it prints in the annotations. + * symtab.c (lookup_symtab): Use the new xfullpath function, in order + to be able to match a filename with either the real filename, or + the name of any symbolic link to this file. + (lookup_partial_symtab): Ditto. + +2002-04-04 Michael Snyder <msnyder@redhat.com> + + * breakpoint.c: Add support for hardware breakpoints in overlays. + (overlay_events_enabled): New state variable. + (insert_breakpoints): Use overlay_events_enabled to decide + whether to attempt to set a breakpoint at the overlay load addr. + Handle bp_hardware_breakpoint as well as bp_breakpoint. + (remove_breakpoint): Use overlay_events_enabled to decide + whether breakpoints need to be removed from overlay load addr. + Handle bp_hardware_breakpoint as well as bp_breakpoint. + (bpstat_stop_status): Handle bp_hardware_breakpoint in overlays. + (create_overlay_event_breakpoint, enable_overlay_breakpoints, + disable_overlay_breakpoints): Update overlay_events_enabled. + +2002-04-04 Daniel Jacobowitz <drow@mvista.com> + + * dwarf2read.c (struct function_range): New. + (cu_first_fn, cu_last_fn, cu_cached_fn): New. + (check_cu_functions): New. + (read_file_scope): Initialize global function lists. + Call dwarf_decode_line after processing children. + (read_func_scope): Add to global function list. + (dwarf_decode_lines): Call check_cu_functions everywhere + record_line is called. Call record_line with a linenumber + of 0 to mark sequence ends. + +2002-04-04 Michal Ludvig <mludvig@suse.cz> + + * x86-64-linux-nat.c (child_xfer_memory): x86-64 ptrace() ABI + change sync with glibc. + +2002-04-03 Jim Blandy <jimb@redhat.com> + + * configure.in: Call AC_C_INLINE. + * configure: Regenerated. + +2002-04-01 Daniel Jacobowitz <drow@mvista.com> + + * rs6000-tdep.c: Change #include of "bfd/libcoff.h" + and "bfd/libbfd.h" to "libcoff.h" and "libbfd.h". + +2002-03-31 Mark Kettenis <kettenis@gnu.org> + + * NEWS: Mention gcore support on FreeBSD/i386. + + * fbsd-proc.c: New file. + * config/i386/nm-fbsd.h (CHILD_PID_TO_EXEC_FILE): Define. + * config/i386/fbsd.mh (NATDEPFILES): Add gcore.o and fbsd-proc.o. + + * lin-lwp.c (child_wait): Check SAVE_ERRNO instead of ERRNO in + while statement. + +2002-03-29 Jim Blandy <jimb@redhat.com> + + * cli/cli-dump.c (_initialize_cli_dump): Older GCC's tolerate + unescaped newlines in string literals, but newer ones don't. So + escape them. + +2002-03-26 Michael Snyder <msnyder@redhat.com> + Andrew Cagney <cagney@redhat.com> + + * cli/cli-dump.c: New file. Dump memory to file, + restore file to memory. + * cli/cli-dump.h: New file. + * Makefile.in: Add rules, dependencies for cli-dump.o. + * NEWS: Mention new commands. + +2002-03-28 Michael Snyder <msnyder@redhat.com> + + * symfile.c (symbol_file_add): Move test for null symbols to later. + +2002-03-27 Andrew Cagney <ac131313@redhat.com> + + From veksler at il.ibm.com: + * utils.c (gdb_realpath): If canonicalize_file_name fails, return + the xstrduped original path. + Fix PR gdb/417. + +2002-03-27 Michael Snyder <msnyder@redhat.com> + + * breakpoint.c (_initialize_breakpoint): Clean up help string. + * infcmd.c (_initialize_infcmd): Ditto. + * language.c (_initialize_language): Ditto. + * symfile.c (_initialize_symfile): Ditto. + * top.c (_init_main): Ditto. + * cli/cli-cmds.c (init_cli_cmds): Ditto. + +2002-03-27 Elena Zannoni <ezannoni@redhat.com> + + * rs6000-tdep.c (struct rs6000_framedata): Add fields for AltiVec + vector registers handling. + (skip_prologue): Handle new AltiVec instructions. Fill in new + fields of frame data. + (frame_get_saved_regs): Fill in information for AltiVec registers. + +2002-03-27 Jim Blandy <jimb@redhat.com> + + * symtab.h (SYMBOL_INIT_MANGLED_NAME): Turn this macro's body into + a function; leave this macro here to invoke that function. + (symbol_init_mangled_name): Declaration for that function. + * symtab.c (symbol_init_mangled_name): New function. + +2002-03-27 Andrew Cagney <ac131313@redhat.com> + + * valarith.c: Replace strerror with safe_strerror. + * tracepoint.c: Ditto. + * lin-lwp.c: Ditto. + * go32-nat.c: Ditto. + * inflow.c: Ditto. + * gnu-nat.c: Ditto. + +2002-03-27 Andreas Schwab <schwab@suse.de> + + * event-top.c (command_line_handler): Remove useless if. + +2002-03-27 Andreas Jaeger <aj@suse.de> + + * dwarf2cfi.c: Give credit to Daniel Berlin, reformat copyright + comment. + +2002-03-27 Michal Ludvig <mludvig@suse.cz> + + * x86-64-tdep.h (X86_64_NUM_REGS, X86_64_NUM_GREGS): Delete #defines. + (x86_64_num_regs, x86_64_num_gregs): Added extern variables. + * x86-64-linux-nat.c (x86_64_regmap): Swapped RBX <> RDX, added DS, ES, FS, GS. + (x86_64_linux_dr_get_status, supply_gregset), + (fill_gregset): Changed X86_64_NUM_GREGS to x86_64_num_gregs. + * x86-64-tdep.c (x86_64_register_raw_size_table): Delete. + (x86_64_register_info_table): Add. + (X86_64_NUM_REGS, X86_64_NUM_GREGS): Add. + (x86_64_register_raw_size, x86_64_register_virtual_type), + (x86_64_register_name, _initialize_x86_64_tdep): Changed to reflect new + general x86_64_register_info_table. + (i386_gdbarch_init): gdbarch_register_bytes is now set + dynamicaly during initialization. + * regformats/reg-x86-64.dat: Synced with changes to registers above. + * gdbserver/linux-x86-64-low.c: Ditto. + +2002-03-27 Daniel Jacobowitz <drow@mvista.com> + + * gdbserver/server.c (main): Call target_signal_to_host_p + and target_signal_to_host on signals received from the remote. + * gdbserver/remote-utils.c (prepare_resume_reply): Call + target_signal_from_host on signals sent to the remote. + * gdbserver/server.h: Add prototypes. Include "gdb/signals.h". + * gdbserver/Makefile.in: Add signals.o. Add -I${INCLUDE_DIR}. + +2002-03-27 Daniel Jacobowitz <drow@mvista.com> + + * signals/signals.c: Include "server.h" in gdbserver build. + (target_signal_from_name): Don't use STREQ. + (_initialize_signals): Likewise. Don't include function in + gdbserver build. + +2002-03-27 Daniel Jacobowitz <drow@mvista.com> + + * signals.c: Moved to... + * signals/signals.c: Here. + * Makefile (signals.o): Update. + +2002-03-26 Jeff Law (law@redhat.com) + + * somread.c (som_symtab_read): Remove some commented out code and + updated related comments. Do not set the minimal symbol table to + mst_solib_trampoline for ST_ENTRY symbols with SS_LOCAL scope + in a dynamic executable. + * hppa-tdep.c (find_proc_framesize): Sanely handle the case + where we are unable to find the minimal symbol for the given + PC value. + +2002-03-25 Jeff Law (law@redhat.com) + + * linux-proc.c (read_mapping): Scan up to end of line for filename. + +2002-03-25 Michal Ludvig <mludvig@suse.cz> + + * x86-64-tdep.c (x86_64_skip_prologue): Rewritten from scratch. + +2002-03-23 Andrew Cagney <ac131313@redhat.com> + + * command.h: Update copyright. + (struct cmd_list_element): Replace definition with opaque + declaration. + (enum cmd_types): Document that it will eventually be moved to + cli/cli-decode.h + (CMD_DEPRECATED, DEPRECATED_WARN_USER): Delete macros. + (MALLOCED_REPLACEMENT): Delete macro. + * Makefile.in (cli_decode_h): Add $(command_h). + (top.o, completer.o, maint.o): Add dependency on $(cli_decode_h). + * top.c: Include "cli/cli-decode.h". + * completer.c: Include "cli/cli-decode.h". + * maint.c: Include "cli/cli-decode.h". + * cli/cli-decode.h: Include "command.h". + (enum command_class): Delete. + (enum cmd_types): Comment out. + (enum cmd_auto_boolean): Delete. + (enum var_types): Delete. + +2002-03-23 Andrew Cagney <ac131313@redhat.com> + + * cli/cli-decode.c: Include "gdb_assert.h". + (add_set_or_show_cmd): New static function. + (add_set_cmd): Rewrite. Use add_set_or_show_cmd. + (add_show_from_set): Rewrite. Use add_set_or_show_cmd. Don't copy + all fields, such as func, from the set command. + +2002-03-23 Andrew Cagney <ac131313@redhat.com> + + * MAINTAINERS (sh-elf): Change warning flag to -w. + +2002-03-23 Andrew Cagney <cagney@redhat.com> + + * defs.h (error): Add printf format attribute. + * thread-db.c (thread_from_lwp): Fix error format string. + * stack.c (parse_frame_specification): Ditto. + * cli/cli-decode.c (undef_cmd_error): Ditto. + * scm-lang.c (scm_lookup_name): Ditto. + * tracepoint.c (trace_error): Ditto. + * remote-utils.c (usage): Ditto. + * remote.c (compare_sections_command): Ditto. + Fix PR gdb/328. + +2002-03-22 Andrew Cagney <ac131313@redhat.com> + + * gdbtypes.c (append_composite_type_field): New function. + (init_composite_type): New function. + * gdbtypes.h (append_composite_type_field): Declare. + (init_composite_type): Ditto. + +2002-03-22 Elena Zannoni <ezannoni@redhat.com> + + * ppc-linux-tdep.c (ppc_sysv_abi_use_struct_convention): New + function. + * ppc-tdep.h (ppc_sysv_abi_use_struct_convention): Export. + * rs6000-tdep.c (rs6000_gdbarch_init): Use different + structure returning convention for SYSV ABI case, but not + for GNU/Linux, FreeBSD, or NetBSD. + +2002-03-22 Daniel Jacobowitz <drow@mvista.com> + + * symtab.h (lookup_block_symbol): Add mangled_name argument + to prototype. + + * symmisc.c (maintenance_check_symtabs): Call lookup_block_symbol + with new mangled_name argument. + * linespec.c (decode_line_1): Likewise. + * valops (value_of_this): Likewise. + * symtab.c (lookup_transparent_type): Likewise. + (lookup_symbol_aux): Likewise. Accept new mangled_name argument. + (lookup_symbol): If we are given a mangled name, pass it down + to lookup_symbol_aux. + (lookup_block_symbol): If we are given a mangled name to check + against, only return symbols which match it. + +2002-03-22 Christopher Faylor <cgf@redhat.com> + + * win32-nat.c (child_create_inferior): Check for proper shell to use + here, in case the user changes it on the fly. + (_initialize_inftarg): Remove shell path considerations. + +2002-03-21 Elena Zannoni <ezannoni@redhat.com> + + * rs6000-tdep.c (rs6000_gdbarch_init): Use correct max size value + for gdbarch_max_register_raw_size and max_register_virtual_size. + Adjust copyright year. + +2002-03-21 Daniel Jacobowitz <drow@mvista.com> + + * dbxread.c (process_one_symbol): Extend the first N_SLINE + in a function to cover the entire beginning of the function + as well if it does not already. + +2002-03-21 Tom Rix <trix@redhat.com> + + * rs6000-nat.c (rs6000_ptrace32): Renamed from ptrace32. + (rs6000_ptrace64): Renamed from ptrace64. + +2002-03-20 Martin M. Hunt <hunt@redhat.com> + + * gdbserver/remote-utils.c (remote_open): Don't call + getprotobyname, we're all using TCP here so just use + IPPROTO_TCP. + * gdbserver/gdbreplay.c (remote_open): Ditto. + +2002-03-20 Martin M. Hunt <hunt@redhat.com> + + * regcache.c (_initialize_regcache): No need to call + build_regcache() at this time; it gets called whenever + the gdbarch changes. + +2002-03-20 David O'Brien <obrien@FreeBSD.org> + + * sparc-nat.c: Include sys/param.h where possible. + +2002-03-20 Daniel Jacobowitz <drow@mvista.com> + + Fix PR gdb/422. + * c-lang.c (c_create_fundamental_type): Handle FT_COMPLEX, + FT_DBL_PREC_COMPLEX, and FT_EXT_PREC_COMPLEX. + * dwarf2read.c (read_base_type): Set TYPE_TARGET_TYPE for + complex types. + * stabsread.c (rs6000_builtin_type): Likewise. + (read_sun_floating_type): Likewise. + +2002-03-19 Peter Schauer <pes@regent.e-technik.tu-muenchen.de> + + * stabsread.c (read_member_functions): Remove skip code for duplicate + constructor/destructor methods. Use standard parsing for these + methods and just do not chain them to the list of methods after + parsing. + +2002-03-19 Alexandre Oliva <aoliva@redhat.com> + + * coffread.c: Remove redundant static declarations. Replace + occurrences of `PTR' with `void *'. + * elfread.c, mdebugread.c, minsyms.c, mipsread.c: Likewise. + * top.h (quit_cover): Likewise. + * defs.h (catch_errors): Likewise. + +2002-03-18 Andrew Cagney <ac131313@redhat.com> + + * defs.h (XMALLOC): Define. + * gdb-events.sh (XMALLOC): Delete macro. + * gdb-events.c, gdb-events.h: Regenerate. + * gdbarch.sh (XMALLOC): Delete macro. + * gdbarch.c: Regenerate. + * serial.c (XMALLOC): Delete macro. + * ui-file.c (XMALLOC): Ditto. + * ser-unix.h (XMALLOC): Ditto. + * sh-tdep.c (XMALLOC): Ditto. + * ui-out.c (XMALLOC): Ditto. + * utils.c (XMALLOC): Ditto. + * i386-tdep.c (XMALLOC): Ditto. + * gdb-events.c (XMALLOC): Ditto. + * d10v-tdep.c (XMALLOC): Ditto. + * cli-out.c (XMALLOC): Ditto. + + * cli-out.c, d10v-tdep.c, gdb-events.c: Update copyright. + * gdb-events.sh, i386-tdep.c, ser-unix.h, serial.c: Ditto. + * ui-file.c, ui-out.c: Ditto. + +2002-03-18 Andrew Cagney <ac131313@redhat.com> + + * command.h (struct cmd_list_element): Add field context. + (set_cmd_context, get_cmd_context): Declare. + * cli/cli-decode.h: Ditto. + * cli/cli-decode.c (get_cmd_context): New function. + (set_cmd_context): New function. + (add_cmd): Initialize context. + Part of fixing PR gdb/145 and PR gdb/146. + +2002-03-17 Andrew Cagney <ac131313@redhat.com> + + * cli/cli-decode.c (cmd_type): New function. + * command.h (cmd_type): Declare. + * infrun.c (set_schedlock_func): Call function cmd_type. + * kod.c (kod_set_os): Call cmd_type. + * cris-tdep.c (cris_version_update): Use function cmd_type. + (cris_mode_update, cris_abi_update): Ditto. + + * command.h: (execute_cmd_post_hook): Declare. + (execute_cmd_pre_hook): Declare. + * cli/cli-script.c (clear_hook_in_cleanup): New function. + (execute_cmd_post_hook, execute_cmd_pre_hook): New + functions. Execute pre/post hook while ensuring that afterwords + hook_in is cleared. + * top.c (execute_command): Use execute_cmd_post_hook, and + execute_cmd_pre_hook to execute pre/post commands. + * infrun.c (normal_stop): Pass stop_command and not pre_hook to + hook_stop_stub. + (hook_stop_stub): Call execute_cmd_pre_hook. + +2002-03-17 Andrew Cagney <ac131313@redhat.com> + + * kod.c (kod_set_os): Revert previous change. Is called by ``info + set'' and this leads to a core dump. Move xstrdup of + operating_system to after check that it is not NULL. + +2002-03-17 Andrew Cagney <ac131313@redhat.com> + + * kod.c (kod_set_os): Remove unnecessary check that + ``command->type'' is set_cmd. + + * valprint.c (set_input_radix): Use input_radix. + (set_output_radix): Use output_radix. + (set_input_radix_1, set_output_radix_1): Add FIXME - bad radix + isn't reverted. + +2002-03-16 Andrew Cagney <ac131313@redhat.com> + + * value.h (struct value): Delete field ``substring_addr''. Change + aligner fields to force_doublest_align, force_longest_align, + force_core_addr_align and force_pointer_aligh. + + * value.h (struct value): Fix typo in above change. + +2002-03-16 Peter Schauer <pes@regent.e-technik.tu-muenchen.de> + + * ia64-tdep.c (ia64_gdbarch_init): Call set_gdbarch_frame_args_skip, + to fix internal_error from ``maintenance print architecture''. + +2002-03-16 Peter Schauer <pes@regent.e-technik.tu-muenchen.de> + + * cp-valprint.c (cp_is_vtbl_ptr_type): Handle vtbl field type + for gcc versions after gcc-2.8.1. + +2002-03-16 Peter Schauer <pes@regent.e-technik.tu-muenchen.de> + + * eval.c (evaluate_subexp_standard): Fix setup of ``this'' pointer + for method resolution. Restore adjustment of ``this'' pointer after + calling value_struct_elt, which was accidentally removed during the + HP merge. + +2002-03-15 Andrew Cagney <ac131313@redhat.com> + + * eval.c (evaluate_subexp_standard): Pass ``selected_frame'' to + value_of_register. + * findvar.c (value_of_register): Add ``frame'' parameter. Pass to + get_saved_register. + * value.h (value_of_register): Update. + +2002-03-14 Richard Henderson <rth@redhat.com> + + * configure.in: Detect declaration for canonicalize_file_name. + * utils.c (canonicalize_file_name): Declare, if needed. + (gdb_realpath): Prefer realpath if available and usable. + * config.in, configure: Rebuild. + +2002-03-14 Richard Henderson <rth@redhat.com> + + * dwarf2read.c (read_array_type): Accept DW_FORM_data8 as + a constant array bound. + + * MAINTAINERS: Add myself to write-after-approval. + +2002-03-14 Michael Snyder <msnyder@redhat.com> + + * symfile.c (syms_from_objfile): Return immediately if no syms. + (symbol_file_add): Return immediately if no syms. + (find_sym_fns): Return immediately if no syms. + +2002-03-13 Michal Ludvig <mludvig@suse.cz> + + * gdbserver/remote-util.c (remote_open): Print remote-side's + IP address when remote debugging over the network. + +2002-03-12 David O'Brien <obrien@FreeBSD.org> + + * config/sparc/fbsd.mh: Fix copyright. + * config/sparc/fbsd.mt: Likewise. + +2002-03-11 Richard Earnshaw <rearnsha@arm.com> + + * MAINTAINERS: Fix typo in name of gdb warnings option. + (x86-64): Fix formating so that this can be parsed by awk. + +2002-03-10 Daniel Jacobowitz <drow@mvista.com> + + * Makefile.in (defs_h): Add $(INCLUDE_DIR)/gdb/signals.h. + * defs.h: Include "gdb/signals.h". + (enum target_signal): Move to $(INCLUDE_DIR)/gdb/signals.h. + +2002-03-10 Michal Ludvig <mludvig@suse.cz> + + * x86-64-tdep.h (sys/reg.h, x86_64_regmap): Moved to x86-64-linux-nat.c + * x86-64-linux-nat.c (sys/reg.h, x86_64_regmap): Moved here + from x86-64-tdep.h + +2002-03-10 Daniel Jacobowitz <drow@mvista.com> + Don Howard <dhoward@redhat.com> + + * mips-tdep.c (ST0_FR): Define. + (mips2_fp_compat): New function, temporarily disabled. + (mips_read_fp_register_single): New function. + (mips_read_fp_register_double): New function. + (mips_print_register): Use them. + (do_fp_register_row): Likewise. + +2002-03-09 Andrew Cagney <ac131313@redhat.com> + + * MAINTAINERS: Add Jim Ingham and Klee Dienes to ``write after + approval''. + +2002-03-08 Peter Schauer <pes@regent.e-technik.tu-muenchen.de> + + * stabsread.c (read_member_functions): Fix is_stub test for + static member functions, improve comment. + +2002-03-07 Richard Earnshaw <rearnsha@arm.com> + + * remote-rdi.c (myprint): Replace 'PTR' with 'void *'. + (mywrite, mywritec, mypause, myreadc, mygets): Likewise. + (_initialize_remote_rdi): Use add_set_boolean_cmd to register + commands that set boolean values. + (arm_rdi_remove_breakpoint): Rewrite to avoid uninitialized warning. + (arm_rdi_resume): Always initialize PC. + (arm_rdi_open): Don't use rslt as a boolean. + (arm_rdi_create_inferior, arm_rdi_close, arm_rdi_resume) + (arm_rdi_fetch_registers, arm_rdi_store_registers) + (arm_rdi_xfer_memory, arm_rdi_files_info, arm_rdi_kill) + (arm_rdi_insert_breakpoint, arm_rdi_remove_breakpoint): Likewise. + +2002-03-06 Alexandre Oliva <aoliva@redhat.com> + + * configure.in (gdb_cv_bigtoc): Check for -bbigtoc on AIX. + * configure: Rebuilt. + +2002-03-06 Stephane Carrez <Stephane.Carrez@worldnet.fr> + + * m68hc11-tdep.c (_initialize_m68hc11_tdep): Don't set tm_print_insn. + (m68hc11_gdbarch_init): But use set_gdbarch_print_insn instead. + +2002-03-06 Andrew Cagney <ac131313@redhat.com> + + * cli/cli-decode.c (set_cmd_completer): New function. + * command.h (set_cmd_completer): Declare. + * cli/cli-decode.h (set_cmd_completer): Ditto. + + * breakpoint.c (_initialize_breakpoint): Use set_cmd_completer. + * cli/cli-cmds.c (init_cli_cmds): Ditto. + * win32-nat.c (_initialize_inftarg): Ditto. + * remote-rdi.c (_initialize_remote_rdi): Ditto. + * proc-api.c (_initialize_proc_api): Ditto. + * hppa-tdep.c (_initialize_hppa_tdep): Ditto. + * source.c (_initialize_source): Ditto. + * exec.c (_initialize_exec): Ditto. + * solib.c (_initialize_solib): Ditto. + * top.c (init_main): Ditto. + * tracepoint.c (_initialize_tracepoint): Ditto. + * symfile.c (_initialize_symfile): Ditto. + * printcmd.c (_initialize_printcmd): Ditto. + * infcmd.c (_initialize_infcmd): Ditto. + * corefile.c (_initialize_core): Ditto. + +2002-03-05 Andrew Cagney <ac131313@redhat.com> + + * MAINTAINERS (Past Maintainers): Add Frank Ch. Eigler. + +2002-03-05 Andrew Cagney <ac131313@redhat.com> + + * MAINTAINERS: Fix Mac OS X and Objective-C/C++. + +2002-03-05 Andrew Cagney <ac131313@redhat.com> + + * NEWS: Update headings, 5.2 has branched. + +2002-03-04 Daniel Jacobowitz <drow@mvista.com> + + * gdbserver/linux-low.c (PTRACE_XFER_TYPE): Change to long. + (num_regs, regmap): Move inside HAVE_LINUX_USRREGS. + (register_addr, REGISTER_RAW_SIZE): Likewise. + (usr_store_inferior_registers): Use PTRACE_XFER_TYPE. + * gdbserver/linux-x86-64-low.c: Remove extra #endif. + +2002-03-03 Michal Ludvig <mludvig@suse.cz> + + * MAINTAINERS (x86-64): Add myself. + * x86-64-tdep.c (x86_64_push_arguments): Fixed typo naregs->nregs, + changed value_ptr -> struct value * + +2002-03-01 David O'Brien <obrien@FreeBSD.org> + + * configure.host (sparc64-*-freebsd): Add. + * configure.tgt: Likewise. + * config/sparc/fbsd.mh: New file. + * config/sparc/fbsd.mt: Likewise. + * config/sparc/nm-fbsd.h: Likewise. + * config/sparc/tm-fbsd.h: Likewise. + +2002-03-01 Daniel Jacobowitz <drow@mvista.com> + + * config/djgpp/fnchange.lst: Add regformats/reg-i386-linux.dat and + regformats/reg-s390x.dat. + +2002-03-01 Andrew Cagney <ac131313@redhat.com> + + * utils.c: Add FIXME explaining true/false problem. + +2002-02-28 Andrew Cagney <ac131313@redhat.com> + + * MAINTAINERS (Past Maintainers): Add J.T. Conklin. + +2002-02-28 Michael Chastain <mec@shout.net> + + * MAINTAINERS: Fix typo: gdb.satbs -> gdb.stabs . + +2002-02-28 Daniel Jacobowitz <drow@mvista.com> + + * gdbserver/linux-s390-low.c: New file. + * regformats/reg-s390.dat: New file. + * regformats/reg-s390x.dat: New file. + * gdbserver/configure.srv: Add S/390. + * gdbserver/Makefile.in: Add S/390. + * configure.tgt: Enable gdbserver for S/390. + +2002-02-28 Eli Zaretskii <eliz@is.elta.co.il> + + * go32-nat.c (_initialize_go32_nat): Don't use periods in the + first line of the doc string for "info dos", except at the end of + the sentence, since the short help stops at the first period. + +2002-02-28 Jason Merrill <jason@redhat.com> + + * dwarf2read.c (dwarf_cfi_name): Add new codes. + +2002-02-27 Fred Fish <fnf@redhat.com> + + * blockframe.c (generic_fix_call_dummy): Fix obvious typo in + comment (dumy -> dummy). + +2002-02-27 Peter Schauer <pes@regent.e-technik.tu-muenchen.de> + + * symtab.c (gdb_mangle_name): Handle fully mangled v3 abi physnames. + +2002-02-27 Rodney Brown <rbrown64@csc.com.au> + + * utils.c (gdb_realpath): Add pathconf fallback for sco3.2v5. + +2002-02-27 Daniel Jacobowitz <drow@mvista.com> + + * gdbserver/acconfig.h: New file. + * gdbserver/i387-fp.c: New file. + * gdbserver/i387-fp.h: New file. + * gdbserver/linux-x86-64.c: New file. + * regformats/reg-x86-64.dat: New file. + * configure.tgt: Add x86_64-*-linux* gdbserver support. + * gdbserver/configure.srv: Add x86_64-*-linux* and regset support. + * gdbserver/configure.in: Add support for regsets. + * gdbserver/config.in: Regenerate. + * gdbserver/configure: Regenerate. + * gdbserver/Makefile.in: Likewise. Add $(linux_low_h). + * gdbserver/linux-low.h: New file. + * gdbserver/linux-low.c: Include "linux-low.h". Add support + for regsets. + * gdbserver/linux-arm-low.c: Include "linux-low.h". + * gdbserver/linux-ia64-low.c: Include "linux-low.h". + * gdbserver/linux-m68k-low.c: Include "linux-low.h". + * gdbserver/linux-mips-low.c: Include "linux-low.h". + * gdbserver/linux-ppc-low.c: Include "linux-low.h". + * gdbserver/linux-sh-low.c: Include "linux-low.h". + * gdbserver/linux-i386-low.c: Include "linux-low.h". Include + "i387-fp.h". Add PTRACE_GETREGS and friends. + * gdbserver/regcache.c (supply_register): New function. + (supply_register_by_name): New function. + (collect_register): New function. + (collect_register_by_name): New function. + +2002-02-27 Daniel Jacobowitz <drow@mvista.com> + + * gdbserver/Makefile.in (INTERNAL_CFLAGS): Remove -DGDBSERVER. + (config.status): Add configure.srv dependency. + (server_h): Add config.h dependency. + +2002-02-27 Daniel Jacobowitz <drow@mvista.com> + + * regformats/reg-i386-linux.dat: New file, with $orig_eax. + * gdbserver/Makefile.in: Add rules for reg-i386-linux.o. + * gdbserver/configure.srv: Change i386-*-linux* to use + reg-i386-linux.o. + +2002-02-26 Andrew Cagney <ac131313@redhat.com> + + * x86-64-tdep.c: Re-indent. Update copyright date. + +2002-02-26 Andrew Cagney <ac131313@redhat.com> + + From Michal Ludvig <mludvig@suse.cz>: + * x86-64-tdep.c (value.h): Delete. + (gdb_assert.h): Include. + (x86_64_register_convert_to_virtual, + x86_64_register_convert_to_raw ): Add check which lets only + floating-point values to be converted. + (value_push): Delete. + (x86_64_push_arguments): Order of arguments pushed on stack fixed. + (i386_gdbarch_init): Number of register_bytes fixed. + +2002-02-26 Andrew Cagney <ac131313@redhat.com> + + * MAINTAINERS: Add x86-64 target. + +2002-02-26 Andrew Cagney <ac131313@redhat.com> + + * memattr.c (mem_command): Eliminate ``true'' and ``false''. + * osfsolib.c (solib_map_sections): Ditto. + * irix5-nat.c (solib_map_sections): Ditto. + * corelow.c (gdb_check_format): Ditto. + * symfile.c (symfile_bfd_open): Ditto. + * solib.c (solib_map_sections): Ditto. + Fix PR gdb/354. + +2002-02-26 Andrew Cagney <ac131313@redhat.com> + + * remote.c (_initialize_remote): By default, disable ``e'' and + ``E'' step out-of-range packets. + +2002-02-26 Andreas Schwab <schwab@suse.de> + + * config/m68k/tm-linux.h (FRAME_SAVED_PC): Define as + m68k_linux_frame_saved_pc. + (IN_SIGTRAMP): Define as m68k_linux_in_sigtramp instead of + in_sigtramp. + (SIGCONTEXT_PC_OFFSET): Remove. + * m68klinux-nat.c (m68k_linux_frame_saved_pc, + m68k_linux_sigtramp_saved_pc): New functions. + (IS_SIGTRAMP, IS_RT_SIGTRAMP): Define. + (SIGCONTEXT_PC_OFFSET): Moved here from config/m68k/tm-linux.h. + (UCONTEXT_PC_OFFSET): Define. + (m68k_linux_in_sigtramp): Renamed from in_sigtramp, handle both + non-RT and RT signal trampolines. + +2002-02-26 Richard Earnshaw <rearnsha@arm.com> + + * config/arm/tm-embed.h (TARGET_UPAGES): Delete. + (TARGET_NBPG, STACK_END_ADDR): Delete + (VARIABLES_INSIDE_BLOCK): Delete. + +2002-02-25 Andrew Cagney <ac131313@redhat.com> + + * utils.c (perror_with_name): Make string parameter constant. + (print_sys_errmsg): Ditto. + (query): Ditto. + * defs.h (perror_with_name): Update. + (print_sys_errmsg): Update. + (query): Update. + +2002-02-25 Daniel Jacobowitz <drow@mvista.com> + + From Eliot Dresselhaus <eliot@ayrnetworks.com>: + * gdbserver/linux-mips-low.c (cannot_fetch_register): Fix typo. + +2002-02-25 Peter Schauer <pes@regent.e-technik.tu-muenchen.de> + + * rs6000-nat.c (set_host_arch): Do not switch to a new architecture + if it already matches the current architecture from the exec file. + Include arch-utils.h for gdbarch_info_init prototype. + * Makefile.in (rs6000-nat.o): Update dependencies. + +2002-02-25 Eli Zaretskii <eliz@is.elta.co.il> + + * config/djgpp/djconfig.sh: Set NM=nm and CFLAGS="-g -O2" in the + list of exported variables. + +2002-02-24 Daniel Jacobowitz <drow@mvista.com> + + * gdbserver/configure.srv: New file. + * gdbserver/configure.in: Use configure.srv instead + of the host/target makefile fragments. Set GDBSERVER_DEPFILES + from it. + * gdbserver/configure: Regenerated. + * gdbserver/terminal.h: New file. + * gdbserver/Makefile.in: Update for configure changes. Remove + more unneeded include paths. + +2002-02-24 Andrew Cagney <ac131313@redhat.com> + + From wiz at danbala: + * config/sparc/tm-sp64.h: Fix grammar and typos. + Fix PR gdb/287. + +2002-02-24 Andrew Cagney <ac131313@redhat.com> + + * lin-lwp.c, thread-db.c, defs.h, cris-tdep.c: Replace ``Linux'' + with either ``GNU/Linux'' or ``Linux kernel''. Update copyright. + * m68klinux-nat.c, sparc-linux-nat.c, x86-64-linux-nat.c: Ditto. + * x86-64-linux-tdep.c, gregset.h, gdb_wait.h: Ditto. + * ia64-linux-nat.c, infrun.c, linux-proc.c: Ditto. + * proc-service.c, i386-linux-tdep.c, ppc-linux-tdep.c: Ditto. + * s390-tdep.c: Ditto. + * config/nm-linux.h, config/alpha/nm-linux.h: Ditto. + * config/alpha/tm-alpha.h, config/alpha/tm-alphalinux.h: + * config/alpha/xm-alphalinux.h, config/i386/nm-linux.h: Ditto. + * config/i386/nm-x86-64.h, config/i386/tm-linux.h: Ditto. + * config/m68k/tm-linux.h, config/mips/nm-linux.h: Ditto. + * config/mips/tm-linux.h, config/mips/xm-linux.h: Ditto. + * config/powerpc/tm-linux.h, config/s390/nm-linux.h: Ditto. + * config/s390/tm-linux.h, config/sh/tm-linux.h: Ditto. + * config/sparc/nm-linux.h, config/sparc/tm-linux.h: Ditto. + * config/sparc/tm-sp64linux.h, config/sparc/xm-linux.h: Ditto. + Fix PR gdb/378. + +2002-02-23 Andrew Cagney <ac131313@redhat.com> + + * lin-thread.c: Delete file. + * configure.in (gdb_cv_struct_reg_r_gs): Update comment to refer + to gdb_proc_service.h. + * configure: Re-generate. + + * ocd.c (ocd_open): Do not try to open the "ocd" device. + * serial.c (serial_open): Delete check for "ocd". + Fix PR gdb/349. + + * Makefile.in (linux-thread.o): Delete target. + * linux-thread.c: Delete file. + + * config/djgpp/fnchange.lst: Rename bfd/elf32-sh64.c. Tweak other + renamed SH files to be consistent. + + * symtab.c (sort_search_symbols): Use xfree. + +2002-02-23 Richard Earnshaw <rearnsha@arm.com> + + * arm-linux-tdep.c (arm_linux_init_abi): Register + IN_SOLIB_CALL_TRAMPOLINE and SKIP_TRAMPOLINE_CODE + * config/arm/tm-linux.h (IN_SOLIB_CALL_TRAMPOLINE): Replace old + definition with undef, since we don't want the sysvr4 definition. + (SKIP_TRAMPOLINE_CODE): Likewise. + +2002-02-23 Andrew Cagney <ac131313@redhat.com> + + From 2002-02-22 Alfred M. Szmidt <ams@kemisten.nu>: + + * configure.in: (AC_CHECK_FUNCS) Added test for + canonicalize_file_name Regenerated. + * config.in, configure: Regenerated. + * utils.c: (gdb_realpath) If HAVE_CANONICALIZE_FILE_NAME is + defined use canonicalize_file_name. + +2002-02-23 Michael Chastain <mec@shout.net> + + * MAINTAINERS: Remove Michael Chastain from "paper trail" list. + +2002-02-23 Andrew Cagney <ac131313@redhat.com> + + * README: Remove references to cygnus.com. + * MAINTAINERS: Change Past Maintainer addresses to ``foo at bar + dot com'' form. Remove references to cygnus.com and sourceware. + +2002-02-23 Andrew Cagney <ac131313@redhat.com> + + From 2002-02-19 Paul Eggert <eggert@twinsun.com>: + * Makefile.in (VER): Change "head -1" to "sed q", since POSIX + 1003.1-2001 no longer allows "head -1". + * gdb/Makefile.in (version.c): Likewise. + * gdb/doc/Makefile.in (GDBvn.texi): Likewise. + * gdb/CONTRIBUTE: Change "diff -c3" to "diff -c", which is + equivalent. POSIX 1003.1-2001 no longer allows "diff -c3". + +2002-02-23 Andrew Cagney <ac131313@redhat.com> + + * cli/cli-decode.c (cmd_cfunc_eq): New function. + * command.h (cmd_cfunc_eq): Declare. + * cli/cli-decode.h (cmd_cfunc_eq): Ditto. + + * cli/cli-cmds.h (is_complete_command): Change parameter to a + ``struct cmd_list_element *''. + * cli/cli-cmds.c (is_complete_command): Update. Use + cmd_cfunc_eq. + * top.c (execute_command): Pass the command to + is_complete_command. + * tracepoint.c: Replace function.cfunc with cmd_cfunc_eq. + +2002-02-23 Andrew Cagney <ac131313@redhat.com> + + From 2002-02-20 Martin Schwidefsky <schwidefsky@de.ibm.com>: + * config/s390/tm-s390.h (GDB_TARGET_IS_ESAME): Use renamed + architecture defines. + * s390-tdep.c (s390_gdbarch_init): Likewise. + +2002-02-23 Richard Earnshaw <rearnsha@arm.com> + + * arm-linux-tdep.c (arm_linux_extract_return_value): Make static. + (arm_linux_push_arguments): Likewise. + (arm_linux_init_abi): Register them. Also register linux-specific + call_dummy_words. + (find_minsym_and_objfile): Use strcmp, not STREQ. + * config/arm/tm-linux.h (CALL_DUMMY_WORDS): Delete. + (arm_linux_call_dummy_words): Delete declaration. + (EXTRACT_RETURN_VALUE, PUSH_ARGUMENTS): Delete. + (arm_linux_extract_return_value, arm_linux_push_arguments): Delete + declarations. + (LOWEST_PC): Delete. + +2002-02-23 Peter Schauer <pes@regent.e-technik.tu-muenchen.de> + + * maint.c (print_section_info): Do not prepend `0x' to filepos + output, it will be handled by local_hex_string_custom. + +2002-02-23 Richard Earnshaw <rearnsha@arm.com> + + * arm-linux-nat.c (store_newfpe_single): Use regcache_collect. + (store_newfpe_double, store_newfpe_extended, store_fpregister) + (store_register, store_regs, fill_gregset, fill_fpregset): Likewise. + +2002-02-22 Jim Blandy <jimb@redhat.com> + + Indicate that the bcache functions don't change the strings + they're passed. + * bcache.h (bcache, hash): Add `const' keywords to declarations. + * bcache.c (bcache, hash): Add `const' keywords to definitions. + +2002-02-22 Pierre Muller <muller@ics.u-strasbg.fr> + + * win32-nat.c (child_create_inferior): Fix create flags setting bug. + +2002-02-21 Christopher Faylor <cgf@redhat.com> + + * win32-nat.c (register_loaded_dll): Just use raw name when we can't + find the complete path to a loaded DLL. + +2002-02-21 Fred Fish <fnf@redhat.com> + + * dbxread.c (process_one_symbol): When finding an N_FUN symbol + that marks the end of the range of a function, enter a line number + entry that has a line number of zero and a PC offset that matches + the end of the function. This starts a range of PC's for which no + line number information is known. + * symtab.c (find_pc_sect_line): If our best fit is in a range of + PC's for which no line number info is found (line number is zero) + then we didn't find any valid line information. + * symtab.h: Document use of zero line number entry. + +2002-02-21 Elena Zannoni <ezannoni@redhat.com> + + * ppc-linux-nat.c (PTRACE_GETVRREGS, PTRACE_SETVRREGS): Define. + (have_ptrace_getvrregs): Define for run time checks. + (gdb_vrregset_t): New type for Altivec register handling. + (fetch_register, store_register): Fetch/store altivec register + when needed. + (fetch_altivec_register, store_altivec_register): New functions. + (supply_vrregset, fill_vrregset): New functions. + (fetch_altivec_registers, store_altivec_registers): New functions. + (fetch_ppc_registers, store_ppc_registers): Fetch/store altivec + registers as well. + +2002-02-21 Jiri Smid <smid@suse.cz> + + * config/i386/x86-64linux.mh (NATDEPFILES): Remove x86-64-nat.o. + +2002-02-21 Richard Earnshaw <rearnsha@arm.com> + + * Makefile.in (armnbsd-nat.o): Update dependencies. + * armnbsd-nat.c (supply_gregset): New function. Common code to + supply the integer register set. + (supply_fparegset): New function. Similar for FPA registers. + (fetch_regs, fetch_fp_regs): Use them. + (fetch_core_registers): Likewise. + (fetch_elfcore_registers): New function. + (arm_netbsd_elfcore_fns): New core-file type specification. + (_initialize_arm_netbsd_nat): Register it. + +2002-02-21 Richard Earnshaw <rearnsha@arm.com> + + * armnbsd-nat.c: Include gdbcore.h. + (FETCH_INFERIOR_REGISTERS): Just error if this isn't defined. + (fetch_regs, fetch_fp_regs, store_regs, store_fp_regs): Add explicit + 'void' to declaration, to shut up ARI. + (fetch_core_registers): Make static. Rewrite using supply_register. + (arm_netbsd_core_fns): New core-file type specification. + (_initialize_arm_netbsd_nat): New function. + +2002-02-21 Christopher Faylor <cgf@redhat.com> + + * win32-nat.c (register_loaded_dll): Correctly check for invalid handle + value. + +2002-02-20 Christopher Faylor <cgf@redhat.com> + + * win32-nat.c (register_loaded_dll): Handle case where FindFirstFile + fails. + +2002-02-20 Daniel Jacobowitz <drow@mvista.com> + + * jv-exp.y (parse_number): Change type of implicit longs + to builtin_type_uint64. + +2002-02-20 Daniel Jacobowitz <drow@mvista.com> + + * gdbserver/linux-low.c (mywait): Change argument to waitpid + to be an integer instead of a `union wait'. + +2002-02-20 Daniel Jacobowitz <drow@mvista.com> + + * mips-linux-nat.c: Call the operating system GNU/Linux. + * mips-linux-tdep.c: Likewise. + * mips-tdep.c: Likewise. + +2002-02-20 Daniel Jacobowitz <drow@mvista.com> + + Fix PR gdb/265. + * jv-exp.y (parse_number): Handle 64-bit integers. + +2002-02-20 Daniel Jacobowitz <drow@mvista.com> + + * gdbserver/configure.in: Remove AM_PROC_CC_STDC. Change + AC_STDC_HEADERS to AC_HEADER_STDC. + * gdbserver/configure: Regenerated. + +2002-02-20 Richard Earnshaw <rearnsha@arm.com> + + * arc-tdep.c (get_longjmp_target): Only compile this function if JB_PC + is defined. + * sparc-tdep.c (get_longjmp_target): Likewise. + +2002-02-20 Richard Earnshaw <rearnsha@arm.com> + + * News: Add news about ARM and Multi-arch. Mention the new target + arm*-*-netbsd*. + +2002-02-19 Jim Blandy <jimb@redhat.com> + + * stabsread.c (error_type_complaint): Improve error message. + +2002-02-19 Daniel Jacobowitz <drow@mvista.com> + + * gdbserver/README: Update documentation. + * gdbserver/configure.in: Update configury to match documentation. + * gdbserver/Makefile.in: Likewise. + * gdbserver/configure: Regenerated. + * gdbserver/aclocal.m4: New file, generated by aclocal. + * gdbserver/config.in: New file, generated by autoheader. + +2002-02-19 Richard Earnshaw <rearnsha@arm.com> + + * config/djgpp/fnchange.lst: Add change rules for armnbsd-tdep.c and + armnbsd-nat.c. + +2002-02-19 Richard Earnshaw <rearnsha@arm.com> + + * arm-tdep.h (enum arm_float_model): New enum. + (struct gdbarch_tdep): Add fp_model. + * arm-tdep.c (arm_gdbarch_init): Set fp_model in tdep. Defer setting + up floating-point conversions until we know the floating-point model + in use by the inferior. Don't complain about being unable to + determine the ABI of the inferior when we don't have one. + (arm_extract_return_value): Support different floating-point models. + (arm_store_return_value): Likewise. + * armnbsd-tdep.c (arm_netbsd_aout_init_abi): Set fp_model in tdep to + ARM_FLOAT_SOFT. + (arm_netbsd_elf_init_abi): Set fp_model to ARM_FLOAT_SOFT_VFP. + +2002-02-19 Peter Schauer <pes@regent.e-technik.tu-muenchen.de> + + * i386-tdep.c (i386_gdbarch_init): Eliminate incorrect use + of ``current_gdbarch''. + +2002-02-19 Richard Earnshaw <rearnsha@arm.com> + + * armnbsd-nat.c : ANSIfy all function declarations. + (fetch_register, fetch_regs, fetch_fp_register, fetch_fp_regs): New. + (fetch_inferior_registers): Re-implement in terms of above. + (store_register, store_regs, store_fp_register, store_fp_regs): New. + (store_inferior_registers): Re-implement in terms of above. + +2002-02-19 Richard Earnshaw <rearnsha@arm.com> + + * arm-linux-nat.c: Linux -> GNU/Linux when not talking about the + kernel. + * arm-linux-tdep.c: Likewise. + * config/arm/tm-linux.h: Likewise. + +2002-02-19 Richard Earnshaw <rearnsha@arm.com> + + * configure.tgt (arm*-*-netbsd*): This variant is now fully multi-arch. + * config/arm/nbsd.mt (TM_FILE): Delete. + * config/arm/tm-nbsd.h: Delete. + +2002-02-19 Richard Earnshaw <rearnsha@arm.com> + + * arm-tdep.c (arm_gdbarch_init): Initialize TARGET_CHAR_SIGNED. + Initialize CALL_DUMMY_LENGTH. + +2002-02-19 Richard Earnshaw <rearnsha@arm.com> + + * armnbsd-tdep.c (arm_netbsd_aout_in_solib_call_trampoline): New + function. + (arm_netbsd_aout_init_abi): Initialize IN_SOLIB_CALL_TRAMPOLINE. + * config/arm/tm-nbsd.h: Don't include config/tm-nbsd.h, it only + defines one thing and that is incorrect for this port. + (IN_SOLIB_CALL_TRAMPOLINE): Delete. + +2002-02-18 Pierre Muller <muller@ics.u-strasbg.fr> + + * go32-nat.c: add i386-tdep.h include to import FP_REGNUM_P macro. + +2002-02-18 Pierre Muller <muller@ics.u-strasbg.fr> + + * win32-nat.c (display_selector): New function. Displays information + about the information returned by GetThreadSelectorEntry API function. + (display_selectors): New function. Displays the infomation of + the selector given as argument, or of CS, DS ans FS selectors + if no argument is given. + ( _initialize_inftarg): Add "w32" as info prefix command. + Add "info w32 selector" as command calling display_selectors. + +2002-02-19 Pierre Muller <muller@ics.u-strasbg.fr> + + * i386-tdep.c (get_longjmp_target): Fix compilation failure + by setting dummy values to JB_PC and JB_ELEMENT_SIZE + if not defined. + +2002-02-18 Richard Earnshaw <rearnsha@arm.com> + + * config/arm/nbsd.mt (TDEPFILES): Add solib-sunos.o. + +2002-02-18 Richard Earnshaw <rearnsha@arm.com> + + * arm-tdep.c (arm_set_call_dummy_breakpoint_offset): New function. + (arm_fix_call_dummy): Call it. + (arm_call_dummy_breakpoint_offset): Delete. + (arm_gdbarch_init): Initialize call_dummy_breakpoint_offset. + * config/arm/tm-arm.h (CALL_DUMMY_BREAKPOINT_OFFSET): Delete. + +2002-02-18 Andrew Cagney <ac131313@redhat.com> + + * gdbarch.sh (FRAME_CHAIN_VALID): Only require at level 2. + Default to func_frame_chain_valid. + * gdbarch.h, gdbarch.c: Re-generate. + * frame.h (FRAME_CHAIN_VALID): Delete definition. + +2002-02-18 Elena Zannoni <ezannoni@redhat.com> + + * ppc-linux-nat.c: Update copyright. + (fetch_register, store_register): Add tid parameter, don't compute + tid here. + (fetch_ppc_registers, store_ppc_registers): Add tid + parameter. Pass it along to callees. + (fetch_inferior_registers, store_inferior_registers): Compute tid + here, and pass it to calleed functions. + (fill_gregset, supply_fpregset): Clean up formatting. + +2002-02-18 Richard Earnshaw <rearnsha@arm.com> + + * arm-tdep.c (arm_gdbarch_init): Initialize coerce_float_to_double. + * config/arm/tm-arm.h (COERCE_FLOAT_TO_DOUBLE): Delete. + +2002-02-18 Richard Earnshaw <rearnsha@arm.com> + + * gdbarch.sh (GET_LONGJMP_TARGET): Add rule. + * gdbarch.c gdbarch.h: Regenerate. + * breakpoint.c (create_longjmp_breakpoint): Always compile this + function. + (breakpoint_reset): Test GET_LONGJMP_TARGET_P(). + * infrun.c (GET_LONGJMP_TARGET): Delete default definition. + (handle_inferior_event): Test GET_LONGJMP_TARGET_P(). + + * arm-tdep.h (struct gdbarch_tdep): Add jb_pc and jb_elt_size fields. + * arm-tdep.c (arm_get_longjmp_target): New function. + (arm_gdbarch_init): Initialize jb_pc to -1. If ABI handler changes + this to a positive value register arm_get_longjmp_target as the + longjmp handler. + * arm-linux-tdep.c (arm_get_longjmp_target): Delete. + (arm_linux_init_abi): Set up longjmp description in tdep. + * armnbsd-nat.c (get_longjmp_target): Delete. + * armnbsd-tdep.c (arm_netbsd_init_abi_common): Set up longjmp + description in tdep. + * config/arm/tm-nbsd.h (JB_ELEMENT_SIZE, JB_PC): Delete. + (get_longjmp_target): Delete declaration. + (GET_LONGJMP_TARGET): Delete. + * config/arm/tm-linux.h (arm_get_longjmp_target): Delete declaration. + (GET_LONGJMP_TARGET): Delete. + +2002-02-17 Kevin Buettner <kevinb@redhat.com> + + From Peter Schauer <pes@regent.e-technik.tu-muenchen.de>: + * ia64-tdep.c (ia64_gdbarch_init): Eliminate incorrect use + of ``current_gdbarch''. + +2002-02-17 Tom Tromey <tromey@redhat.com> + + * cli/cli-cmds.c (compare_strings): New function. + (complete_command): Only print each unique item once. + * completer.h (complete_line): Declare. + * completer.c (complete_line): New function. + (line_completion_function): Use it. + +2002-02-16 Andrew Cagney <ac131313@redhat.com> + + * gdbarch.sh (TARGET_LONG_DOUBLE_BIT): Default to 64. + * gdbarch.h, gdbarch.c: Re-generate. + +2002-02-16 Daniel Jacobowitz <drow@mvista.com> + + * valarith.c (value_x_unop): Fix decrement; support post-decrement. + +2002-02-16 Daniel Jacobowitz <drow@mvista.com> + + From Peter Schauer <Peter.Schauer@Regent.E-Technik.TU-Muenchen.DE>: + * valops.c (value_arg_coerce): Don't take the address of a reference + to convert an argument to a reference. + +2002-02-15 Christopher Faylor <cgf@redhat.com> + + * win32-nat.c (get_image_name): New function. + (handle_load_dll): Use get_image_name function. + (get_child_debug_event): Avoid registering debug events until possibly + execed process is started. + (child_create_inferior): Allow invocation via shell so that command + line redirection, etc. works ok. + (_initialize_inftarg): Add new command: "set shell" to control whether + a shell is used to start a process. + +2002-02-15 Daniel Jacobowitz <drow@mvista.com> + + * gdbserver/linux-mips-low.c (cannot_fetch_register): Use find_regno + instead of find_register_by_number. + (cannot_store_register): Likewise. + +2002-02-14 Pierre Muller <muller@ics.u-strasbg.fr> + + * dwarf2read.c: Replace fprintf (stderr, ...) by + fprintf_unfiltered (gdb_stderr, ...). + +2002-02-15 Daniel Jacobowitz <drow@mvista.com> + + * gdbserver/gdbserver.1: Document --attach. + +2002-02-15 Richard Earnshaw <rearnsha@arm.com> + + * arm-tdep.h (struct gdbarch_tdep): Add fields for breakpoint + descriptions. + * arm-tdep.c (arm_default_arm_le_breakpoint) + (arm_default_arm_be_breakpoint, arm_default_thumb_le_breakpoint) + (arm_default_thumb_be_breakpoint): New. Initialize them from + traditional breakpoint defines. + (arm_breakpoint_from_pc): Use new gdbarch_tdep entries. + (arm_gdbarch_init): Initialize new breakpoint variables. + * arm-linux-tdep.c (arm_linux_arm_le_breakpoint): New. + (arm_linux_init_abi): Initialize linux-specific breakpoint. + * armnbsd-tdep.c (arm_nbsd_arm_le_breakpoint): New. + (arm_netbsd_aout_init_abi, arm_netbsd_elf_init_abi): Split common + code out to ... + (arm_netbsd_init_abi_common): ... here; new function. + * config/arm/tm-arm.h (ARM_LE_BREAKPOINT, ARM_BE_BREAKPOINT) + (THUMB_LE_BREAKPOINT, THUMB_BE_BREAKPOINT): Delete. + * config/arm/tm-linux.h (ARM_LE_BREAKPOINT): Delete. + * config/arm/tm-nbsd.h (ARM_LE_BREAKPOINT): Delete. + +2002-02-15 Richard Earnshaw <rearnsha@arm.com> + + * arm-tdep.h (enum arm_abi): New enum. + (struct gdbarch_tdep): New structure. + (LOWEST_PC): Provide a default. + (arm_gdbarch_register_os_abi): Declare new function. + * arm-tdep.c (arm_abi_names): New array. + (process_note_abi_tag_sections): New function. + (get_elfosabi): New function. + (arm_gdbarch_register_os_abi): New function. + (arm_gdbarch_init): Try to determine the ABI of the inferior. If + support for that ABI has been built in, then call the appropriate + configuration routine. Use gdbarch_num_regs() to get the number + of registers. + (arm_dump_tdep): New function. + (arm_init_abi_eabi_v1, arm_init_abi_eabi_v2, arm_init_abi_apcs): New + place-holder functions. + (_initialize_arm_tdep): Register them. + * config/arm/tm-arm.h (LOWEST_PC): Delete. + + * armnbsd-tdep.c: New file. + * Makefile.in (armnbsd-tdep.o): Add dependencies. + * config/arm/nbsd.mt (TDEPFILES): Add it. + * config/arm/tm-nbsd.h (LOWEST_PC): Delete. + + * armnbsd-nat.c: Include regcache.h. + * Makefile.in (armnbsd-nat.o): Update dependency list. + + * arm-tdep.c (arm_get_next_pc): Use printf_filtered for error message. + +2002-02-14 Daniel Jacobowitz <drow@mvista.com> + + * gdbserver/Makefile.in: Fix typos in target rules. + +2002-02-14 Daniel Jacobowitz <drow@mvista.com> + + Fix part of PR gdb/267. + * linespec.c (find_methods): Handle constructors specially for now. + +2002-02-14 Corinna Vinschen <vinschen@redhat.com> + + * arm-tdep.c (arm_push_arguments): Eliminate special float type + handling. + * config/arm/tm-arm.h (COERCE_FLOAT_TO_DOUBLE): Define to call + standard_coerce_float_to_double(). + +2002-02-14 Christopher Faylor <cgf@redhat.com> + + * config/i386/xm-cygwin.h: Revert inadvertent reinclusion of + GDBINIT_FILENAME. + +2002-02-14 Elena Zannoni <ezannoni@redhat.com> + + * rs6000-tdep.c (rs6000_gdbarch_init): Don't call + find_variant_by_name, because it confuses the multiarch + framework. Return NULL if there isn't an architecture with the + user supplied name, instead of forcing a different one without + recording the change with the multiarch machinery. + (find_variant_by_name): Delete. + +2002-02-14 Peter Schauer <pes@regent.e-technik.tu-muenchen.de> + + * config/i386/i386sol2.mh (NATDEPFILES): Add i387-nat.o, needed by + i386v4-nat.o now. Add gcore.o, Solaris x86 supports gcore. + +2002-02-13 Martin M. Hunt <hunt@redhat.com> + + * stack.c (print_frame_info_base): When calling + print_frame_info_listing_hook, set current_source_symtab. + +2002-02-14 Daniel Jacobowitz <drow@mvista.com> + + * gdbserver/Makefile.in: Add regformats directory to INCLUDE_CFLAGS, + and remove unused $(INCLUDE_DIR). + Add regcache.c to OBS. + Add generated register protocol files to clean target. + Update dependencies for new objects, obsolete old target code. + + * gdbserver/linux-low.c: Remove all platform-specific code to + new files. Remove various dead code. Update to use regcache + functionality. + * gdbserver/remote-utils.c (fromhex): Add return statement + to quiet warning. + (putpkt): Dynamically allocate buf2 because PBUFSIZ is no longer + constant. + (input_interrupt): Add integer parameter to match prototype + of a signal handler. + (outreg): Use register_data (). + (prepare_resume_reply): Use gdbserver_expedite_regs. + * gdbserver/server.c (main): Dynamically allocate own_buf because + PBUFSIZ is no longer constant. Use registers_to_string () and + registers_from_string (). + * gdbserver/server.h: No longer include "defs.h". Add prototypes + for error (), fatal (), and warning (). Update definition of + PBUFSIZ to use regcache functionality. Add include guard. + * gdbserver/utils.c (fatal): Add missing ``const''. + (warning): New function. + + * regformats/regdat.sh: Include "regcache.h" in generated files. + Provide init_registers () function. + * regformats/regdef.h: Add prototype for set_register_cache (). + Add include guard. + + * gdbserver/linux-arm-low.c: New file. + * gdbserver/linux-i386-low.c: New file. + * gdbserver/linux-ia64-low.c: New file. + * gdbserver/linux-m68k-low.c: New file. + * gdbserver/linux-mips-low.c: New file. + * gdbserver/linux-ppc-low.c: New file. + * gdbserver/linux-sh-low.c: New file. + + * gdbserver/regcache.c: New file. + * gdbserver/regcache.h: New file. + + * gdbserver/low-linux.c: Removed obsolete file. + +2002-02-14 Daniel Jacobowitz <drow@mvista.com> + + * config/arm/linux.mt: Update GDBSERVER_DEPFILES. + * config/i386/linux.mt: Likewise. + * config/ia64/linux.mt: Likewise. + * config/m68k/linux.mh: Likewise. + * config/powerpc/linux.mh: Likewise. + * config/mips/linux.mt: Likewise. + + * config/sh/linux.mt: Add GDBSERVER_DEPFILES. + + * config/i386/i386lynx.mh: Mark gdbserver variables + as (currently) obsolete for this target. + * config/i386/nbsd.mt: Likewise. + * config/i386/nbsdelf.mt: Likewise. + * config/m32r/m32r.mt: Likewise. + * config/m68k/m68klynx.mh: Likewise. + * config/m68k/nbsd.mt: Likewise. + * config/m68k/sun3os4.mh: Likewise. + * config/mips/vr5000.mt: Likewise. + * config/ns32k/nbsd.mt: Likewise. + * config/pa/hppabsd.mh: Likewise. + * config/pa/hppaosf.mh: Likewise. + * config/powerpc/nbsd.mt: Likewise. + * config/rs6000/rs6000lynx.mh: Likewise. + * config/s390/s390.mt: Likewise. + * config/s390/s390x.mt: Likewise. + * config/sparc/sparclynx.mh: Likewise. + * config/sparc/sun4os4.mh: Likewise. + * config/i386/x86-64linux.mt: Likewise. + * config/sparc/linux.mh: Likewise. + +2002-02-14 Daniel Jacobowitz <drow@mvista.com> + + * configure.tgt: Configure gdbserver only for known working + targets. Set ${build_gdbserver} instead of modifying ${configdirs}. + * configure.in: Check ${build_gdbserver}. Put gdbserver/ into + SUBDIRS if it is configured. Update comment for ${nativefile}. + * configure: Regenerated. + +2002-02-13 Michael Snyder <msnyder@redhat.com> + + * config/i386/i386v42mp.mh: Add gcore.o to NATDEPFILES. + + * gcore.c (gcore_command): Use gcore_default_target instead of NULL. + (default_gcore_mach): Just return 0, work around a problem in bfd. + (default_gcore_target): OK to return NULL if exec_bfd is null. + (make_mem_sec): Use a cast, avoid a warning. + + * procfs.c (find_memory_regions_callback): Use a cast instead of + calling host_pointer_to_address (which complains if + sizeof (host pointer) != sizeof (target pointer)). + (procfs_make_note_section): Avoid overflow in psargs string. + + * procfs.c (procfs_make_note_section): Make the default + implementation return an error. + +2002-02-13 Rodney Brown <rbrown64@csc.com.au> + + * procfs.c (procfs_make_note_section): Provide a default definition + (for alpha-dec-osf4.0f). Fix typos. + +2002-02-13 Elena Zannoni <ezannoni@redhat.com> + + * linux-proc.c: Add include of regcache.h. + * Makefile.in (linux-proc.o): Add dependency on regcache.h. + +2002-02-13 Andrew Cagney <ac131313@redhat.com> + + From 2002-01-18 Greg McGary <greg@mcgary.org>: + * memattr.c (create_mem_region): Disallow useless empty region. + Regions are half-open intervals, so allow [A..B) [B..C) as + non-overlapping. + +2002-02-13 Michael Chastain <mec@shout.net> + + * defs.h: Kill CONST_PTR. + * c-lang.h (c_builtin_types): Change CONST_PTR to simple "const". + * c-lang.c (c_builtin_types): Likewise. + * ch-lang.c (ch_builtin_types): Likewise. + * f-lang.c (f_builtin_types): Likewise. + * language.c (unknown_builtin_types): Likewise. + * m2-lang.c (m2_builtin_types): Likewise. + * p-lang.c (pascal_builtin_types): Likewise. + * scm-lang.c (c_builtin_types): Likewise. + +2002-02-13 Keith Seitz <keiths@redhat.com> + + * arm-tdep.h (arm_get_next_pc): Add declaration. + +2002-02-13 Richard Earnshaw <rearnsha@arm.com> + + * arm-tdep.c (arm_use_struct_convention): Make static. Move to be + with other related struct-returning functions. + (arm_extract_struct_value_address): New function. + (arm_gdbarch_init): Initialize the above in multi-arch vector. Also + initialize float_format, double_format and long_double_format as + appropriate to the endianness of the target. + * config/arm/tm-arm.h (TARGET_DOUBLE_FORMAT): Delete. + (arm_use_struct_convention): Delete declaration. + (USE_STRUCT_CONVENTION, EXTRACT_STRUCT_VALUE_ADDRESS): Delete. + +2002-02-13 Keith Seitz <keiths@redhat.com> + + * defs.h (core_addr_to_string_nz): New function. + +2002-02-13 Mark Kettenis <kettenis@gnu.org> + + Apply missing bits of 2002-01-15 patch. + * i386v4-nat.c (supply_fpregset): Use i387_supply_fsave. + (fill_fpregset): Use i387_fill_fsave. + +2002-02-12 Keith Seitz <keiths@redhat.com> + + * utils.c (core_addr_to_string): Use phex instead of phex_nz. + (core_addr_to_string_nz): New function. + +2002-02-11 Richard Earnshaw <rearnsha@arm.com> + + * arm-linux-nat.c: Really include arm-tdep.h. + * config/arm/tm-linux.h (struct type, struct value): Declare. + +2002-02-11 Michael Snyder <msnyder@redhat.com> + + * procfs.c: Include elf-bfd.h (for elfcore_write functions). + (gcore section): Ifdef for Solaris and Unixware only. + (procfs_do_thread_registers): Unixware needs one lwpstatus + per thread (not one prstatus or pstatus). + (procfs_make_note_section): Iterate only over kernel threads (lwps), + not over all gdb threads. For unixware, call elfcore_write_pstatus + once before iterating over threads. + +2002-02-11 Richard Earnshaw <rearnsha@arm.com> + + * arm-tdep.h: New file. + * arm-tdep.c: Include arm-tdep.h. + (arm_addr_bits_remove, arm_smash_text_address, arm_saved_pc_after_call) + (arm_skip_prologue, arm_call_dummy_words, arm_fix_call_dummy) + (arm_print_float_info, arm_register_type, convert_to_extended) + (arm_elf_make_msymbols_special, arm_coff_make_msymbol_special) + (arm_extract_return_value, arm_register_name): Make static. + (arm_software_single_step): Similarly. Fix types in declaration. + (arm_register_byte, arm_register_raw_size, arm_register_virtual_size) + (arm_store_return_value, arm_store_struct_return): New functions. + (arm_gdbarch_init): Register the above functions. Also register + call_dummy_start_offset, sizeof_call_dummy_words, + function_start_offset, inner_than, decr_pc_after_break, fp_regnum, + sp_regnum, pc_regnum, register_bytes, num_regs, max_register_raw_size, + max_register_virtual_size, register_size. Set up + prologue_cache.saved_regs here, rather than ... + (_initialize_arm_tdep): ... here. + * config/arm/tm-arm.h (struct type, struct value): Delete forward + declarations. + (arm_addr_bits_remove, arm_smash_text_address, arm_saved_pc_after_call) + (arm_skip_prologue, arm_call_dummy_words, arm_fix_call_dummy) + (arm_print_float_info, arm_register_type, convert_to_extended) + (arm_elf_make_msymbols_special, arm_coff_make_msymbol_special) + (arm_extract_return_value, arm_register_name): Delete declarations. + (SMASH_TEXT_ADDRESS, ADDR_BITS_REMOVE, FUNCTION_START_OFFSET) + (SKIP_PROLOGUE, SAVED_PC_AFTER_CALL, INNER_THAN, BREAKPOINT_FROM_PC) + (DECR_PC_AFTER_BREAK, PRINT_FLOAT_INFO, REGISTER_SIZE, NUM_REGS) + (REGISTER_NAME, REGISTER_BYTES, REGISTER_BYTE, REGISTER_RAW_SIZE) + (REGISTER_VIRTUAL_SIZE, MAX_REGISTER_RAW_SIZE) + (MAX_REGISTER_VIRTUAL_SIZE, REGISTER_VIRTUAL_TYPE, STORE_STRUCT_RETURN) + (EXTRACT_RETURN_VALUE, STORE_RETURN_VALUE, CALL_DUMMY_WORDS) + (SIZEOF_CALL_DUMMY_WORDS, CALL_DUMMY_START_OFFSET, FIX_CALL_DUMMY) + (SOFTWARE_SINGLE_STEP_P, SOFTWARE_SINGLE_STEP) + (ELF_MAKE_MSYMBOL_SPECIAL, COFF_MAKE_MSYMBOL_SPECIAL) Delete. + (arm_pc_is_thumb, arm_pc_is_thumb_dummy, thumb_get_next_pc) + (arm_get_next_pc): No-longer static -- these are needed by the RDI + interface. + * arm-linux-nat.c arm-linux-tdep.c armnbsd-nat.c: Include arm-tdep.h. + * remote-rdi.c remote-rdp.c: Likewise. + * Makefile.in (arm-linux-nat.o, arm-linux-tdep.o arm-tdep.o) + (armnbsd-nat.o, remote-rdi.o, remote_rdp.o): Update dependencies. + * config/arm/tm-nbsd.h (SOFTWARE_SINGLE_STEP_P): Delete bogus + definition. + + * arm-tdep.h (ARM_A1_REGNUM, ARM_A4_REGNUM, ARM_AP_REGNUM) + (ARM_SP_REGNUM, ARM_LR_REGNUM, ARM_PC_REGNUM, ARM_F0_REGNUM) + (ARM_F3_REGNUM, ARM_F7_REGNUM, ARM_FPS_REGNUM, ARM_PS_REGNUM): Renamed + from non-ARM_ prefixed definitions. + * arm-tdep.c armnbsd-nat.c arm-linux-nat.c arm-linux-tdep.c: Update + all uses of above. + * remote-rdi.c remote-rdp.c: Likewise. + * arm-linux-nat.c (ARM_CPSR_REGNUM): Renamed from CPSR_REGNUM. + +2002-02-11 Richard Earnshaw <rearnsha@arm.com> + + * arm-tdep.c (arm_frameless_function_invocation) + (arm_frame_args_address, arm_frame_locals_address, arm_frame_num_args) + (arm_frame_chain, arm_init_extra_frame_info, arm_frame_saved_pc) + (arm_read_fp, arm_frame_init_saved_regs, arm_push_dummy_frame) + (arm_pop_frame, arm_get_next_pc): Make static. + (arm_gdbarch_init): Register above in gdbarch structure. + (arm_read_fp): Renamed from arm_target_read_fp. + (arm_pc_is_thumb, arm_pc_is_thumb_dummy): Make static. + * config/arm/tm-arm.h (arm_frameless_function_invocation) + (arm_frame_args_address, arm_frame_locals_address, arm_frame_num_args) + (arm_frame_chain, arm_init_extra_frame_info, arm_frame_saved_pc) + (arm_target_read_fp, arm_frame_init_saved_regs, arm_push_dummy_frame) + (arm_pop_frame, arm_get_next_pc, arm_pc_is_thumb) + (arm_pc_is_thumb_dummy): Delete declarations. + (INIT_EXTRA_FRAME_INFO, TARGET_READ_FP, FRAME_CHAIN) + (FRAMELESS_FUNCTION_INVOCATION, FRAME_SAVED_PC, FRAME_ARGS_ADDRESS) + (FRAME_LOCALS_ADDRESS, FRAME_NUM_ARGS, FRAME_ARGS_SKIP) + (FRAME_INIT_SAVED_REGS, PUSH_DUMMY_FRAME, POP_FRAME): Delete. + +2002-02-10 Daniel Jacobowitz <drow@mvista.com> + + * symtab.c (compare_search_syms): New function. + (sort_search_symbols): New function. + (search_symbols): Sort symbols after searching rather than + before. + +2002-02-10 Andrew Cagney <ac131313@redhat.com> + + * NEWS: Linux -> GNU/Linux. + +2002-02-10 Andrew Cagney <ac131313@redhat.com> + + * gdbarch.sh: For for level one methods, disallow a definition + when partially multi-arched. Add comments explaining rationale. + * gdbarch.h: Re-generate. + +2002-02-10 Andrew Cagney <ac131313@redhat.com> + + * gdbarch.sh (EXTRA_STACK_ALIGNMENT_NEEDED): Don't require when + multi-arch partial. + +2002-02-10 Andrew Cagney <ac131313@redhat.com> + + * gdbarch.sh: Map LEVEL onto a symbolic GT_LEVEL. Exit on bad + field. Use diff -u. + * gdbarch.c: Re-generate. + +2002-02-10 Andrew Cagney <ac131313@redhat.com> + + * config/mips/tm-mips.h (CALL_DUMMY_LOCATION): Delete. + * gdbarch.sh (PUSH_RETURN_ADDRESS): Don't require when multi-arch + partial. + +2002-02-10 Andrew Cagney <ac131313@redhat.com> + + * gdbarch.sh (REGISTER_CONVERTIBLE): Don't require when + multi-arch partial. + (PUSH_ARGUMENTS): Switch to using predefault. + * gdbarch.c: Regenerate. + +2002-02-10 Andrew Cagney <ac131313@redhat.com> + + * valops.c (PUSH_ARGUMENTS): Delete definition. + * gdbarch.sh (PUSH_ARGUMENTS): Don't require when multi-arch + partial. Default to default_push_arguments. + * gdbarch.h, gdbarch.c: Regenerate. + +2002-02-09 Andrew Cagney <ac131313@redhat.com> + + * defs.h (throw_exception): Rename return_to_top_level. Update + comments. + * utils.c (error_stream, internal_verror, quit): Ditto. + * top.c (throw_exception, catcher): Ditto. + * sparclet-rom.c (sparclet_load): Ditto. + * remote.c (interrupt_query, minitelnet): Ditto. + * remote-sds.c (interrupt_query): Ditto. + * remote-mips.c (mips_error, mips_kill): Ditto. + * ocd.c (interrupt_query): Ditto. + * monitor.c (monitor_interrupt_query): Ditto. + * m3-nat.c (suspend_all_threads, thread_resume_command): Ditto. + * target.h: Update comment. + + * m3-nat.c, ocd.c, sparclet-rom.c: Update copyright. + +2002-02-09 Andrew Cagney <ac131313@redhat.com> + + * gdbarch.sh (TARGET_LONG_DOUBLE_FORMAT): Default to + default_double_format. + * gdbarch.h, gdbarch.c: Re-generate. + * findvar.c (floatformat_unknown): Delete variable definition. + * doublest.h (floatformat_unknown): Delete variable declaration. + +2002-02-09 Jim Blandy <jimb@redhat.com> + + * stabsread.c (read_type): Add code to parse Sun's syntax for + prototyped function types. + +2002-02-09 Andrew Cagney <ac131313@redhat.com> + + * Makefile.in (SUBDIR_CLI_INITS): Set to SUBDIR_CLI_SRCS. + (SUBDIR_MI_INITS): Set to SUBDIR_MI_SRCS. + +2002-02-09 Peter Schauer <pes@regent.e-technik.tu-muenchen.de> + + * xcoffsolib.c (_initialize_xcoffsolib): Renamed from + _initialize_solib. Fixes name clash with solib.c:_initialize_solib, + now _initialize_xcoffsolib gets called again and overrides the + commands from solib.c in a native configuration. + +2002-02-09 Mark Kettenis <kettenis@gnu.org> + + * doublest.c (store_typed_floating): Don't try to return a value. + Fixes PR gdb/290. + +2002-02-08 Jim Blandy <jimb@redhat.com> + + * c-typeprint.c (c_type_print_varspec_suffix): If a function type + is prototyped and has no arguments, print its argument list as + `(void)'. + +2002-02-08 Chris Demetriou <cgd@broadcom.com> + + * MAINTAINERS (write-after-approval): Add myself. + (paper-trail): I've escaped! + +2002-02-08 Christopher Faylor <cgf@redhat.com> + + * win32-nat.c (cygwin_pid_to_str): Revert 2002-02-08 change xasprintf + changes. + (_initialize_check_for_gdb_ini): Ditto. + +2002-02-08 Martin M. Hunt <hunt@redhat.com> + + * win32-nat.c (cygwin_pid_to_str): Fix typo. + xaprintf -> xasprintf. + +2002-02-08 Pierre Muller <muller@ics.u-strasbg.fr> + + * win32-nat.c: Remove use of printf and sprintf functions. + +2002-02-08 Richard Earnshaw <rearnsha@arm.com> + + * arm-tdep.c (arm_frame_chain_valid): Make static. + (arm_push_arguments): Likewise. + (arm_gdbarch_init): New function. + (_initialize_arm_tdep): Call it. + * config/arm/tm-arm.h (GDB_MULTI_ARCH): Set to 1. + (TARGET_DOUBLE_FORMAT): Test TARGET_BYTE_ORDER, not target_byte_order. + (FRAME_CHAIN_VALID): Delete. + (arm_frame_chain_valid): Delete declaration. + (PUSH_ARGUMENTS): Delete. + (arm_push_arguments): Delete declaration. + (CALL_DUMMY_P): Delete. + +2002-02-08 Andrew Cagney <ac131313@redhat.com> + Corinna Vinschen <vinschen@redhat.com> + + * gdbtypes.c (build_gdbtypes): Disable setting a specific float format + on builtin float types. + +2002-02-08 Daniel Jacobowitz <drow@mvista.com> + + * utils.c: Include <curses.h> before "bfd.h". + * tui/tui-hooks.c: Likewise. + * tui/tui.c: Likewise. + * tui/tuiCommand.c: Likewise. + * tui/tuiData.c: Likewise. + * tui/tuiDataWin.c: Likewise. + * tui/tuiDisassem.c: Likewise. + * tui/tuiGeneralWin.c: Likewise. + * tui/tuiIO.c: Likewise. + * tui/tuiLayout.c: Likewise. + * tui/tuiRegs.c: Likewise. + * tui/tuiSource.c: Likewise. + * tui/tuiSourceWin.c: Likewise. + * tui/tuiStack.c: Likewise. + * tui/tuiWin.c: Likewise. + +2002-02-07 Elena Zannoni <ezannoni@redhat.com> + + * sh-tdep.c (sh_nofp_frame_init_saved_regs): Extend where[] array + to include space for pseudoregs as well. Update loops accordingly. + (sh_fp_frame_init_saved_regs): Ditto. + (sh_init_extra_frame_info, sh_pop_frame): Split long lines. + +2002-02-07 Andrew Cagney <ac131313@redhat.com> + + * MAINTAINERS: Andreas Schwab is GNU/Linux m68k maintainer. + Add Richard Earnshaw to Arm maintainers. + +2002-02-07 Andrew Cagney <ac131313@redhat.com> + + * defs.h (warning_begin): Delete declaration. + + * config/powerpc/tm-ppcle-eabi.h (TARGET_BYTE_ORDER_DEFAULT): + Delete macro. + +2002-02-07 Michael Snyder <msnyder@redhat.com> + + * solib-legacy.c (legacy_svr4_fetch_link_map_offsets): + Logic bug, remove misplaced else. + +2002-02-07 Klee Dienes <klee@apple.com> + + * fork-inferior.c (fork_inferior): Add '!' to the list of + characters that need to be quoted when building a string for the + shell. Quote '!' specifically with a backslash, since CSH chokes + when trying to evaluate "str!str". + +2002-02-06 Nick Clifton <nickc@cambridge.redhat.com> + + * rdi-share/host.h: Only provide a typedef for bool if it is not + defined. + +2002-02-04 Michael Snyder <msnyder@redhat.com> + + * breakpoint.h (enum bptype): Add new overlay event bp type. + (enable_overlay_breakpoints, disable_overlay_breakpoints): Export. + + * breakpoint.c (create_internal_breakpoint): New function. + (internal_breakpoint_number): Moved into create_internal_breakpoint. + (create_longjmp_breakpoint): Use create_internal_breakpoint. + (create_thread_event_breakpoint): Ditto. + (create_solib_event_breakpoint): Ditto. + (create_overlay_event_breakpoint): New function. + (enable_overlay_breakpoints, disable_overlay_breakpoints): New funcs. + (update_breakpoints_after_exec): Delete and re-initialize + overlay event breakpoints after an exec. Add FIXME comment + about longjmp breakpoint. + (print_it_typical): Ignore overlay event breakpoints. + (print_one_breakpoint): Ditto. + (mention): Ditto. + (bpstat_what): Do not stop for overlay event breakpoints. + (delete_breakpoint): Don't delete overlay event breakpoints. + (breakpoint_re_set_one): Delete the overlay event breakpoint. + (breakpoint_re_set): Re-create overlay event breakpoint. + + * symfile.c (overlay_auto_command): Enable overlay breakpoints. + (overlay_manual_command): Disable overlay breakpoints. + (overlay_off_command): Disable overlay breakpoints. + +2002-02-06 Richard Earnshaw <rearnsha@arm.com> + + * arm-tdep.c: Include elf-bfd.h and coff/internal.h. + (MSYMBOL_SET_SPECIAL, MSYMBOL_IS_SPECIAL, MSYMBOL_SIZE): Move defines + to here from config/tm-arm.h. + (coff_sym_is_thumb): Make static. + (arm_elf_make_msymbol_special): New function. + (arm_coff_make_msymbol_special): New function. + * config/arm/tm-arm.h (MSYMBOL_SET_SPECIAL): Delete definition. + (MSYMBOL_IS_SPECIAL, MSYMBOL_SIZE): Likewise. + (coff_sym_is_thumb): Delete declaration. + (arm_elf_make_msymbol_special): Declare. + (arm_coff_make_msymbol_special): Declare. + (ELF_MAKE_MSYMBOL_SPECIAL): Call arm_elf_make_msymbol_special. + (COFF_MAKE_MSYMBOL_SPECIAL): Call arm_coff_make_msymbol_special. + +2002-02-06 Richard Earnshaw <rearnsha@arm.com> + + * arm-tdep.c (arm_software_single_step): ANSIfy function declaration. + +2002-02-06 Richard Earnshaw <rearnsha@arm.com> + + * gdbarch.sh (PRINT_FLOAT_INFO): Add rule. + * gdbarch.c gdbarch.h: Regenerate. + * arch-utils.c (default_print_float_info): New function. + * arch-utils.h (default_print_float_info): Prototype it. + * infcmd.c (float_info): Call PRINT_FLOAT_INFO. + * doc/gdbint.texinfo (FLOAT_INFO): Mark as deprecated. + (PRINT_FLOAT_INFO): Document it. + + * arm-tdep.c (arm_print_float_info): Renamed from arm_float_info. + * config/arm/tm-arm.h (FLOAT_INFO): Delete. + (PRINT_FLOAT_INFO): Define. + +2002-02-06 Pierre Muller <muller@ics.u-strasbg.fr> + + * win32-nat.c (_initialize_check_for_gdb_ini): + Add typecast to sprintf argument to suppress a warning. + +2002-02-05 Pierre Muller <muller@ics.u-strasbg.fr> + + * win32-nat.c (last_sig): Changed type of variable to target_signal, + to allow easier handling of pass state. + (DEBUG_EXCEPTION_SIMPLE): New macro, used in handle_exception, + that gives exception name and address. + (handle_exception): Use DEBUG_EXCEPTION_SIMPLE macro + and set last_sig value to ourstatus->value.sig. Some missing + exceptions added. + (child_continue): Correctly report continue_status. + (get_child_debug_event,do_initial_child_stuff): Set last_sig to + TARGET_SIGNAL_0 (new default value). + (child_resume): consider sig argument passed to decide if + the exception should be passed to debuggee or not. + +2002-02-05 Michael Snyder <msnyder@redhat.com> + + * regcache.c (fetch_register): Call target_fetch_register + only if we don't call FETCH_PSEUDO_REGISTER. + (store_register): Call target_store_register only if we + don't call STORE_PSEUDO_REGISTER. + +2002-02-05 Elena Zannoni <ezannoni@redhat.com> + + * gdbarch.sh: Add definitions for COFF_MAKEMSYMBOL_SPECIAL and + ELF_MAKE_MSYMBOL_SPECIAL. + * gdbarch.c, gdbarch.h: Regenerate. + * arch-utils.c (default_make_msymbol_special): New function. + * arch-utils.h (default_make_msymbol_special): Export. + * elfread.c (elf_symtab_read): Compile use of + ELF_MAKE_MSYMBOL_SPECIAL unconditionally because it is now + multiarched. + * coffread.c (coff_symtab_read): Ditto, for + COFF_MAKE_MSYMBOL_SPECIAL. + +2002-02-05 Jim Blandy <jimb@redhat.com> + + * solib-svr4.c (svr4_truncate_ptr): New function. + (svr4_relocate_section_addresses): Do the address arithmetic with + the appropriate truncation for target addresses, even when + CORE_ADDR is larger than a target address. + +2002-02-05 Daniel Jacobowitz <drow@mvista.com> + + * gdbserver/linux-low.c (mywait): Cast second argument of waitpid + to (int *). + +2002-02-05 Daniel Jacobowitz <drow@mvista.com> + + * gdbserver/linux-low.c (kill_inferior): Remove commented out + code. + +2002-02-05 Daniel Jacobowitz <drow@mvista.com> + + * c-valprint.c (c_val_print): Handle TYPE_CODE_COMPLEX. + +2002-02-05 Daniel Jacobowitz <drow@mvista.com> + + * gdbserver/linux-low.c: Remove unused include files. + +2002-02-05 Daniel Jacobowitz <drow@mvista.com> + + * gdbserver/linux-low.c: Define PTRACE_ARG3_TYPE. + (read_inferior_memory): Use it. + (write_inferior_memory): Likewise. + +2002-02-05 Daniel Jacobowitz <drow@mvista.com> + + * gdbserver/linux-low.c (create_inferior): Call strerror instead of + grubbing through sys_errlist. + +2002-02-05 Daniel Jacobowitz <drow@mvista.com> + + * gdbserver/linux-low.c: New file, copied exactly from low-linux.c. + +2002-02-04 Pierre Muller <muller@ics.u-strasbg.fr> + * win32-nat.c (handle_exception): Handle Ctrl-Break exception. + +2002-02-04 Andrew Cagney <ac131313@redhat.com> + + * cli/cli-decode.c (do_cfunc, set_cmd_cfunc): New functions. + (do_sfunc, set_cmd_sfunc): New functions. + + * command.h (struct cmd_list_element): Add field func. + * cli/cli-decode.h (struct cmd_list_element): Ditto. + * command.h (set_cmd_sfunc, set_cmd_cfunc): Declare. + * cli/cli-decode.h: Ditto. + + * cli/cli-decode.c (help_cmd): Test for func not cfunc/sfunc. + (help_all, help_cmd_list): Ditto. + (find_cmd, complete_on_cmdlist): Ditto. + * top.c (execute_command): Ditto. + + * cli/cli-setshow.c (do_setshow_command): Call func instead of + function.sfunc. + + * infcmd.c (notice_args_read): Fix function signature. + + * cli/cli-cmds.c (init_cli_cmds): Use set_cmd_sfunc. + * cli/cli-decode.c (add_set_cmd): Ditto. + * utils.c (initialize_utils): Ditto. + * maint.c (_initialize_maint_cmds): Ditto. + * infrun.c (_initialize_infrun): Ditto. + * demangle.c (_initialize_demangler): Ditto. + * remote.c (add_packet_config_cmd): Ditto. + * mips-tdep.c (_initialize_mips_tdep): Ditto. + * cris-tdep.c (_initialize_cris_tdep): Ditto. + * proc-api.c (_initialize_proc_api): Ditto. + * kod.c (_initialize_kod): Ditto. + * valprint.c (_initialize_valprint): Ditto. + * top.c (init_main): Ditto. + * infcmd.c (_initialize_infcmd): Ditto. + * corefile.c (_initialize_core): Ditto. + * arm-tdep.c (_initialize_arm_tdep): Ditto. + * arch-utils.c (initialize_current_architecture): Ditto. + (_initialize_gdbarch_utils): Ditto. + * alpha-tdep.c (_initialize_alpha_tdep): Ditto. + + * cli/cli-decode.c (add_cmd): Use set_cmd_cfunc. + * wince.c (_initialize_inftarg): Ditto. + * symfile.c (_initialize_symfile): Ditto. + * mips-tdep.c (_initialize_mips_tdep): Ditto. + * language.c (_initialize_language): Ditto. + * arc-tdep.c (_initialize_arc_tdep): Ditto. + +2002-02-04 Michael Snyder <msnyder@redhat.com> + + * memattr.c (_initialize_mem): Elaborate the help for 'mem' command. + +2002-02-04 Daniel Jacobowitz <drow@mvista.com> + + * gdbserver/Makefile.in: Add regformats directory to INCLUDE_CFLAGS. + Add rules for building the register data files. + +2002-02-04 Daniel Jacobowitz <drow@mvista.com> + + * regformats/regdat.sh: Add braces to the definition of + expedite_regs_${arch}. + +2002-02-04 Daniel Jacobowitz <drow@mvista.com> + + * regformats/regdef.h (struct reg): Add comment describing the + requirements for offset and size fields. + +2002-02-04 Andreas Schwab <schwab@suse.de> + + * config/ia64/linux.mh: Don't set NAT_CLIBS and REGEX. + * config/ia64/linux.mt: Don't set GDBSERVER_LIBS. + +2002-02-04 Richard Earnshaw <rearnsha@arm.com> + + * gdbarch.sh (copyright): Update years in generated header. + (SMASH_TEXT_ADDRESS): Add rule. + * gdbarch.h, gdbarch.c: Re-generate. + * coffread.c: Multi-arch uses of SMASH_TEXT_ADDRESS. + * dbxread.c: Likewise. + * dwarfread.c: Likewise. + * elfread.c: Likewise. + * somread.c: Likewise. + + * arm-tdep.c (arm_smash_text_address): New function. + * config/arm/tm-arm.h (SMASH_TEXT_ADDRESS): Define in terms of above. + +2002-02-04 Pierre Muller <muller@ics.u-strasbg.fr> + + Add support for hardware watchpoints on win32 native. + * win32-nat.c (CONTEXT_DEBUG_DR macro): Add use of + CONTEXT_DEBUG_REGISTERS. + (dr variable): New variable. Static array containing a local copy + of debug registers. + (debug_registers_changed): New variable. Reflects when debug registers + are changed and need to be written to inferior. + (debug_registers_used): New variable. Reflects when any debug register + was set, used when new threads are created. + (cygwin_set_dr, cygwin_set_dr7, cygwin_get_dr6): New functions used by + i386-nat code. + (thread_rec): Set dr array if id is the thread of current_event . + (child_continue, child_resume): Change the debug registers for all + threads if debug_registers_changed. + (child_add_thread): Change the debug registers if debug_registers_used. + * config/i386/cygwin.mh: Add use of i386-nat.o file. + Link nm.h to new nm-cygwin.h file. + + config/i386/nm-cygwin.h: New file. Contains the macros used for use + of hardware registers. + +2002-02-03 Andrew Cagney <ac131313@redhat.com> + + * valprint.c (print_floating): Allow non TYPE_CODE_FLT types. + Restore behavour broken by 2002-01-20 Andrew Cagney + <ac131313@redhat.com> IEEE_FLOAT removal. + +2002-02-03 Daniel Jacobowitz <drow@mvista.com> + + * c-valprint.c (c_val_print): Pass a proper valaddr to + cp_print_class_method. + * valops.c (search_struct_method): If there is only one method + and args is NULL, return that method. + +2002-02-03 Daniel Jacobowitz <drow@mvista.com> + + * gdbtypes.c (init_simd_type): Use TYPE_TAG_NAME instead of + accessing tag_name directly. + +2002-02-03 Daniel Jacobowitz <drow@mvista.com> + + * ax-gdb.c (find_field): Use TYPE_TAG_NAME instead + of accessing tag_name directly. + +2002-02-03 Daniel Jacobowitz <drow@mvista.com> + + PR gdb/280 + * gdbtypes.c (replace_type): New function. + * gdbtypes.h (replace_type): Add prototype. + * stabsread.c (read_type): Use replace_type. + +2002-02-03 Richard Earnshaw <rearnsha@arm.com> + + * Makefile.in (memattr.o): Add missing dependencies rule. + +2002-02-03 Peter Schauer <pes@regent.e-technik.tu-muenchen.de> + + * breakpoint.c (break_at_finish_command): Really export. + (break_at_finish_at_depth_command): Ditto. + (tbreak_at_finish_command): Ditto. + * hppa-tdep.c: Include completer.h. + * Makefile.in (hppa-tdep.o): Add dependency on $(completer_h). + (COMMON_OBS): Remove duplicate ui-file.o, frame.o, doublest.o. + +2002-02-01 Andrew Cagney <ac131313@redhat.com> + + * utils.c (do_write): New function. + (error_stream): Rewrite combining the code from error_begin and + verror. + (verror): Rewrite using error_stream. + (error_begin): Delete function. + +2002-02-01 Andrew Cagney <ac131313@redhat.com> + + * utils.c (error_begin): Make static. + * defs.h (error_begin): Delete declaration. + + * linespec.c (cplusplus_error): Replace cplusplus_hint. + (decode_line_1): Use cplusplus_error instead of error_begin, + cplusplus_hint and return_to_top_level. + * coffread.c (coff_symfile_read): Use error instead of error_begin + and return_to_top_level. + * infrun.c (default_skip_permanent_breakpoint): Ditto. + +2002-02-01 Andrew Cagney <ac131313@redhat.com> + + * language.h (type_error, range_error): Make string parameter + constant. + * language.c (warning_pre_print): Delete extern declaration. + * dwarfread.c (warning_pre_print): Ditto. + * language.c (type_error, range_error): Rewrite to use verror and + vwarning instead of warning_begin. + +2002-02-01 Michael Snyder <msnyder@redhat.com> + + * breakpoint.c (breakpoint_re_set): Delete ancient #if 0 code. + (set_ignore_count): Move misplaced comment back where it belongs. + +2002-02-01 Andrew Cagney <ac131313@redhat.com> + + * command.h (NO_FUNCTION): Delete macro. + * cli/cli-decode.h (NO_FUNCTION): Ditto. + * top.c (execute_command): Replace NO_FUNCTION with NULL. + * tracepoint.c (_initialize_tracepoint): Ditto. + * cli/cli-decode.c (add_set_cmd): Ditto. + * cli/cli-cmds.c (init_cli_cmds): Ditto. + +2002-02-01 Daniel Jacobowitz <drow@mvista.com> + + * gnu-v3-abi.c (gnuv3_virtual_fn_field): Update comments. + Update ``this'' pointer when calling virtual functions. + +2002-02-01 Michael Snyder <msnyder@redhat.com> + + * breakpoint.c (create_temp_exception_breakpoint): Delete. + * hppa-tdep.c: Deprecate xbreak, txbreak and bx commands. + +2002-02-01 Daniel Jacobowitz <drow@mvista.com> + + * regformats/reg-arm.dat: New file. + * regformats/reg-i386.dat: New file. + * regformats/reg-ia64.dat: New file. + * regformats/reg-m68k.dat: New file. + * regformats/reg-mips.dat: New file. + * regformats/reg-ppc.dat: New file. + * regformats/reg-sh.dat: New file. + * regformats/regdef.h: New file. + * regformats/regdat.sh: New file. + +2002-02-01 Richard Earnshaw <reanrsha@arm.com> + + * arm-tdep.c (arm_frameless_function_invocation): Add some comments. + (arm_frame_args_address, arm_frame_locals_address): New functions. + (arm_frame_num_args): New function. + * config/tm-arm.h (FRAME_ARGS_ADDRESS): Call arm_frame_args_address. + (FRAME_LOCALS_ADDRESS): Call arm_frame_locals_address. + (FRMA_NUM_ARGS): Call arm_frame_num_args. + +2002-01-31 Michael Snyder <msnyder@redhat.com> + + * breakpoint.c (break_at_finish_command): Export. + (break_at_finish_at_depth_command): Export. + (tbreak_at_finish_command): Export. + (_initialize_breakpoint): Delete "xbreak" and "tbreak" commands. + * hppa-tdep.c (_initialize_hppa_tdep): Add "xbreak" and + "tbreak" commands, which are HPPA specific. + + * printcmd.c (disassemble_command): Remove an ancient + artifact of an old merge. + + * symfile.h (enum overlay_debugging_state): + Define enum constant values for overlay mode. + * symfile.c (overlay_debugging): Use enums instead of literals. + (overlay_is_mapped, overlay_auto_command, + overlay_manual_command): Ditto. + + * breakpoint.c (insert_breakpoints, remove_breakpoint, + breakpoint_here_p, breakpoint_inserted_here_p, + breakpoint_thread_match, bpstat_stop_status, + describe_other_breakpoints, check_duplicates, clear_command): + Coding standard fixes. + + * target.c (target_xfer_memory): Add spaces, coding standard. + (do_xfer_memory): Add missing line to trust-readonly + code: check bfd SEC_READONLY flag for section. + +2002-01-31 Andrew Cagney <ac131313@redhat.com> + + * PROBLEMS: Fix typo, 5.1->5.1.1. + +2002-01-30 Daniel Jacobowitz <drow@mvista.com> + + * symtab.c (find_pc_sect_psymtab): Do not search psymtabs for + data symbols, since we search based on textlow and texthigh. + (find_pc_sect_symtab): Likewise. + +2002-01-30 Andrew Cagney <ac131313@redhat.com> + + * defs.h (vwarning): Declare. + * utils.c (vwarning): New function. + (warning): Call vwarning. + (warning_begin): Delete function. + + * rs6000-nat.c (vmap_ldinfo): Use the function warning to print + the warning message. + * d10v-tdep.c (d10v_address_to_pointer) [0]: Delete call to + warning_begin. + +2002-01-30 Michael Snyder <msnyder@redhat.com> + + * NEWS: Mention "set trust-readonly-sections" command. + Mention generate-core-file command. + +2002-01-15 Michael Snyder <msnyder@redhat.com> + + * target.c: New command, "set trust-readonly-sections on". + (do_xfer_memory): Honor the suggestion to trust readonly sections + by reading them from the object file instead of from the target. + (initialize_targets): Register command "set trust-readonly-sections". + +2002-01-29 Andrew Cagney <ac131313@redhat.com> + + * parse.c (target_map_name_to_register): Simplify, search regs and + pseudo-regs using a single loop. + +2002-01-30 Andrew Cagney <ac131313@redhat.com> + + * PROBLEMS: Note that the i386 fix was missing from 5.1.1. + +2002-01-15 Rodney Brown <rbrown64@csc.com.au> + + * config/i386/tm-i386v4.h: Define HAVE_I387_REGS. + * config/i386/i386v42mp.mh: Add i387-nat.o . + * i386v4-nat.c: Include i387-nat.h. + (supply_fpregset): Use i387_supply_fsave. + (fill_fpregset): Use i387_fill_fsave. + +2002-01-30 Richard Earnshaw <rearnsha@arm.com> + + * arm-tdep.c (arm_call_dummy_words): Define. + * arm-linux-tdep.c (arm_linux_call_dummy_words): Define. + * config/arm/tm-arm.h (CALL_DUMMY_P): Define. + (CALL_DUMMY_WORDS): Define. + (arm_call_dummy_words): Declare. + * config/arm/tm-linux.h (CALL_DUMMY_WORDS): Define. + (arm_linux_call_dummy_words): Declare. + +2002-01-30 Andreas Schwab <schwab@suse.de> + + * m68klinux-nat.c: Fix last change to use regcache_collect + instead of referencing registers[] directly. + +2002-01-29 Andrew Cagney <ac131313@redhat.com> + + * parse.c (target_map_name_to_register): Delete code wrapped in + #ifdef REGISTER_NAME_ALIAS_HOOK. + +2002-01-28 Michael Snyder <msnyder@redhat.com> + + * regcache.c (legacy_read_register_gen): Need to be able to + read pseudo-register as well as real register. + (legacy_write_register_gen): Ditto. + +2002-01-28 Andrew Cagney <ac131313@redhat.com> + + * config/mips/tm-wince.h (TARGET_BYTE_ORDER): Delete. + * config/sparc/tm-sparc.h (TARGET_BYTE_ORDER): Delete. + * config/ns32k/tm-umax.h (TARGET_BYTE_ORDER): Delete. + * config/ia64/tm-ia64.h (TARGET_BYTE_ORDER): Delete. + * config/m32r/tm-m32r.h (TARGET_BYTE_ORDER): Delete. + * config/m68k/tm-m68k.h (TARGET_BYTE_ORDER): Delete. + * config/m88k/tm-m88k.h (TARGET_BYTE_ORDER): Delete. + * config/mn10200/tm-mn10200.h (TARGET_BYTE_ORDER): Delete. + * config/pa/tm-hppa.h (TARGET_BYTE_ORDER): Delete. + * config/sh/tm-wince.h (TARGET_BYTE_ORDER): Delete. + * config/v850/tm-v850.h (TARGET_BYTE_ORDER): Delete. + * config/vax/tm-vax.h (TARGET_BYTE_ORDER): Delete. + * config/z8k/tm-z8k.h (TARGET_BYTE_ORDER): Delete. + * config/i960/tm-i960.h (TARGET_BYTE_ORDER): Delete. + * config/i386/tm-i386.h (TARGET_BYTE_ORDER): Delete. + * config/h8500/tm-h8500.h (TARGET_BYTE_ORDER): Delete. + * config/h8300/tm-h8300.h (TARGET_BYTE_ORDER): Delete. + * config/fr30/tm-fr30.h (TARGET_BYTE_ORDER): Delete. + * config/d30v/tm-d30v.h (TARGET_BYTE_ORDER): Delete. + * config/alpha/tm-alpha.h (TARGET_BYTE_ORDER): Delete. + +2002-01-28 Andrew Cagney <ac131313@redhat.com> + + * arch-utils.c (TARGET_BYTE_ORDER_DEFAULT): Delete macro. + (target_byte_order): Initialize to BFD_ENDIAN_BIG. + (initialize_current_architecture): Update target_byte_order using + information from BFD. + * config/mcore/tm-mcore.h (TARGET_BYTE_ORDER_DEFAULT): + * config/arm/tm-arm.h (TARGET_BYTE_ORDER_DEFAULT): Delete. + +2002-01-28 Andrew Cagney <ac131313@redhat.com> + + * config/vax/tm-vax.h (INVALID_FLOAT): Move macro from here... + * vax-tdep.c (INVALID_FLOAT): To here. Document why it is broken. + + * rs6000-tdep.c (rs6000_do_registers_info): Delete code wrapped in + #ifdef INVALID_FLOAT. + * infcmd.c (do_registers_info): Ditto. + * values.c (unpack_double): Ditto. Add comment. + + * config/ns32k/tm-umax.h (INVALID_FLOAT): Delete macro that was + already commented out. + +2002-01-26 Andreas Schwab <schwab@suse.de> + + * config/m68k/nm-linux.h (FETCH_INFERIOR_REGISTERS): Define. + * m68klinux-nat.c: Update ptrace interface for fetching/storing + registers and add support for PTRACE_GETREGS. + +2002-01-24 Andrew Cagney <ac131313@redhat.com> + + GDB 5.1.1 released from 5.1 branch. + * NEWS: Add 5.1.1 news. + * README: Sync with 5.1 branch. + +2002-01-23 Fred Fish <fnf@redhat.com> + + * mdebugread.c (parse_partial_symbols): Only copy stabstring1 to + stabstring on initial malloc. Reallocing will copy it for us, + if necessary. + +2002-01-23 Elena Zannoni <ezannoni@redhat.com> + + * Makefile.in (hpread_h): Delete. + (HFILES_NO_SRCDIR): Remove hpread.h. + (ALLDEPFILES): Remove hp-psymtab-read.c and hp-symtab-read.c. + (hpread.o): Update dependencies. + (hp-psymtab-read.o, hp-symtab-read.o): Remove. + + * hp-psymtab-read.c: Remove file. + * hp-symtab-read.c: Remove file. + * hpread.h: Remove file. + + * hpread.c: Merge all contents of hp-psymtab-read.c, + hp-symtab-read.c and hpread.h into this file, as it was prior to + January 1999. + + * config/pa/hpux11w.mh, config/pa/hpux11.mh, + config/pa/hpux1020.mh, config/pa/hppaosf.mh, + config/pa/hppahpux.mh, config/pa/hppabsd.mh (NATDEPFILES): + Remove hp-psymtab-read.o and hp-symtab-read.o, add hpread.o. + +2002-01-23 Elena Zannoni <ezannoni@redhat.com> + + * ppc-linux-nat.c (ppc_register_u_addr, supply_gregset, + fill_gregset): Call gdbarch_tdep() just once, assign result to + variable and use that, instead of calling the function several + times. + +2002-01-24 Alexandre Oliva <aoliva@redhat.com> + + * configure.host: Accept sparcv9 as alias for sparc64. + * configure.tgt: Likewise. + +2002-01-22 Kevin Buettner <kevinb@redhat.com> + + * solib-aix5.c (build_so_list_from_mapfile) + (aix5_relocate_main_executable): Fix xcalloc() calls so order of + arguments is not reversed. + * solib-sunos.c (sunos_relocate_main_executable): Likewise. + * solib-svr4.c (svr4_relocate_main_executable): Likewise. + +2002-01-22 Elena Zannoni <ezannoni@redhat.com> + + * sh-tdep.c (sh_pseudo_register_read): New function. Renamed and + modified version of obsolete sh_fetch_pseudo_register. + (sh_fetch_pseudo_register): Rename to sh_pseudo_register_read. + (sh4_register_read): New function. + (sh_pseudo_register_write): New function. Renamed and modified + version of obsolete sh_store_pseudo_register. + (sh_store_pseudo_register): Rename to sh_pseudo_register_write. + (sh4_register_write): New function. + (sh_gdbarch_init): Remove setting of gdbarch function + fetch_pseudo_register and store_pseudo_register. Remove setting of + register_convert_to_raw, register_convert_to_virtual, + register_convertible. + (sh_sh4_register_convertible): Delete. No longer needed. All is + taken care by architecture specific functions + register_read/register_write. + (sh_sh4_register_convert_to_virtual): Make static. + (sh_sh4_register_convert_to_raw): Ditto. + +2002-01-22 Andrew Cagney <ac131313@redhat.com> + + * doublest.c (floatformat_is_negative): Assert FMT is non NULL. + (floatformat_is_nan, floatformat_mantissa): Ditto. + + * gdbtypes.c (_initialize_gdbtypes): Initialize TYPE_FLOATFORMAT + for builtin_type_ieee_single_little, builtin_type_ieee_double_big, + builtin_type_ieee_double_little, + builtin_type_ieee_double_littlebyte_bigword, + builtin_type_m68881_ext, builtin_type_i960_ext, + builtin_type_m88110_ext, builtin_type_m88110_harris_ext, + builtin_type_arm_ext_big, builtin_type_arm_ext_littlebyte_bigword, + builtin_type_ia64_spill_big, builtin_type_ia64_spill_little and + builtin_type_ia64_quad_big, builtin_type_ia64_quad_little. + +2002-01-22 Corinna Vinschen <vinschen@redhat.com> + + * xstormy16-tdep.c (xstormy16_scan_prologue): Add frameless + parameter. Set frameless flag if it exists and depended of + whether the scanned function is frameless or not. + (xstormy16_skip_prologue): If function is frameless, return + result of xstormy16_scan_prologue(). + (xstormy16_frame_init_saved_regs): Adjust xstormy16_scan_prologue() + call. + +2002-01-21 Elena Zannoni <ezannoni@redhat.com> + + * sh-tdep.c (sh_fp_frame_init_saved_regs, sh_push_arguments, + sh_generic_show_regs, sh3_show_regs, sh3e_show_regs, + sh3_dsp_show_regs, sh4_show_regs, sh_dsp_show_regs, + sh_sh4_register_byte, sh_sh4_register_raw_size, + sh_sh3e_register_virtual_type, sh_sh4_register_virtual_type, + sh_sh4_register_convertible, sh_sh4_register_convert_to_virtual, + sh_sh4_register_convert_to_raw, sh_fetch_pseudo_register, + sh_store_pseudo_register, sh_do_pseudo_register): Call + gdbarch_tdep() just once, assign result to variable and use that, + instead of calling the function several times. + +2002-01-20 Mark Kettenis <kettenis@gnu.org> + + * go32-nat.c (fetch_register): Use FP_REGNUM_P and FPC_REGNUM_P + macros instead of LAST_FPU_CTRL_REGNUM. + (store_register): Likewise. + +2002-01-21 Jim Blandy <jimb@redhat.com> + + * infcmd.c (run_command): Check that the `exec' target layer's BFD + is up-to-date before running the program, not just when a program + exits. + +2002-01-21 Fred Fish <fnf@redhat.com> + + * arm-tdep.c (thumb_skip_prologue): Quit scanning prologue + when we have found all instructions we are looking for. + +2002-01-21 Richard Earnshaw <rearnsha@arm.com> + + * arm-tdep.c (arm_register_name): New function. + (arm_registers_names): Make static. + * config/arm/tm-arm.h (arm_register_names): Delete declaration. + (arm_register_name): Declare. + (REGISTER_NAME): Use it. + +2002-01-21 Richard Earnshaw <rearnsha@arm.com> + Kevin Buettner <kevinb@redhat.com> + + Convert arm targets to new FRAME interface. + * arm-tdep.c (struct frame_extra_info): Remove fsr. + (arm_frame_find_save_regs): Delete. + (arm_frame_init_saved_regs): New. + (arm_init_extra_frame_info): Alloacte saved_regs as required. + Allocate extra_info as required. Convert all uses of fsr.regs + to use saved_regs, similarly all uses of EXTRA_FRAME_INFO fields + to use extra_info. + (thumb_scan_prologue, arm_scan_prologue, arm_find_callers_reg) + (arm_frame_chain, arm_frame_saved_pc, arm_pop_frame): Likewise. + (check_prologue_cache, save_prologue_cache): Likewise. + (_initialize_arm_tdep): Ensure prologue_cache is correctly set up. + * config/arm/tm-arm.h (EXTRA_FRAME_INFO): Delete. + (FRAME_FIND_SAVED_REGS): Delete. + (arm_frame_find_saved_regs): Delete prototype. + (arm_frame_init_saved_regs): New prototype. + (FRAME_INIT_SAVED_REGS): Define. + +2002-01-20 Andrew Cagney <ac131313@redhat.com> + + * config/arc/tm-arc.h (IEEE_FLOAT): Delete. + +2002-01-20 Andrew Cagney <ac131313@redhat.com> + + From Jeff Law <law@redhat.com>: + * infttrace.c: Include <sys/pstat.h>. + (child_pid_to_exec_file): Revamp. Use pstat call to get the + exec file if the ttrace equivalent fails. + +2002-01-20 Andrew Cagney <ac131313@redhat.com> + + * rdi-share/devsw.c (openLogFile): Delete unused ``struct tm lt''. + (closeLogFile): Ditto. + +2002-01-20 Michael Chastain <mec@shout.net> + + * top.c (print_gdb_version): Bump copyright year to 2002. + +2002-01-20 Andrew Cagney <ac131313@redhat.com> + + * MAINTAINERS (Blanket Write Privs): Add Kevin Buettner, Elena + Zannoni and Eli Zaretskii. + +2002-01-20 Daniel Jacobowitz <drow@mvista.com> + + * buildsym.c: Update copyright years. + * c-typeprint.c: Likewise. + * dwarf2read.c: Likewise. + * f-typeprint.c: Likewise. + * gdbtypes.c: Likewise. + * gdbtypes.h: Likewise. + * hp-symtab-read.c: Likewise. + * hpread.c: Likewise. + * mdebugread.c: Likewise. + * p-typeprint.c: Likewise. + +2002-01-20 Andrew Cagney <ac131313@redhat.com> + + * remote-sim.c (gdbsim_open): Simplify code testing the macro + TARGET_BYTE_ORDER_SELECTABLE_P. Assume the target is always + byte-order selectable. + * sparc-tdep.c (sparc_target_architecture_hook): Ditto. + * arch-utils.c: Ditto. + (set_endian): Ditto. + (set_endian_from_file): Ditto. + * gdbserver/low-sim.c (create_inferior): Ditto. + * gdbarch.sh: Ditto. + * gdbarch.h: Re-generate. + * config/powerpc/tm-ppc-eabi.h (TARGET_BYTE_ORDER_SELECTABLE_P): + * config/sparc/tm-sparclite.h (TARGET_BYTE_ORDER_SELECTABLE): + * config/sparc/tm-sparclet.h (TARGET_BYTE_ORDER_SELECTABLE): + * config/mcore/tm-mcore.h (TARGET_BYTE_ORDER_SELECTABLE_P): + * config/arm/tm-wince.h (TARGET_BYTE_ORDER_SELECTABLE_P): + * config/arm/tm-linux.h (TARGET_BYTE_ORDER_SELECTABLE_P): + * config/arc/tm-arc.h (TARGET_BYTE_ORDER_SELECTABLE): + * config/arm/tm-arm.h (TARGET_BYTE_ORDER_SELECTABLE_P): Delete + macro definition. + * config/mips/tm-wince.h: Remove #undef of macro + TARGET_BYTE_ORDER_SELECTABLE. + * config/sh/tm-wince.h: Ditto. + +2002-01-20 Daniel Jacobowitz <drow@mvista.com> + + * gdbtypes.h (struct cplus_struct_type): Add is_artificial to + member function fields. Add accessor macro + TYPE_FN_FIELD_ARTIFICIAL. + * dwarf2read.c (dwarf2_add_member_fn): Check for artificial methods. + * c-typeprint.c (c_type_print_base): Skip artificial member + functions. + +2002-01-20 Daniel Jacobowitz <drow@mvista.com> + + * f-typeprint.c: Delete unused function f_type_print_args. + * p-typeprint.c: Delete unused function pascal_type_print_args. + +2002-01-20 Daniel Jacobowitz <drow@mvista.com> + + * gdbtypes.h (struct type): Fix whitespace. Remove obsolete + comment. Add ``artificial'' to ``union field_location''. + + * dwarf2read.c: Remove ad-hoc TYPE_FIELD_ARTIFICIAL. + + * buildsym.c (finish_block): Initialize TYPE_FIELD_ARTIFICIAL to 0. + * mdebugread.c (parse_symbol): Likewise. + * stabsread.c (define_symbol): Likewise. + * hp-symtab-read.c (hpread_function_type): Likewise, instead of + initializing TYPE_FIELD_BITPOS to n (obsolete). + (hpread_doc_function_type): Likewise. + * hpread.c (hpread_function_type): Likewise. + +2002-01-20 Andrew Cagney <ac131313@redhat.com> + + * configure.in (host_makefile_frag): Only require a host makefile + fragment when a native build. + * configure: Re-generate. + +2002-01-20 Andrew Cagney <ac131313@redhat.com> + + * doublest.h (floatformat_from_type): Declare. + * doublest.c (floatformat_from_type): New function. + (convert_typed_floating): Use. + + * valprint.c (print_floating): Replace checks for IEEE_FLOAT with + call to function floatformat_from_type. + + * gdbarch.sh (IEEE_FLOAT): Delete. + * gdbarch.h, gdbarch.c: Re-generate. + * config/i960/tm-i960.h (IEEE_FLOAT): Delete macro. + * config/i386/tm-i386.h (IEEE_FLOAT): Ditto. + * config/z8k/tm-z8k.h (IEEE_FLOAT): Ditto. + * config/sparc/tm-sparc.h (IEEE_FLOAT): Ditto. + * config/pa/tm-hppa.h (IEEE_FLOAT): Ditto. + * config/m88k/tm-m88k.h (IEEE_FLOAT): Ditto. + * config/m68k/tm-m68k.h (IEEE_FLOAT): Ditto. + * config/h8500/tm-h8500.h (IEEE_FLOAT): Ditto. + * config/h8300/tm-h8300.h (IEEE_FLOAT): Ditto. + * config/fr30/tm-fr30.h (IEEE_FLOAT): Ditto. + * config/arm/tm-arm.h (IEEE_FLOAT): Ditto. + * config/alpha/tm-alpha.h (IEEE_FLOAT): Ditto. + + * s390-tdep.c (s390_gdbarch_init): Do not set ieee_float. + * x86-64-tdep.c (i386_gdbarch_init): Ditto. + * sparc-tdep.c (sparc_gdbarch_init): Ditto. + * sh-tdep.c (sh_gdbarch_init): Ditto. + * mips-tdep.c (mips_gdbarch_init): Ditto. + * m68hc11-tdep.c (m68hc11_gdbarch_init): Ditto. + * cris-tdep.c (cris_gdbarch_init): Ditto. + +2002-01-20 Jiri Smid <smid@suse.cz> + + * configure.host, configure.tgt: Support x86-64. + * NEWS: Note new target x86-64. + + * config/i386/x86-64linux.mh (NATDEPFILES): x86-64-nat.o removed. + * x86-64-linux-nat.c (x86_64_register_u_addr): New function. + * config/i386/nm-x86-64.h (ATTACH_LWP): Removed. + * Makefile.in (x86-64-tdep.o, x86-64-linux-tdep.o, + x86-64-linux-nat.o): Fix dependencies. + +2002-01-19 Andrew Cagney <ac131313@redhat.com> + + * utils.c: Remove #ifndef MALLOC_INCOMPATIBLE. + * config/sparc/xm-sun4os4.h (PTRACE_ARG3_TYPE): Move macro .... + * config/sparc/nm-sun4os4.h (PTRACE_ARG3_TYPE): ... to here. + * config/sparc/xm-sun4os4.h: Delete file. + * config/sparc/sun4os4.mh (XM_FILE): Delete makefile variable. + +2002-01-19 Andrew Cagney <ac131313@redhat.com> + + * config/sparc/sparclynx.mh (XM_FILE): Delete. + * config/rs6000/rs6000lynx.mh (XM_FILE): Delete. + * config/m68k/m68klynx.mh (XM_FILE): Delete. + * config/i386/i386lynx.mh (XM_FILE): Delete. + * config/rs6000/xm-rs6000ly.h: Delete file. + * config/sparc/xm-sparclynx.h: Delete file. + * config/m68k/xm-m68klynx.h: Delete file. + * config/i386/xm-i386lynx.h: Delete file. + * config/xm-lynx.h: Delete file. + * config/djgpp/fnchange.lst: Update. + +2002-01-19 Jason Thorpe <thorpej@wasabisystems.com> + + * alpha-tdep.c (alpha_register_byte): New function. + (alpha_register_raw_size): Ditto. + (alpha_register_virtual_size): Ditto. + (alpha_skip_prologue_internal): Renamed from + alpha_skip_prologue. + (alpha_skip_prologue): New version that calls + alpha_skip_prologue_internal. + (alpha_in_lenient_prologue): Use alpha_skip_prologue_internal. + * config/alpha/tm-alpha.h (SKIP_PROLOGUE): Remove + second argument from alpha_skip_prologue. + (REGISTER_BYTE): Use alpha_register_byte. + (REGISTER_RAW_SIZE): Use alpha_register_raw_size. + (REGISTER_VIRTUAL_SIZE): Use alpha_register_virtual_size. + (FRAMELESS_FUNCTION_INVOCATION): Use + generic_frameless_function_invocation_not. + (FRAME_NUM_ARGS): Use frame_num_args_unknown. + (COERCE_FLOAT_TO_DOUBLE): Use standard_coerce_float_to_double. + +2002-01-19 Andrew Cagney <ac131313@redhat.com> + + * config/mips/xm-news-mips.h: Delete file. + * config/mips/news-mips.mh (XM_FILE): Delete makefile variable. + + * config/m88k/xm-m88k.h: Delete file. + * config/m88k/xm-dgux.h: Do not include xm-m88k.h. + * config/m88k/xm-delta88v4.h: Ditto. + * config/m88k/xm-delta88.h: Ditto. + + * config/alpha/xm-fbsd.h: Delete file. + * config/alpha/fbsd.mh (XM_FILE): Delete makefile variable. + + * config/sparc/xm-sparc.h: Delete file. + * Makefile.in (xm-sun4os4.h): Delete dependency. + * config/sparc/xm-sun4sol2.h: Do not include xm-sparc.h. + * config/sparc/xm-sun4os4.h: Ditto. + * config/sparc/xm-linux.h: Ditto. + + * config/i386/xm-windows.h: Delete file. + +2002-01-19 Andrew Cagney <ac131313@redhat.com> + + * utils.c: Include <sys/param.h> for MAXPATHLEN. + (gdb_realpath): Use MAXPATHLEN when PATH_MAX is not defined. + +2002-01-19 Jason Thorpe <thorpej@wasabisystems.com> + + * alpha-tdep.c (alpha_call_dummy_words): New. + * config/alpha/tm-alpha.h (CALL_DUMMY): Remove. + (CALL_DUMMY_P): Define. + (CALL_DUMMY_WORDS): Define. + (SIZEOF_CALL_DUMMY_WORDS): Define. + +2002-01-19 Per Bothner <per@bothner.com> + + * gnu-v3-abi.c (gnuv3_rtti_type): Guard that vtable_symbol_name + isn't NULL, which can happen with some gcj-3.x-produced code. + +2002-01-19 Jason Thorpe <thorpej@wasabisystems.com> + + * alpha-tdep.c (alpha_register_virtual_type): New function. + (alpha_init_frame_pc_first): Ditto. + (alpha_fix_call_dummy): Ditto. + (alpha_store_struct_return): Ditto. + (alpha_extract_struct_value_address): Ditto. + * config/alpha/tm-alpha.h (REGISTER_VIRTUAL_TYPE): Use + alpha_register_virtual_type. + (STORE_STRUCT_RETURN): Use alpha_store_struct_return. + (EXTRACT_STRUCT_VALUE_ADDRESS): Use + alpha_extract_struct_value_address. + (FIX_CALL_DUMMY): Use alpha_fix_call_dummy. + (INIT_FRAME_PC): Use init_frame_pc_noop. + (INIT_FRAME_PC_FIRST): Use alpha_init_frame_pc_first. + +2002-01-19 Mark Kettenis <kettenis@gnu.org> + + * i386gnu-nat.c: Include "i386-tdep.h". + (fetch_fpregs): Simplify code dealing with uninitialized floating + point states such that it doesn't require FP7_REGNUM. + +2002-01-18 Jason Thorpe <thorpej@wasabisystems.com> + + * alpha-tdep.c (frame_extra_info): New. + (alpha_find_saved_regs): Make static. Use + frame->extra_info. + (alpha_frame_init_saved_regs): New function. + (alpha_frame_saved_pc): Use frame->extra_info. + (temp_saved_regs): Don't declare as struct frame_saved_regs. + (heuristic_proc_desc): Adjust for temp_saved_regs changes. + (init_extra_frame_info): Rename to... + (alpha_init_extra_frame_info): ...this. Use frame->extra_info. + (alpha_print_extra_frame_info): New function. + (alpha_frame_locals_address): Ditto. + (alpha_frame_args_address): Ditto. + (alpha_pop_frame): Use frame->extra_info. + * config/alpha/tm-alpha.h (FRAME_ARGS_ADDRESS): Use + alpha_frame_args_address. + (FRAME_LOCALS_ADDRESS): Use alpha_frame_locals_address. + (alpha_find_saved_regs): Remove prototype. + (FRAME_INIT_SAVED_REGS): Use alpha_frame_init_saved_regs. + (EXTRA_FRAME_INFO): Remove. + (INIT_EXTRA_FRAME_INFO): Use alpha_init_extra_frame_info. + (PRINT_EXTRA_FRAME_INFO): Use alpha_print_extra_frame_info. + +2002-01-18 Jason Thorpe <thorpej@wasabisystems.com> + + * alpha-tdep.c (alpha_osf_in_sigtramp): New function. + (alpha_cannot_fetch_register): Ditto. + (alpha_cannot_store_register): Ditto. + (alpha_register_convertible): Ditto. + (alpha_use_struct_convention): Ditto. + * config/alpha/tm-alpha.h: Update copyright years. + (IN_SIGTRAMP): Use alpha_osf_in_sigtramp. + (INNER_THAN): Use core_addr_lessthan. + (CANNOT_FETCH_REGISTER): Use alpha_cannot_fetch_register. + (CANNOT_STORE_REGISTER): Use alpha_cannot_store_register. + (REGISTER_CONVERTIBLE): Use alpha_register_convertible. + (USE_STRUCT_CONVENTION): Use alpha_use_struct_convention. + (FRAME_CHAIN): Remove unnecessary cast. + +2002-01-18 Andrew Cagney <ac131313@redhat.com> + + * NEWS: Document that testsuite/gdb.hp/gdb.threads-hp/ is + obsolete. + +2002-01-18 Andrew Cagney <ac131313@redhat.com> + + * infptrace.c: Remove ATTRIBUTE_UNUSED. Update copyright. + * monitor.c, remote-array.c, remote-bug.c: Ditto. + * remote-e7000.c, remote-es.c, remote-mips.c: Ditto. + * remote-nindy.c, remote-os9k.c, remote-rdi.c: Ditto. + * remote-rdp.c, remote-sds.c, remote-sim.c: Ditto. + * remote-st.c, remote-vx.c, remote.c, win32-nat.c: Ditto. + * x86-64-linux-nat.c: Ditto. + +2002-01-18 Jason Thorpe <thorpej@wasabisystems.com> + + * alpha-tdep.c (alpha_register_name): New function. + * config/alpha/tm-alpha.h (REGISTER_NAMES): Remove. + (REGISTER_NAME): Define. + +2002-01-18 Jason Thorpe <thorpej@wasabisystems.com> + + * config/nm-nbsd.h (KERNEL_U_ADDR): Remove. + +2002-01-18 Jason Thorpe <thorpej@wasabisystems.com> + + * alpha-tdep.c: Update copyright years. + (alpha_next_pc): New function. + (alpha_software_single_step): Ditto. + * config/alpha/tm-alpha.h: Add prototype for + alpha_software_single_step. + +2002-01-18 Jason Thorpe <thorpej@wasabisystems.com> + + * alphabsd-nat.c: Update copyright years. + (fill_gregset): Use regcache_collect. + (fill_fpregset): Likewise. + (fetch_inferior_registers): Only fetch integer registers + if requested to do so. + (store_inferior_registers): Only store integer registers + if requested to do so. + +2002-01-17 Andrew Cagney <ac131313@redhat.com> + + * config/alpha/alpha-osf3.mh (XDEPFILES): Delete. + * config/alpha/alpha-osf2.mh (XDEPFILES): Delete. + * config/alpha/alpha-osf1.mh (XDEPFILES): Delete. + * config/alpha/alpha-linux.mh (XDEPFILES): Delete. + * config/alpha/fbsd.mh (XDEPFILES): Delete. + * config/arm/linux.mh (XDEPFILES): Delete. + * config/arm/nbsd.mh (XDEPFILES): Delete. + * config/i386/i386dgux.mh (XDEPFILES): Delete. + * config/i386/i386sol2.mh (XDEPFILES): Delete. + * config/i386/i386m3.mh (XDEPFILES): Delete. + (NATDEPFILES): Move i387-tdep.o and core-aout.o to here. + * config/i386/i386gnu.mh (XDEPFILES): Delete. + * config/i386/fbsd.mh (XDEPFILES): Delete. + * config/i386/i386bsd.mh (XDEPFILES): Delete. + * config/i386/i386sco5.mh (XDEPFILES): Delete. + * config/i386/i386v4.mh (XDEPFILES): Delete. + * config/i386/i386v42mp.mh (XDEPFILES): Delete. + * config/i386/i386sco4.mh (XDEPFILES): Delete. + * config/i386/i386aix.mh (XDEPFILES): Delete. + * config/i386/go32.mh (XDEPFILES): Delete. + * config/i386/cygwin.mh (XDEPFILES): Delete. + * config/i386/i386lynx.mh (XDEPFILES): Delete. + * config/i386/i386mach.mh (XDEPFILES): Delete. + * config/i386/i386v32.mh (XDEPFILES): Delete. + * config/i386/linux.mh (XDEPFILES): Delete. + * config/i386/nbsdelf.mh (XDEPFILES): Delete. + * config/i386/ncr3000.mh (XDEPFILES): Delete. + * config/i386/i386mk.mh (NATDEPFILES): Rename XDEPFILES. + * config/i386/i386sco.mh (XDEPFILES): Delete. + * config/i386/i386v.mh (XDEPFILES): Delete. + * config/i386/nbsd.mh (XDEPFILES): Delete. + * config/i386/ptx.mh (NATDEPFILES): Rename XDEPFILES. + * config/i386/ptx4.mh (NATDEPFILES): Rename XDEPFILES. + * config/i386/symmetry.mh (XDEPFILES): Delete. + * config/i386/obsd.mh (XDEPFILES): Delete. + * config/i386/x86-64linux.mh (XDEPFILES): Delete. + * config/ia64/linux.mh (XDEPFILES): Delete. + * config/ia64/aix.mh (XDEPFILES): Delete. + * config/m68k/apollo68b.mh (XDEPFILES): Delete. + * config/m68k/dpx2.mh (XDEPFILES): Delete. + * config/m68k/3b1.mh (NATDEPFILES): Rename XDEPFILES. + * config/m68k/apollo68v.mh (XDEPFILES): Delete. + * config/m68k/hp300bsd.mh (XDEPFILES): Delete. + * config/m68k/linux.mh (XDEPFILES): Delete. + * config/m68k/m68klynx.mh (XDEPFILES): Delete. + * config/m68k/m68kv4.mh (XDEPFILES): Delete. + * config/m68k/nbsd.mh (XDEPFILES): Delete. + * config/m68k/sun2os3.mh (XDEPFILES): Delete. + * config/m68k/sun2os4.mh (XDEPFILES): Delete. + * config/m68k/sun3os3.mh (XDEPFILES): Delete. + * config/m68k/sun3os4.mh (XDEPFILES): Delete. + * config/m88k/delta88.mh (XDEPFILES): Delete. + * config/m88k/delta88v4.mh (XDEPFILES): Delete. + * config/m88k/m88k.mh (XDEPFILES): Delete. + * config/mips/littlemips.mh (NATDEPFILES): Rename XDEPFILES. + * config/mips/linux.mh (XDEPFILES): Delete. + * config/mips/irix6.mh (XDEPFILES): Delete. + * config/mips/irix5.mh (XDEPFILES): Delete. + * config/mips/irix4.mh (XDEPFILES): Delete. + * config/mips/irix3.mh (XDEPFILES): Delete. + * config/mips/decstation.mh (XDEPFILES): Delete. + * config/mips/mipsm3.mh (XDEPFILES): Delete. + (NATDEPFILES): Move core-aout.o to here. + * config/ns32k/nbsd.mh (XDEPFILES): Delete. + * config/pa/hpux1020.mh (XDEPFILES): Delete. + * config/pa/hppabsd.mh (XDEPFILES): Delete. + * config/pa/hppahpux.mh (XDEPFILES): Delete. + * config/pa/hpux11w.mh (XDEPFILES): Delete. + * config/pa/hppaosf.mh (XDEPFILES): Delete. + * config/pa/hpux11.mh (XDEPFILES): Delete. + * config/powerpc/aix.mh (XDEPFILES): Delete. + * config/powerpc/nbsd.mh (XDEPFILES): Delete. + * config/powerpc/linux.mh (XDEPFILES): Delete. + * config/romp/rtbsd.mh: Rename XDEPFILES. + * config/rs6000/rs6000lynx.mh (XDEPFILES): Delete. + * config/rs6000/aix4.mh (XDEPFILES): Delete. + * config/rs6000/rs6000.mh (XDEPFILES): Delete. + * config/s390/s390.mh (XDEPFILES): Delete. + * config/vax/vaxbsd.mh (NATDEPFILES): Rename XDEPFILES. + * config/sparc/sun4sol2.mh (XDEPFILES): Delete. + * config/sparc/sun4os4.mh (XDEPFILES): Delete. + * config/sparc/sparclynx.mh (XDEPFILES): Delete. + * config/sparc/nbsdelf.mh (XDEPFILES): Delete. + * config/sparc/nbsd.mh (XDEPFILES): Delete. + * config/sparc/linux.mh (XDEPFILES): Delete. + * config/vax/vaxult.mh (XDEPFILES): Delete. + * config/vax/vaxult2.mh (XDEPFILES): Delete. + * Makefile.in (DEPFILES): Remove XDEPFILES. + +2002-01-17 Andrew Cagney <ac131313@redhat.com> + + * utils.c (internal_verror): Fix comments, default is yes not no. + Update queries to match. Default to quit and dump core. + +2002-01-17 Andrew Cagney <ac131313@redhat.com> + + * breakpoint.c: Update assuming #if UI_OUT is always true. Update + copyright. + * defs.h, event-top.c, gdbcmd.h: Ditto. + * infcmd.c, infrun.c, main.c, printcmd.c, remote.c: Ditto. + * source.c, stack.c, symfile.c, symtab.c, thread.c: Ditto. + * top.c, cli/cli-cmds.c, cli/cli-decode.c: Ditto. + * cli/cli-script.c, cli/cli-script.h, cli/cli-setshow.c: Ditto. + * mi/ChangeLog, mi/mi-cmd-break.c, mi/mi-cmd-stack.c: Ditto. + * mi/mi-main.c:Ditto. + + * stack.c, symfile.c: Update copyright. + +2002-01-17 Daniel Jacobowitz <drow@mvista.com> + + * gdbserver/low-hppabsd.c, gdbserver/low-lynx.c, + gdbserver/low-nbsd.c, gdbserver/low-sim.c, + gdbserver/low-sparc.c, gdbserver/low-sun3.c, + gdbserver/low-linux.c, gdbserver/server.c: Correct copyright notices. + +2002-01-17 Daniel Jacobowitz <drow@mvista.com> + + * gdbserver/low-hppabsd.c (myattach): New function, returning -1. + * gdbserver/low-lynx.c (myattach): Likewise. + * gdbserver/low-nbsd.c (myattach): Likewise. + * gdbserver/low-sim.c (myattach): Likewise. + * gdbserver/low-sparc.c (myattach): Likewise. + * gdbserver/low-sun3.c (myattach): Likewise. + + * gdbserver/low-linux.c (myattach): New function. + + * gdbserver/server.c (attach_inferior): New function. + (main): Handle "--attach". + +2002-01-16 Andrew Cagney <ac131313@redhat.com> + + * MAINTAINERS (language support): Daniel Jacobwitz is C++ + maintainer. + +2002-01-15 Daniel Jacobowitz <drow@mvista.com> + + * c-typeprint.c (is_type_conversion_operator): Add additional + check for non-conversion operators. + +2002-01-15 Michael Snyder <msnyder@redhat.com> + + * linux-proc.c: Add "info proc" command, a la procfs.c. + (read_mapping): New function, abstract and re-use code. + (linux_find_memory_regions): Use new func read_mapping. + (linux_info_proc_cmd): New function, implement "info proc". + (_initialize_linux_proc): Add new command "info proc". + +2002-01-15 Michael Snyder <msnyder@redhat.com> + + * symfile.c (generic_load): Use bfd_map_over_sections method + instead of manipulating bfd structure members directly. + (add_section_size_callback): New function, bfd sections callback + used by generic_load. + (load_sections_callback): New function, bfd sections callback + used by generic_load. + +2002-01-15 Elena Zannoni <ezannoni@redhat.com> + + [Based on work by Jim Blandy] + * gdbtypes.h (builtin_type_v16qi, builtin_type_v8hi): Export. + (builtin_type_vec128): Export. + * gdbtypes.c (builtin_type_v16qi, builtin_type_v8hi): New SIMD + types. + (builtin_type_vec128): New builtin type for 128 bit vector + registers. + (build_gdbtypes): Initialize builtin_type_v16qi and + builtin_type_v8hi. Create the vec128 register builtin type + structure. + (build_builtin_type_vec128): New function. + (_initialize_gdbtypes): Register builtin_type_v16qi and + builtin_type_v8hi with gdbarch. Same for builtin_type_vec128. + * rs6000-tdep.c (rs6000_register_virtual_type): Change type of + AltiVec register to new builtin type. + +2001-01-15 Daniel Jacobowitz <drow@mvista.com> + + * stabsread.c (read_type): Pass dbx_lookup_type (typenums) + to make_cv_type. + +2002-01-14 Andrew Cagney <ac131313@redhat.com> + + * config/pa/tm-hppa.h (DEPRECATED_CLEAN_UP_REGISTER_VALUE): Rename + CLEAN_UP_REGISTER_VALUE. + * regcache.c (supply_register): Update only call. + +2002-01-14 Andrew Cagney <ac131313@redhat.com> + + * configure.tgt: Mark a29k-*-aout*, a29k-*-coff*, a29k-*-elf*, + a29k-*-ebmon*, a29k-*-kern*, a29k-*-none*, a29k-*-udi* and + a29k-*-vxworks* targets as obsolete. + +2002-01-14 Michael Snyder <msnyder@redhat.com> + + * linux-proc.c (linux_do_thread_registers): Ignore fpxregs + until we can resolve portability issues. + * gregset.h: Remove references to fpxregs. + * gcore.c (gcore_command): Initialize note_sec to NULL. + +2002-01-13 Andrew Cagney <ac131313@redhat.com> + + * signals.c (target_signal_to_name): Rewrite. Only use + signals[].name when in bounds and non-NULL. + +2002-01-13 Andrew Cagney <ac131313@redhat.com> + + From Petr Ledvina <ledvinap@kae.zcu.cz>: + * signals.c (target_signal_to_name): Verify that SIG is within the + bounds of the signals array. + +2002-01-13 Andrew Cagney <ac131313@redhat.com> + + * MAINTAINERS: Remove arm-coff and arm-pe from target list. + +2002-01-13 Keith Seitz <keiths@redhat.com> + + * stack.c (print_frame_info_base): Print the frame's pc + only if when print_frame_info_listing_hook is not defined. + +2002-01-13 Keith Seitz <keiths@redhat.com> + + * varobj.c (varobj_set_value): Make sure that there were no + errors evaluating the object before attempting to set its + value. + value_cast now properly adjusts VALUE_ADDRESS for baseclasses, + so this offset adjustment is no longer necessary. + (create_child): Don't set the error flag if the child is + a CPLUS_FAKE_CHILD. + (value_of_child): If value_fetch_lazy fails, return NULL + so that callers will be notified that an error occurred. + (c_value_of_variable): Delay check of variable's validity + until later. We actually want all structs and unions to have + the value "{...}". + Do not return "???" for variables which could not be evaluated. + This error condition must be returned to the caller so that it + can get the error condition from gdb. + (cplus_name_of_child): Adjust index for vptr before figuring + out the name of the child. + (cplus_value_of_child): If a child's (real) parent is not valid, + don't even bother trying to give a value for it. Just return + an error. Change all instances in this function. + (cplus_type_of_child): If our parent is one of the "fake" + parents, we need to get at the type of the real parent, and + derive the child's true type using this information. + +2002-01-13 Andrew Cagney <ac131313@redhat.com> + + From 2002-01-09 John Marshall <johnm@falch.net>: + * CONTRIBUTE, README, TODO: Change sourceware.cygnus.com to + sources.redhat.com, and tweak some related URLs which had + suffered from linkrot. + +2002-01-13 Andrew Cagney <ac131313@redhat.com> + + From Jeff law: + * hppa-tdep.c (hppa_push_arguments): Correct handling of 5-7 byte + structures passed in registers. + +2002-01-13 Eli Zaretskii <eliz@is.elta.co.il> + + * go32-nat.c (save_npx) [__DJGPP_MINOR__ < 3]: Remove extraneous + white space which prevented compilation. Reported by DSK + <dsk@student.unsw.edu.au>. + +2002-01-11 Michael Snyder <msnyder@redhat.com> + + * symfile.c (build_section_addr_info_from_section_tab): + Use bfd access method instead of manipulating bfd directly. + (syms_from_objfile): Ditto. + (simple_overlay_update_1): Ditto. + (simple_overlay_update): Ditto. + (generic_load): Ditto. + (overlay_unmapped_address): FIXME comment, bfd access methods. + (sections_overlap): FIXME comment, bfd access methods. + (pc_in_mapped_range): FIXME comment, bfd access methods. + (pc_in_unmapped_range): FIXME comment, bfd access methods. + (section_is_mapped): FIXME comment, bfd access methods. + (section_is_overlay): FIXME comment, bfd access methods. + + * symfile.c (generic_load): Whitespace and long line cleanups. + Remove duplicate variable, change several local variables to + more appropriate data types. + (print_transfer_performance): Use %lu instead of %ld for ulongs. + +2002-01-12 Andrew Cagney <ac131313@redhat.com> + + From Peter Schauer: + * language.c (longest_local_hex_string_custom): Use phex_nz to + convert NUM to a hex string. + +2002-01-12 Elena Zannoni <ezannoni@redhat.com> + + * sh-tdep.c (sh_gdbarch_init): Move setting of long_bit earlier in + the function. + Update Copyright year. + +2002-01-12 Andrew Cagney <ac131313@redhat.com> + + * language.c (longest_raw_hex_string): Delete unused function. + +2002-01-11 Petr Sorfa <petrs@caldera.com> + + * MAINTAINERS (write-after-approval): Add myself. + * dwarf2read.c (read_tag_string_type): Handling of + DW_AT_byte_size. + (read_tag_string_type): FORTRAN fix to prevent propagation of + first string size. + (set_cu_language): Handling of DW_LANG_Fortran95 + +2002-01-11 Richard Earnshaw <rearnsha@arm.com> + + * armnbsd-nat.c (fetch_inferior_registers): Change inferior_pid -> + GETPID(inferior_ptid). + (store_inferior_registers): Likewise. + +2002-01-10 Jason Merrill <jason@redhat.com> + + * dwarf2read.c (decode_locdesc): Implement DW_OP_litn, DW_OP_dup. + Fix DW_OP_minus. + +2002-01-10 Andrew Cagney <ac131313@redhat.com> + + * config/djgpp/fnchange.lst: Add renames for bfd/ChangeLog-0001 + and bfd/elf32-sh-nbsd.c. + +2002-01-10 Michael Snyder <msnyder@redhat.com> + + * NEWS: Mention --pid and corefile/proc-id behavior change. + + * Makefile.in: Add rules for gcore.o and linux-proc.o. + * gcore.c: Include cli/cli-decode.h instead of command.h. + + * main.c (captured_main): Add new command line option "--pid". + If the second command line argument (following the symbol-file) + begins with a digit, try to attach to it before trying to open + it as a corefile. + (print_gdb_help): Document the "--pid" argument. + +2002-01-10 Eli Zaretskii <eliz@is.elta.co.il> + + * completer.c (command_completer): New function. + + * completer.h <command_completer>: Add prototype. + + * cli/cli-cmds.c (init_cli_cmds): Make command_completer be the + completer for the "help" command. + +2002-01-09 Jason Merrill <jason@redhat.com> + + * c-typeprint.c (is_type_conversion_operator): Fix thinko. + +2002-01-09 Michael Snyder <msnyder@redhat.com> + + * i386-linux-nat.c (fill_fpxregset): Make global. + (store_fpxregset): Ditto. + + * gregset.h (gdb_fpxregset_t): Define. + (supply_fpxregset): Prototype. + (fill_fpxregset): Prototype. + + * exec.c (exec_make_note_section): Don't call elfcore_write_prpsinfo. + +2002-01-09 Richard Earnshaw <rearnsha@arm.com> + + * config/arm/arm-tdep.h (arm_software_single_step): Remove PARAMS. + * config/arm/nm-nbsd.h (arm_register_u_addr): Likewise. + * config/arm/tm-nbsd.h (get_longjmp_target): Likewise. + +2002-01-09 Andrew Cagney <ac131313@redhat.com> + + * MAINTAINERS: Update target maintainer rules so that any + Maintainer can approve a tested patch for a maintenance-only + target. + +2002-01-09 Richard Earnshaw <rearnsha@arm.com> + + * MAINTAINERS (write-after-approval): Add myself. + + * arm-tdep.c (arm_init_extra_frame_info): Cast NULL argument to + IN_SIGTRAMP. + +2002-01-08 Michael Snyder <msnyder@redhat.com> + + * linux-proc.c (child_pid_to_exec_file): Use readlink to get the + real name of the executable, rather than the /proc name. + +2002-01-03 Michael Snyder <msnyder@redhat.com> + + Implement a "generate-core-file" command in gdb, save target state. + * gcore.c: New file. Implement new command 'generate-core-file'. + Save a corefile image of the current state of the inferior. + * linux-proc.c: Add linux-specific code for saving corefiles. + * target.h (struct target_ops): Add new target vectors for saving + corefiles; to_find_memory_regions and to_make_corefile_notes. + (target_find_memory_regions): New macro. + (target_make_corefile_notes): New macro. + * target.c (update_current_target): Inherit new target methods. + (dummy_find_memory_regions): New place-holder method. + (dummy_make_corefile_notes): New place-holder method. + (init_dummy_target): Initialize new dummy target vectors. + * exec.c (exec_set_find_memory_regions): New function. + Allow the exec_ops vector for memory regions to be taken over. + (exec_make_note_section): New function, target vector method. + * defs.h (exec_set_find_memory_regions): Export prototype. + * procfs.c (proc_find_memory_regions): New function, corefile method. + (procfs_make_note_section): New function, corefile method. + (init_procfs_ops): Set new target vector pointers. + (find_memory_regions_callback): New function. + (procfs_do_thread_registers): New function. + (procfs_corefile_thread_callback): New function. + * sol-thread.c (sol_find_memory_regions): New function. + (sol_make_note_section): New function. + (init_sol_thread_ops): Initialize new target vectors. + * inftarg.c (inftarg_set_find_memory_regions): New function. + Allow to_find_memory_regions vector to be taken over. + (inftarg_set_make_corefile_notes): New function. + Allow to_make_corefile_notes vector to be taken over. + * thread-db.c (thread_db_new_objfile): Don't activate thread-db + interface layer if not target_has_execution (may be a corefile). + * config/i386/linux.mh: Add gcore.o to NATDEPFILES. + * config/sparc/sun4sol2.mh: Ditto. + * config/alpha/alpha-linux.mh: Ditto. + * config/arm/linux.mh: Ditto. + * config/i386/x86-64linux.mh: Ditto. + * config/ia64/linux.mh: Ditto. + * config/m68k/linux.mh: Ditto. + * config/mips/linux.mh: Ditto. + * config/powerpc/linux.mh: Ditto. + * config/sparc/linux.mh: Ditto. + +2002-01-07 Michael Snyder <msnyder@redhat.com> + + * arm-linux-nat.c: Remove references to regcache.c internal data + (registers[] and register_valid[]). + +2002-01-07 Michael Snyder <msnyder@redhat.com> + + * linux-proc.c: New file. Implement child_pid_to_exec_file, + so that attaching to a pid will automatically read the process's + symbol file and shlibs. + * Makefile.in: Add rule for linux-proc.o. + * config/nm-linux.h: Define CHILD_PID_TO_EXEC_FILE. + * config/alpha/alpha-linux.mh: Add linux-proc.o to NATDEPFILES. + * config/arm/linux.mh: Ditto. + * config/i386/linux.mh: Ditto. + * config/i386/x86-64linux.mh: Ditto. + * config/ia64/linux.mh: Ditto. + * config/m68k/linux.mh: Ditto. + * config/mips/linux.mh: Ditto. + * config/powerpc/linux.mh: Ditto. + * config/sparc/linux.mh: Ditto. + +2002-01-06 Pierre Muller <muller@ics.u-strasbg.fr> + + * win32-nat.c: Add i386-tdep.h dependency. + +2002-01-07 Michael Snyder <msnyder@redhat.com> + + * solib.c (info_sharedlibrary_command): Use TARGET_PTR_BIT + instead of bfd_get_arch_size. Don't bail out just because + there's no exec_bfd. + + * cp-valprint.c (cp_print_value): FIXME comment, alloca size. + * p-valprint.c (pascal_object_print_value): Ditto. + * somread.c (som_symtab_read): Ditto. + * symfile.c (simple_free_overlay_region_table): Ditto. + * valops.c (value_assign): Ditto. + + * tracepoint.c (tracepoint_save_command): From Klee Dienes -- + use tilde_expand and strerror for opening save-tracepoints file. + + * thread-db.c (thread_db_new_objfile): Indendation fix. + + * infptrace.c (GDB_MAX_ALLOCA): New define. + (child_xfer_memory): Use xmalloc/xfree instead of alloca if the + size of the buffer exceeds GDB_MAX_ALLOCA (default 1 megabyte, + can be overridden with whatever value is appropriate to the host). + * infttrace.c (child_xfer_memory): Add FIXME warning about use of + alloca to allocate potentially large buffer. + * rs6000-nat.c (child_xfer_memory): Ditto. + * symm-nat.c (child_xfer_memory): Ditto. + * x86-64-linux-nat.c (child_xfer_memory): Ditto. + +2002-01-07 Jackie Smith Cashion <jsmith@redhat.com> + + From Nick Clifton <nickc@redhat.com> + * d10v-tdep.c: Set STACK_START to 0x200bffe. + +2002-01-07 Michael Snyder <msnyder@redhat.com> + + * solib-legacy.c (legacy_svr4_fetch_link_map_offsets): + Don't use exec_bfd if it's NULL. + +2002-01-06 Mark Kettenis <kettenis@gnu.org> + + * valops.c (value_arg_coerce): Fix formatting. + +2002-01-06 Andrew Cagney <ac131313@redhat.com> + + * hp-psymtab-read.c: Include "gdb_string.h" instead of <string.h>. + * gnu-nat.c: Ditto. + +2002-01-06 Andrew Cagney <ac131313@redhat.com> + + * MAINTAINERS: Note that alpha-dec-osf4.0a, arc-elf, arm-coff, + arm-elf, arm-pe, d30v-elf, fr30-elf, h8300hms, h8500hms, + i960-coff, m32r-elf, m68k-elf, m88k, mcore-elf, mn10200-elf, + ns32k-netbsd, hppa1.1-hp-proelf, v850-elf, vax-dec-vms5.5 and + z8k-coff have not been multi-arched. Update z8k-coff build + status. + +2002-01-06 Andrew Cagney <ac131313@redhat.com> + + * MAINTAINERS: Mark a29k target as obsolete. + * Makefile.in (a29k-tdep.o, remote-adapt.o, remote-eb.o) + (remote-mm.o, remote-udi.o): Obsolete. Remove references in + comments. + * NEWS: Note that a29k targets are obsolete. + * a29k-tdep.c: Mark as obsolete. + * configure.tgt: Mark a29k-*-aout*, a29k-*-coff*, a29k-*-elf*, + a29k-*-ebmon*, a29k-*-kern*, a29k-*-none*, a29k-*-udi* and + a29k-*-vxworks* targets as obsolete. + * remote-adapt.c: Obsolete. + * remote-eb.c: Obsolete. + * remote-mm.c: Obsolete. + * remote-udi.c: Obsolete. + * config/a29k/a29k-udi.mt: Obsolete. + * config/a29k/a29k.mt: Obsolete. + * config/a29k/tm-a29k.h: Obsolete. + * config/a29k/tm-vx29k.h: Obsolete. + * config/a29k/vx29k.mt: Obsolete. + +2002-01-05 Andrew Cagney <ac131313@redhat.com> + + * rs6000-tdep.c (rs6000_do_registers_info): Replace BIG_ENDIAN + with BFD_ENDIAN_BIG. + +2002-01-05 Andrew Cagney <ac131313@redhat.com> + + * configure.in (AC_CHECK_HEADERS): Do not check for <endian.h>. + * configure, config.in: Re-generate. + * config/vax/xm-vaxbsd.h: Do not include <machine/endian.h>. + * defs.h: Do not include <endian.h>. + +2002-01-05 Jason Thorpe <thorpej@wasabisystems.com> + + * acconfig.h (HAVE_PT_GETXMMREGS): New. + * config.in: Regenerate. + * configure.in: Update copyright years. + Add test for PT_GETXMMREGS supplied by <sys/ptrace.h>. + * configure: Regenerate. + * i386bsd-nat.c: Update copyright years. + (fill_gregset): Use regcache_collect. + (fetch_inferior_registers): Only fetch integer registers + if requested to do so. Add support for XMM registers + using PT_GETXMMREGS. + (store_inferior_registers): Only store integer registers + if requested to do so. Add support for XMM registers + using PT_SETXMMREGS. + * i386nbsd-nat.c (fetch_inferior_registers): Remove. + (store_inferior_registers): Remove. + (fetch_core_registers): Use supply_gregset and i387_supply_fsave. + (fetch_elfcore_registers): New function. + (i386nbsd_elfcore_fns): New. + (_initialize_i386nbsd_nat): Register i386nbsd_elfcore_fns. + * config/i386/nbsd.mh (NATDEPFILES): Add i387-nat.o and + i386bsd-nat.o. + * config/i386/nbsdelf.mh (NATDEPFILES): Likewise. + * config/i386/nbsd.mt (TDEPFILES): Add i386bsd-nat.o. + * config/i386/nbsdelf.mt (TDEPFILES): Likewise. + * config/i386/tm-nbsd.h: Update copyright years. + (HAVE_SSE_REGS): Define. + (IN_SIGTRAMP): Define as i386bsd_in_sigtramp. + (SIGTRAMP_START): Redefine as i386bsd_sigtramp_start. + (SIGTRAMP_END): Redefine as i386bsd_sigtramp_end. + (SIGCONTEXT_PC_OFFSET): Remove. + (FRAME_SAVED_PC): Define as i386bsd_frame_saved_pc. + +2002-01-05 Andrew Cagney <ac131313@redhat.com> + + * configure.tgt: Remove powerpc-*-macos* target. + * config/m68k/xm-mpw.h: Delete file. + * config/xm-mpw.h: Delete file. + * ser-mac.c: Delete file. + * mpw-make.sed: Delete file. + * mpw-config.in: Delete file. + * mac-xdep.c: Delete file. + * mac-gdb.r: Delete file. + * mac-defs.h: Delete file. + * mac-nat.c: Delete file. + * config/powerpc/macos.mh: Delete file. + * config/powerpc/macos.mt: Delete file. + * config/powerpc/nm-macos.h: Delete file. + * config/powerpc/tm-macos.h: Delete file. + * source.c (openp, open_source_file): Remove obsolete code. + * top.c (gdb_readline): Ditto. + * utils.c (query): Ditto. + * event-top.c (display_gdb_prompt): Ditto. + * Makefile.in (ser-mac.o): Delete obsolete target. + * NEWS: Update. + +2002-01-04 Andrew Cagney <ac131313@redhat.com> + + * defs.h (BIG_ENDIAN): Delete macro definition. + * a29k-tdep.c, arch-utils.c, arm-tdep.c, ax-gdb.c, ch-exp.c, + coffread.c, cris-tdep.c, d10v-tdep.c, d30v-tdep.c, defs.h, + findvar.c, infcmd.c, mem-break.c, mips-tdep.c, mn10300-tdep.c, + printcmd.c, remote-os9k.c, remote-rdi.c, remote-rdp.c, + remote-sim.c, remote.c, rs6000-tdep.c, sh-tdep.c, sparcl-tdep.c, + stabsread.c, valops.c, valprint.c, config/a29k/tm-a29k.h, + config/a29k/tm-vx29k.h, config/arm/tm-arm.h, + config/d30v/tm-d30v.h, config/fr30/tm-fr30.h, + config/h8300/tm-h8300.h, config/h8500/tm-h8500.h, + config/m32r/tm-m32r.h, config/m68k/tm-m68k.h, + config/m88k/tm-m88k.h, config/mips/tm-mips.h, config/pa/tm-hppa.h, + config/sparc/tm-sparc.h, config/z8k/tm-z8k.h, mi/mi-cmd-disas.c, + mi/mi-main.c: Replace BIG_ENDIAN with BFD_ENDIAN_BIG. + * gdbarch.sh: Replace BIG_ENDIAN with BFD_ENDIAN_BIG. + * gdbarch.c: Re-generate. + +2002-01-04 Daniel Jacobowitz <drow@mvista.com> + + * thread-db.c (thread_db_new_objfile): Do not enable thread_db + for core files. + +2002-01-04 Jason Thorpe <thorpej@wasabisystems.com> + + * config/arm/nbsd.mh (XDEPFILES): Remove ser-tcp.o. + +2002-01-04 Andrew Cagney <ac131313@redhat.com> + + * value.h (value_ptr): Delete typedef. + +2002-01-04 Jason Thorpe <thorpej@wasabisystems.com> + + * i386nbsd-nat.c: Update copyright years. + Include i386-tdep.h. + +2002-01-04 Elena Zannoni <ezannoni@redhat.com> + + * stabsread.c: Update copyright years. + + From Debashis Mahata <debashis.mahata@wipro.com>: + (read_struct_fields): Deal with Sun C compiler erroneous stab + output for structs and unions. + Fix PR gdb/269. + +2002-01-04 Daniel Jacobowitz <drow@mvista.com> + + * p-valprint.c: Include "cp-abi.h" for baseclass_offset + prototype. + +2002-01-04 Daniel Jacobowitz <drow@mvista.com> + + * cp-abi.c: Fix whitespace. + (baseclass_offset): New wrapper function. + * cp-abi.h (baseclass_offset): Add prototype. + (struct cp_abi_ops): Add baseclass_offset pointer. + + * valops.c (vb_match): Move to... + * gnu-v2-abi.c (vb_match): here. + * valops.c (baseclass_offset): Move to... + * gnu-v2-abi.c (gnuv2_baseclass_offset): here, and rename. + + * gnu-v3-abi.c (gnuv3_baseclass_offset): New function. + + * gnu-v2-abi.c (init_gnuv2_ops): Initialize baseclass_offset. + * gnu-v3-abi.c (init_gnuv3_ops): Likewise. + * hpacc-abi.c (init_hpacc_ops): Likewise. + +2002-01-04 Daniel Jacobowitz <drow@mvista.com> + + * valops.c (find_overload_match): Accept obj as a + reference parameter. Update it before returning. + * value.h (find_overload_match): Update prototype. + * eval.c (evaluate_subexp_standard): Pass object to + find_overload_match by reference. + +2002-01-03 Andrew Cagney <ac131313@redhat.com> + + * valarith.c: Replace value_ptr with struct value pointer. Remove + register attribute from value declarations. + * valops.c: Ditto. + * value.h: Ditto. + * scm-lang.c (scm_lookup_name): Ditto. + +2002-01-03 Michael Snyder <msnyder@redhat.com> + + Abstract the functionality of iterating over mapped memory + regions into a general purpose iterator function. + * procfs.c (iterate_over_mappings): New function, general purpose + iterator for memory sections. + (proc_iterate_over_mappings): Reimplement using iterate_over_mappings. + (solib_mappings_callback): New function, callback for above. + (info_proc_mappings): Reimpliment using iterate_over_mappings. + (info_mappings_callback): New function, callback for above. + + * procfs.c (proc_set_watchpoint): Add cast to suppress warning. + +2002-01-01 Mark Kettenis <kettenis@gnu.org> + + * i386-tdep.h (struct gdbarch_tdep): Add `os_ident' member. + * i386-tdep.c: Include "elf-bfd.h". + (process_note_abi_tag_sections): New function. + (i386_gdbarch_init): Add code to recognize various OS/ABI + combinations. + + * maint.c (_initialize_maint_cmds): Add missing \ in + string-literal. + +For older changes see ChangeLog-2001 + +Local Variables: +mode: change-log +left-margin: 8 +fill-column: 74 +version-control: never +End: diff --git a/gdb/Makefile.in b/gdb/Makefile.in new file mode 100644 index 0000000..ca17a2b --- /dev/null +++ b/gdb/Makefile.in @@ -0,0 +1,2595 @@ +# Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, +# 1999, 2000, 2001, 2002 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 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +host_alias = @host_alias@ +target_alias = @target_alias@ +program_transform_name = @program_transform_name@ +bindir = @bindir@ +libdir = @libdir@ +tooldir = $(libdir)/$(target_alias) + +datadir = @datadir@ +mandir = @mandir@ +man1dir = $(mandir)/man1 +man2dir = $(mandir)/man2 +man3dir = $(mandir)/man3 +man4dir = $(mandir)/man4 +man5dir = $(mandir)/man5 +man6dir = $(mandir)/man6 +man7dir = $(mandir)/man7 +man8dir = $(mandir)/man8 +man9dir = $(mandir)/man9 +infodir = @infodir@ +htmldir = $(prefix)/html +includedir = @includedir@ + +# This can be referenced by `INTLDEPS' as computed by CY_GNU_GETTEXT. +top_builddir = . + +SHELL = @SHELL@ +EXEEXT = @EXEEXT@ + +AWK = @AWK@ +LN_S = @LN_S@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ + +AR = @AR@ +AR_FLAGS = qv +RANLIB = @RANLIB@ +DLLTOOL = @DLLTOOL@ +WINDRES = @WINDRES@ +MIG = @MIG@ + +# Flags that describe where you can find the termcap library. +# This can be overridden in the host Makefile fragment file. +TERMCAP = @TERM_LIB@ + +# If you are compiling with GCC, make sure that either 1) You have the +# fixed include files where GCC can reach them, or 2) You use the +# -traditional flag. Otherwise the ioctl calls in inflow.c +# will be incorrectly compiled. The "fixincludes" script in the gcc +# distribution will fix your include files up. +CC=@CC@ + +# Directory containing source files. +srcdir = @srcdir@ +VPATH = @srcdir@ + +YACC=@YACC@ + +# This is used to rebuild ada-lex.c from ada-lex.l. If the program is +# not defined, but ada-lex.c is present, compilation will continue, +# possibly with a warning. +FLEX = flex + +YLWRAP = $(srcdir)/../ylwrap + +# where to find makeinfo, preferably one designed for texinfo-2 +MAKEINFO=makeinfo + +MAKEHTML = texi2html + +MAKEHTMLFLAGS = -glossary -menu -split_chapter + +# Set this up with gcc if you have gnu ld and the loader will print out +# line numbers for undefined references. +#CC_LD=gcc -static +CC_LD=$(CC) + +# Where is our "include" directory? Typically $(srcdir)/../include. +# This is essentially the header file directory for the library +# routines in libiberty. +INCLUDE_DIR = $(srcdir)/../include +INCLUDE_CFLAGS = -I$(INCLUDE_DIR) + +# Where is the "-liberty" library? Typically in ../libiberty. +LIBIBERTY = ../libiberty/libiberty.a + +# Configured by the --with-mmalloc option to configure. +MMALLOC = @MMALLOC@ +MMALLOC_CFLAGS = @MMALLOC_CFLAGS@ + +# Configured by the --with-uiout option to configure. +UIOUT_CFLAGS = @UIOUT_CFLAGS@ + +# Where is the BFD library? Typically in ../bfd. +BFD_DIR = ../bfd +BFD = $(BFD_DIR)/libbfd.a +BFD_SRC = $(srcdir)/$(BFD_DIR) +BFD_CFLAGS = -I$(BFD_DIR) -I$(BFD_SRC) + +# Where is the READLINE library? Typically in ../readline. +READLINE_DIR = ../readline +READLINE = $(READLINE_DIR)/libreadline.a +READLINE_SRC = $(srcdir)/$(READLINE_DIR) +READLINE_CFLAGS = -I$(READLINE_SRC)/.. + +WARN_CFLAGS = @WARN_CFLAGS@ +WERROR_CFLAGS = @WERROR_CFLAGS@ +GDB_WARN_CFLAGS = $(WARN_CFLAGS) +GDB_WERROR_CFLAGS = $(WERROR_CFLAGS) + +# Where is the INTL library? Typically in ../intl. +INTL_DIR = ../intl +INTL = @INTLLIBS@ +INTL_DEPS = @INTLDEPS@ +INTL_SRC = $(srcdir)/$(INTL_DIR) +INTL_CFLAGS = -I$(INTL_DIR) -I$(INTL_SRC) + +# Where is the ICONV library? This can be empty if libc has iconv. +LIBICONV = @LIBICONV@ + +# +# CLI sub directory definitons +# +SUBDIR_CLI_OBS = \ + cli-dump.o \ + cli-decode.o cli-script.o cli-cmds.o cli-setshow.o cli-utils.o +SUBDIR_CLI_SRCS = \ + cli/cli-dump.c \ + cli/cli-decode.c cli/cli-script.c cli/cli-cmds.c cli/cli-setshow.c \ + cli/cli-utils.c +SUBDIR_CLI_DEPS = +SUBDIR_CLI_INITS = \ + $(SUBDIR_CLI_SRCS) +SUBDIR_CLI_LDFLAGS= +SUBDIR_CLI_CFLAGS= +SUBDIR_CLI_ALL= +SUBDIR_CLI_CLEAN= +SUBDIR_CLI_INSTALL= +SUBDIR_CLI_UNINSTALL= + +# +# MI sub directory definitons +# +SUBDIR_MI_OBS = \ + mi-out.o mi-console.o \ + mi-cmds.o mi-cmd-var.o mi-cmd-break.o mi-cmd-stack.o \ + mi-cmd-disas.o \ + mi-main.o mi-parse.o mi-getopt.o +SUBDIR_MI_SRCS = \ + mi/mi-out.c mi/mi-console.c \ + mi/mi-cmds.c \ + mi/mi-cmd-var.c mi/mi-cmd-break.c mi/mi-cmd-stack.c \ + mi/mi-cmd-disas.c \ + mi/mi-main.c mi/mi-parse.c mi/mi-getopt.c +SUBDIR_MI_DEPS = +SUBDIR_MI_INITS = \ + $(SUBDIR_MI_SRCS) +SUBDIR_MI_LDFLAGS= +SUBDIR_MI_CFLAGS= \ + -DMI_OUT=1 +SUBDIR_MI_ALL= +SUBDIR_MI_CLEAN= +SUBDIR_MI_INSTALL= +SUBDIR_MI_UNINSTALL= + +# +# TUI sub directory definitions +# +SUBDIR_TUI_OBS = \ + tui-file.o tui.o tuiData.o tuiSource.o tuiStack.o tuiIO.o \ + tuiGeneralWin.o tuiLayout.o tuiWin.o tuiCommand.o \ + tuiDisassem.o tuiSourceWin.o tuiRegs.o tuiDataWin.o \ + tui-out.o tui-hooks.o +SUBDIR_TUI_SRCS = \ + tui/tui-file.c tui/tui.c tui/tuiData.c tui/tuiSource.c \ + tui/tuiStack.c tui/tuiIO.c \ + tui/tuiGeneralWin.c tui/tuiLayout.c \ + tui/tuiWin.c tui/tuiCommand.c \ + tui/tuiDisassem.c tui/tuiSourceWin.c \ + tui/tuiRegs.c tui/tuiDataWin.c tui/tui-out.c tui/tui-hooks.c +SUBDIR_TUI_DEPS = +SUBDIR_TUI_INITS = \ + $(SUBDIR_TUI_SRCS) +SUBDIR_TUI_LDFLAGS= +SUBDIR_TUI_CFLAGS= \ + -DTUI=1 -I${srcdir}/tui +SUBDIR_TUI_ALL= +SUBDIR_TUI_CLEAN= +SUBDIR_TUI_INSTALL= +SUBDIR_TUI_UNINSTALL= + + + +# Opcodes currently live in one of two places. Either they are in the +# opcode library, typically ../opcodes, or they are in a header file +# in INCLUDE_DIR. +# Where is the "-lopcodes" library, with (some of) the opcode tables and +# disassemblers? +OPCODES_DIR = ../opcodes +OPCODES_SRC = $(srcdir)/$(OPCODES_DIR) +OPCODES = $(OPCODES_DIR)/libopcodes.a +# Where are the other opcode tables which only have header file +# versions? +OP_INCLUDE = $(INCLUDE_DIR)/opcode +OPCODES_CFLAGS = -I$(OP_INCLUDE) + +# The simulator is usually nonexistent; targets that include one +# should set this to list all the .o or .a files to be linked in. +SIM = + +WIN32LIBS = @WIN32LIBS@ + +# Where is the TCL library? Typically in ../tcl. +LIB_INSTALL_DIR = $(libdir) +# This variable is needed when doing dynamic linking. +LIB_RUNTIME_DIR = $(libdir) +TCL = @TCL_LD_SEARCH_FLAGS@ @TCL_BUILD_LIB_SPEC@ +TCL_CFLAGS = @TCLHDIR@ +TCL_DEPS = @TCL_DEPS@ +GDBTKLIBS = @GDBTKLIBS@ +# Extra flags that the GDBTK files need: +GDBTK_CFLAGS = @GDBTK_CFLAGS@ + +# Where is the TK library? Typically in ../tk. +TK = @TK_BUILD_LIB_SPEC@ +TK_CFLAGS = @TKHDIR@ @TK_BUILD_INCLUDES@ +TK_DEPS = @TK_DEPS@ + +# Where is Itcl? Typically in ../itcl/itcl. +ITCL_CFLAGS = @ITCLHDIR@ +ITCL = @ITCLLIB@ +ITCL_DEPS = @ITCL_DEPS@ + +# Where is Itk? Typically in ../itcl/itk. +ITK_CFLAGS = @ITKHDIR@ +ITK = @ITKLIB@ +ITK_DEPS = @ITK_DEPS@ + +# Where is Tix? Typically in ../tix. +TIX_CFLAGS = @TIXHDIR@ +TIX = @TIXLIB@ +TIX_DEPS = @TIX_DEPS@ + +X11_CFLAGS = @TK_XINCLUDES@ +X11_LDFLAGS = +X11_LIBS = + +WIN32LDAPP = @WIN32LDAPP@ + +LIBGUI = @LIBGUI@ +GUI_CFLAGS_X = @GUI_CFLAGS_X@ +IDE_CFLAGS=$(GUI_CFLAGS_X) $(IDE_CFLAGS_X) + +# The version of gdbtk we're building. This should be kept +# in sync with GDBTK_VERSION and friends in gdbtk.h. +GDBTK_VERSION = 1.0 +GDBTK_LIBRARY = $(datadir)/insight$(GDBTK_VERSION) + +# Gdbtk requires an absolute path to the source directory or +# the testsuite won't run properly. +GDBTK_SRC_DIR = @GDBTK_SRC_DIR@ + +SUBDIR_GDBTK_OBS = \ + gdbtk.o gdbtk-bp.o gdbtk-cmds.o gdbtk-hooks.o \ + gdbtk-register.o gdbtk-stack.o gdbtk-varobj.o gdbtk-wrapper.o +SUBDIR_GDBTK_SRCS = \ + gdbtk/generic/gdbtk.c gdbtk/generic/gdbtk-bp.c \ + gdbtk/generic/gdbtk-cmds.c gdbtk/generic/gdbtk-hooks.c \ + gdbtk/generic/gdbtk-register.c gdbtk/generic/gdbtk-stack.c \ + gdbtk/generic/gdbtk-varobj.c gdbtk/generic/gdbtk-wrapper.c +SUBDIR_GDBTK_DEPS = \ + $(LIBGUI) $(ITCL_DEPS) $(ITK_DEPS) $(TIX_DEPS) $(TK_DEPS) $(TCL_DEPS) +SUBDIR_GDBTK_INITS = gdbtk/generic/gdbtk.c +SUBDIR_GDBTK_LDFLAGS= +SUBDIR_GDBTK_CFLAGS= -DGDBTK +SUBDIR_GDBTK_ALL= +SUBDIR_GDBTK_CLEAN= +SUBDIR_GDBTK_INSTALL= install-gdbtk +SUBDIR_GDBTK_UNINSTALL= + +CONFIG_OBS= @CONFIG_OBS@ +CONFIG_LIB_OBS= @CONFIG_LIB_OBS@ +CONFIG_SRCS= @CONFIG_SRCS@ +CONFIG_DEPS= @CONFIG_DEPS@ +CONFIG_INITS= @CONFIG_INITS@ +CONFIG_LDFLAGS = @CONFIG_LDFLAGS@ +ENABLE_CFLAGS= @ENABLE_CFLAGS@ +CONFIG_ALL= @CONFIG_ALL@ +CONFIG_CLEAN= @CONFIG_CLEAN@ +CONFIG_CLEAN= @CONFIG_CLEAN@ +CONFIG_INSTALL = @CONFIG_INSTALL@ +CONFIG_UNINSTALL = @CONFIG_UNINSTALL@ + +# -I. for config files. +# -I$(srcdir) for gdb internal headers. +# -I$(srcdir)/config for more generic config files. + +# It is also possible that you will need to add -I/usr/include/sys if +# your system doesn't have fcntl.h in /usr/include (which is where it +# should be according to Posix). +DEFS = @DEFS@ +GDB_CFLAGS = -I. -I$(srcdir) -I$(srcdir)/config -DLOCALEDIR="\"$(prefix)/share/locale\"" $(DEFS) + +# M{H,T}_CFLAGS, if defined, have host- and target-dependent CFLAGS +# from the config directory. +GLOBAL_CFLAGS = $(MT_CFLAGS) $(MH_CFLAGS) +#PROFILE_CFLAGS = -pg + +# CFLAGS is specifically reserved for setting from the command line +# when running make. I.E. "make CFLAGS=-Wmissing-prototypes". +CFLAGS = @CFLAGS@ + +# Need to pass this to testsuite for "make check". Probably should be +# consistent with top-level Makefile.in and gdb/testsuite/Makefile.in +# so "make check" has the same result no matter where it is run. +CXXFLAGS = -g -O + +# INTERNAL_CFLAGS is the aggregate of all other *CFLAGS macros. +INTERNAL_WARN_CFLAGS = \ + $(CFLAGS) $(GLOBAL_CFLAGS) $(PROFILE_CFLAGS) \ + $(GDB_CFLAGS) $(OPCODES_CFLAGS) $(READLINE_CFLAGS) \ + $(BFD_CFLAGS) $(MMALLOC_CFLAGS) $(INCLUDE_CFLAGS) \ + $(INTL_CFLAGS) $(ENABLE_CFLAGS) $(UIOUT_CFLAGS) \ + $(GDB_WARN_CFLAGS) +INTERNAL_CFLAGS = $(INTERNAL_WARN_CFLAGS) $(GDB_WERROR_CFLAGS) + +# LDFLAGS is specifically reserved for setting from the command line +# when running make. +LDFLAGS = @LDFLAGS@ + +# Profiling options need to go here to work. +# I think it's perfectly reasonable for a user to set -pg in CFLAGS +# and have it work; that's why CFLAGS is here. +INTERNAL_LDFLAGS = $(CFLAGS) $(GLOBAL_CFLAGS) $(PROFILE_CFLAGS) $(MH_LDFLAGS) $(LDFLAGS) $(CONFIG_LDFLAGS) @HLDFLAGS@ +HLDENV = @HLDENV@ + +# If your system is missing alloca(), or, more likely, it's there but +# it doesn't work, then refer to libiberty. + +# Libraries and corresponding dependencies for compiling gdb. +# {X,T}M_CLIBS, defined in *config files, have host- and target-dependent libs. +# TERMCAP comes after readline, since readline depends on it. +# MMALLOC comes after anything else that might want an allocation function. +# LIBIBERTY appears twice on purpose. +# If you have the Cygnus libraries installed, +# you can use 'CLIBS=$(INSTALLED_LIBS)' 'CDEPS=' +INSTALLED_LIBS=-lbfd -lreadline -lopcodes -liberty \ + $(TERMCAP) $(XM_CLIBS) $(TM_CLIBS) $(NAT_CLIBS) $(GDBTKLIBS) @LIBS@ \ + -lmmalloc -lintl -liberty +CLIBS = $(SIM) $(BFD) $(READLINE) $(OPCODES) $(INTL) $(LIBIBERTY) \ + $(TERMCAP) $(XM_CLIBS) $(TM_CLIBS) $(NAT_CLIBS) $(GDBTKLIBS) @LIBS@ \ + $(LIBICONV) \ + $(MMALLOC) $(LIBIBERTY) $(WIN32LIBS) +CDEPS = $(XM_CDEPS) $(TM_CDEPS) $(NAT_CDEPS) $(SIM) $(BFD) $(READLINE) \ + $(OPCODES) $(MMALLOC) $(INTL_DEPS) $(LIBIBERTY) $(CONFIG_DEPS) + +ADD_FILES = $(XM_ADD_FILES) $(TM_ADD_FILES) $(NAT_ADD_FILES) +ADD_DEPS = $(XM_ADD_FILES) $(TM_ADD_FILES) $(NAT_ADD_FILES) + +DIST=gdb + +LINT=/usr/5bin/lint +LINTFLAGS= $(GDB_CFLAGS) $(OPCODES_CFLAGS) $(READLINE_CFLAGS) \ + $(BFD_CFLAGS) $(MMALLOC_CFLAGS) $(INCLUDE_CFLAGS) \ + $(INTL_CFLAGS) + +RUNTEST = `if [ -f $${rootsrc}/../dejagnu/runtest ] ; then \ + echo $${rootsrc}/../dejagnu/runtest ; else echo runtest; \ + fi` + +RUNTESTFLAGS= + +# This is ser-unix.o for any system which supports a v7/BSD/SYSV/POSIX +# interface to the serial port. Hopefully if get ported to OS/2, VMS, +# etc., then there will be (as part of the C library or perhaps as +# part of libiberty) a POSIX interface. But at least for now the +# host-dependent makefile fragment might need to use something else +# besides ser-unix.o +SER_HARDWIRE = @SER_HARDWIRE@ + +# The `remote' debugging target is supported for most architectures, +# but not all (e.g. 960) +REMOTE_OBS = remote.o dcache.o remote-utils.o tracepoint.o ax-general.o ax-gdb.o + +# This is remote-sim.o if a simulator is to be linked in. +SIM_OBS = + +ANNOTATE_OBS = annotate.o + +# Host and target-dependent makefile fragments come in here. +@host_makefile_frag@ +@target_makefile_frag@ +# End of host and target-dependent makefile fragments + +# Possibly ignore the simulator. If the simulator is being ignored, +# these expand into SIM= and SIM_OBJ=, overriding the entries from +# target_makefile_frag +# +@IGNORE_SIM@ +@IGNORE_SIM_OBS@ + +FLAGS_TO_PASS = \ + "prefix=$(prefix)" \ + "exec_prefix=$(exec_prefix)" \ + "infodir=$(infodir)" \ + "libdir=$(libdir)" \ + "mandir=$(mandir)" \ + "datadir=$(datadir)" \ + "includedir=$(includedir)" \ + "against=$(against)" \ + "AR=$(AR)" \ + "AR_FLAGS=$(AR_FLAGS)" \ + "CC=$(CC)" \ + "CFLAGS=$(CFLAGS)" \ + "CXX=$(CXX)" \ + "CXXFLAGS=$(CXXFLAGS)" \ + "DLLTOOL=$(DLLTOOL)" \ + "RANLIB=$(RANLIB)" \ + "MAKEINFO=$(MAKEINFO)" \ + "MAKEHTML=$(MAKEHTML)" \ + "MAKEHTMLFLAGS=$(MAKEHTMLFLAGS)" \ + "INSTALL=$(INSTALL)" \ + "INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \ + "INSTALL_DATA=$(INSTALL_DATA)" \ + "RUNTEST=$(RUNTEST)" \ + "RUNTESTFLAGS=$(RUNTESTFLAGS)" + +# Flags that we pass when building the testsuite. + +# empty for native, $(target_alias)/ for cross +target_subdir = @target_subdir@ + +CC_FOR_TARGET = ` \ + if [ -f $${rootme}/../gcc/xgcc ] ; then \ + if [ -f $${rootme}/../$(target_subdir)newlib/Makefile ] ; then \ + echo $${rootme}/../gcc/xgcc -B$${rootme}/../gcc/ -idirafter $${rootme}/$(target_subdir)newlib/targ-include -idirafter $${rootsrc}/../$(target_subdir)newlib/libc/include -nostdinc -B$${rootme}/../$(target_subdir)newlib/; \ + else \ + echo $${rootme}/../gcc/xgcc -B$${rootme}/../gcc/; \ + fi; \ + else \ + if [ "$(host_canonical)" = "$(target_canonical)" ] ; then \ + echo $(CC); \ + else \ + t='$(program_transform_name)'; echo gcc | sed -e '' $$t; \ + fi; \ + fi` + +CXX = gcc +CXX_FOR_TARGET = ` \ + if [ -f $${rootme}/../gcc/xgcc ] ; then \ + if [ -f $${rootme}/../$(target_subdir)newlib/Makefile ] ; then \ + echo $${rootme}/../gcc/xgcc -B$${rootme}/../gcc/ -idirafter $${rootme}/$(target_subdir)newlib/targ-include -idirafter $${rootsrc}/../$(target_subdir)newlib/libc/include -nostdinc -B$${rootme}/../$(target_subdir)newlib/; \ + else \ + echo $${rootme}/../gcc/xgcc -B$${rootme}/../gcc/; \ + fi; \ + else \ + if [ "$(host_canonical)" = "$(target_canonical)" ] ; then \ + echo $(CXX); \ + else \ + t='$(program_transform_name)'; echo gcc | sed -e '' $$t; \ + fi; \ + fi` + +# OBSOLETE CHILLFLAGS = $(CFLAGS) +# OBSOLETE CHILL = gcc +# OBSOLETE CHILL_FOR_TARGET = ` \ +# OBSOLETE if [ -f $${rootme}/../gcc/Makefile ] ; then \ +# OBSOLETE echo $${rootme}/../gcc/xgcc -B$${rootme}/../gcc/ -L$${rootme}/../gcc/ch/runtime/; \ +# OBSOLETE else \ +# OBSOLETE if [ "$(host_canonical)" = "$(target_canonical)" ] ; then \ +# OBSOLETE echo $(CC); \ +# OBSOLETE else \ +# OBSOLETE t='$(program_transform_name)'; echo gcc | sed -e '' $$t; \ +# OBSOLETE fi; \ +# OBSOLETE fi` +# OBSOLETE CHILL_LIB = ` \ +# OBSOLETE if [ -f $${rootme}/../gcc/ch/runtime/libchill.a ] ; then \ +# OBSOLETE echo $${rootme}/../gcc/ch/runtime/chillrt0.o \ +# OBSOLETE $${rootme}/../gcc/ch/runtime/libchill.a; \ +# OBSOLETE else \ +# OBSOLETE echo -lchill; \ +# OBSOLETE fi` + +# The use of $$(x_FOR_TARGET) reduces the command line length by not +# duplicating the lengthy definition. +TARGET_FLAGS_TO_PASS = \ + "prefix=$(prefix)" \ + "exec_prefix=$(exec_prefix)" \ + "against=$(against)" \ + 'CC=$$(CC_FOR_TARGET)' \ + "CC_FOR_TARGET=$(CC_FOR_TARGET)" \ + "CFLAGS=$(CFLAGS)" \ + 'CXX=$$(CXX_FOR_TARGET)' \ + "CXX_FOR_TARGET=$(CXX_FOR_TARGET)" \ + "CXXFLAGS=$(CXXFLAGS)" \ + "INSTALL=$(INSTALL)" \ + "INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \ + "INSTALL_DATA=$(INSTALL_DATA)" \ + "MAKEINFO=$(MAKEINFO)" \ + "MAKEHTML=$(MAKEHTML)" \ + "RUNTEST=$(RUNTEST)" \ + "RUNTESTFLAGS=$(RUNTESTFLAGS)" + +# All source files that go into linking GDB. +# Links made at configuration time should not be specified here, since +# SFILES is used in building the distribution archive. + +SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \ + ax-general.c ax-gdb.c bcache.c blockframe.c breakpoint.c \ + charset.c \ + buildsym.c c-exp.y c-lang.c c-typeprint.c c-valprint.c \ + coffread.c \ + complaints.c completer.c corefile.c cp-valprint.c dbxread.c \ + demangle.c dwarfread.c dwarf2read.c elfread.c environ.c eval.c \ + event-loop.c event-top.c \ + expprint.c f-exp.y f-lang.c f-typeprint.c f-valprint.c \ + findvar.c regcache.c gdbarch.c arch-utils.c gdbtypes.c osabi.c \ + inf-loop.c infcmd.c inflow.c infrun.c language.c \ + kod.c kod-cisco.c \ + ui-out.c cli-out.c \ + varobj.c wrapper.c \ + jv-exp.y jv-lang.c jv-valprint.c jv-typeprint.c \ + m2-exp.y m2-lang.c m2-typeprint.c m2-valprint.c main.c maint.c \ + memattr.c mem-break.c minsyms.c mipsread.c nlmread.c objfiles.c \ + p-exp.y p-lang.c p-typeprint.c p-valprint.c parse.c \ + macrotab.c macroexp.c macrocmd.c macroscope.c \ + printcmd.c remote.c scm-exp.c scm-lang.c \ + scm-valprint.c source.c stabsread.c stack.c symfile.c \ + symmisc.c symtab.c linespec.c target.c thread.c top.c tracepoint.c \ + typeprint.c utils.c valarith.c valops.c valprint.c values.c \ + serial.c ser-unix.c mdebugread.c \ + tui/tui.c tui/tui.h tui/tuiCommand.c tui/tuiCommand.h \ + tui/tuiData.c tui/tuiData.h tui/tuiDataWin.c tui/tuiDataWin.h \ + tui/tuiDisassem.c tui/tuiDisassem.h tui/tuiGeneralWin.c \ + tui/tuiGeneralWin.h tui/tuiIO.c tui/tuiIO.h tui/tuiLayout.c \ + tui/tuiLayout.h tui/tuiRegs.c tui/tuiRegs.h tui/tuiSource.c \ + tui/tuiSource.h tui/tuiSourceWin.c tui/tuiSourceWin.h \ + tui/tuiStack.c tui/tuiStack.h tui/tuiWin.c tui/tuiWin.h \ + tui/tui-file.h tui/tui-file.c tui/tui-out.c tui/tui-hooks.c \ + ui-file.h ui-file.c \ + frame.c doublest.c \ + builtin-regs.c std-regs.c \ + gnu-v2-abi.c gnu-v3-abi.c hpacc-abi.c cp-abi.c cp-support.c + +LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c + +# "system" headers. Using these in dependencies is a rather personal +# choice. (-rich, summer 1993) +# (Why would we not want to depend on them? If one of these changes in a +# non-binary-compatible way, it is a real pain to remake the right stuff +# without these dependencies -kingdon, 13 Mar 1994) +aout_aout64_h = $(INCLUDE_DIR)/aout/aout64.h +aout_stabs_gnu_h = $(INCLUDE_DIR)/aout/stabs_gnu.h +getopt_h = $(INCLUDE_DIR)/getopt.h +floatformat_h = $(INCLUDE_DIR)/floatformat.h +bfd_h = $(BFD_DIR)/bfd.h +callback_h = $(INCLUDE_DIR)/gdb/callback.h +coff_sym_h = $(INCLUDE_DIR)/coff/sym.h +coff_symconst_h = $(INCLUDE_DIR)/coff/symconst.h +coff_ecoff_h = $(INCLUDE_DIR)/coff/ecoff.h +dis_asm_h = $(INCLUDE_DIR)/dis-asm.h +elf_sh_h = $(INCLUDE_DIR)/elf/sh.h +elf_bfd_h = $(BFD_SRC)/elf-bfd.h +libaout_h = $(BFD_SRC)/libaout.h +remote_sim_h = $(INCLUDE_DIR)/gdb/remote-sim.h +demangle_h = $(INCLUDE_DIR)/demangle.h +obstack_h = $(INCLUDE_DIR)/obstack.h +opcode_m68hc11_h = $(INCLUDE_DIR)/opcode/m68hc11.h +sh_opc_h = $(OPCODES_SRC)/sh-opc.h +gdb_sim_arm_h = $(INCLUDE_DIR)/gdb/sim-arm.h +gdb_sim_d10v_h = $(INCLUDE_DIR)/gdb/sim-d10v.h +gdb_sim_sh_h = $(INCLUDE_DIR)/gdb/sim-sh.h +splay_tree_h = $(INCLUDE_DIR)/splay-tree.h + +readline_headers = \ + $(READLINE_SRC)/chardefs.h \ + $(READLINE_SRC)/history.h \ + $(READLINE_SRC)/keymaps.h \ + $(READLINE_SRC)/readline.h + +xm_h = @xm_h@ +tm_h = @tm_h@ +nm_h = @nm_h@ + +# +# gdb/ header files +# + +acconfig_h = acconfig.h +ada_lang_h = ada-lang.h $(value_h) $(gdbtypes_h) +alpha_tdep_h = alpha-tdep.h $(osabi_h) +alphabsd_tdep_h = alphabsd-tdep.h +annotate_h = annotate.h $(symtab_h) $(gdbtypes_h) +arch_utils_h = arch-utils.h +arm_tdep_h = arm-tdep.h $(osabi_h) +ax_gdb_h = ax-gdb.h +ax_h = ax.h $(doublest_h) +bcache_h = bcache.h +breakpoint_h = breakpoint.h $(frame_h) $(value_h) $(gdb_events_h) +buildsym_h = buildsym.h +builtin_regs_h = builtin-regs.h +c_lang_h = c-lang.h $(value_h) $(macroexp_h) +call_cmds_h = call-cmds.h +ch_lang_h = ch-lang.h +cli_out_h = cli-out.h +coff_solib_h = coff-solib.h +command_h = command.h +complaints_h = complaints.h +completer_h = completer.h +cp_abi_h = cp-abi.h +cp_support_h = cp-support.h +dcache_h = dcache.h +defs_h = defs.h $(config_h) $(gdb_locale_h) $(gdb_signals_h) $(ansidecl_h) \ + $(libiberty_h) $(progress_h) $(bfd_h) $(tui_h) $(ui_file_h) $(xm_h) \ + $(nm_h) $(tm_h) $(fopen_same_h) $(gdbarch_h) $(arch_utils_h) +doublest_h = doublest.h $(floatformat_h) +dst_h = dst.h +dwarf2cfi_h = dwarf2cfi.h +environ_h = environ.h +event_loop_h = event-loop.h +event_top_h = event-top.h +expression_h = expression.h $(symtab_h) $(doublest_h) +f_lang_h = f-lang.h +frame_h = frame.h +gdb_events_h = gdb-events.h +gdb_stabs_h = gdb-stabs.h +gdb_h = gdb.h +gdb_assert_h = gdb_assert.h +gdb_dirent_h = gdb_dirent.h +gdb_locale_h = gdb_locale.h +gdb_obstack_h = gdb_obstack.h $(obstack_h) +gdb_proc_service_h = gdb_proc_service.h $(gregset_h) +gdb_regex_h = gdb_regex.h $(xregex_h) +gdb_stat_h = gdb_stat.h +gdb_string_h = gdb_string.h +gdb_thread_db_h = gdb_thread_db.h +gdb_vfork_h = gdb_vfork.h +gdb_wait_h = gdb_wait.h +gdbarch_h = gdbarch.h $(dis_asm_h) $(value_h) $(inferior_h) +gdbcmd_h = gdbcmd.h $(command_h) $(ui_out_h) +gdbcore_h = gdbcore.h $(bfd_h) +gdbthread_h = gdbthread.h $(breakpoint_h) +gdbtypes_h = gdbtypes.h +gnu_nat_h = gnu-nat.h +gregset_h = gregset.h +i386_linux_tdep_h = i386-linux-tdep.h +i386_tdep_h = i386-tdep.h $(osabi_h) +i387_tdep_h = i387-tdep.h +inf_loop_h = inf-loop.h +inferior_h = inferior.h $(breakpoint_h) $(target_h) +jv_lang_h = jv-lang.h +kod_h = kod.h +language_h = language.h +linespec_h = linespec.h +m2_lang_h = m2-lang.h +macroexp_h = macroexp.h +macroscope_h = macroscope.h $(macrotab_h) $(symtab_h) +macrotab_h = macrotab.h +memattr_h = memattr.h +minimon_h = minimon.h +mipsnbsd_tdep_h = mipsnbsd-tdep.h +monitor_h = monitor.h +nbsd_tdep_h = nbsd-tdep.h +ns32k_tdep_h = ns32k-tdep.h $(osabi_h) +objfiles_h = objfiles.h $(gdb_obstack_h) $(symfile_h) +ocd_h = ocd.h +osabi_h = osabi.h +p_lang_h = p-lang.h +pa64solib_h = pa64solib.h +parser_defs_h = parser-defs.h $(doublest_h) +ppc_tdep_h = ppc-tdep.h $(osabi_h) +ppcnbsd_tdep_h = ppcnbsd-tdep.h +proc_utils_h = proc-utils.h +regcache_h = regcache.h +remote_utils_h = remote-utils.h $(target_h) +remote_h = remote.h +scm_lang_h = scm-lang.h $(scm_tags_h) +scm_tags_h = scm-tags.h +ser_unix_h = ser-unix.h +serial_h = serial.h +sh_tdep_h = sh-tdep.h $(osabi_h) +shnbsd_tdep_h = shnbsd-tdep.h +sim_regno_h = sim-regno.h +solib_svr4_h = solib-svr4.h +solib_h = solib.h +solist_h = solist.h +somsolib_h = somsolib.h +source_h = source.h +sparcnbsd_tdep_h = sparcnbsd-tdep.h +srec_h = srec.h +stabsread_h = stabsread.h +symfile_h = symfile.h +symtab_h = symtab.h +target_h = target.h $(bfd_h) $(symtab_h) $(dcache_h) $(memattr_h) +terminal_h = terminal.h +top_h = top.h +tracepoint_h = tracepoint.h +typeprint_h = typeprint.h +ui_file_h = ui-file.h +ui_out_h = ui-out.h +valprint_h = valprint.h +value_h = value.h $(doublest_h) $(symtab_h) $(gdbtypes_h) $(expression_h) +varobj_h = varobj.h $(symtab_h) $(gdbtypes_h) +vax_tdep_h = vax-tdep.h $(osabi_h) +version_h = version.h +wince_stub_h = wince-stub.h +wrapper_h = wrapper.h $(gdb_h) +x86_64_tdep_h = x86-64-tdep.h $(i386_tdep_h) +xcoffsolib_h = xcoffsolib.h +xmodem_h = xmodem.h + +# +# gdb/cli/ headers +# + +cli_cmds_h = $(srcdir)/cli/cli-cmds.h +cli_decode_h = $(srcdir)/cli/cli-decode.h $(gdb_regex_h) $(command_h) +cli_dump_h = $(srcdir)/cli/cli-dump.h +cli_script_h = $(srcdir)/cli/cli-script.h +cli_setshow_h = $(srcdir)/cli/cli-setshow.h +cli_utils_h = $(srcdir)/cli/cli-utils.h + +# +# gdb/mi/ headers +# + +mi_cmds_h = $(srcdir)/mi/mi-cmds.h +mi_console_h = $(srcdir)/mi/mi-console.h +mi_getopt_h = $(srcdir)/mi/mi-getopt.h +mi_out_h = $(srcdir)/mi/mi-out.h +mi_parse_h = $(srcdir)/mi/mi-parse.h + +# +# gdb/tui/ headers +# + +tui_file_h = $(srcdir)/tui/tui-file.h +tui_h = $(srcdir)/tui/tui.h $(ansidecl_h) +tuiCommand_h = $(srcdir)/tui/tuiCommand.h +tuiData_h = $(srcdir)/tui/tuiData.h +tuiDataWin_h = $(srcdir)/tui/tuiDataWin.h +tuiDisassem_h = $(srcdir)/tui/tuiDisassem.h +tuiGeneralWin_h = $(srcdir)/tui/tuiGeneralWin.h +tuiIO_h = $(srcdir)/tui/tuiIO.h +tuiLayout_h = $(srcdir)/tui/tuiLayout.h +tuiRegs_h = $(srcdir)/tui/tuiRegs.h +tuiSource_h = $(srcdir)/tui/tuiSource.h $(defs_h) +tuiSourceWin_h = $(srcdir)/tui/tuiSourceWin.h +tuiStack_h = $(srcdir)/tui/tuiStack.h +tuiWin_h = $(srcdir)/tui/tuiWin.h + +charset_h = charset.h + +# Header files that need to have srcdir added. Note that in the cases +# where we use a macro like $(gdbcmd_h), things are carefully arranged +# so that each .h file is listed exactly once (M-x tags-search works +# wrong if TAGS has files twice). Because this is tricky to get +# right, it is probably easiest just to list .h files here directly. + +HFILES_NO_SRCDIR = bcache.h buildsym.h call-cmds.h coff-solib.h defs.h \ + environ.h $(gdbcmd_h) gdb.h gdbcore.h \ + gdb-stabs.h $(inferior_h) language.h minimon.h monitor.h \ + objfiles.h parser-defs.h serial.h solib.h \ + symfile.h stabsread.h target.h terminal.h typeprint.h xcoffsolib.h \ + macrotab.h macroexp.h macroscope.h \ + c-lang.h f-lang.h \ + jv-lang.h \ + m2-lang.h p-lang.h \ + complaints.h valprint.h \ + nindy-share/b.out.h \ + nindy-share/block_io.h nindy-share/coff.h \ + nindy-share/env.h nindy-share/stop.h \ + vx-share/dbgRpcLib.h vx-share/ptrace.h vx-share/vxTypes.h \ + vx-share/vxWorks.h vx-share/wait.h vx-share/xdr_ld.h \ + vx-share/xdr_ptrace.h vx-share/xdr_rdb.h gdbthread.h \ + dcache.h remote-utils.h top.h somsolib.h + +# Header files that already have srcdir in them, or which are in objdir. + +HFILES_WITH_SRCDIR = ../bfd/bfd.h + + +# GDB "info" files, which should be included in their entirety +INFOFILES = gdb.info* + +REMOTE_EXAMPLES = m68k-stub.c i386-stub.c sparc-stub.c rem-multi.shar + +# {X,T,NAT}DEPFILES are something of a pain in that it's hard to +# default their values the way we do for SER_HARDWIRE; in the future +# maybe much of the stuff now in {X,T,NAT}DEPFILES will go into other +# variables analogous to SER_HARDWIRE which get defaulted in this +# Makefile.in + +DEPFILES = $(TDEPFILES) $(SER_HARDWIRE) $(NATDEPFILES) \ + $(REMOTE_OBS) $(SIM_OBS) $(CONFIG_LIB_OBS) + +SOURCES = $(SFILES) $(ALLDEPFILES) $(YYFILES) $(CONFIG_SRCS) +# Don't include YYFILES (*.tab.c) because we already include *.y in SFILES, +# and it's more useful to see it in the .y file. +TAGFILES_NO_SRCDIR = $(SFILES) $(HFILES_NO_SRCDIR) $(ALLDEPFILES) \ + $(SUBDIR_CLI_SRCS) +TAGFILES_WITH_SRCDIR = $(HFILES_WITH_SRCDIR) + +COMMON_OBS = version.o blockframe.o breakpoint.o findvar.o regcache.o \ + charset.o \ + source.o values.o eval.o valops.o valarith.o valprint.o printcmd.o \ + symtab.o symfile.o symmisc.o linespec.o infcmd.o infrun.o \ + expprint.o environ.o stack.o thread.o \ + macrotab.o macrocmd.o macroexp.o macroscope.o \ + event-loop.o event-top.o inf-loop.o completer.o \ + gdbarch.o arch-utils.o gdbtypes.o osabi.o copying.o $(DEPFILES) \ + memattr.o mem-break.o target.o parse.o language.o $(YYOBJ) buildsym.o \ + builtin-regs.o std-regs.o \ + signals.o \ + kod.o kod-cisco.o \ + gdb-events.o \ + exec.o bcache.o objfiles.o minsyms.o maint.o demangle.o \ + dbxread.o coffread.o elfread.o \ + dwarfread.o dwarf2read.o mipsread.o stabsread.o corefile.o \ + c-lang.o f-lang.o \ + ui-out.o cli-out.o \ + varobj.o wrapper.o \ + jv-lang.o jv-valprint.o jv-typeprint.o \ + m2-lang.o p-lang.o p-typeprint.o p-valprint.o \ + scm-exp.o scm-lang.o scm-valprint.o complaints.o typeprint.o \ + c-typeprint.o f-typeprint.o m2-typeprint.o \ + c-valprint.o cp-valprint.o f-valprint.o m2-valprint.o \ + nlmread.o serial.o mdebugread.o top.o utils.o \ + ui-file.o \ + frame.o doublest.o \ + gnu-v2-abi.o gnu-v3-abi.o hpacc-abi.o cp-abi.o cp-support.o + +OBS = $(COMMON_OBS) $(ANNOTATE_OBS) + +TSOBS = inflow.o + +SUBDIRS = @SUBDIRS@ + +# For now, shortcut the "configure GDB for fewer languages" stuff. +YYFILES = c-exp.tab.c \ + ada-exp.tab.c \ + jv-exp.tab.c \ + f-exp.tab.c m2-exp.tab.c p-exp.tab.c +YYOBJ = c-exp.tab.o \ + jv-exp.tab.o \ + f-exp.tab.o m2-exp.tab.o p-exp.tab.o + +# Things which need to be built when making a distribution. + +DISTSTUFF = $(YYFILES) + +# Prevent Sun make from putting in the machine type. Setting +# TARGET_ARCH to nothing works for SunOS 3, 4.0, but not for 4.1. +.c.o: + $(CC) -c $(INTERNAL_CFLAGS) $< + +all: gdb$(EXEEXT) $(CONFIG_ALL) + @$(MAKE) $(FLAGS_TO_PASS) DO=all "DODIRS=`echo $(SUBDIRS) | sed 's/testsuite//'`" subdir_do + +installcheck: + +# The check target can not use subdir_do, because subdir_do does not +# use TARGET_FLAGS_TO_PASS. +check: force + @if [ -f testsuite/Makefile ]; then \ + rootme=`pwd`; export rootme; \ + rootsrc=`cd $(srcdir); pwd`; export rootsrc; \ + cd testsuite; \ + $(MAKE) $(TARGET_FLAGS_TO_PASS) check; \ + else true; fi + +info dvi install-info clean-info html install-html: force + @$(MAKE) $(FLAGS_TO_PASS) DO=$@ "DODIRS=$(SUBDIRS)" subdir_do + +gdb.z:gdb.1 + nroff -man $(srcdir)/gdb.1 | col -b > gdb.t + pack gdb.t ; rm -f gdb.t + mv gdb.t.z gdb.z + +# Traditionally "install" depends on "all". But it may be useful +# not to; for example, if the user has made some trivial change to a +# source file and doesn't care about rebuilding or just wants to save the +# time it takes for make to check that all is up to date. +# install-only is intended to address that need. +install: all install-only +install-only: $(CONFIG_INSTALL) + transformed_name=`t='$(program_transform_name)'; \ + echo gdb | sed -e $$t` ; \ + if test "x$$transformed_name" = x; then \ + transformed_name=gdb ; \ + else \ + true ; \ + fi ; \ + $(srcdir)/../mkinstalldirs $(bindir) ; \ + $(INSTALL_PROGRAM) gdb$(EXEEXT) $(bindir)/$$transformed_name$(EXEEXT) ; \ + $(srcdir)/../mkinstalldirs $(man1dir) ; \ + $(INSTALL_DATA) $(srcdir)/gdb.1 $(man1dir)/$$transformed_name.1 + @$(MAKE) DO=install "DODIRS=$(SUBDIRS)" $(FLAGS_TO_PASS) subdir_do + +uninstall: force $(CONFIG_UNINSTALL) + transformed_name=`t='$(program_transform_name)'; \ + echo gdb | sed -e $$t` ; \ + if test "x$$transformed_name" = x; then \ + transformed_name=gdb ; \ + else \ + true ; \ + fi ; \ + rm -f $(bindir)/$$transformed_name$(EXEEXT) $(man1dir)/$$transformed_name.1 + rm -rf $(GDBTK_LIBRARY) + @$(MAKE) DO=uninstall "DODIRS=$(SUBDIRS)" $(FLAGS_TO_PASS) subdir_do + +install-gdbtk: + $(SHELL) $(srcdir)/../mkinstalldirs $(GDBTK_LIBRARY) ; \ + $(SHELL) $(srcdir)/../mkinstalldirs $(libdir)/insight$(GDBTK_VERSION) ; \ + $(INSTALL_DATA) $(srcdir)/gdbtk/plugins/plugins.tcl $(libdir)/insight$(GDBTK_VERSION)/plugins.tcl ; \ + $(SHELL) $(srcdir)/../mkinstalldirs \ + $(GDBTK_LIBRARY)/images \ + $(GDBTK_LIBRARY)/images2 ; \ + $(SHELL) $(srcdir)/../mkinstalldirs $(GDBTK_LIBRARY)/help \ + $(GDBTK_LIBRARY)/help/images \ + $(GDBTK_LIBRARY)/help/trace ; \ + cd $(srcdir)/gdbtk/library ; \ + for i in *.tcl *.itcl *.ith *.itb images/*.gif images2/*.gif images/icons.txt images2/icons.txt tclIndex help/*.html help/trace/*.html help/trace/index.toc help/images/*.gif; \ + do \ + $(INSTALL_DATA) $$i $(GDBTK_LIBRARY)/$$i ; \ + done ; + +# We do this by grepping through sources. If that turns out to be too slow, +# maybe we could just require every .o file to have an initialization routine +# of a given name (top.o -> _initialize_top, etc.). +# +# Formatting conventions: The name of the _initialize_* routines must start +# in column zero, and must not be inside #if. +# +# Note that the set of files with init functions might change, or the names +# of the functions might change, so this files needs to depend on all the +# object files that will be linked into gdb. +# +# FIXME: There are 2 problems with this approach. First, if the INIT_FILES +# list includes a file twice (because of some mistake somewhere else) +# the _initialize_* function will be included twice in init.c. Second, +# init.c may force unnecessary files to be linked in. + +# FIXME: cagney/2002-06-09: gdb/564: gdb/563: Force the order so that +# the first call is to _initialize_gdbtypes. This is a hack to ensure +# that all the architecture dependant global builtin_type_* variables +# are initialized before anything else (per-architecture code is +# called in the same order that it is registered). The ``correct +# fix'' is to have all the builtin types made part of the architecture +# and initialize them on-demand (using gdbarch_data) just like +# everything else. The catch is that other modules still take the +# address of these builtin types forcing them to be variables, sigh! + +INIT_FILES = $(OBS) $(TSOBS) $(CONFIG_OBS) $(CONFIG_INITS) +init.c: $(INIT_FILES) + @echo Making init.c + @rm -f init.c-tmp init.l-tmp + @-echo $(INIT_FILES) | \ + tr ' ' '\012' | \ + sed -e '/^Onindy.o/d' \ + -e '/^init.o/d' \ + -e '/^nindy.o/d' \ + -e '/ttyflush.o/d' \ + -e '/xdr_ld.o/d' \ + -e '/xdr_ptrace.o/d' \ + -e '/xdr_rdb.o/d' \ + -e '/udr.o/d' \ + -e '/udip2soc.o/d' \ + -e '/udi2go32.o/d' \ + -e '/version.o/d' \ + -e '/^[a-z0-9A-Z_]*_[SU].o/d' \ + -e '/[a-z0-9A-Z_]*-exp.tab.o/d' \ + -e 's/\.o/.c/' \ + -e 's,signals\.c,signals/signals\.c,' \ + -e 's|\([^ ][^ ]*\)|$(srcdir)/\1|g' | \ + while read f; do grep '^_initialize_[a-z_0-9A-Z]* *(' $$f 2>/dev/null; done | \ + sed -e 's/^.*://' -e 's/^\([a-z_0-9A-Z]*\).*/\1/' | \ + ( echo _initialize_gdbtypes ; grep -v '^_initialize_gdbtypes$$' ) > init.l-tmp + @echo '/* Do not modify this file. */' >>init.c-tmp + @echo '/* It is created automatically by the Makefile. */'>>init.c-tmp + @echo '#include "defs.h"' >>init.c-tmp + @echo '#include "call-cmds.h"' >>init.c-tmp + @sed -e 's/\(.*\)/extern initialize_file_ftype \1;/' <init.l-tmp >>init.c-tmp + @echo 'void' >>init.c-tmp + @echo 'initialize_all_files (void)' >>init.c-tmp + @echo '{' >>init.c-tmp + @sed -e 's/\(.*\)/ \1 ();/' <init.l-tmp >>init.c-tmp + @echo '}' >>init.c-tmp + @rm init.l-tmp + @mv init.c-tmp init.c + +.PRECIOUS: init.c + +init.o: init.c $(defs_h) $(call_cmds_h) + +# Removing the old gdb first works better if it is running, at least on SunOS. +gdb$(EXEEXT): main.o libgdb.a $(CONFIG_OBS) $(ADD_DEPS) $(CDEPS) $(TDEPLIBS) + rm -f gdb$(EXEEXT) + $(HLDENV) $(CC_LD) $(INTERNAL_LDFLAGS) $(WIN32LDAPP) -o gdb$(EXEEXT) \ + main.o libgdb.a $(CONFIG_OBS) $(TDEPLIBS) $(TUI_LIBRARY) $(CLIBS)\ + $(LOADLIBES) + +nlm: force + rootme=`pwd`; export rootme; $(MAKE) $(TARGET_FLAGS_TO_PASS) DO=all DODIRS=nlm subdir_do + +# Create a library of the gdb object files and build GDB by linking +# against that. +# +# init.o is very important. It pulls in the rest of GDB. +LIBGDB_OBS= $(OBS) $(TSOBS) $(ADD_FILES) init.o +libgdb.a: $(LIBGDB_OBS) + -rm -f libgdb.a + $(AR) q libgdb.a $(LIBGDB_OBS) + $(RANLIB) libgdb.a + +saber_gdb: $(SFILES) $(DEPFILES) copying.c version.c + #setopt load_flags $(CFLAGS) $(BFD_CFLAGS) -DHOST_SYS=SUN4_SYS + #load ./init.c $(SFILES) + #unload $(srcdir)/c-exp.y + #unload $(srcdir)/jv-exp.y + #unload $(srcdir)/m2-exp.y + #unload $(srcdir)/p-exp.y + #unload vx-share/*.h + #unload nindy-share/[A-Z]* + #load c-exp.tab.c + #load jv-exp.tab.c + #load m2-exp.tab.c + #load p-exp.tab.c + #load copying.c version.c + #load ../opcodes/libopcodes.a + #load ../libiberty/libiberty.a + #load ../bfd/libbfd.a + #load ../readline/libreadline.a + #load ../mmalloc/libmmalloc.a + #load ../intl/libintl.a + #load -ltermcap + #load `echo " "$(DEPFILES) | sed -e 's/\.o/.c/g' -e 's, , ../,g'` + echo "Load .c corresponding to:" $(DEPFILES) + + +# A Mach 3.0 program to force gdb back to command level + +stop-gdb: stop-gdb.o + ${CC_LD} $(GLOBAL_CFLAGS) $(LDFLAGS) -o stop-gdb \ + stop-gdb.o $(CLIBS) $(LOADLIBES) + +# This is useful when debugging GDB, because some Unix's don't let you run GDB +# on itself without copying the executable. So "make gdb1" will make +# gdb and put a copy in gdb1, and you can run it with "gdb gdb1". +# Removing gdb1 before the copy is the right thing if gdb1 is open +# in another process. +gdb1$(EXEEXT): gdb$(EXEEXT) + rm -f gdb1$(EXEEXT) + cp gdb$(EXEEXT) gdb1$(EXEEXT) + +# FIXME. These are not generated by "make depend" because they only are there +# for some machines. +# But these rules don't do what we want; we want to hack the foo.o: tm.h +# dependency to do the right thing. +tm-sun3.h tm-hp300bsd.h tm-altos.h: tm-m68k.h +tm-hp300hpux.h tm-sun2.h tm-3b1.h: tm-m68k.h +xm-i386-sv32.h: xm-i386.h +tm-i386gas.h: tm-i386.h +tm-sun4os4.h: tm-sparc.h +xm-vaxult.h: xm-vax.h +xm-vaxbsd.h: xm-vax.h + +# Put the proper machine-specific files first, so M-. on a machine +# specific routine gets the one for the correct machine. (FIXME: those +# files go in twice; we should be removing them from the main list). + +# TAGS depends on all the files that go into it so you can rebuild TAGS +# with `make TAGS' and not have to say `rm TAGS' first. + +TAGS: $(TAGFILES_NO_SRCDIR) $(TAGFILES_WITH_SRCDIR) + @echo Making TAGS + @etags $(srcdir)/$(TM_FILE) \ + $(srcdir)/$(XM_FILE) \ + $(srcdir)/$(NAT_FILE) \ + `(for i in $(DEPFILES) $(TAGFILES_NO_SRCDIR); do \ + echo $(srcdir)/$$i ; \ + done ; for i in $(TAGFILES_WITH_SRCDIR); do \ + echo $$i ; \ + done) | sed -e 's/\.o$$/\.c/'` \ + `find $(srcdir)/config -name '*.h' -print` + +tags: TAGS + +clean mostlyclean: $(CONFIG_CLEAN) + @$(MAKE) $(FLAGS_TO_PASS) DO=clean "DODIRS=$(SUBDIRS)" subdir_do + rm -f *.o *.a $(ADD_FILES) *~ init.c-tmp init.l-tmp version.c-tmp + rm -f init.c version.c + rm -f gdb$(EXEEXT) core make.log + rm -f gdb[0-9]$(EXEEXT) + +# This used to depend on c-exp.tab.c m2-exp.tab.c TAGS +# I believe this is wrong; the makefile standards for distclean just +# describe removing files; the only sort of "re-create a distribution" +# functionality described is if the distributed files are unmodified. +# NB: While GDBSERVER might be configured on native systems, it isn't +# always included in SUBDIRS. Remove the gdbserver files explictly. +distclean: clean + @$(MAKE) $(FLAGS_TO_PASS) DO=distclean "DODIRS=$(SUBDIRS)" subdir_do + rm -f gdbserver/config.status gdbserver/config.log + rm -f gdbserver/tm.h gdbserver/xm.h gdbserver/nm.h + rm -f gdbserver/Makefile gdbserver/config.cache + rm -f nm.h tm.h xm.h config.status config.h stamp-h .gdbinit + rm -f y.output yacc.acts yacc.tmp y.tab.h + rm -f config.log config.cache + rm -f Makefile + +maintainer-clean: local-maintainer-clean do-maintainer-clean distclean +realclean: maintainer-clean + +local-maintainer-clean: + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + rm -f c-exp.tab.c \ + ada-lex.c ada-exp.tab.c \ + jv-exp.tab \ + f-exp.tab.c m2-exp.tab.c p-exp.tab.c + rm -f TAGS $(INFOFILES) + rm -f $(YYFILES) + rm -f nm.h tm.h xm.h config.status + +do-maintainer-clean: + @$(MAKE) $(FLAGS_TO_PASS) DO=maintainer-clean "DODIRS=$(SUBDIRS)" \ + subdir_do + +diststuff: $(DISTSTUFF) + cd doc; $(MAKE) $(MFLAGS) diststuff + +subdir_do: force + @for i in $(DODIRS); do \ + if [ -f ./$$i/Makefile ] ; then \ + if (cd ./$$i; \ + $(MAKE) $(FLAGS_TO_PASS) $(DO)) ; then true ; \ + else exit 1 ; fi ; \ + else true ; fi ; \ + done + +Makefile: Makefile.in config.status @frags@ + $(SHELL) config.status + +config.h: stamp-h ; @true +stamp-h: config.in config.status + CONFIG_HEADERS=config.h:config.in $(SHELL) config.status + +config.status: configure + $(SHELL) config.status --recheck + +force: + +# Documentation! +# GDB QUICK REFERENCE (TeX dvi file, CM fonts) +doc/refcard.dvi: + cd doc; $(MAKE) refcard.dvi $(FLAGS_TO_PASS) + +# GDB QUICK REFERENCE (PostScript output, common PS fonts) +doc/refcard.ps: + cd doc; $(MAKE) refcard.ps $(FLAGS_TO_PASS) + +# GDB MANUAL: TeX dvi file +doc/gdb.dvi: + cd doc; $(MAKE) gdb.dvi $(FLAGS_TO_PASS) + +# GDB MANUAL: info file +doc/gdb.info: + cd doc; $(MAKE) gdb.info $(FLAGS_TO_PASS) + +# Make copying.c from COPYING +$(srcdir)/copying.c: @MAINTAINER_MODE_TRUE@ \ + $(srcdir)/COPYING $(srcdir)/copying.awk + awk -f $(srcdir)/copying.awk \ + < $(srcdir)/COPYING > $(srcdir)/copying.tmp + mv $(srcdir)/copying.tmp $(srcdir)/copying.c + +version.c: Makefile version.in + rm -f version.c-tmp version.c + echo '#include "version.h"' >> version.c-tmp + echo 'const char version[] = "'"`sed q ${srcdir}/version.in`"'";' >> version.c-tmp + echo 'const char host_name[] = "$(host_alias)";' >> version.c-tmp + echo 'const char target_name[] = "$(target_alias)";' >> version.c-tmp + mv version.c-tmp version.c +version.o: version.c $(version_h) + + +# LANG-exp.tab.c is generated in objdir from LANG-exp.y if it doesn't +# exist in srcdir, then compiled in objdir to LANG-exp.tab.o. + +# If we said LANG-exp.tab.c rather than ./c-exp.tab.c some makes would +# sometimes re-write it into $(srcdir)/c-exp.tab.c. + +# Remove bogus decls for malloc/realloc/free which conflict with +# everything else. Strictly speaking c-exp.tab.c should therefore +# depend on Makefile.in, but that was a pretty big annoyance. + +# See comments above ... +.PRECIOUS: c-exp.tab.c +c-exp.tab.o: c-exp.tab.c +c-exp.tab.c: c-exp.y + $(SHELL) $(YLWRAP) "$(YACC)" $(srcdir)/c-exp.y y.tab.c c-exp.tmp -- $(YFLAGS) + -sed -e '/extern.*malloc/d' \ + -e '/extern.*realloc/d' \ + -e '/extern.*free/d' \ + -e '/include.*malloc.h/d' \ + -e 's/malloc/xmalloc/g' \ + -e 's/realloc/xrealloc/g' \ + -e '/^#line.*y.tab.c/d' \ + < c-exp.tmp > c-exp.new + -rm c-exp.tmp + mv c-exp.new ./c-exp.tab.c + +# See comments above ... +.PRECIOUS: jv-exp.tab.c +jv-exp.tab.o: jv-exp.tab.c +jv-exp.tab.c: jv-exp.y + $(SHELL) $(YLWRAP) "$(YACC)" $(srcdir)/jv-exp.y y.tab.c jv-exp.tmp -- $(YFLAGS) + -sed -e '/extern.*malloc/d' \ + -e '/extern.*realloc/d' \ + -e '/extern.*free/d' \ + -e '/include.*malloc.h/d' \ + -e 's/malloc/xmalloc/g' \ + -e 's/realloc/xrealloc/g' \ + -e '/^#line.*y.tab.c/d' \ + < jv-exp.tmp > jv-exp.new + -rm jv-exp.tmp + mv jv-exp.new ./jv-exp.tab.c + +# See comments above ... +.PRECIOUS: f-exp.tab.c +f-exp.tab.o: f-exp.tab.c +f-exp.tab.c: f-exp.y c-exp.tab.c + $(SHELL) $(YLWRAP) "$(YACC)" $(srcdir)/f-exp.y y.tab.c f-exp.tmp -- $(YFLAGS) + -sed -e '/extern.*malloc/d' \ + -e '/extern.*realloc/d' \ + -e '/extern.*free/d' \ + -e '/include.*malloc.h/d' \ + -e 's/malloc/xmalloc/g' \ + -e 's/realloc/xrealloc/g' \ + -e '/^#line.*y.tab.c/d' \ + < f-exp.tmp > f-exp.new + -rm f-exp.tmp + mv f-exp.new ./f-exp.tab.c + +# See comments above ... +.PRECIOUS: m2-exp.tab.c +m2-exp.tab.o: m2-exp.tab.c +m2-exp.tab.c: m2-exp.y + $(SHELL) $(YLWRAP) "$(YACC)" $(srcdir)/m2-exp.y y.tab.c m2-exp.tmp -- $(YFLAGS) + -sed -e '/extern.*malloc/d' \ + -e '/extern.*realloc/d' \ + -e '/extern.*free/d' \ + -e '/include.*malloc.h/d' \ + -e 's/malloc/xmalloc/g' \ + -e 's/realloc/xrealloc/g' \ + -e '/^#line.*y.tab.c/d' \ + < m2-exp.tmp > m2-exp.new + -rm m2-exp.tmp + mv m2-exp.new ./m2-exp.tab.c + +# See comments above ... +.PRECIOUS: ada-exp.tab.c +ada-exp.tab.o: ada-exp.tab.c +ada-exp.tab.c: ada-exp.y + $(YACC) $(YFLAGS) $(srcdir)/ada-exp.y + -sed -e '/extern.*malloc/d' \ + -e '/extern.*realloc/d' \ + -e '/extern.*free/d' \ + -e '/include.*malloc.h/d' \ + -e 's/malloc/xmalloc/g' \ + -e 's/realloc/xrealloc/g' \ + < y.tab.c > ada-exp.new + -rm y.tab.c + mv ada-exp.new ./ada-exp.tab.c + +# See comments above ... +.PRECIOUS: ada-lex.c +ada-lex.o: ada-lex.c +ada-lex.c: ada-lex.l + @if [ "$(FLEX)" ] && $(FLEX) --version >/dev/null 2>&1; then \ + echo $(FLEX) -Isit $(srcdir)/ada-lex.l ">" ada-lex.c; \ + $(FLEX) -Isit $(srcdir)/ada-lex.l > ada-lex.c; \ + elif [ ! -f ada-lex.c -a ! -f $(srcdir)/ada-lex.c ]; then \ + echo "ada-lex.c missing and flex not available."; \ + false; \ + elif [ ! -f ada-lex.c ]; then \ + echo "Warning: ada-lex.c older than ada-lex.l and flex not available."; \ + fi + +# See comments above ... +.PRECIOUS: p-exp.tab.c +p-exp.tab.o: p-exp.tab.c +p-exp.tab.c: p-exp.y + $(SHELL) $(YLWRAP) "$(YACC)" $(srcdir)/p-exp.y y.tab.c p-exp.tmp -- $(YFLAGS) + -sed -e '/extern.*malloc/d' \ + -e '/extern.*realloc/d' \ + -e '/extern.*free/d' \ + -e '/include.*malloc.h/d' \ + -e 's/malloc/xmalloc/g' \ + -e 's/realloc/xrealloc/g' \ + -e '/^#line.*y.tab.c/d' \ + < p-exp.tmp > p-exp.new + -rm p-exp.tmp + mv p-exp.new ./p-exp.tab.c + +lint: $(LINTFILES) + $(LINT) $(INCLUDE_CFLAGS) $(LINTFLAGS) $(LINTFILES) \ + `echo $(DEPFILES) | sed 's/\.o /\.c /g'` + +gdb.cxref: $(SFILES) + cxref -I. $(SFILES) >gdb.cxref + +force_update: + +# GNU Make has an annoying habit of putting *all* the Makefile variables +# into the environment, unless you include this target as a circumvention. +# Rumor is that this will be fixed (and this target can be removed) +# in GNU Make 4.0. +.NOEXPORT: + +# GNU Make 3.63 has a different problem: it keeps tacking command line +# overrides onto the definition of $(MAKE). This variable setting +# will remove them. +MAKEOVERRIDES= + +## This is ugly, but I don't want GNU make to put these variables in +## the environment. Older makes will see this as a set of targets +## with no dependencies and no actions. +# OBSOLETE unexport CHILLFLAGS CHILL_LIB CHILL_FOR_TARGET : + +ALLDEPFILES = a68v-nat.c \ + aix-thread.c \ + alpha-nat.c alphabsd-nat.c \ + alpha-tdep.c alpha-linux-tdep.c alphabsd-tdep.c alphanbsd-tdep.c \ + alpha-osf1-tdep.c alphafbsd-tdep.c \ + arm-linux-nat.c arm-linux-tdep.c arm-tdep.c \ + armnbsd-nat.c armnbsd-tdep.c \ + avr-tdep.c \ + coff-solib.c \ + core-sol2.c core-regset.c core-aout.c corelow.c \ + dcache.c delta68-nat.c dpx2-nat.c exec.c fork-child.c \ + go32-nat.c h8300-tdep.c h8500-tdep.c \ + hp300ux-nat.c hppa-tdep.c hppab-nat.c hppah-nat.c hpread.c \ + i386-tdep.c i386b-nat.c i386v-nat.c i386-linux-nat.c \ + i386v4-nat.c i386ly-tdep.c \ + i386bsd-nat.c i386bsd-tdep.c i386fbsd-nat.c \ + i387-tdep.c \ + i386-linux-tdep.c i386-nat.c \ + i386gnu-nat.c i386gnu-tdep.c \ + ia64-linux-nat.c ia64-linux-tdep.c ia64-tdep.c \ + infptrace.c inftarg.c irix4-nat.c irix5-nat.c \ + lynx-nat.c m3-nat.c \ + m68hc11-tdep.c \ + m68k-tdep.c \ + mcore-tdep.c \ + mips-linux-nat.c mips-linux-tdep.c \ + mips-nat.c \ + mips-irix-tdep.c \ + mips-tdep.c mipsm3-nat.c mipsv4-nat.c \ + mipsnbsd-nat.c mipsnbsd-tdep.c \ + nbsd-tdep.c \ + nindy-share/Onindy.c nindy-share/nindy.c \ + nindy-share/ttyflush.c nindy-tdep.c \ + ns32k-tdep.c solib-osf.c \ + somread.c somsolib.c $(HPREAD_SOURCE) \ + ppc-sysv-tdep.o ppc-linux-nat.c ppc-linux-tdep.c \ + ppcnbsd-nat.o ppcnbsd-tdep.o \ + procfs.c \ + remote-array.c remote-e7000.c \ + remote-es.c remote-hms.c remote-mips.c \ + remote-rdp.c remote-sim.c \ + remote-st.c remote-utils.c dcache.c \ + remote-vx.c \ + rs6000-nat.c rs6000-tdep.c \ + s390-tdep.c s390-nat.c \ + ser-go32.c ser-pipe.c ser-tcp.c \ + sh-tdep.c shnbsd-tdep.c shnbsd-nat.c \ + solib.c solib-irix.c solib-svr4.c solib-sunos.c sparc-linux-nat.c \ + sparc-nat.c \ + sparc64nbsd-nat.c sparcnbsd-nat.c sparcnbsd-tdep.c \ + sparc-tdep.c sparcl-tdep.c sun3-nat.c \ + symm-tdep.c symm-nat.c \ + vax-tdep.c \ + vx-share/xdr_ld.c vx-share/xdr_ptrace.c vx-share/xdr_rdb.c \ + win32-nat.c \ + xcoffread.c xcoffsolib.c \ + xstormy16-tdep.c \ + z8k-tdep.c + +# Some files need explict build rules (due to -Werror problems) or due +# to sub-directory fun 'n' games. + +# Provide explicit rule/dependency - works for more makes. +copying.o: $(srcdir)/copying.c + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/copying.c + +hpux-thread.o: $(srcdir)/hpux-thread.c + $(CC) -c $(INTERNAL_CFLAGS) -I$(srcdir)/osf-share \ + -I$(srcdir)/osf-share/HP800 -I/usr/include/dce \ + $(srcdir)/hpux-thread.c + +# FIXME: Procfs.o gets -Wformat errors because things like pid_t don't +# match output format strings. +procfs.o: $(srcdir)/procfs.c + $(CC) -c $(INTERNAL_WARN_CFLAGS) $(NO_WERROR_CFLAGS) $(srcdir)/procfs.c + +v850ice.o: $(srcdir)/v850ice.c + $(CC) -c $(INTERNAL_CFLAGS) $(IDE_CFLAGS) $(ITCL_CFLAGS) \ + $(TIX_CFLAGS) $(TCL_CFLAGS) $(TK_CFLAGS) $(X11_CFLAGS) \ + $(GDBTK_CFLAGS) \ + $(srcdir)/v850ice.c + +# FIXME: z8k-tdep.c calls _initialize_gdbtypes(). Since that isn't +# declared -Wimplicit fails. It should be using the GDBARCH framework. +# cagney 1999-09-02. +z8k-tdep.o: $(srcdir)/z8k-tdep.c + $(CC) -c $(INTERNAL_WARN_CFLAGS) $(NO_WERROR_CFLAGS) \ + $(srcdir)/z8k-tdep.c + +# +# Generated YACC/LEX dependencies +# + +c-exp.tab.o: c-exp.tab.c $(defs_h) $(gdb_string_h) $(expression_h) \ + $(value_h) $(parser_defs_h) $(language_h) $(c_lang_h) $(bfd_h) \ + $(charset_h) \ + $(symfile_h) $(objfiles_h) + +jv-exp.tab.o: jv-exp.tab.c jv-lang.h $(defs_h) $(expression_h) \ + $(gdbtypes_h) $(language_h) $(parser_defs_h) $(symtab_h) $(value_h) \ + $(bfd_h) $(objfiles_h) $(symfile_h) + +f-exp.tab.o: f-exp.tab.c f-lang.h $(defs_h) $(expression_h) \ + $(language_h) $(parser_defs_h) $(value_h) $(bfd_h) $(objfiles_h) \ + $(symfile_h) + +m2-exp.tab.o: m2-exp.tab.c $(defs_h) $(expression_h) $(gdbtypes_h) \ + $(language_h) m2-lang.h $(parser_defs_h) $(symtab_h) $(value_h) \ + $(bfd_h) $(objfiles_h) $(symfile_h) + +p-exp.tab.o: p-exp.tab.c $(defs_h) $(expression_h) $(gdbtypes_h) \ + $(language_h) p-lang.h $(parser_defs_h) $(symtab_h) $(value_h) \ + $(bfd_h) $(objfiles_h) $(symfile_h) + +ada-exp.tab.o: ada-exp.tab.c ada-lex.c ada-lang.h \ + $(defs_h) $(expression_h) \ + $(gdbtypes_h) language.h parser-defs.h $(symtab_h) $(value_h) \ + $(bfd_h) objfiles.h symfile.h + +# +# The dependencies. In aphabetic order. +# + +a68v-nat.o: a68v-nat.c $(defs_h) $(inferior_h) $(regcache_h) +abug-rom.o: abug-rom.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \ + $(serial_h) $(regcache_h) +ada-lang.o: ada-lang.c $(gdb_string_h) $(demangle_h) $(defs_h) $(symtab_h) \ + $(gdbtypes_h) $(gdbcmd_h) $(expression_h) $(parser_defs_h) \ + $(language_h) $(c_lang_h) $(inferior_h) $(symfile_h) $(objfiles_h) \ + $(breakpoint_h) $(gdbcore_h) $(ada_lang_h) $(ui_out_h) +ada-tasks.o: ada-tasks.c $(defs_h) $(command_h) $(value_h) $(language_h) \ + $(inferior_h) $(symtab_h) $(target_h) $(gdbcore_h) $(gregset_h) \ + $(ada_lang_h) +ada-typeprint.o: ada-typeprint.c $(defs_h) $(gdb_obstack_h) $(bfd_h) \ + $(symtab_h) $(gdbtypes_h) $(expression_h) $(value_h) $(gdbcore_h) \ + $(target_h) $(command_h) $(gdbcmd_h) $(language_h) $(demangle_h) \ + $(c_lang_h) $(typeprint_h) $(ada_lang_h) $(gdb_string_h) +ada-valprint.o: ada-valprint.c $(defs_h) $(symtab_h) $(gdbtypes_h) \ + $(expression_h) $(value_h) $(demangle_h) $(valprint_h) $(language_h) \ + $(annotate_h) $(ada_lang_h) $(c_lang_h) +aix-thread.o: aix-thread.c $(defs_h) $(gdb_assert_h) $(gdbthread_h) \ + $(target_h) $(inferior_h) $(regcache_h) $(gdbcmd_h) $(language_h) \ + $(ppc_tdep_h) +alpha-linux-tdep.o: alpha-linux-tdep.c $(defs_h) $(frame_h) $(gdbcore_h) \ + $(value_h) $(alpha_tdep_h) +alpha-nat.o: alpha-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) $(target_h) \ + $(regcache_h) $(alpha_tdep_h) $(gregset_h) +alpha-osf1-tdep.o: alpha-osf1-tdep.c $(defs_h) $(frame_h) $(gdbcore_h) \ + $(value_h) $(alpha_tdep_h) +alpha-tdep.o: alpha-tdep.c $(defs_h) $(frame_h) $(inferior_h) $(symtab_h) \ + $(value_h) $(gdbcmd_h) $(gdbcore_h) $(dis_asm_h) $(symfile_h) \ + $(objfiles_h) $(gdb_string_h) $(linespec_h) $(regcache_h) \ + $(doublest_h) $(arch_utils_h) $(elf_bfd_h) $(alpha_tdep_h) +alphabsd-nat.o: alphabsd-nat.c $(defs_h) $(inferior_h) $(regcache_h) \ + $(alpha_tdep_h) $(alphabsd_tdep_h) $(gregset_h) +alphabsd-tdep.o: alphabsd-tdep.c $(defs_h) $(regcache_h) $(alpha_tdep_h) \ + $(alphabsd_tdep_h) +alphafbsd-tdep.o: alphafbsd-tdep.c $(defs_h) $(value_h) $(alpha_tdep_h) +alphanbsd-tdep.o: alphanbsd-tdep.c $(defs_h) $(gdbcore_h) $(frame_h) \ + $(regcache_h) $(value_h) $(solib_svr4_h) $(alpha_tdep_h) \ + $(alphabsd_tdep_h) $(nbsd_tdep_h) +annotate.o: annotate.c $(defs_h) $(annotate_h) $(value_h) $(target_h) \ + $(gdbtypes_h) $(breakpoint_h) +# OBSOLETE arc-tdep.o: arc-tdep.c +arch-utils.o: arch-utils.c $(defs_h) $(arch_utils_h) $(gdbcmd_h) \ + $(inferior_h) $(symtab_h) $(frame_h) $(inferior_h) $(breakpoint_h) \ + $(gdb_wait_h) $(gdbcore_h) $(gdbcmd_h) $(target_h) $(annotate_h) \ + $(gdb_string_h) $(regcache_h) $(gdb_assert_h) $(sim_regno_h) \ + $(version_h) $(floatformat_h) +arm-linux-nat.o: arm-linux-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) \ + $(gdb_string_h) $(regcache_h) $(arm_tdep_h) $(gregset_h) +arm-linux-tdep.o: arm-linux-tdep.c $(defs_h) $(target_h) $(value_h) \ + $(gdbtypes_h) $(floatformat_h) $(gdbcore_h) $(frame_h) $(regcache_h) \ + $(doublest_h) $(arm_tdep_h) $(symtab_h) $(symfile_h) $(objfiles_h) +arm-tdep.o: arm-tdep.c $(defs_h) $(frame_h) $(inferior_h) $(gdbcmd_h) \ + $(gdbcore_h) $(symfile_h) $(gdb_string_h) $(dis_asm_h) $(regcache_h) \ + $(doublest_h) $(value_h) $(arch_utils_h) $(solib_svr4_h) \ + $(arm_tdep_h) $(gdb_sim_arm_h) $(elf_bfd_h) $(coff_internal_h) \ + $(elf_arm_h) $(gdb_assert_h) $(bfd_in2_h) $(libcoff_h) +armnbsd-nat.o: armnbsd-nat.c $(defs_h) $(arm_tdep_h) $(inferior_h) \ + $(regcache_h) $(gdbcore_h) +armnbsd-tdep.o: armnbsd-tdep.c $(defs_h) $(arm_tdep_h) $(nbsd_tdep_h) \ + $(solib_svr4_h) +avr-tdep.o: avr-tdep.c $(defs_h) $(gdbcmd_h) $(gdbcore_h) $(inferior_h) \ + $(symfile_h) $(arch_utils_h) $(regcache_h) $(gdb_string_h) +ax-gdb.o: ax-gdb.c $(defs_h) $(symtab_h) $(symfile_h) $(gdbtypes_h) \ + $(value_h) $(expression_h) $(command_h) $(gdbcmd_h) $(frame_h) \ + $(target_h) $(ax_h) $(ax_gdb_h) $(gdb_string_h) +ax-general.o: ax-general.c $(defs_h) $(ax_h) $(value_h) $(gdb_string_h) +bcache.o: bcache.c $(defs_h) $(gdb_obstack_h) $(bcache_h) $(gdb_string_h) +blockframe.o: blockframe.c $(defs_h) $(symtab_h) $(bfd_h) $(symfile_h) \ + $(objfiles_h) $(frame_h) $(gdbcore_h) $(value_h) $(target_h) \ + $(inferior_h) $(annotate_h) $(regcache_h) $(gdb_assert_h) +breakpoint.o: breakpoint.c $(defs_h) $(symtab_h) $(frame_h) $(breakpoint_h) \ + $(gdbtypes_h) $(expression_h) $(gdbcore_h) $(gdbcmd_h) $(value_h) \ + $(command_h) $(inferior_h) $(gdbthread_h) $(target_h) $(language_h) \ + $(gdb_string_h) $(demangle_h) $(annotate_h) $(symfile_h) \ + $(objfiles_h) $(linespec_h) $(completer_h) $(gdb_h) $(ui_out_h) \ + $(cli_script_h) $(gdb_events_h) $(source_h) +buildsym.o: buildsym.c $(defs_h) $(bfd_h) $(gdb_obstack_h) $(symtab_h) \ + $(symfile_h) $(objfiles_h) $(gdbtypes_h) $(complaints_h) \ + $(gdb_string_h) $(expression_h) $(language_h) $(bcache_h) \ + $(filenames_h) $(macrotab_h) $(demangle_h) $(buildsym_h) \ + $(stabsread_h) +builtin-regs.o: builtin-regs.c $(defs_h) $(builtin_regs_h) $(gdbtypes_h) \ + $(gdb_string_h) $(gdb_assert_h) +c-lang.o: c-lang.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_h) \ + $(parser_defs_h) $(language_h) $(c_lang_h) $(valprint_h) \ + $(macroscope_h) $(gdb_assert_h) +c-typeprint.o: c-typeprint.c $(defs_h) $(gdb_obstack_h) $(bfd_h) $(symtab_h) \ + $(gdbtypes_h) $(expression_h) $(value_h) $(gdbcore_h) $(target_h) \ + $(language_h) $(demangle_h) $(c_lang_h) $(typeprint_h) $(cp_abi_h) \ + $(gdb_string_h) +c-valprint.o: c-valprint.c $(defs_h) $(gdb_string_h) $(symtab_h) \ + $(gdbtypes_h) $(expression_h) $(value_h) $(valprint_h) $(language_h) \ + $(c_lang_h) $(cp_abi_h) +# OBSOLETE ch-exp.o: ch-exp.c +# OBSOLETE ch-lang.o: ch-lang.c +# OBSOLETE ch-typeprint.o: ch-typeprint.c +# OBSOLETE ch-valprint.o: ch-valprint.c +cli-out.o: cli-out.c $(defs_h) $(ui_out_h) $(cli_out_h) $(gdb_string_h) \ + $(gdb_assert_h) +coff-solib.o: coff-solib.c $(defs_h) $(frame_h) $(bfd_h) $(gdbcore_h) \ + $(symtab_h) $(symfile_h) $(objfiles_h) +coffread.o: coffread.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(demangle_h) \ + $(breakpoint_h) $(bfd_h) $(gdb_obstack_h) $(gdb_string_h) \ + $(coff_internal_h) $(libcoff_h) $(symfile_h) $(objfiles_h) \ + $(buildsym_h) $(gdb_stabs_h) $(stabsread_h) $(complaints_h) \ + $(target_h) $(gdb_assert_h) +complaints.o: complaints.c $(defs_h) $(complaints_h) $(gdb_assert_h) \ + $(command_h) $(gdbcmd_h) +completer.o: completer.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_h) \ + $(filenames_h) $(cli_decode_h) $(gdbcmd_h) $(completer_h) +copying.o: copying.c $(defs_h) $(command_h) $(gdbcmd_h) +core-aout.o: core-aout.c $(defs_h) $(gdbcore_h) $(value_h) $(regcache_h) \ + $(gdb_dirent_h) $(gdb_stat_h) +core-regset.o: core-regset.c $(defs_h) $(gdb_string_h) $(inferior_h) \ + $(target_h) $(command_h) $(gdbcore_h) $(gregset_h) +core-sol2.o: core-sol2.c $(defs_h) $(gdb_string_h) $(regcache_h) \ + $(inferior_h) $(target_h) $(command_h) $(gdbcore_h) $(gregset_h) +corefile.o: corefile.c $(defs_h) $(gdb_string_h) $(inferior_h) $(symtab_h) \ + $(command_h) $(gdbcmd_h) $(bfd_h) $(target_h) $(gdbcore_h) \ + $(dis_asm_h) $(gdb_stat_h) $(completer_h) +corelow.o: corelow.c $(defs_h) $(gdb_string_h) $(frame_h) $(inferior_h) \ + $(symtab_h) $(command_h) $(bfd_h) $(target_h) $(gdbcore_h) \ + $(gdbthread_h) $(regcache_h) $(symfile_h) +cp-abi.o: cp-abi.c $(defs_h) $(value_h) $(cp_abi_h) $(gdb_string_h) +cp-support.o: cp-support.c $(defs_h) $(cp_support_h) +cp-valprint.o: cp-valprint.c $(defs_h) $(gdb_obstack_h) $(symtab_h) \ + $(gdbtypes_h) $(expression_h) $(value_h) $(command_h) $(gdbcmd_h) \ + $(demangle_h) $(annotate_h) $(gdb_string_h) $(c_lang_h) $(target_h) \ + $(cp_abi_h) +cpu32bug-rom.o: cpu32bug-rom.c $(defs_h) $(gdbcore_h) $(target_h) \ + $(monitor_h) $(serial_h) $(regcache_h) +cris-tdep.o: cris-tdep.c $(defs_h) $(frame_h) $(symtab_h) $(inferior_h) \ + $(gdbtypes_h) $(gdbcore_h) $(gdbcmd_h) $(target_h) $(value_h) \ + $(opcode_cris_h) $(arch_utils_h) $(regcache_h) $(symfile_h) \ + $(solib_h) $(solib_svr4_h) +# OBSOLETE cxux-nat.o: cxux-nat.c +d10v-tdep.o: d10v-tdep.c $(defs_h) $(frame_h) $(symtab_h) $(gdbtypes_h) \ + $(gdbcmd_h) $(gdbcore_h) $(gdb_string_h) $(value_h) $(inferior_h) \ + $(dis_asm_h) $(symfile_h) $(objfiles_h) $(language_h) \ + $(arch_utils_h) $(regcache_h) $(floatformat_h) $(gdb_sim_d10v_h) \ + $(sim_regno_h) +# OBSOLETE d30v-tdep.o: d30v-tdep.c +dbug-rom.o: dbug-rom.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \ + $(serial_h) $(regcache_h) +dbxread.o: dbxread.c $(defs_h) $(gdb_string_h) $(gdb_obstack_h) \ + $(gdb_stat_h) $(symtab_h) $(breakpoint_h) $(target_h) $(gdbcore_h) \ + $(libaout_h) $(symfile_h) $(objfiles_h) $(buildsym_h) $(stabsread_h) \ + $(gdb_stabs_h) $(demangle_h) $(language_h) $(complaints_h) \ + $(cp_abi_h) $(aout_aout64_h) $(aout_stab_gnu_h) +dcache.o: dcache.c $(defs_h) $(dcache_h) $(gdbcmd_h) $(gdb_string_h) \ + $(gdbcore_h) $(target_h) +delta68-nat.o: delta68-nat.c $(defs_h) +demangle.o: demangle.c $(defs_h) $(command_h) $(gdbcmd_h) $(demangle_h) \ + $(gdb_string_h) +dink32-rom.o: dink32-rom.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \ + $(serial_h) $(symfile_h) $(inferior_h) $(regcache_h) +doublest.o: doublest.c $(defs_h) $(doublest_h) $(floatformat_h) \ + $(gdb_assert_h) $(gdb_string_h) $(gdbtypes_h) +dpx2-nat.o: dpx2-nat.c $(defs_h) $(gdbcore_h) $(gdb_string_h) +dsrec.o: dsrec.c $(defs_h) $(serial_h) $(srec_h) +# OBSOLETE dstread.o: dstread.c +dve3900-rom.o: dve3900-rom.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \ + $(serial_h) $(inferior_h) $(command_h) $(gdb_string_h) $(regcache_h) +dwarf2cfi.o: dwarf2cfi.c $(defs_h) $(gdbcore_h) $(symtab_h) $(symfile_h) \ + $(objfiles_h) $(target_h) $(elf_dwarf2_h) $(inferior_h) \ + $(regcache_h) $(dwarf2cfi_h) $(gdb_assert_h) +dwarf2read.o: dwarf2read.c $(defs_h) $(bfd_h) $(symtab_h) $(gdbtypes_h) \ + $(symfile_h) $(objfiles_h) $(elf_dwarf2_h) $(buildsym_h) \ + $(demangle_h) $(expression_h) $(filenames_h) $(macrotab_h) \ + $(language_h) $(complaints_h) $(bcache_h) $(gdb_string_h) \ + $(gdb_assert_h) +dwarfread.o: dwarfread.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(symfile_h) \ + $(objfiles_h) $(elf_dwarf_h) $(buildsym_h) $(demangle_h) \ + $(expression_h) $(language_h) $(complaints_h) $(gdb_string_h) +elfread.o: elfread.c $(defs_h) $(bfd_h) $(gdb_string_h) $(elf_bfd_h) \ + $(elf_mips_h) $(symtab_h) $(symfile_h) $(objfiles_h) $(buildsym_h) \ + $(stabsread_h) $(gdb_stabs_h) $(complaints_h) $(demangle_h) +environ.o: environ.c $(defs_h) $(environ_h) $(gdb_string_h) +eval.o: eval.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \ + $(value_h) $(expression_h) $(target_h) $(frame_h) $(language_h) \ + $(f_lang_h) $(cp_abi_h) +event-loop.o: event-loop.c $(defs_h) $(event_loop_h) $(event_top_h) \ + $(gdb_string_h) +event-top.o: event-top.c $(defs_h) $(top_h) $(inferior_h) $(target_h) \ + $(terminal_h) $(event_loop_h) $(event_top_h) $(gdbcmd_h) +exec.o: exec.c $(defs_h) $(frame_h) $(inferior_h) $(target_h) $(gdbcmd_h) \ + $(language_h) $(symfile_h) $(objfiles_h) $(completer_h) $(value_h) \ + $(gdb_string_h) $(gdbcore_h) $(gdb_stat_h) $(xcoffsolib_h) +expprint.o: expprint.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_h) \ + $(value_h) $(language_h) $(parser_defs_h) +f-lang.o: f-lang.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \ + $(expression_h) $(parser_defs_h) $(language_h) $(f_lang_h) \ + $(valprint_h) +f-typeprint.o: f-typeprint.c $(defs_h) $(gdb_obstack_h) $(bfd_h) $(symtab_h) \ + $(gdbtypes_h) $(expression_h) $(value_h) $(gdbcore_h) $(target_h) \ + $(f_lang_h) $(gdb_string_h) +f-valprint.o: f-valprint.c $(defs_h) $(gdb_string_h) $(symtab_h) \ + $(gdbtypes_h) $(expression_h) $(value_h) $(valprint_h) $(language_h) \ + $(f_lang_h) $(frame_h) $(gdbcore_h) $(command_h) +fbsd-proc.o: fbsd-proc.c $(defs_h) $(gdbcore_h) $(inferior_h) \ + $(gdb_string_h) $(elf_bfd_h) $(gregset_h) +findvar.o: findvar.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(frame_h) \ + $(value_h) $(gdbcore_h) $(inferior_h) $(target_h) $(gdb_string_h) \ + $(gdb_assert_h) $(floatformat_h) $(symfile_h) $(regcache_h) \ + $(builtin_regs_h) +fork-child.o: fork-child.c $(defs_h) $(gdb_string_h) $(frame_h) \ + $(inferior_h) $(target_h) $(gdb_wait_h) $(gdb_vfork_h) $(gdbcore_h) \ + $(terminal_h) $(gdbthread_h) $(command_h) +# OBSOLETE fr30-tdep.o: fr30-tdep.c +frame.o: frame.c $(defs_h) $(frame_h) $(target_h) $(value_h) $(inferior_h) \ + $(regcache_h) $(gdb_assert_h) +frv-tdep.o: frv-tdep.c $(defs_h) $(inferior_h) $(symfile_h) $(gdbcore_h) \ + $(arch_utils_h) $(regcache_h) +gcore.o: gcore.c $(defs_h) $(cli_decode_h) $(inferior_h) $(gdbcore_h) \ + $(elf_bfd_h) $(symfile_h) $(objfiles_h) +gdb-events.o: gdb-events.c $(defs_h) $(gdb_events_h) $(gdbcmd_h) +gdbarch.o: gdbarch.c $(defs_h) $(arch_utils_h) $(gdbcmd_h) $(inferior_h) \ + $(gdb_string_h) $(symtab_h) $(frame_h) $(inferior_h) $(breakpoint_h) \ + $(gdb_wait_h) $(gdbcore_h) $(gdbcmd_h) $(target_h) $(gdbthread_h) \ + $(annotate_h) $(symfile_h) $(value_h) $(symcat_h) $(floatformat_h) \ + $(gdb_assert_h) $(gdb_string_h) $(gdb_events_h) +gdbtypes.o: gdbtypes.c $(defs_h) $(gdb_string_h) $(bfd_h) $(symtab_h) \ + $(symfile_h) $(objfiles_h) $(gdbtypes_h) $(expression_h) \ + $(language_h) $(target_h) $(value_h) $(demangle_h) $(complaints_h) \ + $(gdbcmd_h) $(wrapper_h) $(cp_abi_h) $(gdb_assert_h) +gnu-nat.o: gnu-nat.c $(gdb_string_h) $(defs_h) $(inferior_h) $(symtab_h) \ + $(value_h) $(language_h) $(target_h) $(gdb_wait_h) $(gdbcmd_h) \ + $(gdbcore_h) $(gdbthread_h) $(gdb_assert_h) $(gnu_nat_h) \ + $(exc_request_S_h) $(notify_S_h) $(process_reply_S_h) \ + $(msg_reply_S_h) $(exc_request_U_h) $(msg_U_h) +gnu-v2-abi.o: gnu-v2-abi.c $(defs_h) $(gdb_string_h) $(symtab_h) \ + $(gdbtypes_h) $(value_h) $(demangle_h) $(cp_abi_h) +gnu-v3-abi.o: gnu-v3-abi.c $(defs_h) $(value_h) $(cp_abi_h) $(demangle_h) \ + $(gdb_assert_h) $(gdb_string_h) +go32-nat.o: go32-nat.c $(defs_h) $(inferior_h) $(gdb_wait_h) $(gdbcore_h) \ + $(command_h) $(gdbcmd_h) $(floatformat_h) $(buildsym_h) \ + $(i387_tdep_h) $(i386_tdep_h) $(value_h) $(regcache_h) \ + $(gdb_string_h) +h8300-tdep.o: h8300-tdep.c $(defs_h) $(frame_h) $(symtab_h) $(dis_asm_h) \ + $(gdbcmd_h) $(gdbtypes_h) $(gdbcore_h) $(gdb_string_h) $(value_h) \ + $(regcache_h) +h8500-tdep.o: h8500-tdep.c $(defs_h) $(frame_h) $(symtab_h) $(gdbtypes_h) \ + $(gdbcmd_h) $(value_h) $(dis_asm_h) $(gdbcore_h) $(regcache_h) +hp300ux-nat.o: hp300ux-nat.c $(defs_h) $(frame_h) $(inferior_h) \ + $(regcache_h) +hpacc-abi.o: hpacc-abi.c $(defs_h) $(value_h) $(gdb_regex_h) $(gdb_string_h) \ + $(gdbtypes_h) $(gdbcore_h) $(cp_abi_h) +hppa-tdep.o: hppa-tdep.c $(defs_h) $(frame_h) $(bfd_h) $(inferior_h) \ + $(value_h) $(regcache_h) $(completer_h) $(symtab_h) $(a_out_encap_h) \ + $(gdb_stat_h) $(gdb_wait_h) $(gdbcore_h) $(gdbcmd_h) $(target_h) \ + $(symfile_h) $(objfiles_h) +hppab-nat.o: hppab-nat.c $(defs_h) $(inferior_h) $(target_h) $(regcache_h) +hppah-nat.o: hppah-nat.c $(defs_h) $(inferior_h) $(target_h) $(gdbcore_h) \ + $(gdb_wait_h) $(regcache_h) +hppam3-nat.o: hppam3-nat.c $(defs_h) $(inferior_h) $(floatformat_h) \ + $(regcache_h) +hpread.o: hpread.c $(defs_h) $(bfd_h) $(gdb_string_h) $(hp_symtab_h) \ + $(syms_h) $(symtab_h) $(symfile_h) $(objfiles_h) $(buildsym_h) \ + $(complaints_h) $(gdb_stabs_h) $(gdbtypes_h) $(demangle_h) \ + $(gdb_string_h) +hpux-thread.o: hpux-thread.c $(defs_h) $(gdbthread_h) $(target_h) \ + $(inferior_h) $(regcache_h) $(gdbcore_h) +i386-linux-nat.o: i386-linux-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) \ + $(regcache_h) $(gdb_assert_h) $(gdb_string_h) $(gregset_h) \ + $(i387_tdep_h) $(i386_tdep_h) $(i386_linux_tdep_h) +i386-linux-tdep.o: i386-linux-tdep.c $(defs_h) $(gdbcore_h) $(frame_h) \ + $(value_h) $(regcache_h) $(inferior_h) $(symtab_h) $(symfile_h) \ + $(objfiles_h) $(solib_svr4_h) $(i386_tdep_h) $(i386_linux_tdep_h) +i386-nat.o: i386-nat.c $(defs_h) $(breakpoint_h) $(command_h) $(gdbcmd_h) +i386-sol2-tdep.o: i386-sol2-tdep.c $(defs_h) $(value_h) $(i386_tdep_h) +i386-stub.o: i386-stub.c +i386-tdep.o: i386-tdep.c $(defs_h) $(gdb_string_h) $(frame_h) $(inferior_h) \ + $(gdbcore_h) $(objfiles_h) $(target_h) $(floatformat_h) $(symfile_h) \ + $(symtab_h) $(gdbcmd_h) $(command_h) $(arch_utils_h) $(regcache_h) \ + $(doublest_h) $(value_h) $(gdb_assert_h) $(i386_tdep_h) \ + $(i387_tdep_h) +# OBSOLETE i386aix-nat.o: i386aix-nat.c +i386b-nat.o: i386b-nat.c $(defs_h) +i386bsd-nat.o: i386bsd-nat.c $(defs_h) $(inferior_h) $(regcache_h) \ + $(gdb_assert_h) $(gregset_h) $(i386_tdep_h) $(i387_tdep_h) +i386bsd-tdep.o: i386bsd-tdep.c $(defs_h) $(arch_utils_h) $(frame_h) \ + $(gdbcore_h) $(regcache_h) $(gdb_string_h) $(i386_tdep_h) +i386fbsd-nat.o: i386fbsd-nat.c $(defs_h) $(inferior_h) $(regcache_h) +i386gnu-nat.o: i386gnu-nat.c $(defs_h) $(inferior_h) $(floatformat_h) \ + $(regcache_h) $(gdb_assert_h) $(i386_tdep_h) $(gnu_nat_h) \ + $(i387_tdep_h) +i386gnu-tdep.o: i386gnu-tdep.c $(defs_h) $(i386_tdep_h) +i386ly-tdep.o: i386ly-tdep.c $(defs_h) $(gdbcore_h) $(inferior_h) \ + $(regcache_h) $(target_h) $(i386_tdep_h) +# OBSOLETE i386m3-nat.o: i386m3-nat.c +# OBSOLETE i386mach-nat.o: i386mach-nat.c +i386nbsd-tdep.o: i386nbsd-tdep.c $(defs_h) $(gdbtypes_h) $(gdbcore_h) \ + $(regcache_h) $(arch_utils_h) $(i386_tdep_h) $(i387_tdep_h) \ + $(nbsd_tdep_h) $(solib_svr4_h) +i386obsd-nat.o: i386obsd-nat.c $(defs_h) +i386v-nat.o: i386v-nat.c $(defs_h) $(frame_h) $(inferior_h) $(language_h) \ + $(gdbcore_h) $(gdb_stat_h) $(floatformat_h) $(target_h) +i386v4-nat.o: i386v4-nat.c $(defs_h) $(value_h) $(inferior_h) $(regcache_h) \ + $(i386_tdep_h) $(i387_tdep_h) $(gregset_h) +i387-tdep.o: i387-tdep.c $(defs_h) $(frame_h) $(inferior_h) $(language_h) \ + $(value_h) $(gdbcore_h) $(floatformat_h) $(regcache_h) \ + $(gdb_assert_h) $(gdb_string_h) $(doublest_h) $(i386_tdep_h) +# OBSOLETE i960-tdep.o: i960-tdep.c +ia64-aix-nat.o: ia64-aix-nat.c $(defs_h) $(inferior_h) $(target_h) \ + $(gdbcore_h) $(regcache_h) $(symtab_h) $(bfd_h) $(symfile_h) \ + $(objfiles_h) $(gdb_stat_h) +ia64-aix-tdep.o: ia64-aix-tdep.c $(defs_h) +ia64-linux-nat.o: ia64-linux-nat.c $(defs_h) $(inferior_h) $(target_h) \ + $(gdbcore_h) $(regcache_h) $(gregset_h) +ia64-linux-tdep.o: ia64-linux-tdep.c $(defs_h) $(arch_utils_h) +ia64-tdep.o: ia64-tdep.c $(defs_h) $(inferior_h) $(symfile_h) $(gdbcore_h) \ + $(arch_utils_h) $(floatformat_h) $(regcache_h) $(doublest_h) \ + $(value_h) $(objfiles_h) $(elf_common_h) $(elf_bfd_h) +inf-loop.o: inf-loop.c $(defs_h) $(inferior_h) $(target_h) $(event_loop_h) \ + $(event_top_h) $(inf_loop_h) $(remote_h) +infcmd.o: infcmd.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \ + $(frame_h) $(inferior_h) $(environ_h) $(value_h) $(gdbcmd_h) \ + $(symfile_h) $(gdbcore_h) $(target_h) $(language_h) $(symfile_h) \ + $(objfiles_h) $(completer_h) $(ui_out_h) $(event_top_h) \ + $(parser_defs_h) $(regcache_h) +inflow.o: inflow.c $(defs_h) $(frame_h) $(inferior_h) $(command_h) \ + $(serial_h) $(terminal_h) $(target_h) $(gdbthread_h) $(gdb_string_h) +infptrace.o: infptrace.c $(defs_h) $(frame_h) $(inferior_h) $(target_h) \ + $(gdb_string_h) $(regcache_h) $(gdb_wait_h) $(command_h) \ + $(gdb_dirent_h) $(gdbcore_h) $(gdb_stat_h) +infrun.o: infrun.c $(defs_h) $(gdb_string_h) $(symtab_h) $(frame_h) \ + $(inferior_h) $(breakpoint_h) $(gdb_wait_h) $(gdbcore_h) $(gdbcmd_h) \ + $(cli_script_h) $(target_h) $(gdbthread_h) $(annotate_h) \ + $(symfile_h) $(top_h) $(inf_loop_h) $(regcache_h) $(value_h) +inftarg.o: inftarg.c $(defs_h) $(frame_h) $(inferior_h) $(target_h) \ + $(gdbcore_h) $(command_h) $(gdb_stat_h) $(gdb_wait_h) +infttrace.o: infttrace.c $(defs_h) $(frame_h) $(inferior_h) $(target_h) \ + $(gdb_string_h) $(gdb_wait_h) $(command_h) $(gdbcore_h) +irix4-nat.o: irix4-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) $(regcache_h) \ + $(gregset_h) +irix5-nat.o: irix5-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) $(target_h) \ + $(regcache_h) $(gdb_string_h) $(gregset_h) +jv-lang.o: jv-lang.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_h) \ + $(parser_defs_h) $(language_h) $(gdbtypes_h) $(symtab_h) \ + $(symfile_h) $(objfiles_h) $(gdb_string_h) $(value_h) $(c_lang_h) \ + $(jv_lang_h) $(gdbcore_h) +jv-typeprint.o: jv-typeprint.c $(defs_h) $(symtab_h) $(gdbtypes_h) \ + $(value_h) $(demangle_h) $(jv_lang_h) $(gdb_string_h) $(typeprint_h) \ + $(c_lang_h) $(cp_abi_h) +jv-valprint.o: jv-valprint.c $(defs_h) $(symtab_h) $(gdbtypes_h) \ + $(gdbcore_h) $(expression_h) $(value_h) $(demangle_h) $(valprint_h) \ + $(language_h) $(jv_lang_h) $(c_lang_h) $(annotate_h) $(gdb_string_h) +kod-cisco.o: kod-cisco.c $(defs_h) $(gdb_string_h) $(kod_h) +kod.o: kod.c $(defs_h) $(command_h) $(gdbcmd_h) $(target_h) $(gdb_string_h) \ + $(kod_h) +language.o: language.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \ + $(value_h) $(gdbcmd_h) $(expression_h) $(language_h) $(target_h) \ + $(parser_defs_h) $(jv_lang_h) +lin-lwp.o: lin-lwp.c $(defs_h) $(gdb_assert_h) $(gdb_string_h) $(gdb_wait_h) \ + $(gdbthread_h) $(inferior_h) $(target_h) $(regcache_h) $(gdbcmd_h) +linespec.o: linespec.c $(defs_h) $(symtab_h) $(frame_h) $(command_h) \ + $(symfile_h) $(objfiles_h) $(demangle_h) $(value_h) $(completer_h) \ + $(cp_abi_h) $(source_h) +linux-proc.o: linux-proc.c $(defs_h) $(inferior_h) $(regcache_h) \ + $(gregset_h) $(gdbcore_h) $(gdbthread_h) $(elf_bfd_h) \ + $(cli_decode_h) $(gdb_string_h) +lynx-nat.o: lynx-nat.c $(defs_h) $(frame_h) $(inferior_h) $(target_h) \ + $(gdbcore_h) $(regcache_h) +m2-lang.o: m2-lang.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_h) \ + $(parser_defs_h) $(language_h) $(m2_lang_h) $(c_lang_h) \ + $(valprint_h) +m2-typeprint.o: m2-typeprint.c $(defs_h) $(bfd_h) $(symtab_h) $(gdbtypes_h) \ + $(expression_h) $(value_h) $(gdbcore_h) $(target_h) $(m2_lang_h) +m2-valprint.o: m2-valprint.c $(defs_h) $(symtab_h) $(gdbtypes_h) \ + $(m2_lang_h) +m3-nat.o: m3-nat.c $(defs_h) $(inferior_h) $(symtab_h) $(value_h) \ + $(language_h) $(target_h) $(gdb_wait_h) $(gdbcmd_h) $(gdbcore_h) \ + $(regcache_h) +m32r-rom.o: m32r-rom.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \ + $(serial_h) $(symtab_h) $(command_h) $(gdbcmd_h) $(symfile_h) \ + $(gdb_string_h) $(objfiles_h) $(inferior_h) $(regcache_h) +m32r-stub.o: m32r-stub.c $(syscall_h) +m32r-tdep.o: m32r-tdep.c $(defs_h) $(frame_h) $(inferior_h) $(target_h) \ + $(value_h) $(bfd_h) $(gdb_string_h) $(gdbcore_h) $(symfile_h) \ + $(regcache_h) +m68hc11-tdep.o: m68hc11-tdep.c $(defs_h) $(frame_h) $(symtab_h) \ + $(gdbtypes_h) $(gdbcmd_h) $(gdbcore_h) $(gdb_string_h) $(value_h) \ + $(inferior_h) $(dis_asm_h) $(symfile_h) $(objfiles_h) \ + $(arch_utils_h) $(regcache_h) $(target_h) $(opcode_m68hc11_h) \ + $(elf_m68hc11_h) $(elf_bfd_h) +m68k-stub.o: m68k-stub.c +m68k-tdep.o: m68k-tdep.c $(defs_h) $(frame_h) $(symtab_h) $(gdbcore_h) \ + $(value_h) $(gdb_string_h) $(inferior_h) $(regcache_h) \ + $(arch_utils_h) $(gregset_h) +m68klinux-nat.o: m68klinux-nat.c $(defs_h) $(frame_h) $(inferior_h) \ + $(language_h) $(gdbcore_h) $(regcache_h) $(gdb_stat_h) \ + $(floatformat_h) $(target_h) $(gregset_h) +m68knbsd-nat.o: m68knbsd-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) \ + $(regcache_h) +m68knbsd-tdep.o: m68knbsd-tdep.c $(defs_h) $(gdbtypes_h) $(regcache_h) +# OBSOLETE m88k-nat.o: m88k-nat.c +# OBSOLETE m88k-tdep.o: m88k-tdep.c +macrocmd.o: macrocmd.c $(defs_h) $(macrotab_h) $(macroexp_h) $(macroscope_h) \ + $(command_h) $(gdbcmd_h) +macroexp.o: macroexp.c $(defs_h) $(gdb_obstack_h) $(bcache_h) $(macrotab_h) \ + $(macroexp_h) $(gdb_assert_h) +macroscope.o: macroscope.c $(defs_h) $(macroscope_h) $(symtab_h) $(target_h) \ + $(frame_h) $(inferior_h) $(source_h) +macrotab.o: macrotab.c $(defs_h) $(gdb_obstack_h) $(splay_tree_h) \ + $(symtab_h) $(symfile_h) $(objfiles_h) $(macrotab_h) $(gdb_assert_h) \ + $(bcache_h) $(complaints_h) +main.o: main.c $(defs_h) $(top_h) $(target_h) $(inferior_h) $(symfile_h) \ + $(gdbcore_h) $(getopt_h) $(gdb_stat_h) $(gdb_string_h) \ + $(event_loop_h) $(ui_out_h) +maint.o: maint.c $(defs_h) $(command_h) $(gdbcmd_h) $(symtab_h) \ + $(gdbtypes_h) $(demangle_h) $(gdbcore_h) $(expression_h) \ + $(language_h) $(symfile_h) $(objfiles_h) $(value_h) $(cli_decode_h) +mcore-rom.o: mcore-rom.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \ + $(gdb_string_h) $(regcache_h) $(serial_h) +mcore-tdep.o: mcore-tdep.c $(defs_h) $(frame_h) $(symtab_h) $(value_h) \ + $(gdbcmd_h) $(regcache_h) $(symfile_h) $(gdbcore_h) $(inferior_h) \ + $(arch_utils_h) +mdebugread.o: mdebugread.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(gdbcore_h) \ + $(symfile_h) $(objfiles_h) $(gdb_obstack_h) $(buildsym_h) \ + $(stabsread_h) $(complaints_h) $(demangle_h) $(gdb_assert_h) \ + $(coff_sym_h) $(coff_symconst_h) $(gdb_stat_h) $(gdb_string_h) \ + $(bfd_h) $(coff_ecoff_h) $(libaout_h) $(aout_aout64_h) \ + $(aout_stab_gnu_h) $(expression_h) $(language_h) +mem-break.o: mem-break.c $(defs_h) $(symtab_h) $(breakpoint_h) $(inferior_h) \ + $(target_h) +memattr.o: memattr.c $(defs_h) $(command_h) $(gdbcmd_h) $(memattr_h) \ + $(target_h) $(value_h) $(language_h) $(gdb_string_h) +minsyms.o: minsyms.c $(defs_h) $(gdb_string_h) $(symtab_h) $(bfd_h) \ + $(symfile_h) $(objfiles_h) $(demangle_h) $(value_h) $(cp_abi_h) +mips-irix-tdep.o: mips-irix-tdep.c $(defs_h) $(osabi_h) $(elf_bfd_h) +mips-linux-nat.o: mips-linux-nat.c $(defs_h) +mips-linux-tdep.o: mips-linux-tdep.c $(defs_h) $(gdbcore_h) $(target_h) \ + $(solib_svr4_h) +mips-nat.o: mips-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) $(regcache_h) +mips-tdep.o: mips-tdep.c $(defs_h) $(gdb_string_h) $(frame_h) $(inferior_h) \ + $(symtab_h) $(value_h) $(gdbcmd_h) $(language_h) $(gdbcore_h) \ + $(symfile_h) $(objfiles_h) $(gdbtypes_h) $(target_h) $(arch_utils_h) \ + $(regcache_h) $(osabi_h) $(opcode_mips_h) $(elf_mips_h) $(elf_bfd_h) \ + $(symcat_h) +mipsm3-nat.o: mipsm3-nat.c $(defs_h) $(inferior_h) $(regcache_h) +mipsnbsd-nat.o: mipsnbsd-nat.c $(defs_h) $(inferior_h) $(regcache_h) \ + $(mipsnbsd_tdep_h) +mipsnbsd-tdep.o: mipsnbsd-tdep.c $(defs_h) $(gdbcore_h) $(regcache_h) \ + $(target_h) $(value_h) $(osabi_h) $(mipsnbsd_tdep_h) $(solib_svr4_h) \ + $(nbsd_tdep_h) +mipsread.o: mipsread.c $(defs_h) $(gdb_string_h) $(bfd_h) $(symtab_h) \ + $(symfile_h) $(objfiles_h) $(buildsym_h) $(stabsread_h) \ + $(coff_sym_h) $(coff_internal_h) $(coff_ecoff_h) $(libcoff_h) \ + $(libecoff_h) $(elf_common_h) $(elf_mips_h) +mipsv4-nat.o: mipsv4-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) $(target_h) \ + $(regcache_h) $(gregset_h) +mn10200-tdep.o: mn10200-tdep.c $(defs_h) $(frame_h) $(inferior_h) \ + $(target_h) $(value_h) $(bfd_h) $(gdb_string_h) $(gdbcore_h) \ + $(symfile_h) $(regcache_h) +mn10300-tdep.o: mn10300-tdep.c $(defs_h) $(frame_h) $(inferior_h) \ + $(target_h) $(value_h) $(bfd_h) $(gdb_string_h) $(gdbcore_h) \ + $(symfile_h) $(regcache_h) $(arch_utils_h) +mon960-rom.o: mon960-rom.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \ + $(serial_h) $(srec_h) $(xmodem_h) $(symtab_h) $(symfile_h) \ + $(inferior_h) $(gdb_string_h) +monitor.o: monitor.c $(defs_h) $(gdbcore_h) $(target_h) $(gdb_string_h) \ + $(command_h) $(serial_h) $(monitor_h) $(gdbcmd_h) $(inferior_h) \ + $(gdb_regex_h) $(srec_h) $(regcache_h) +nbsd-tdep.o: nbsd-tdep.c $(defs_h) $(gdb_string_h) $(solib_svr4_h) +nindy-tdep.o: nindy-tdep.c $(defs_h) $(symtab_h) $(frame_h) $(gdbcore_h) +nlmread.o: nlmread.c $(defs_h) $(bfd_h) $(symtab_h) $(symfile_h) \ + $(objfiles_h) $(buildsym_h) $(stabsread_h) +ns32k-tdep.o: ns32k-tdep.c $(defs_h) $(frame_h) $(gdbtypes_h) $(gdbcore_h) \ + $(inferior_h) $(regcache_h) $(target_h) $(arch_utils_h) \ + $(ns32k_tdep_h) +ns32knbsd-nat.o: ns32knbsd-nat.c $(defs_h) $(inferior_h) $(target_h) \ + $(gdbcore_h) $(regcache_h) +ns32knbsd-tdep.o: ns32knbsd-tdep.c $(defs_h) $(ns32k_tdep_h) +objfiles.o: objfiles.c $(defs_h) $(bfd_h) $(symtab_h) $(symfile_h) \ + $(objfiles_h) $(gdb_stabs_h) $(target_h) $(bcache_h) $(gdb_stat_h) \ + $(gdb_obstack_h) $(gdb_string_h) $(breakpoint_h) $(mmalloc_h) +ocd.o: ocd.c $(defs_h) $(gdbcore_h) $(gdb_string_h) $(frame_h) $(inferior_h) \ + $(bfd_h) $(symfile_h) $(target_h) $(gdbcmd_h) $(objfiles_h) \ + $(gdb_stabs_h) $(serial_h) $(ocd_h) $(regcache_h) +op50-rom.o: op50-rom.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \ + $(serial_h) +# OBSOLETE os9kread.o: os9kread.c +osabi.o: osabi.c $(defs_h) $(gdb_string_h) $(osabi_h) $(elf_bfd_h) +p-lang.o: p-lang.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \ + $(expression_h) $(parser_defs_h) $(language_h) $(p_lang_h) \ + $(valprint_h) +p-typeprint.o: p-typeprint.c $(defs_h) $(gdb_obstack_h) $(bfd_h) $(symtab_h) \ + $(gdbtypes_h) $(expression_h) $(value_h) $(gdbcore_h) $(target_h) \ + $(language_h) $(p_lang_h) $(typeprint_h) $(gdb_string_h) +p-valprint.o: p-valprint.c $(defs_h) $(gdb_obstack_h) $(symtab_h) \ + $(gdbtypes_h) $(expression_h) $(value_h) $(command_h) $(gdbcmd_h) \ + $(gdbcore_h) $(demangle_h) $(valprint_h) $(typeprint_h) \ + $(language_h) $(target_h) $(annotate_h) $(p_lang_h) $(cp_abi_h) +pa64solib.o: pa64solib.c $(defs_h) $(frame_h) $(bfd_h) $(libhppa_h) \ + $(gdbcore_h) $(symtab_h) $(breakpoint_h) $(symfile_h) $(objfiles_h) \ + $(inferior_h) $(gdb_stabs_h) $(gdb_stat_h) $(gdbcmd_h) $(language_h) \ + $(regcache_h) +parse.o: parse.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \ + $(frame_h) $(expression_h) $(value_h) $(command_h) $(language_h) \ + $(parser_defs_h) $(gdbcmd_h) $(symfile_h) $(inferior_h) \ + $(doublest_h) $(builtin_regs_h) $(gdb_assert_h) +ppc-bdm.o: ppc-bdm.c $(defs_h) $(gdbcore_h) $(gdb_string_h) $(frame_h) \ + $(inferior_h) $(bfd_h) $(symfile_h) $(target_h) $(gdbcmd_h) \ + $(objfiles_h) $(gdb_stabs_h) $(serial_h) $(ocd_h) $(ppc_tdep_h) \ + $(regcache_h) +ppc-linux-nat.o: ppc-linux-nat.c $(defs_h) $(frame_h) $(inferior_h) \ + $(gdbcore_h) $(regcache_h) $(gregset_h) $(ppc_tdep_h) +ppc-linux-tdep.o: ppc-linux-tdep.c $(defs_h) $(frame_h) $(inferior_h) \ + $(symtab_h) $(target_h) $(gdbcore_h) $(gdbcmd_h) $(symfile_h) \ + $(objfiles_h) $(regcache_h) $(value_h) $(solib_svr4_h) $(ppc_tdep_h) +ppc-sysv-tdep.o: ppc-sysv-tdep.c $(defs_h) $(gdbcore_h) $(inferior_h) \ + $(regcache_h) $(value_h) $(ppc_tdep_h) +ppcbug-rom.o: ppcbug-rom.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \ + $(serial_h) $(regcache_h) +ppcnbsd-nat.o: ppcnbsd-nat.c $(defs_h) $(inferior_h) $(ppc_tdep_h) \ + $(ppcnbsd_tdep_h) +ppcnbsd-tdep.o: ppcnbsd-tdep.c $(defs_h) $(gdbcore_h) $(regcache_h) \ + $(target_h) $(breakpoint_h) $(value_h) $(ppc_tdep_h) \ + $(ppcnbsd_tdep_h) $(nbsd_tdep_h) $(solib_svr4_h) +printcmd.o: printcmd.c $(defs_h) $(gdb_string_h) $(frame_h) $(symtab_h) \ + $(gdbtypes_h) $(value_h) $(language_h) $(expression_h) $(gdbcore_h) \ + $(gdbcmd_h) $(target_h) $(breakpoint_h) $(demangle_h) $(valprint_h) \ + $(annotate_h) $(symfile_h) $(objfiles_h) $(completer_h) $(ui_out_h) \ + $(gdb_assert_h) +proc-api.o: proc-api.c $(defs_h) $(gdbcmd_h) $(completer_h) $(proc_utils_h) +proc-events.o: proc-events.c $(defs_h) +proc-flags.o: proc-flags.c $(defs_h) +proc-service.o: proc-service.c $(defs_h) $(gdb_proc_service_h) $(inferior_h) \ + $(symtab_h) $(target_h) $(gregset_h) +proc-why.o: proc-why.c $(defs_h) $(proc_utils_h) +procfs.o: procfs.c $(defs_h) $(inferior_h) $(target_h) $(gdbcore_h) \ + $(elf_bfd_h) $(gdbcmd_h) $(gdbthread_h) $(gdb_dirent_h) $(X_OK) \ + $(gdb_stat_h) $(proc_utils_h) $(gregset_h) +ptx4-nat.o: ptx4-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) $(regcache_h) \ + $(gregset_h) +regcache.o: regcache.c $(defs_h) $(inferior_h) $(target_h) $(gdbarch_h) \ + $(gdbcmd_h) $(regcache_h) $(gdb_assert_h) $(gdb_string_h) \ + $(gdbcmd_h) +remote-array.o: remote-array.c $(defs_h) $(gdbcore_h) $(target_h) \ + $(gdb_string_h) $(command_h) $(serial_h) $(monitor_h) \ + $(remote_utils_h) $(inferior_h) $(version_h) $(regcache_h) +# OBSOLETE remote-bug.o: remote-bug.c +remote-e7000.o: remote-e7000.c $(defs_h) $(gdbcore_h) $(gdbarch_h) \ + $(inferior_h) $(target_h) $(value_h) $(command_h) $(gdb_string_h) \ + $(gdbcmd_h) $(serial_h) $(remote_utils_h) $(symfile_h) $(regcache_h) +remote-es.o: remote-es.c $(defs_h) $(gdb_string_h) $(frame_h) $(inferior_h) \ + $(target_h) $(command_h) $(symfile_h) $(remote_utils_h) $(gdbcore_h) \ + $(serial_h) $(regcache_h) $(value_h) +remote-est.o: remote-est.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \ + $(serial_h) $(regcache_h) +remote-hms.o: remote-hms.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \ + $(serial_h) $(regcache_h) +remote-mips.o: remote-mips.c $(defs_h) $(inferior_h) $(bfd_h) $(symfile_h) \ + $(gdbcmd_h) $(gdbcore_h) $(serial_h) $(target_h) $(remote_utils_h) \ + $(gdb_string_h) $(gdb_stat_h) $(regcache_h) +# OBSOLETE remote-nindy.o: remote-nindy.c +# OBSOLETE remote-nrom.o: remote-nrom.c +# OBSOLETE remote-os9k.o: remote-os9k.c +remote-rdi.o: remote-rdi.c $(defs_h) $(gdb_string_h) $(frame_h) \ + $(inferior_h) $(bfd_h) $(symfile_h) $(target_h) $(gdbcmd_h) \ + $(objfiles_h) $(gdb_stabs_h) $(gdbthread_h) $(gdbcore_h) \ + $(breakpoint_h) $(completer_h) $(regcache_h) $(arm_tdep_h) \ + $(rdi_share_ardi_h) $(rdi_share_adp_h) $(rdi_share_hsys_h) +remote-rdp.o: remote-rdp.c $(defs_h) $(inferior_h) $(value_h) \ + $(gdb_callback_h) $(command_h) $(symfile_h) $(remote_utils_h) \ + $(gdb_string_h) $(gdbcore_h) $(regcache_h) $(serial_h) $(arm_tdep_h) +remote-sds.o: remote-sds.c $(defs_h) $(gdb_string_h) $(frame_h) \ + $(inferior_h) $(bfd_h) $(symfile_h) $(target_h) $(gdbcmd_h) \ + $(objfiles_h) $(gdb_stabs_h) $(gdbthread_h) $(gdbcore_h) \ + $(regcache_h) $(serial_h) +remote-sim.o: remote-sim.c $(defs_h) $(inferior_h) $(value_h) \ + $(gdb_string_h) $(terminal_h) $(target_h) $(gdbcore_h) \ + $(gdb_callback_h) $(gdb_remote_sim_h) $(remote_utils_h) $(command_h) \ + $(regcache_h) $(gdb_assert_h) $(sim_regno_h) +remote-st.o: remote-st.c $(defs_h) $(gdbcore_h) $(target_h) $(gdb_string_h) \ + $(serial_h) $(regcache_h) +remote-utils.o: remote-utils.c $(defs_h) $(gdb_string_h) $(gdbcmd_h) \ + $(target_h) $(serial_h) $(gdbcore_h) $(inferior_h) $(remote_utils_h) \ + $(regcache_h) +remote-vx.o: remote-vx.c $(defs_h) $(frame_h) $(inferior_h) $(target_h) \ + $(gdbcore_h) $(command_h) $(symtab_h) $(complaints_h) $(gdbcmd_h) \ + $(bfd_h) $(symfile_h) $(objfiles_h) $(gdb_stabs_h) $(regcache_h) \ + $(gdb_string_h) $(vx_share_ptrace_h) $(vx_share_xdr_ptrace_h) \ + $(vx_share_xdr_ld_h) $(vx_share_xdr_rdb_h) $(vx_share_dbgRpcLib_h) +remote-vx68.o: remote-vx68.c $(defs_h) $(vx_share_regPacket_h) $(frame_h) \ + $(inferior_h) $(target_h) $(gdbcore_h) $(command_h) $(symtab_h) \ + $(symfile_h) $(regcache_h) $(gdb_string_h) $(vx_share_ptrace_h) \ + $(vx_share_xdr_ptrace_h) $(vx_share_xdr_ld_h) $(vx_share_xdr_rdb_h) \ + $(vx_share_dbgRpcLib_h) +# OBSOLETE remote-vx960.o: remote-vx960.c +remote-vxmips.o: remote-vxmips.c $(defs_h) $(vx_share_regPacket_h) \ + $(frame_h) $(inferior_h) $(target_h) $(gdbcore_h) $(command_h) \ + $(symtab_h) $(symfile_h) $(regcache_h) $(gdb_string_h) \ + $(vx_share_ptrace_h) $(vx_share_xdr_ptrace_h) $(vx_share_xdr_ld_h) \ + $(vx_share_xdr_rdb_h) $(vx_share_dbgRpcLib_h) +remote-vxsparc.o: remote-vxsparc.c $(defs_h) $(vx_share_regPacket_h) \ + $(frame_h) $(inferior_h) $(target_h) $(gdbcore_h) $(command_h) \ + $(symtab_h) $(symfile_h) $(regcache_h) $(gdb_string_h) \ + $(vx_share_ptrace_h) $(vx_share_xdr_ptrace_h) $(vx_share_xdr_ld_h) \ + $(vx_share_xdr_rdb_h) $(vx_share_dbgRpcLib_h) +remote.o: remote.c $(defs_h) $(gdb_string_h) $(inferior_h) $(bfd_h) \ + $(symfile_h) $(target_h) $(gdbcmd_h) $(objfiles_h) $(gdb_stabs_h) \ + $(gdbthread_h) $(remote_h) $(regcache_h) $(value_h) $(gdb_assert_h) \ + $(event_loop_h) $(event_top_h) $(inf_loop_h) $(serial_h) \ + $(gdbcore_h) +rom68k-rom.o: rom68k-rom.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \ + $(serial_h) $(regcache_h) $(value_h) +rs6000-nat.o: rs6000-nat.c $(defs_h) $(inferior_h) $(target_h) $(gdbcore_h) \ + $(xcoffsolib_h) $(symfile_h) $(objfiles_h) $(libbfd_h) $(bfd_h) \ + $(gdb_stabs_h) $(regcache_h) $(arch_utils_h) $(language_h) \ + $(ppc_tdep_h) $(gdb_stat_h) +rs6000-tdep.o: rs6000-tdep.c $(defs_h) $(frame_h) $(inferior_h) $(symtab_h) \ + $(target_h) $(gdbcore_h) $(gdbcmd_h) $(symfile_h) $(objfiles_h) \ + $(arch_utils_h) $(regcache_h) $(doublest_h) $(value_h) \ + $(parser_defs_h) $(libbfd_h) $(coff_internal_h) $(libcoff_h) \ + $(coff_xcoff_h) $(libxcoff_h) $(elf_bfd_h) $(solib_svr4_h) \ + $(ppc_tdep_h) +s390-nat.o: s390-nat.c $(defs_h) $(tm_h) $(regcache_h) +s390-tdep.o: s390-tdep.c $(arch_utils_h) $(frame_h) $(inferior_h) \ + $(symtab_h) $(target_h) $(gdbcore_h) $(gdbcmd_h) $(symfile_h) \ + $(objfiles_h) $(tm_h) $(__bfd_bfd_h) $(floatformat_h) $(regcache_h) \ + $(value_h) $(gdb_assert_h) +scm-exp.o: scm-exp.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_h) \ + $(parser_defs_h) $(language_h) $(value_h) $(c_lang_h) $(scm_lang_h) \ + $(scm_tags_h) +scm-lang.o: scm-lang.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_h) \ + $(parser_defs_h) $(language_h) $(value_h) $(c_lang_h) $(scm_lang_h) \ + $(scm_tags_h) $(gdb_string_h) $(gdbcore_h) $(source_h) +scm-valprint.o: scm-valprint.c $(defs_h) $(symtab_h) $(gdbtypes_h) \ + $(expression_h) $(parser_defs_h) $(language_h) $(value_h) \ + $(scm_lang_h) $(valprint_h) $(gdbcore_h) +ser-e7kpc.o: ser-e7kpc.c $(defs_h) $(serial_h) $(gdb_string_h) +ser-go32.o: ser-go32.c $(defs_h) $(gdbcmd_h) $(serial_h) $(gdb_string_h) +ser-pipe.o: ser-pipe.c $(defs_h) $(serial_h) $(ser_unix_h) $(gdb_vfork_h) \ + $(gdb_string_h) +ser-tcp.o: ser-tcp.c $(defs_h) $(serial_h) $(ser_unix_h) $(gdb_string_h) +ser-unix.o: ser-unix.c $(defs_h) $(serial_h) $(ser_unix_h) $(terminal_h) \ + $(gdb_string_h) $(event_loop_h) +serial.o: serial.c $(defs_h) $(serial_h) $(gdb_string_h) $(gdbcmd_h) +sh-stub.o: sh-stub.c +sh-tdep.o: sh-tdep.c $(defs_h) $(frame_h) $(symtab_h) $(symfile_h) \ + $(gdbtypes_h) $(gdbcmd_h) $(gdbcore_h) $(value_h) $(dis_asm_h) \ + $(inferior_h) $(gdb_string_h) $(arch_utils_h) $(floatformat_h) \ + $(regcache_h) $(doublest_h) $(sh_tdep_h) $(elf_bfd_h) \ + $(solib_svr4_h) $(elf_sh_h) $(gdb_sim_sh_h) +sh3-rom.o: sh3-rom.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \ + $(serial_h) $(srec_h) $(arch_utils_h) $(regcache_h) $(sh_tdep_h) +shnbsd-nat.o: shnbsd-nat.c $(defs_h) $(inferior_h) $(shnbsd_tdep_h) +shnbsd-tdep.o: shnbsd-tdep.c $(defs_h) $(gdbcore_h) $(regcache_h) $(value_h) \ + $(solib_svr4_h) $(nbsd_tdep_h) $(sh_tdep_h) $(shnbsd_tdep_h) +sol-thread.o: sol-thread.c $(defs_h) $(gdbthread_h) $(target_h) \ + $(inferior_h) $(gdbcmd_h) $(gdbcore_h) $(regcache_h) $(symfile_h) \ + $(gregset_h) +solib-aix5.o: solib-aix5.c $(defs_h) $(gdb_string_h) $(elf_external_h) \ + $(symtab_h) $(bfd_h) $(symfile_h) $(objfiles_h) $(gdbcore_h) \ + $(command_h) $(target_h) $(frame_h) $(gdb_regex_h) $(inferior_h) \ + $(environ_h) $(language_h) $(gdbcmd_h) $(solist_h) +solib-irix.o: solib-irix.c $(defs_h) $(symtab_h) $(bfd_h) $(symfile_h) \ + $(objfiles_h) $(gdbcore_h) $(target_h) $(inferior_h) $(solist_h) +solib-legacy.o: solib-legacy.c $(defs_h) $(gdbcore_h) $(solib_svr4_h) +solib-osf.o: solib-osf.c $(defs_h) $(gdb_string_h) $(bfd_h) $(symtab_h) \ + $(symfile_h) $(objfiles_h) $(target_h) $(inferior_h) $(solist_h) +solib-sunos.o: solib-sunos.c $(defs_h) $(gdb_string_h) $(symtab_h) $(bfd_h) \ + $(symfile_h) $(objfiles_h) $(gdbcore_h) $(inferior_h) $(solist_h) +solib-svr4.o: solib-svr4.c $(defs_h) $(elf_external_h) $(elf_common_h) \ + $(elf_mips_h) $(symtab_h) $(bfd_h) $(symfile_h) $(objfiles_h) \ + $(gdbcore_h) $(target_h) $(inferior_h) $(solist_h) $(solib_svr4_h) +solib.o: solib.c $(defs_h) $(gdb_string_h) $(symtab_h) $(bfd_h) $(symfile_h) \ + $(objfiles_h) $(gdbcore_h) $(command_h) $(target_h) $(frame_h) \ + $(gdb_regex_h) $(inferior_h) $(environ_h) $(language_h) $(gdbcmd_h) \ + $(completer_h) $(filenames_h) $(solist_h) +somread.o: somread.c $(defs_h) $(bfd_h) $(symtab_h) $(symfile_h) \ + $(objfiles_h) $(buildsym_h) $(stabsread_h) $(gdb_stabs_h) \ + $(complaints_h) $(gdb_string_h) $(demangle_h) $(som_h) $(libhppa_h) +somsolib.o: somsolib.c $(defs_h) $(frame_h) $(bfd_h) $(som_h) $(libhppa_h) \ + $(gdbcore_h) $(symtab_h) $(breakpoint_h) $(symfile_h) $(objfiles_h) \ + $(inferior_h) $(gdb_stabs_h) $(gdb_stat_h) $(gdbcmd_h) $(language_h) \ + $(regcache_h) +source.o: source.c $(defs_h) $(symtab_h) $(expression_h) $(language_h) \ + $(command_h) $(source_h) $(gdbcmd_h) $(frame_h) $(value_h) \ + $(gdb_string_h) $(gdb_stat_h) $(gdbcore_h) $(gdb_regex_h) \ + $(symfile_h) $(objfiles_h) $(annotate_h) $(gdbtypes_h) $(linespec_h) \ + $(filenames_h) $(completer_h) $(ui_out_h) +sparc-linux-nat.o: sparc-linux-nat.c $(defs_h) $(regcache_h) $(gregset_h) +sparc-nat.o: sparc-nat.c $(defs_h) $(inferior_h) $(target_h) $(gdbcore_h) \ + $(regcache_h) +sparc-stub.o: sparc-stub.c +sparc-tdep.o: sparc-tdep.c $(defs_h) $(arch_utils_h) $(frame_h) \ + $(inferior_h) $(target_h) $(value_h) $(bfd_h) $(gdb_string_h) \ + $(regcache_h) $(osabi_h) $(gregset_h) $(gdbcore_h) $(symfile_h) +sparc64nbsd-nat.o: sparc64nbsd-nat.c $(defs_h) $(inferior_h) $(regcache_h) \ + $(sparcnbsd_tdep_h) +sparcl-stub.o: sparcl-stub.c +sparcl-tdep.o: sparcl-tdep.c $(defs_h) $(gdbcore_h) $(breakpoint_h) \ + $(target_h) $(serial_h) $(regcache_h) +sparclet-rom.o: sparclet-rom.c $(defs_h) $(gdbcore_h) $(target_h) \ + $(monitor_h) $(serial_h) $(srec_h) $(symtab_h) $(symfile_h) \ + $(regcache_h) +sparclet-stub.o: sparclet-stub.c +sparcnbsd-nat.o: sparcnbsd-nat.c $(defs_h) $(inferior_h) $(regcache_h) \ + $(sparcnbsd_tdep_h) +sparcnbsd-tdep.o: sparcnbsd-tdep.c $(defs_h) $(gdbcore_h) $(regcache_h) \ + $(target_h) $(value_h) $(osabi_h) $(sparcnbsd_tdep_h) $(nbsd_tdep_h) \ + $(solib_svr4_h) +stabsread.o: stabsread.c $(defs_h) $(gdb_string_h) $(bfd_h) $(gdb_obstack_h) \ + $(symtab_h) $(gdbtypes_h) $(expression_h) $(symfile_h) $(objfiles_h) \ + $(aout_stab_gnu_h) $(libaout_h) $(aout_aout64_h) $(gdb_stabs_h) \ + $(buildsym_h) $(complaints_h) $(demangle_h) $(language_h) \ + $(doublest_h) $(stabsread_h) $(cp_abi_h) $(cp_support_h) +stack.o: stack.c $(defs_h) $(gdb_string_h) $(value_h) $(symtab_h) \ + $(gdbtypes_h) $(expression_h) $(language_h) $(frame_h) $(gdbcmd_h) \ + $(gdbcore_h) $(target_h) $(breakpoint_h) $(demangle_h) $(inferior_h) \ + $(annotate_h) $(ui_out_h) $(source_h) +standalone.o: standalone.c $(gdb_stat_h) $(defs_h) $(symtab_h) $(frame_h) \ + $(inferior_h) $(gdb_wait_h) +std-regs.o: std-regs.c $(defs_h) $(builtin_regs_h) $(frame_h) $(gdbtypes_h) \ + $(value_h) $(gdb_string_h) +stop-gdb.o: stop-gdb.c $(defs_h) +sun3-nat.o: sun3-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) $(regcache_h) +symfile.o: symfile.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(gdbcore_h) \ + $(frame_h) $(target_h) $(value_h) $(symfile_h) $(objfiles_h) \ + $(gdbcmd_h) $(breakpoint_h) $(language_h) $(complaints_h) \ + $(demangle_h) $(inferior_h) $(gdb_stabs_h) $(gdb_obstack_h) \ + $(completer_h) $(bcache_h) $(gdb_string_h) $(gdb_stat_h) $(source_h) +symm-nat.o: symm-nat.c $(defs_h) $(frame_h) $(inferior_h) $(symtab_h) \ + $(target_h) $(regcache_h) $(gdb_stat_h) $(gdbcore_h) $(gdbcore_h) +symm-tdep.o: symm-tdep.c $(defs_h) $(frame_h) $(inferior_h) $(symtab_h) \ + $(gdb_stat_h) $(gdbcore_h) +symmisc.o: symmisc.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(bfd_h) \ + $(symfile_h) $(objfiles_h) $(breakpoint_h) $(command_h) \ + $(gdb_obstack_h) $(language_h) $(bcache_h) $(gdb_string_h) +symtab.o: symtab.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(gdbcore_h) \ + $(frame_h) $(target_h) $(value_h) $(symfile_h) $(objfiles_h) \ + $(gdbcmd_h) $(call_cmds_h) $(gdb_regex_h) $(expression_h) \ + $(language_h) $(demangle_h) $(inferior_h) $(linespec_h) \ + $(filenames_h) $(gdb_obstack_h) $(gdb_string_h) $(gdb_stat_h) \ + $(cp_abi_h) $(source_h) +target.o: target.c $(defs_h) $(gdb_string_h) $(target_h) $(gdbcmd_h) \ + $(symtab_h) $(inferior_h) $(bfd_h) $(symfile_h) $(objfiles_h) \ + $(gdb_wait_h) $(dcache_h) $(regcache_h) +thread-db.o: thread-db.c $(defs_h) $(gdb_assert_h) $(gdb_proc_service_h) \ + $(gdb_thread_db_h) $(bfd_h) $(gdbthread_h) $(inferior_h) \ + $(symfile_h) $(objfiles_h) $(target_h) $(regcache_h) +thread.o: thread.c $(defs_h) $(symtab_h) $(frame_h) $(inferior_h) \ + $(environ_h) $(value_h) $(target_h) $(gdbthread_h) $(command_h) \ + $(gdbcmd_h) $(regcache_h) $(gdb_h) $(gdb_string_h) $(ui_out_h) +top.o: top.c $(defs_h) $(gdbcmd_h) $(call_cmds_h) $(cli_cmds_h) \ + $(cli_script_h) $(cli_setshow_h) $(cli_decode_h) $(symtab_h) \ + $(inferior_h) $(target_h) $(breakpoint_h) $(gdbtypes_h) \ + $(expression_h) $(value_h) $(language_h) $(terminal_h) $(annotate_h) \ + $(completer_h) $(top_h) $(version_h) $(serial_h) $(doublest_h) \ + $(gdb_assert_h) $(event_top_h) $(gdb_string_h) $(gdb_stat_h) \ + $(ui_out_h) $(cli_out_h) +tracepoint.o: tracepoint.c $(defs_h) $(symtab_h) $(frame_h) $(gdbtypes_h) \ + $(expression_h) $(gdbcmd_h) $(value_h) $(target_h) $(language_h) \ + $(gdb_string_h) $(inferior_h) $(tracepoint_h) $(remote_h) \ + $(linespec_h) $(regcache_h) $(completer_h) $(gdb_events_h) $(ax_h) \ + $(ax_gdb_h) +typeprint.o: typeprint.c $(defs_h) $(gdb_obstack_h) $(bfd_h) $(symtab_h) \ + $(gdbtypes_h) $(expression_h) $(value_h) $(gdbcore_h) $(command_h) \ + $(gdbcmd_h) $(target_h) $(language_h) $(cp_abi_h) $(gdb_string_h) +ui-file.o: ui-file.c $(defs_h) $(ui_file_h) $(gdb_string_h) +ui-out.o: ui-out.c $(defs_h) $(gdb_string_h) $(expression_h) $(language_h) \ + $(ui_out_h) $(gdb_assert_h) +utils.o: utils.c $(config_h) $(defs_h) $(gdb_assert_h) $(gdb_string_h) \ + $(event_top_h) $(gdbcmd_h) $(serial_h) $(bfd_h) $(target_h) \ + $(demangle_h) $(expression_h) $(language_h) $(annotate_h) \ + $(filenames_h) $(inferior_h) $(mmalloc_h) +uw-thread.o: uw-thread.c $(defs_h) $(gdbthread_h) $(target_h) $(inferior_h) \ + $(regcache_h) $(gregset_h) +v850-tdep.o: v850-tdep.c $(defs_h) $(frame_h) $(inferior_h) $(target_h) \ + $(value_h) $(bfd_h) $(gdb_string_h) $(gdbcore_h) $(symfile_h) \ + $(arch_utils_h) $(regcache_h) $(symtab_h) +v850ice.o: v850ice.c $(defs_h) $(gdb_string_h) $(frame_h) $(symtab_h) \ + $(inferior_h) $(breakpoint_h) $(symfile_h) $(target_h) $(objfiles_h) \ + $(gdbcore_h) $(value_h) $(command_h) $(regcache_h) +valarith.o: valarith.c $(defs_h) $(value_h) $(symtab_h) $(gdbtypes_h) \ + $(expression_h) $(target_h) $(language_h) $(gdb_string_h) \ + $(doublest_h) +valops.o: valops.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(value_h) $(frame_h) \ + $(inferior_h) $(gdbcore_h) $(target_h) $(demangle_h) $(language_h) \ + $(gdbcmd_h) $(regcache_h) $(cp_abi_h) $(gdb_string_h) \ + $(gdb_assert_h) +valprint.o: valprint.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \ + $(value_h) $(gdbcore_h) $(gdbcmd_h) $(target_h) $(language_h) \ + $(annotate_h) $(valprint_h) $(floatformat_h) $(doublest_h) +values.o: values.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \ + $(value_h) $(gdbcore_h) $(command_h) $(gdbcmd_h) $(target_h) \ + $(language_h) $(scm_lang_h) $(demangle_h) $(doublest_h) \ + $(gdb_assert_h) $(regcache_h) +varobj.o: varobj.c $(defs_h) $(value_h) $(expression_h) $(frame_h) \ + $(language_h) $(wrapper_h) $(gdbcmd_h) $(gdb_string_h) $(varobj_h) +vax-tdep.o: vax-tdep.c $(defs_h) $(symtab_h) $(opcode_vax_h) $(gdbcore_h) \ + $(inferior_h) $(regcache_h) $(frame_h) $(value_h) $(arch_utils_h) \ + $(vax_tdep_h) +w89k-rom.o: w89k-rom.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \ + $(serial_h) $(xmodem_h) $(regcache_h) +win32-nat.o: win32-nat.c $(defs_h) $(tm_h) $(frame_h) $(inferior_h) \ + $(target_h) $(gdbcore_h) $(command_h) $(completer_h) $(regcache_h) \ + $(top_h) $(i386_tdep_h) $(buildsym_h) $(symfile_h) $(objfiles_h) \ + $(gdb_string_h) $(gdbthread_h) $(gdbcmd_h) +wince-stub.o: wince-stub.c $(wince_stub_h) +wince.o: wince.c $(defs_h) $(frame_h) $(inferior_h) $(target_h) $(gdbcore_h) \ + $(command_h) $(buildsym_h) $(symfile_h) $(objfiles_h) \ + $(gdb_string_h) $(gdbthread_h) $(gdbcmd_h) $(wince_stub_h) \ + $(regcache_h) +wrapper.o: wrapper.c $(defs_h) $(value_h) $(wrapper_h) +x86-64-linux-nat.o: x86-64-linux-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) \ + $(regcache_h) $(gdb_assert_h) $(x86_64_tdep_h) +x86-64-linux-tdep.o: x86-64-linux-tdep.c $(defs_h) $(inferior_h) \ + $(gdbcore_h) $(regcache_h) $(x86_64_tdep_h) $(dwarf2cfi_h) +x86-64-tdep.o: x86-64-tdep.c $(defs_h) $(inferior_h) $(gdbcore_h) \ + $(gdbcmd_h) $(arch_utils_h) $(regcache_h) $(symfile_h) $(objfiles_h) \ + $(x86_64_tdep_h) $(dwarf2cfi_h) $(gdb_assert_h) +xcoffread.o: xcoffread.c $(defs_h) $(bfd_h) $(gdb_string_h) $(gdb_stat_h) \ + $(coff_internal_h) $(libcoff_h) $(coff_xcoff_h) $(libxcoff_h) \ + $(coff_rs6000_h) $(symtab_h) $(gdbtypes_h) $(symfile_h) \ + $(objfiles_h) $(buildsym_h) $(stabsread_h) $(expression_h) \ + $(complaints_h) $(gdb_stabs_h) $(aout_stab_gnu_h) +xcoffsolib.o: xcoffsolib.c $(defs_h) $(bfd_h) $(xcoffsolib_h) $(inferior_h) \ + $(gdbcmd_h) $(symfile_h) $(frame_h) $(gdb_regex_h) +xmodem.o: xmodem.c $(defs_h) $(serial_h) $(target_h) $(xmodem_h) +xstormy16-tdep.o: xstormy16-tdep.c $(defs_h) $(value_h) $(inferior_h) \ + $(symfile_h) $(arch_utils_h) $(regcache_h) $(gdbcore_h) \ + $(objfiles_h) +z8k-tdep.o: z8k-tdep.c $(defs_h) $(frame_h) $(symtab_h) $(gdbcmd_h) \ + $(gdbtypes_h) $(dis_asm_h) $(gdbcore_h) $(regcache_h) $(value_h) + +# +# gdb/cli/ dependencies +# +# Need to explicitly specify the compile rule as make will do nothing +# or try to compile the object file into the mi directory. + +cli-cmds.o: $(srcdir)/cli/cli-cmds.c $(defs_h) $(completer_h) $(target_h) \ + $(gdb_wait_h) $(gdb_regex_h) $(gdb_string_h) $(filenames_h) \ + $(ui_out_h) $(top_h) $(cli_decode_h) $(cli_script_h) \ + $(cli_setshow_h) $(cli_cmds_h) $(source_h) $(linespec_h) \ + $(expression_h) $(language_h) $(objfiles_h) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-cmds.c +cli-decode.o: $(srcdir)/cli/cli-decode.c $(defs_h) $(symtab_h) \ + $(gdb_regex_h) $(gdb_string_h) $(ui_out_h) $(cli_cmds_h) \ + $(cli_decode_h) $(gdb_assert_h) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-decode.c +cli-dump.o: $(srcdir)/cli/cli-dump.c $(defs_h) $(gdb_string_h) \ + $(cli_decode_h) $(cli_cmds_h) $(value_h) $(completer_h) \ + $(cli_dump_h) $(gdb_assert_h) $(target_h) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-dump.c +cli-script.o: $(srcdir)/cli/cli-script.c $(defs_h) $(value_h) $(language_h) \ + $(ui_out_h) $(gdb_string_h) $(top_h) $(cli_cmds_h) $(cli_decode_h) \ + $(cli_script_h) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-script.c +cli-setshow.o: $(srcdir)/cli/cli-setshow.c $(defs_h) $(value_h) \ + $(gdb_string_h) $(ui_out_h) $(cli_decode_h) $(cli_cmds_h) \ + $(cli_setshow_h) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-setshow.c +cli-utils.o: $(srcdir)/cli/cli-utils.c $(defs_h) $(cli_utils_h) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-utils.c + +# +# GDBTK sub-directory +# +# Need to explicitly specify the compile rule as make will do nothing +# or try to compile the object file into the mi directory. + +gdbres.o: $(srcdir)/gdbtk/gdb.rc $(srcdir)/gdbtk/gdbtool.ico + $(WINDRES) --include $(srcdir)/gdbtk $(srcdir)/gdbtk/gdb.rc gdbres.o + +gdbtk.o: $(srcdir)/gdbtk/generic/gdbtk.c \ + $(srcdir)/gdbtk/generic/gdbtk.h $(defs_h) \ + $(symtab_h) $(inferior_h) $(command_h) \ + $(bfd_h) $(symfile_h) $(objfiles_h) $(target_h) $(gdb_string_h) \ + $(tracepoint_h) $(top_h) + $(CC) -c $(INTERNAL_CFLAGS) $(IDE_CFLAGS) $(ITCL_CFLAGS) \ + $(ITK_CFLAGS) $(TIX_CFLAGS) \ + $(TCL_CFLAGS) $(TK_CFLAGS) $(X11_CFLAGS) $(GDBTK_CFLAGS)\ + $(srcdir)/gdbtk/generic/gdbtk.c \ + -DGDBTK_LIBRARY=\"$(GDBTK_LIBRARY)\" -DSRC_DIR=\"$(GDBTK_SRC_DIR)\" + +gdbtk-bp.o: $(srcdir)/gdbtk/generic/gdbtk-bp.c \ + $(srcdir)/gdbtk/generic/gdbtk.h \ + $(srcdir)/gdbtk/generic/gdbtk-cmds.h \ + $(defs_h) $(breakpoint_h) $(tracepoint_h) \ + $(symfile_h) $(symtab_h) $(gdb_string_h) + $(CC) -c $(INTERNAL_CFLAGS) $(IDE_CFLAGS) $(ITCL_CFLAGS) \ + $(TIX_CFLAGS) $(TCL_CFLAGS) $(TK_CFLAGS) $(X11_CFLAGS) \ + $(GDBTK_CFLAGS) $(srcdir)/gdbtk/generic/gdbtk-bp.c \ + -DGDBTK_LIBRARY=\"$(GDBTK_LIBRARY)\" + +gdbtk-cmds.o: $(srcdir)/gdbtk/generic/gdbtk-cmds.c \ + $(srcdir)/gdbtk/generic/gdbtk.h $(srcdir)/gdbtk/generic/gdbtk-cmds.h \ + $(defs_h) $(symtab_h) $(inferior_h) \ + $(command_h) $(bfd_h) $(top_h) $(symfile_h) $(objfiles_h) $(target_h) \ + $(gdb_string_h) $(tracepoint_h) $(source_h) $(regcache_h) + $(CC) -c $(INTERNAL_CFLAGS) $(IDE_CFLAGS) $(ITCL_CFLAGS) \ + $(TIX_CFLAGS) $(TCL_CFLAGS) $(TK_CFLAGS) $(X11_CFLAGS) \ + $(GDBTK_CFLAGS) $(srcdir)/gdbtk/generic/gdbtk-cmds.c \ + -DGDBTK_LIBRARY=\"$(GDBTK_LIBRARY)\" + +gdbtk-hooks.o: $(srcdir)/gdbtk/generic/gdbtk-hooks.c \ + $(srcdir)/gdbtk/generic/gdbtk.h $(defs_h) \ + $(symtab_h) $(inferior_h) $(command_h) \ + $(bfd_h) $(symfile_h) $(objfiles_h) $(target_h) $(gdb_string_h) \ + $(tracepoint_h) + $(CC) -c $(INTERNAL_CFLAGS) $(IDE_CFLAGS) $(ITCL_CFLAGS) $(TIX_CFLAGS) \ + $(TCL_CFLAGS) $(TK_CFLAGS) $(X11_CFLAGS) $(GDBTK_CFLAGS)\ + $(srcdir)/gdbtk/generic/gdbtk-hooks.c -DGDBTK_LIBRARY=\"$(GDBTK_LIBRARY)\" + +gdbtk-register.o: $(srcdir)/gdbtk/generic/gdbtk-register.c \ + $(srcdir)/gdbtk/generic/gdbtk.h \ + $(srcdir)/gdbtk/generic/gdbtk-cmds.h \ + $(defs_h) $(frame_h) $(value_h) $(gdb_string_h) + $(CC) -c $(INTERNAL_CFLAGS) $(IDE_CFLAGS) $(ITCL_CFLAGS) \ + $(TIX_CFLAGS) $(TCL_CFLAGS) $(TK_CFLAGS) $(X11_CFLAGS) \ + $(GDBTK_CFLAGS) $(srcdir)/gdbtk/generic/gdbtk-register.c \ + -DGDBTK_LIBRARY=\"$(GDBTK_LIBRARY)\" + +gdbtk-stack.o: $(srcdir)/gdbtk/generic/gdbtk-stack.c \ + $(srcdir)/gdbtk/generic/gdbtk.h $(srcdir)/gdbtk/generic/gdbtk-cmds.h \ + $(srcdir)/gdbtk/generic/gdbtk-wrapper.h \ + $(defs_h) $(frame_h) $(value_h) $(target_h) $(breakpoint_h) \ + $(linespec_h) + $(CC) -c $(INTERNAL_CFLAGS) $(IDE_CFLAGS) $(ITCL_CFLAGS) \ + $(TIX_CFLAGS) $(TCL_CFLAGS) $(TK_CFLAGS) $(X11_CFLAGS) \ + $(GDBTK_CFLAGS) $(srcdir)/gdbtk/generic/gdbtk-stack.c \ + -DGDBTK_LIBRARY=\"$(GDBTK_LIBRARY)\" + +gdbtk-varobj.o: $(srcdir)/gdbtk/generic/gdbtk-varobj.c \ + $(srcdir)/gdbtk/generic/gdbtk.h \ + $(defs_h) $(value_h) $(varobj_h) $(gdb_string_h) + $(CC) -c $(INTERNAL_CFLAGS) $(IDE_CFLAGS) $(ITCL_CFLAGS) $(TIX_CFLAGS) \ + $(TCL_CFLAGS) $(TK_CFLAGS) $(X11_CFLAGS) $(GDBTK_CFLAGS)\ + $(srcdir)/gdbtk/generic/gdbtk-varobj.c + +gdbtk-wrapper.o: $(srcdir)/gdbtk/generic/gdbtk-wrapper.c \ + $(srcdir)/gdbtk/generic/gdbtk-wrapper.h \ + $(defs_h) $(frame_h) $(value_h) + $(CC) -c $(INTERNAL_CFLAGS) $(IDE_CFLAGS) $(GDBTK_CFLAGS)\ + $(srcdir)/gdbtk/generic/gdbtk-wrapper.c + +# +# gdb/mi/ dependencies +# +# Need to explicitly specify the compile rule as make will do nothing +# or try to compile the object file into the mi directory. + +mi-cmd-break.o: $(srcdir)/mi/mi-cmd-break.c $(defs_h) $(mi_cmds_h) \ + $(ui_out_h) $(mi_out_h) $(breakpoint_h) $(gdb_string_h) \ + $(mi_getopt_h) $(gdb_events_h) $(gdb_h) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/mi/mi-cmd-break.c +mi-cmd-disas.o: $(srcdir)/mi/mi-cmd-disas.c $(defs_h) $(target_h) $(value_h) \ + $(mi_cmds_h) $(mi_getopt_h) $(ui_out_h) $(gdb_string_h) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/mi/mi-cmd-disas.c +mi-cmd-stack.o: $(srcdir)/mi/mi-cmd-stack.c $(defs_h) $(target_h) $(frame_h) \ + $(value_h) $(mi_cmds_h) $(ui_out_h) $(symtab_h) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/mi/mi-cmd-stack.c +mi-cmd-var.o: $(srcdir)/mi/mi-cmd-var.c $(defs_h) $(mi_cmds_h) $(ui_out_h) \ + $(mi_out_h) $(varobj_h) $(value_h) $(gdb_string_h) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/mi/mi-cmd-var.c +mi-cmds.o: $(srcdir)/mi/mi-cmds.c $(defs_h) $(top_h) $(mi_cmds_h) \ + $(gdb_string_h) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/mi/mi-cmds.c +mi-console.o: $(srcdir)/mi/mi-console.c $(defs_h) $(mi_console_h) \ + $(gdb_string_h) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/mi/mi-console.c +mi-getopt.o: $(srcdir)/mi/mi-getopt.c $(defs_h) $(mi_getopt_h) \ + $(gdb_string_h) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/mi/mi-getopt.c +mi-main.o: $(srcdir)/mi/mi-main.c $(defs_h) $(target_h) $(inferior_h) \ + $(gdb_string_h) $(top_h) $(gdbthread_h) $(mi_cmds_h) $(mi_parse_h) \ + $(mi_getopt_h) $(mi_console_h) $(ui_out_h) $(mi_out_h) \ + $(event_loop_h) $(event_top_h) $(gdbcore_h) $(value_h) $(regcache_h) \ + $(gdb_h) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/mi/mi-main.c +mi-out.o: $(srcdir)/mi/mi-out.c $(defs_h) $(ui_out_h) $(mi_out_h) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/mi/mi-out.c +mi-parse.o: $(srcdir)/mi/mi-parse.c $(defs_h) $(mi_cmds_h) $(mi_parse_h) \ + $(gdb_string_h) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/mi/mi-parse.c + +# +# nindy-share sub-directory +# +# Need to explicitly specify the compile rule as make will do nothing +# or try to compile the object file into the mi directory. + +Onindy.o: nindy-share/Onindy.c $(gdb_wait_h) nindy-share/block_io.h \ + nindy-share/env.h + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/nindy-share/Onindy.c + +nindy.o: nindy-share/nindy.c $(gdb_wait_h) nindy-share/block_io.h \ + nindy-share/env.h + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/nindy-share/nindy.c + +ttyflush.o: nindy-share/ttyflush.c $(srcdir)/nindy-share/ttyflush.c + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/nindy-share/ttyflush.c + +# +# rdi-share sub-directory +# +# Need to explicitly specify the compile rule as make will do nothing +# or try to compile the object file into the mi directory. + +rdi-share/libangsd.a: force + @dir=rdi-share; \ + if [ -f ./$${dir}/Makefile ] ; then \ + r=`pwd`; export r; \ + srcroot=`cd $(srcdir); pwd`; export srcroot; \ + (cd $${dir}; $(MAKE) $(FLAGS_TO_PASS) all); \ + else \ + true; \ + fi + +# +# Signals sub-directory +# +# Need to explicitly specify the compile rule as make will do nothing +# or try to compile the object file into the mi directory. + +signals.o: $(srcdir)/signals/signals.c $(defs_h) $(target_h) $(gdb_string_h) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/signals/signals.c + +# +# TUI dependencies +# +# Need to explicitly specify the compile rule as make will do nothing +# or try to compile the object file into the mi directory. + +tui-file.o: $(srcdir)/tui/tui-file.c $(defs_h) $(ui_file_h) $(tui_file_h) \ + $(tui_tuiIO_h) $(tui_h) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/tui/tui-file.c +tui-hooks.o: $(srcdir)/tui/tui-hooks.c $(config_h) $(defs_h) $(symtab_h) \ + $(inferior_h) $(command_h) $(bfd_h) $(symfile_h) $(objfiles_h) \ + $(target_h) $(gdbcore_h) $(event_loop_h) $(frame_h) $(breakpoint_h) \ + $(gdb_events_h) $(tui_h) $(tuiData_h) $(tuiLayout_h) $(tuiIO_h) \ + $(tuiRegs_h) $(tuiWin_h) $(tuiStack_h) $(tuiDataWin_h) \ + $(tuiSourceWin_h) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/tui/tui-hooks.c +tui-out.o: $(srcdir)/tui/tui-out.c $(defs_h) $(ui_out_h) $(tui_h) \ + $(gdb_string_h) $(gdb_assert_h) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/tui/tui-out.c +tui.o: $(srcdir)/tui/tui.c $(config_h) $(defs_h) $(gdbcmd_h) $(tui_h) \ + $(tuiData_h) $(tuiLayout_h) $(tuiIO_h) $(tuiRegs_h) $(tuiStack_h) \ + $(tuiWin_h) $(tuiSourceWin_h) $(readline_h) $(target_h) $(frame_h) \ + $(breakpoint_h) $(inferior_h) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/tui/tui.c +tuiCommand.o: $(srcdir)/tui/tuiCommand.c $(config_h) $(defs_h) $(tui_h) \ + $(tuiData_h) $(tuiWin_h) $(tuiIO_h) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/tui/tuiCommand.c +tuiData.o: $(srcdir)/tui/tuiData.c $(config_h) $(defs_h) $(tui_h) \ + $(tuiData_h) $(tuiGeneralWin_h) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/tui/tuiData.c +tuiDataWin.o: $(srcdir)/tui/tuiDataWin.c $(config_h) $(defs_h) $(tui_h) \ + $(tuiData_h) $(tuiGeneralWin_h) $(tuiRegs_h) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/tui/tuiDataWin.c +tuiDisassem.o: $(srcdir)/tui/tuiDisassem.c $(config_h) $(defs_h) $(symtab_h) \ + $(breakpoint_h) $(frame_h) $(value_h) $(tui_h) $(tuiData_h) \ + $(tuiWin_h) $(tuiLayout_h) $(tuiSourceWin_h) $(tuiStack_h) \ + $(tui_file_h) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/tui/tuiDisassem.c +tuiGeneralWin.o: $(srcdir)/tui/tuiGeneralWin.c $(config_h) $(defs_h) \ + $(tui_h) $(tuiData_h) $(tuiGeneralWin_h) $(tuiWin_h) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/tui/tuiGeneralWin.c +tuiIO.o: $(srcdir)/tui/tuiIO.c $(config_h) $(defs_h) $(terminal_h) \ + $(target_h) $(event_loop_h) $(command_h) $(top_h) $(readline_h) \ + $(tui_h) $(tuiData_h) $(tuiIO_h) $(tuiCommand_h) $(tuiWin_h) \ + $(tuiGeneralWin_h) $(tui_file_h) $(ui_out_h) $(cli_out_h) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/tui/tuiIO.c +tuiLayout.o: $(srcdir)/tui/tuiLayout.c $(config_h) $(defs_h) $(command_h) \ + $(symtab_h) $(frame_h) $(tui_h) $(tuiData_h) $(tuiDataWin_h) \ + $(tuiGeneralWin_h) $(tuiStack_h) $(tuiRegs_h) $(tuiWin_h) \ + $(tuiSourceWin_h) $(tuiDisassem_h) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/tui/tuiLayout.c +tuiRegs.o: $(srcdir)/tui/tuiRegs.c $(config_h) $(defs_h) $(tui_h) \ + $(tuiData_h) $(symtab_h) $(gdbtypes_h) $(gdbcmd_h) $(frame_h) \ + $(inferior_h) $(target_h) $(tuiLayout_h) $(tuiWin_h) $(tuiDataWin_h) \ + $(tuiGeneralWin_h) $(tui_file_h) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/tui/tuiRegs.c +tuiSource.o: $(srcdir)/tui/tuiSource.c $(config_h) $(defs_h) $(symtab_h) \ + $(frame_h) $(breakpoint_h) $(source_h) $(symtab_h) $(tui_h) \ + $(tuiData_h) $(tuiStack_h) $(tuiSourceWin_h) $(tuiSource_h) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/tui/tuiSource.c +tuiSourceWin.o: $(srcdir)/tui/tuiSourceWin.c $(config_h) $(defs_h) \ + $(symtab_h) $(frame_h) $(breakpoint_h) $(value_h) $(tui_h) \ + $(tuiData_h) $(tuiStack_h) $(tuiWin_h) $(tuiGeneralWin_h) \ + $(tuiSourceWin_h) $(tuiSource_h) $(tuiDisassem_h) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/tui/tuiSourceWin.c +tuiStack.o: $(srcdir)/tui/tuiStack.c $(config_h) $(defs_h) $(symtab_h) \ + $(breakpoint_h) $(frame_h) $(command_h) $(tui_h) $(tuiData_h) \ + $(tuiStack_h) $(tuiGeneralWin_h) $(tuiSource_h) $(tuiSourceWin_h) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/tui/tuiStack.c +tuiWin.o: $(srcdir)/tui/tuiWin.c $(config_h) $(defs_h) $(command_h) \ + $(symtab_h) $(breakpoint_h) $(frame_h) $(cli_cmds_h) $(tui_h) \ + $(tuiData_h) $(tuiGeneralWin_h) $(tuiStack_h) $(tuiRegs_h) \ + $(tuiDisassem_h) $(tuiSource_h) $(tuiSourceWin_h) $(tuiDataWin_h) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/tui/tuiWin.c + +# +# vx-share sub-directory +# + +xdr_ld.o: vx-share/xdr_ld.c $(defs_h) vx-share/vxTypes.h \ + vx-share/vxWorks.h vx-share/xdr_ld.h + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/vx-share/xdr_ld.c + +xdr_ptrace.o: vx-share/xdr_ptrace.c $(defs_h) vx-share/vxTypes.h \ + vx-share/vxWorks.h vx-share/xdr_ptrace.h + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/vx-share/xdr_ptrace.c + +xdr_rdb.o: vx-share/xdr_rdb.c $(defs_h) vx-share/vxTypes.h \ + vx-share/vxWorks.h vx-share/xdr_rdb.h + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/vx-share/xdr_rdb.c + +charset.o: charset.c $(defs_h) $(charset_h) $(gdbcmd_h) gdb_assert.h + +c-lang.o: $(charset_h) +utils.o: $(charset_h) +### end of the gdb Makefile.in. diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c new file mode 100644 index 0000000..2838df7 --- /dev/null +++ b/gdb/ada-lang.c @@ -0,0 +1,8311 @@ +/* Ada language support routines for GDB, the GNU debugger. Copyright + 1992, 1993, 1994, 1997, 1998, 1999, 2000 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 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include <stdio.h> +#include "gdb_string.h" +#include <ctype.h> +#include <stdarg.h> +#include "demangle.h" +#include "defs.h" +#include "symtab.h" +#include "gdbtypes.h" +#include "gdbcmd.h" +#include "expression.h" +#include "parser-defs.h" +#include "language.h" +#include "c-lang.h" +#include "inferior.h" +#include "symfile.h" +#include "objfiles.h" +#include "breakpoint.h" +#include "gdbcore.h" +#include "ada-lang.h" +#ifdef UI_OUT +#include "ui-out.h" +#endif + +struct cleanup *unresolved_names; + +void extract_string (CORE_ADDR addr, char *buf); + +static struct type *ada_create_fundamental_type (struct objfile *, int); + +static void modify_general_field (char *, LONGEST, int, int); + +static struct type *desc_base_type (struct type *); + +static struct type *desc_bounds_type (struct type *); + +static struct value *desc_bounds (struct value *); + +static int fat_pntr_bounds_bitpos (struct type *); + +static int fat_pntr_bounds_bitsize (struct type *); + +static struct type *desc_data_type (struct type *); + +static struct value *desc_data (struct value *); + +static int fat_pntr_data_bitpos (struct type *); + +static int fat_pntr_data_bitsize (struct type *); + +static struct value *desc_one_bound (struct value *, int, int); + +static int desc_bound_bitpos (struct type *, int, int); + +static int desc_bound_bitsize (struct type *, int, int); + +static struct type *desc_index_type (struct type *, int); + +static int desc_arity (struct type *); + +static int ada_type_match (struct type *, struct type *, int); + +static int ada_args_match (struct symbol *, struct value **, int); + +static struct value *place_on_stack (struct value *, CORE_ADDR *); + +static struct value *convert_actual (struct value *, struct type *, + CORE_ADDR *); + +static struct value *make_array_descriptor (struct type *, struct value *, + CORE_ADDR *); + +static void ada_add_block_symbols (struct block *, const char *, + namespace_enum, struct objfile *, int); + +static void fill_in_ada_prototype (struct symbol *); + +static int is_nonfunction (struct symbol **, int); + +static void add_defn_to_vec (struct symbol *, struct block *); + +static struct partial_symbol *ada_lookup_partial_symbol (struct partial_symtab + *, const char *, int, + namespace_enum, int); + +static struct symtab *symtab_for_sym (struct symbol *); + +static struct value *ada_resolve_subexp (struct expression **, int *, int, + struct type *); + +static void replace_operator_with_call (struct expression **, int, int, int, + struct symbol *, struct block *); + +static int possible_user_operator_p (enum exp_opcode, struct value **); + +static const char *ada_op_name (enum exp_opcode); + +static int numeric_type_p (struct type *); + +static int integer_type_p (struct type *); + +static int scalar_type_p (struct type *); + +static int discrete_type_p (struct type *); + +static char *extended_canonical_line_spec (struct symtab_and_line, + const char *); + +static struct value *evaluate_subexp (struct type *, struct expression *, + int *, enum noside); + +static struct value *evaluate_subexp_type (struct expression *, int *); + +static struct type *ada_create_fundamental_type (struct objfile *, int); + +static int is_dynamic_field (struct type *, int); + +static struct type *to_fixed_variant_branch_type (struct type *, char *, + CORE_ADDR, struct value *); + +static struct type *to_fixed_range_type (char *, struct value *, + struct objfile *); + +static struct type *to_static_fixed_type (struct type *); + +static struct value *unwrap_value (struct value *); + +static struct type *packed_array_type (struct type *, long *); + +static struct type *decode_packed_array_type (struct type *); + +static struct value *decode_packed_array (struct value *); + +static struct value *value_subscript_packed (struct value *, int, + struct value **); + +static struct value *coerce_unspec_val_to_type (struct value *, long, + struct type *); + +static struct value *get_var_value (char *, char *); + +static int lesseq_defined_than (struct symbol *, struct symbol *); + +static int equiv_types (struct type *, struct type *); + +static int is_name_suffix (const char *); + +static int wild_match (const char *, int, const char *); + +static struct symtabs_and_lines find_sal_from_funcs_and_line (const char *, + int, + struct symbol + **, int); + +static int find_line_in_linetable (struct linetable *, int, struct symbol **, + int, int *); + +static int find_next_line_in_linetable (struct linetable *, int, int, int); + +static struct symtabs_and_lines all_sals_for_line (const char *, int, + char ***); + +static void read_all_symtabs (const char *); + +static int is_plausible_func_for_line (struct symbol *, int); + +static struct value *ada_coerce_ref (struct value *); + +static struct value *value_pos_atr (struct value *); + +static struct value *value_val_atr (struct type *, struct value *); + +static struct symbol *standard_lookup (const char *, namespace_enum); + +extern void markTimeStart (int index); +extern void markTimeStop (int index); + + + +/* Maximum-sized dynamic type. */ +static unsigned int varsize_limit; + +static const char *ada_completer_word_break_characters = + " \t\n!@#$%^&*()+=|~`}{[]\";:?/,-"; + +/* The name of the symbol to use to get the name of the main subprogram */ +#define ADA_MAIN_PROGRAM_SYMBOL_NAME "__gnat_ada_main_program_name" + + /* Utilities */ + +/* extract_string + * + * read the string located at ADDR from the inferior and store the + * result into BUF + */ +void +extract_string (CORE_ADDR addr, char *buf) +{ + int char_index = 0; + + /* Loop, reading one byte at a time, until we reach the '\000' + end-of-string marker */ + do + { + target_read_memory (addr + char_index * sizeof (char), + buf + char_index * sizeof (char), sizeof (char)); + char_index++; + } + while (buf[char_index - 1] != '\000'); +} + +/* Assuming *OLD_VECT points to an array of *SIZE objects of size + ELEMENT_SIZE, grow it to contain at least MIN_SIZE objects, + updating *OLD_VECT and *SIZE as necessary. */ + +void +grow_vect (void **old_vect, size_t * size, size_t min_size, int element_size) +{ + if (*size < min_size) + { + *size *= 2; + if (*size < min_size) + *size = min_size; + *old_vect = xrealloc (*old_vect, *size * element_size); + } +} + +/* True (non-zero) iff TARGET matches FIELD_NAME up to any trailing + suffix of FIELD_NAME beginning "___" */ + +static int +field_name_match (const char *field_name, const char *target) +{ + int len = strlen (target); + return + STREQN (field_name, target, len) + && (field_name[len] == '\0' + || (STREQN (field_name + len, "___", 3) + && !STREQ (field_name + strlen (field_name) - 6, "___XVN"))); +} + + +/* The length of the prefix of NAME prior to any "___" suffix. */ + +int +ada_name_prefix_len (const char *name) +{ + if (name == NULL) + return 0; + else + { + const char *p = strstr (name, "___"); + if (p == NULL) + return strlen (name); + else + return p - name; + } +} + +/* SUFFIX is a suffix of STR. False if STR is null. */ +static int +is_suffix (const char *str, const char *suffix) +{ + int len1, len2; + if (str == NULL) + return 0; + len1 = strlen (str); + len2 = strlen (suffix); + return (len1 >= len2 && STREQ (str + len1 - len2, suffix)); +} + +/* Create a value of type TYPE whose contents come from VALADDR, if it + * is non-null, and whose memory address (in the inferior) is + * ADDRESS. */ +struct value * +value_from_contents_and_address (struct type *type, char *valaddr, + CORE_ADDR address) +{ + struct value *v = allocate_value (type); + if (valaddr == NULL) + VALUE_LAZY (v) = 1; + else + memcpy (VALUE_CONTENTS_RAW (v), valaddr, TYPE_LENGTH (type)); + VALUE_ADDRESS (v) = address; + if (address != 0) + VALUE_LVAL (v) = lval_memory; + return v; +} + +/* The contents of value VAL, beginning at offset OFFSET, treated as a + value of type TYPE. The result is an lval in memory if VAL is. */ + +static struct value * +coerce_unspec_val_to_type (struct value *val, long offset, struct type *type) +{ + CHECK_TYPEDEF (type); + if (VALUE_LVAL (val) == lval_memory) + return value_at_lazy (type, + VALUE_ADDRESS (val) + VALUE_OFFSET (val) + offset, + NULL); + else + { + struct value *result = allocate_value (type); + VALUE_LVAL (result) = not_lval; + if (VALUE_ADDRESS (val) == 0) + memcpy (VALUE_CONTENTS_RAW (result), VALUE_CONTENTS (val) + offset, + TYPE_LENGTH (type) > TYPE_LENGTH (VALUE_TYPE (val)) + ? TYPE_LENGTH (VALUE_TYPE (val)) : TYPE_LENGTH (type)); + else + { + VALUE_ADDRESS (result) = + VALUE_ADDRESS (val) + VALUE_OFFSET (val) + offset; + VALUE_LAZY (result) = 1; + } + return result; + } +} + +static char * +cond_offset_host (char *valaddr, long offset) +{ + if (valaddr == NULL) + return NULL; + else + return valaddr + offset; +} + +static CORE_ADDR +cond_offset_target (CORE_ADDR address, long offset) +{ + if (address == 0) + return 0; + else + return address + offset; +} + +/* Perform execute_command on the result of concatenating all + arguments up to NULL. */ +static void +do_command (const char *arg, ...) +{ + int len; + char *cmd; + const char *s; + va_list ap; + + va_start (ap, arg); + len = 0; + s = arg; + cmd = ""; + for (; s != NULL; s = va_arg (ap, const char *)) + { + char *cmd1; + len += strlen (s); + cmd1 = alloca (len + 1); + strcpy (cmd1, cmd); + strcat (cmd1, s); + cmd = cmd1; + } + va_end (ap); + execute_command (cmd, 0); +} + + + /* Language Selection */ + +/* If the main program is in Ada, return language_ada, otherwise return LANG + (the main program is in Ada iif the adainit symbol is found). + + MAIN_PST is not used. */ + +enum language +ada_update_initial_language (enum language lang, + struct partial_symtab *main_pst) +{ + if (lookup_minimal_symbol ("adainit", (const char *) NULL, + (struct objfile *) NULL) != NULL) + /* return language_ada; */ + /* FIXME: language_ada should be defined in defs.h */ + return language_unknown; + + return lang; +} + + + /* Symbols */ + +/* Table of Ada operators and their GNAT-mangled names. Last entry is pair + of NULLs. */ + +const struct ada_opname_map ada_opname_table[] = { + {"Oadd", "\"+\"", BINOP_ADD}, + {"Osubtract", "\"-\"", BINOP_SUB}, + {"Omultiply", "\"*\"", BINOP_MUL}, + {"Odivide", "\"/\"", BINOP_DIV}, + {"Omod", "\"mod\"", BINOP_MOD}, + {"Orem", "\"rem\"", BINOP_REM}, + {"Oexpon", "\"**\"", BINOP_EXP}, + {"Olt", "\"<\"", BINOP_LESS}, + {"Ole", "\"<=\"", BINOP_LEQ}, + {"Ogt", "\">\"", BINOP_GTR}, + {"Oge", "\">=\"", BINOP_GEQ}, + {"Oeq", "\"=\"", BINOP_EQUAL}, + {"One", "\"/=\"", BINOP_NOTEQUAL}, + {"Oand", "\"and\"", BINOP_BITWISE_AND}, + {"Oor", "\"or\"", BINOP_BITWISE_IOR}, + {"Oxor", "\"xor\"", BINOP_BITWISE_XOR}, + {"Oconcat", "\"&\"", BINOP_CONCAT}, + {"Oabs", "\"abs\"", UNOP_ABS}, + {"Onot", "\"not\"", UNOP_LOGICAL_NOT}, + {"Oadd", "\"+\"", UNOP_PLUS}, + {"Osubtract", "\"-\"", UNOP_NEG}, + {NULL, NULL} +}; + +/* True if STR should be suppressed in info listings. */ +static int +is_suppressed_name (const char *str) +{ + if (STREQN (str, "_ada_", 5)) + str += 5; + if (str[0] == '_' || str[0] == '\000') + return 1; + else + { + const char *p; + const char *suffix = strstr (str, "___"); + if (suffix != NULL && suffix[3] != 'X') + return 1; + if (suffix == NULL) + suffix = str + strlen (str); + for (p = suffix - 1; p != str; p -= 1) + if (isupper (*p)) + { + int i; + if (p[0] == 'X' && p[-1] != '_') + goto OK; + if (*p != 'O') + return 1; + for (i = 0; ada_opname_table[i].mangled != NULL; i += 1) + if (STREQN (ada_opname_table[i].mangled, p, + strlen (ada_opname_table[i].mangled))) + goto OK; + return 1; + OK:; + } + return 0; + } +} + +/* The "mangled" form of DEMANGLED, according to GNAT conventions. + * The result is valid until the next call to ada_mangle. */ +char * +ada_mangle (const char *demangled) +{ + static char *mangling_buffer = NULL; + static size_t mangling_buffer_size = 0; + const char *p; + int k; + + if (demangled == NULL) + return NULL; + + GROW_VECT (mangling_buffer, mangling_buffer_size, + 2 * strlen (demangled) + 10); + + k = 0; + for (p = demangled; *p != '\0'; p += 1) + { + if (*p == '.') + { + mangling_buffer[k] = mangling_buffer[k + 1] = '_'; + k += 2; + } + else if (*p == '"') + { + const struct ada_opname_map *mapping; + + for (mapping = ada_opname_table; + mapping->mangled != NULL && + !STREQN (mapping->demangled, p, strlen (mapping->demangled)); + p += 1) + ; + if (mapping->mangled == NULL) + error ("invalid Ada operator name: %s", p); + strcpy (mangling_buffer + k, mapping->mangled); + k += strlen (mapping->mangled); + break; + } + else + { + mangling_buffer[k] = *p; + k += 1; + } + } + + mangling_buffer[k] = '\0'; + return mangling_buffer; +} + +/* Return NAME folded to lower case, or, if surrounded by single + * quotes, unfolded, but with the quotes stripped away. Result good + * to next call. */ +char * +ada_fold_name (const char *name) +{ + static char *fold_buffer = NULL; + static size_t fold_buffer_size = 0; + + int len = strlen (name); + GROW_VECT (fold_buffer, fold_buffer_size, len + 1); + + if (name[0] == '\'') + { + strncpy (fold_buffer, name + 1, len - 2); + fold_buffer[len - 2] = '\000'; + } + else + { + int i; + for (i = 0; i <= len; i += 1) + fold_buffer[i] = tolower (name[i]); + } + + return fold_buffer; +} + +/* Demangle: + 1. Discard final __{DIGIT}+ or ${DIGIT}+ + 2. Convert other instances of embedded "__" to `.'. + 3. Discard leading _ada_. + 4. Convert operator names to the appropriate quoted symbols. + 5. Remove everything after first ___ if it is followed by + 'X'. + 6. Replace TK__ with __, and a trailing B or TKB with nothing. + 7. Put symbols that should be suppressed in <...> brackets. + 8. Remove trailing X[bn]* suffix (indicating names in package bodies). + The resulting string is valid until the next call of ada_demangle. + */ + +char * +ada_demangle (const char *mangled) +{ + int i, j; + int len0; + const char *p; + char *demangled; + int at_start_name; + static char *demangling_buffer = NULL; + static size_t demangling_buffer_size = 0; + + if (STREQN (mangled, "_ada_", 5)) + mangled += 5; + + if (mangled[0] == '_' || mangled[0] == '<') + goto Suppress; + + p = strstr (mangled, "___"); + if (p == NULL) + len0 = strlen (mangled); + else + { + if (p[3] == 'X') + len0 = p - mangled; + else + goto Suppress; + } + if (len0 > 3 && STREQ (mangled + len0 - 3, "TKB")) + len0 -= 3; + if (len0 > 1 && STREQ (mangled + len0 - 1, "B")) + len0 -= 1; + + /* Make demangled big enough for possible expansion by operator name. */ + GROW_VECT (demangling_buffer, demangling_buffer_size, 2 * len0 + 1); + demangled = demangling_buffer; + + if (isdigit (mangled[len0 - 1])) + { + for (i = len0 - 2; i >= 0 && isdigit (mangled[i]); i -= 1) + ; + if (i > 1 && mangled[i] == '_' && mangled[i - 1] == '_') + len0 = i - 1; + else if (mangled[i] == '$') + len0 = i; + } + + for (i = 0, j = 0; i < len0 && !isalpha (mangled[i]); i += 1, j += 1) + demangled[j] = mangled[i]; + + at_start_name = 1; + while (i < len0) + { + if (at_start_name && mangled[i] == 'O') + { + int k; + for (k = 0; ada_opname_table[k].mangled != NULL; k += 1) + { + int op_len = strlen (ada_opname_table[k].mangled); + if (STREQN + (ada_opname_table[k].mangled + 1, mangled + i + 1, + op_len - 1) && !isalnum (mangled[i + op_len])) + { + strcpy (demangled + j, ada_opname_table[k].demangled); + at_start_name = 0; + i += op_len; + j += strlen (ada_opname_table[k].demangled); + break; + } + } + if (ada_opname_table[k].mangled != NULL) + continue; + } + at_start_name = 0; + + if (i < len0 - 4 && STREQN (mangled + i, "TK__", 4)) + i += 2; + if (mangled[i] == 'X' && i != 0 && isalnum (mangled[i - 1])) + { + do + i += 1; + while (i < len0 && (mangled[i] == 'b' || mangled[i] == 'n')); + if (i < len0) + goto Suppress; + } + else if (i < len0 - 2 && mangled[i] == '_' && mangled[i + 1] == '_') + { + demangled[j] = '.'; + at_start_name = 1; + i += 2; + j += 1; + } + else + { + demangled[j] = mangled[i]; + i += 1; + j += 1; + } + } + demangled[j] = '\000'; + + for (i = 0; demangled[i] != '\0'; i += 1) + if (isupper (demangled[i]) || demangled[i] == ' ') + goto Suppress; + + return demangled; + +Suppress: + GROW_VECT (demangling_buffer, demangling_buffer_size, strlen (mangled) + 3); + demangled = demangling_buffer; + if (mangled[0] == '<') + strcpy (demangled, mangled); + else + sprintf (demangled, "<%s>", mangled); + return demangled; + +} + +/* Returns non-zero iff SYM_NAME matches NAME, ignoring any trailing + * suffixes that encode debugging information or leading _ada_ on + * SYM_NAME (see is_name_suffix commentary for the debugging + * information that is ignored). If WILD, then NAME need only match a + * suffix of SYM_NAME minus the same suffixes. Also returns 0 if + * either argument is NULL. */ + +int +ada_match_name (const char *sym_name, const char *name, int wild) +{ + if (sym_name == NULL || name == NULL) + return 0; + else if (wild) + return wild_match (name, strlen (name), sym_name); + else + { + int len_name = strlen (name); + return (STREQN (sym_name, name, len_name) + && is_name_suffix (sym_name + len_name)) + || (STREQN (sym_name, "_ada_", 5) + && STREQN (sym_name + 5, name, len_name) + && is_name_suffix (sym_name + len_name + 5)); + } +} + +/* True (non-zero) iff in Ada mode, the symbol SYM should be + suppressed in info listings. */ + +int +ada_suppress_symbol_printing (struct symbol *sym) +{ + if (SYMBOL_NAMESPACE (sym) == STRUCT_NAMESPACE) + return 1; + else + return is_suppressed_name (SYMBOL_NAME (sym)); +} + + + /* Arrays */ + +/* Names of MAX_ADA_DIMENS bounds in P_BOUNDS fields of + array descriptors. */ + +static char *bound_name[] = { + "LB0", "UB0", "LB1", "UB1", "LB2", "UB2", "LB3", "UB3", + "LB4", "UB4", "LB5", "UB5", "LB6", "UB6", "LB7", "UB7" +}; + +/* Maximum number of array dimensions we are prepared to handle. */ + +#define MAX_ADA_DIMENS (sizeof(bound_name) / (2*sizeof(char*))) + +/* Like modify_field, but allows bitpos > wordlength. */ + +static void +modify_general_field (char *addr, LONGEST fieldval, int bitpos, int bitsize) +{ + modify_field (addr + sizeof (LONGEST) * bitpos / (8 * sizeof (LONGEST)), + fieldval, bitpos % (8 * sizeof (LONGEST)), bitsize); +} + + +/* The desc_* routines return primitive portions of array descriptors + (fat pointers). */ + +/* The descriptor or array type, if any, indicated by TYPE; removes + level of indirection, if needed. */ +static struct type * +desc_base_type (struct type *type) +{ + if (type == NULL) + return NULL; + CHECK_TYPEDEF (type); + if (type != NULL && TYPE_CODE (type) == TYPE_CODE_PTR) + return check_typedef (TYPE_TARGET_TYPE (type)); + else + return type; +} + +/* True iff TYPE indicates a "thin" array pointer type. */ +static int +is_thin_pntr (struct type *type) +{ + return + is_suffix (ada_type_name (desc_base_type (type)), "___XUT") + || is_suffix (ada_type_name (desc_base_type (type)), "___XUT___XVE"); +} + +/* The descriptor type for thin pointer type TYPE. */ +static struct type * +thin_descriptor_type (struct type *type) +{ + struct type *base_type = desc_base_type (type); + if (base_type == NULL) + return NULL; + if (is_suffix (ada_type_name (base_type), "___XVE")) + return base_type; + else + { + struct type *alt_type = ada_find_parallel_type (base_type, "___XVE"); + if (alt_type == NULL) + return base_type; + else + return alt_type; + } +} + +/* A pointer to the array data for thin-pointer value VAL. */ +static struct value * +thin_data_pntr (struct value *val) +{ + struct type *type = VALUE_TYPE (val); + if (TYPE_CODE (type) == TYPE_CODE_PTR) + return value_cast (desc_data_type (thin_descriptor_type (type)), + value_copy (val)); + else + return value_from_longest (desc_data_type (thin_descriptor_type (type)), + VALUE_ADDRESS (val) + VALUE_OFFSET (val)); +} + +/* True iff TYPE indicates a "thick" array pointer type. */ +static int +is_thick_pntr (struct type *type) +{ + type = desc_base_type (type); + return (type != NULL && TYPE_CODE (type) == TYPE_CODE_STRUCT + && lookup_struct_elt_type (type, "P_BOUNDS", 1) != NULL); +} + +/* If TYPE is the type of an array descriptor (fat or thin pointer) or a + pointer to one, the type of its bounds data; otherwise, NULL. */ +static struct type * +desc_bounds_type (struct type *type) +{ + struct type *r; + + type = desc_base_type (type); + + if (type == NULL) + return NULL; + else if (is_thin_pntr (type)) + { + type = thin_descriptor_type (type); + if (type == NULL) + return NULL; + r = lookup_struct_elt_type (type, "BOUNDS", 1); + if (r != NULL) + return check_typedef (r); + } + else if (TYPE_CODE (type) == TYPE_CODE_STRUCT) + { + r = lookup_struct_elt_type (type, "P_BOUNDS", 1); + if (r != NULL) + return check_typedef (TYPE_TARGET_TYPE (check_typedef (r))); + } + return NULL; +} + +/* If ARR is an array descriptor (fat or thin pointer), or pointer to + one, a pointer to its bounds data. Otherwise NULL. */ +static struct value * +desc_bounds (struct value *arr) +{ + struct type *type = check_typedef (VALUE_TYPE (arr)); + if (is_thin_pntr (type)) + { + struct type *bounds_type = + desc_bounds_type (thin_descriptor_type (type)); + LONGEST addr; + + if (desc_bounds_type == NULL) + error ("Bad GNAT array descriptor"); + + /* NOTE: The following calculation is not really kosher, but + since desc_type is an XVE-encoded type (and shouldn't be), + the correct calculation is a real pain. FIXME (and fix GCC). */ + if (TYPE_CODE (type) == TYPE_CODE_PTR) + addr = value_as_long (arr); + else + addr = VALUE_ADDRESS (arr) + VALUE_OFFSET (arr); + + return + value_from_longest (lookup_pointer_type (bounds_type), + addr - TYPE_LENGTH (bounds_type)); + } + + else if (is_thick_pntr (type)) + return value_struct_elt (&arr, NULL, "P_BOUNDS", NULL, + "Bad GNAT array descriptor"); + else + return NULL; +} + +/* If TYPE is the type of an array-descriptor (fat pointer), the bit + position of the field containing the address of the bounds data. */ +static int +fat_pntr_bounds_bitpos (struct type *type) +{ + return TYPE_FIELD_BITPOS (desc_base_type (type), 1); +} + +/* If TYPE is the type of an array-descriptor (fat pointer), the bit + size of the field containing the address of the bounds data. */ +static int +fat_pntr_bounds_bitsize (struct type *type) +{ + type = desc_base_type (type); + + if (TYPE_FIELD_BITSIZE (type, 1) > 0) + return TYPE_FIELD_BITSIZE (type, 1); + else + return 8 * TYPE_LENGTH (check_typedef (TYPE_FIELD_TYPE (type, 1))); +} + +/* If TYPE is the type of an array descriptor (fat or thin pointer) or a + pointer to one, the type of its array data (a + pointer-to-array-with-no-bounds type); otherwise, NULL. Use + ada_type_of_array to get an array type with bounds data. */ +static struct type * +desc_data_type (struct type *type) +{ + type = desc_base_type (type); + + /* NOTE: The following is bogus; see comment in desc_bounds. */ + if (is_thin_pntr (type)) + return lookup_pointer_type + (desc_base_type (TYPE_FIELD_TYPE (thin_descriptor_type (type), 1))); + else if (is_thick_pntr (type)) + return lookup_struct_elt_type (type, "P_ARRAY", 1); + else + return NULL; +} + +/* If ARR is an array descriptor (fat or thin pointer), a pointer to + its array data. */ +static struct value * +desc_data (struct value *arr) +{ + struct type *type = VALUE_TYPE (arr); + if (is_thin_pntr (type)) + return thin_data_pntr (arr); + else if (is_thick_pntr (type)) + return value_struct_elt (&arr, NULL, "P_ARRAY", NULL, + "Bad GNAT array descriptor"); + else + return NULL; +} + + +/* If TYPE is the type of an array-descriptor (fat pointer), the bit + position of the field containing the address of the data. */ +static int +fat_pntr_data_bitpos (struct type *type) +{ + return TYPE_FIELD_BITPOS (desc_base_type (type), 0); +} + +/* If TYPE is the type of an array-descriptor (fat pointer), the bit + size of the field containing the address of the data. */ +static int +fat_pntr_data_bitsize (struct type *type) +{ + type = desc_base_type (type); + + if (TYPE_FIELD_BITSIZE (type, 0) > 0) + return TYPE_FIELD_BITSIZE (type, 0); + else + return TARGET_CHAR_BIT * TYPE_LENGTH (TYPE_FIELD_TYPE (type, 0)); +} + +/* If BOUNDS is an array-bounds structure (or pointer to one), return + the Ith lower bound stored in it, if WHICH is 0, and the Ith upper + bound, if WHICH is 1. The first bound is I=1. */ +static struct value * +desc_one_bound (struct value *bounds, int i, int which) +{ + return value_struct_elt (&bounds, NULL, bound_name[2 * i + which - 2], NULL, + "Bad GNAT array descriptor bounds"); +} + +/* If BOUNDS is an array-bounds structure type, return the bit position + of the Ith lower bound stored in it, if WHICH is 0, and the Ith upper + bound, if WHICH is 1. The first bound is I=1. */ +static int +desc_bound_bitpos (struct type *type, int i, int which) +{ + return TYPE_FIELD_BITPOS (desc_base_type (type), 2 * i + which - 2); +} + +/* If BOUNDS is an array-bounds structure type, return the bit field size + of the Ith lower bound stored in it, if WHICH is 0, and the Ith upper + bound, if WHICH is 1. The first bound is I=1. */ +static int +desc_bound_bitsize (struct type *type, int i, int which) +{ + type = desc_base_type (type); + + if (TYPE_FIELD_BITSIZE (type, 2 * i + which - 2) > 0) + return TYPE_FIELD_BITSIZE (type, 2 * i + which - 2); + else + return 8 * TYPE_LENGTH (TYPE_FIELD_TYPE (type, 2 * i + which - 2)); +} + +/* If TYPE is the type of an array-bounds structure, the type of its + Ith bound (numbering from 1). Otherwise, NULL. */ +static struct type * +desc_index_type (struct type *type, int i) +{ + type = desc_base_type (type); + + if (TYPE_CODE (type) == TYPE_CODE_STRUCT) + return lookup_struct_elt_type (type, bound_name[2 * i - 2], 1); + else + return NULL; +} + +/* The number of index positions in the array-bounds type TYPE. 0 + if TYPE is NULL. */ +static int +desc_arity (struct type *type) +{ + type = desc_base_type (type); + + if (type != NULL) + return TYPE_NFIELDS (type) / 2; + return 0; +} + + +/* Non-zero iff type is a simple array type (or pointer to one). */ +int +ada_is_simple_array (struct type *type) +{ + if (type == NULL) + return 0; + CHECK_TYPEDEF (type); + return (TYPE_CODE (type) == TYPE_CODE_ARRAY + || (TYPE_CODE (type) == TYPE_CODE_PTR + && TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_ARRAY)); +} + +/* Non-zero iff type belongs to a GNAT array descriptor. */ +int +ada_is_array_descriptor (struct type *type) +{ + struct type *data_type = desc_data_type (type); + + if (type == NULL) + return 0; + CHECK_TYPEDEF (type); + return + data_type != NULL + && ((TYPE_CODE (data_type) == TYPE_CODE_PTR + && TYPE_TARGET_TYPE (data_type) != NULL + && TYPE_CODE (TYPE_TARGET_TYPE (data_type)) == TYPE_CODE_ARRAY) + || + TYPE_CODE (data_type) == TYPE_CODE_ARRAY) + && desc_arity (desc_bounds_type (type)) > 0; +} + +/* Non-zero iff type is a partially mal-formed GNAT array + descriptor. (FIXME: This is to compensate for some problems with + debugging output from GNAT. Re-examine periodically to see if it + is still needed. */ +int +ada_is_bogus_array_descriptor (struct type *type) +{ + return + type != NULL + && TYPE_CODE (type) == TYPE_CODE_STRUCT + && (lookup_struct_elt_type (type, "P_BOUNDS", 1) != NULL + || lookup_struct_elt_type (type, "P_ARRAY", 1) != NULL) + && !ada_is_array_descriptor (type); +} + + +/* If ARR has a record type in the form of a standard GNAT array descriptor, + (fat pointer) returns the type of the array data described---specifically, + a pointer-to-array type. If BOUNDS is non-zero, the bounds data are filled + in from the descriptor; otherwise, they are left unspecified. If + the ARR denotes a null array descriptor and BOUNDS is non-zero, + returns NULL. The result is simply the type of ARR if ARR is not + a descriptor. */ +struct type * +ada_type_of_array (struct value *arr, int bounds) +{ + if (ada_is_packed_array_type (VALUE_TYPE (arr))) + return decode_packed_array_type (VALUE_TYPE (arr)); + + if (!ada_is_array_descriptor (VALUE_TYPE (arr))) + return VALUE_TYPE (arr); + + if (!bounds) + return + check_typedef (TYPE_TARGET_TYPE (desc_data_type (VALUE_TYPE (arr)))); + else + { + struct type *elt_type; + int arity; + struct value *descriptor; + struct objfile *objf = TYPE_OBJFILE (VALUE_TYPE (arr)); + + elt_type = ada_array_element_type (VALUE_TYPE (arr), -1); + arity = ada_array_arity (VALUE_TYPE (arr)); + + if (elt_type == NULL || arity == 0) + return check_typedef (VALUE_TYPE (arr)); + + descriptor = desc_bounds (arr); + if (value_as_long (descriptor) == 0) + return NULL; + while (arity > 0) + { + struct type *range_type = alloc_type (objf); + struct type *array_type = alloc_type (objf); + struct value *low = desc_one_bound (descriptor, arity, 0); + struct value *high = desc_one_bound (descriptor, arity, 1); + arity -= 1; + + create_range_type (range_type, VALUE_TYPE (low), + (int) value_as_long (low), + (int) value_as_long (high)); + elt_type = create_array_type (array_type, elt_type, range_type); + } + + return lookup_pointer_type (elt_type); + } +} + +/* If ARR does not represent an array, returns ARR unchanged. + Otherwise, returns either a standard GDB array with bounds set + appropriately or, if ARR is a non-null fat pointer, a pointer to a standard + GDB array. Returns NULL if ARR is a null fat pointer. */ +struct value * +ada_coerce_to_simple_array_ptr (struct value *arr) +{ + if (ada_is_array_descriptor (VALUE_TYPE (arr))) + { + struct type *arrType = ada_type_of_array (arr, 1); + if (arrType == NULL) + return NULL; + return value_cast (arrType, value_copy (desc_data (arr))); + } + else if (ada_is_packed_array_type (VALUE_TYPE (arr))) + return decode_packed_array (arr); + else + return arr; +} + +/* If ARR does not represent an array, returns ARR unchanged. + Otherwise, returns a standard GDB array describing ARR (which may + be ARR itself if it already is in the proper form). */ +struct value * +ada_coerce_to_simple_array (struct value *arr) +{ + if (ada_is_array_descriptor (VALUE_TYPE (arr))) + { + struct value *arrVal = ada_coerce_to_simple_array_ptr (arr); + if (arrVal == NULL) + error ("Bounds unavailable for null array pointer."); + return value_ind (arrVal); + } + else if (ada_is_packed_array_type (VALUE_TYPE (arr))) + return decode_packed_array (arr); + else + return arr; +} + +/* If TYPE represents a GNAT array type, return it translated to an + ordinary GDB array type (possibly with BITSIZE fields indicating + packing). For other types, is the identity. */ +struct type * +ada_coerce_to_simple_array_type (struct type *type) +{ + struct value *mark = value_mark (); + struct value *dummy = value_from_longest (builtin_type_long, 0); + struct type *result; + VALUE_TYPE (dummy) = type; + result = ada_type_of_array (dummy, 0); + value_free_to_mark (dummy); + return result; +} + +/* Non-zero iff TYPE represents a standard GNAT packed-array type. */ +int +ada_is_packed_array_type (struct type *type) +{ + if (type == NULL) + return 0; + CHECK_TYPEDEF (type); + return + ada_type_name (type) != NULL + && strstr (ada_type_name (type), "___XP") != NULL; +} + +/* Given that TYPE is a standard GDB array type with all bounds filled + in, and that the element size of its ultimate scalar constituents + (that is, either its elements, or, if it is an array of arrays, its + elements' elements, etc.) is *ELT_BITS, return an identical type, + but with the bit sizes of its elements (and those of any + constituent arrays) recorded in the BITSIZE components of its + TYPE_FIELD_BITSIZE values, and with *ELT_BITS set to its total size + in bits. */ +static struct type * +packed_array_type (struct type *type, long *elt_bits) +{ + struct type *new_elt_type; + struct type *new_type; + LONGEST low_bound, high_bound; + + CHECK_TYPEDEF (type); + if (TYPE_CODE (type) != TYPE_CODE_ARRAY) + return type; + + new_type = alloc_type (TYPE_OBJFILE (type)); + new_elt_type = packed_array_type (check_typedef (TYPE_TARGET_TYPE (type)), + elt_bits); + create_array_type (new_type, new_elt_type, TYPE_FIELD_TYPE (type, 0)); + TYPE_FIELD_BITSIZE (new_type, 0) = *elt_bits; + TYPE_NAME (new_type) = ada_type_name (type); + + if (get_discrete_bounds (TYPE_FIELD_TYPE (type, 0), + &low_bound, &high_bound) < 0) + low_bound = high_bound = 0; + if (high_bound < low_bound) + *elt_bits = TYPE_LENGTH (new_type) = 0; + else + { + *elt_bits *= (high_bound - low_bound + 1); + TYPE_LENGTH (new_type) = + (*elt_bits + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT; + } + + /* TYPE_FLAGS (new_type) |= TYPE_FLAG_FIXED_INSTANCE; */ + /* FIXME: TYPE_FLAG_FIXED_INSTANCE should be defined in gdbtypes.h */ + return new_type; +} + +/* The array type encoded by TYPE, where ada_is_packed_array_type (TYPE). + */ +static struct type * +decode_packed_array_type (struct type *type) +{ + struct symbol **syms; + struct block **blocks; + const char *raw_name = ada_type_name (check_typedef (type)); + char *name = (char *) alloca (strlen (raw_name) + 1); + char *tail = strstr (raw_name, "___XP"); + struct type *shadow_type; + long bits; + int i, n; + + memcpy (name, raw_name, tail - raw_name); + name[tail - raw_name] = '\000'; + + /* NOTE: Use ada_lookup_symbol_list because of bug in some versions + * of gcc (Solaris, e.g.). FIXME when compiler is fixed. */ + n = ada_lookup_symbol_list (name, get_selected_block (NULL), + VAR_NAMESPACE, &syms, &blocks); + for (i = 0; i < n; i += 1) + if (syms[i] != NULL && SYMBOL_CLASS (syms[i]) == LOC_TYPEDEF + && STREQ (name, ada_type_name (SYMBOL_TYPE (syms[i])))) + break; + if (i >= n) + { + warning ("could not find bounds information on packed array"); + return NULL; + } + shadow_type = SYMBOL_TYPE (syms[i]); + + if (TYPE_CODE (shadow_type) != TYPE_CODE_ARRAY) + { + warning ("could not understand bounds information on packed array"); + return NULL; + } + + if (sscanf (tail + sizeof ("___XP") - 1, "%ld", &bits) != 1) + { + warning ("could not understand bit size information on packed array"); + return NULL; + } + + return packed_array_type (shadow_type, &bits); +} + +/* Given that ARR is a struct value* indicating a GNAT packed array, + returns a simple array that denotes that array. Its type is a + standard GDB array type except that the BITSIZEs of the array + target types are set to the number of bits in each element, and the + type length is set appropriately. */ + +static struct value * +decode_packed_array (struct value *arr) +{ + struct type *type = decode_packed_array_type (VALUE_TYPE (arr)); + + if (type == NULL) + { + error ("can't unpack array"); + return NULL; + } + else + return coerce_unspec_val_to_type (arr, 0, type); +} + + +/* The value of the element of packed array ARR at the ARITY indices + given in IND. ARR must be a simple array. */ + +static struct value * +value_subscript_packed (struct value *arr, int arity, struct value **ind) +{ + int i; + int bits, elt_off, bit_off; + long elt_total_bit_offset; + struct type *elt_type; + struct value *v; + + bits = 0; + elt_total_bit_offset = 0; + elt_type = check_typedef (VALUE_TYPE (arr)); + for (i = 0; i < arity; i += 1) + { + if (TYPE_CODE (elt_type) != TYPE_CODE_ARRAY + || TYPE_FIELD_BITSIZE (elt_type, 0) == 0) + error + ("attempt to do packed indexing of something other than a packed array"); + else + { + struct type *range_type = TYPE_INDEX_TYPE (elt_type); + LONGEST lowerbound, upperbound; + LONGEST idx; + + if (get_discrete_bounds (range_type, &lowerbound, &upperbound) < 0) + { + warning ("don't know bounds of array"); + lowerbound = upperbound = 0; + } + + idx = value_as_long (value_pos_atr (ind[i])); + if (idx < lowerbound || idx > upperbound) + warning ("packed array index %ld out of bounds", (long) idx); + bits = TYPE_FIELD_BITSIZE (elt_type, 0); + elt_total_bit_offset += (idx - lowerbound) * bits; + elt_type = check_typedef (TYPE_TARGET_TYPE (elt_type)); + } + } + elt_off = elt_total_bit_offset / HOST_CHAR_BIT; + bit_off = elt_total_bit_offset % HOST_CHAR_BIT; + + v = ada_value_primitive_packed_val (arr, NULL, elt_off, bit_off, + bits, elt_type); + if (VALUE_LVAL (arr) == lval_internalvar) + VALUE_LVAL (v) = lval_internalvar_component; + else + VALUE_LVAL (v) = VALUE_LVAL (arr); + return v; +} + +/* Non-zero iff TYPE includes negative integer values. */ + +static int +has_negatives (struct type *type) +{ + switch (TYPE_CODE (type)) + { + default: + return 0; + case TYPE_CODE_INT: + return !TYPE_UNSIGNED (type); + case TYPE_CODE_RANGE: + return TYPE_LOW_BOUND (type) < 0; + } +} + + +/* Create a new value of type TYPE from the contents of OBJ starting + at byte OFFSET, and bit offset BIT_OFFSET within that byte, + proceeding for BIT_SIZE bits. If OBJ is an lval in memory, then + assigning through the result will set the field fetched from. OBJ + may also be NULL, in which case, VALADDR+OFFSET must address the + start of storage containing the packed value. The value returned + in this case is never an lval. + Assumes 0 <= BIT_OFFSET < HOST_CHAR_BIT. */ + +struct value * +ada_value_primitive_packed_val (struct value *obj, char *valaddr, long offset, + int bit_offset, int bit_size, + struct type *type) +{ + struct value *v; + int src, /* Index into the source area. */ + targ, /* Index into the target area. */ + i, srcBitsLeft, /* Number of source bits left to move. */ + nsrc, ntarg, /* Number of source and target bytes. */ + unusedLS, /* Number of bits in next significant + * byte of source that are unused. */ + accumSize; /* Number of meaningful bits in accum */ + unsigned char *bytes; /* First byte containing data to unpack. */ + unsigned char *unpacked; + unsigned long accum; /* Staging area for bits being transferred */ + unsigned char sign; + int len = (bit_size + bit_offset + HOST_CHAR_BIT - 1) / 8; + /* Transmit bytes from least to most significant; delta is the + * direction the indices move. */ + int delta = BITS_BIG_ENDIAN ? -1 : 1; + + CHECK_TYPEDEF (type); + + if (obj == NULL) + { + v = allocate_value (type); + bytes = (unsigned char *) (valaddr + offset); + } + else if (VALUE_LAZY (obj)) + { + v = value_at (type, + VALUE_ADDRESS (obj) + VALUE_OFFSET (obj) + offset, NULL); + bytes = (unsigned char *) alloca (len); + read_memory (VALUE_ADDRESS (v), bytes, len); + } + else + { + v = allocate_value (type); + bytes = (unsigned char *) VALUE_CONTENTS (obj) + offset; + } + + if (obj != NULL) + { + VALUE_LVAL (v) = VALUE_LVAL (obj); + if (VALUE_LVAL (obj) == lval_internalvar) + VALUE_LVAL (v) = lval_internalvar_component; + VALUE_ADDRESS (v) = VALUE_ADDRESS (obj) + VALUE_OFFSET (obj) + offset; + VALUE_BITPOS (v) = bit_offset + VALUE_BITPOS (obj); + VALUE_BITSIZE (v) = bit_size; + if (VALUE_BITPOS (v) >= HOST_CHAR_BIT) + { + VALUE_ADDRESS (v) += 1; + VALUE_BITPOS (v) -= HOST_CHAR_BIT; + } + } + else + VALUE_BITSIZE (v) = bit_size; + unpacked = (unsigned char *) VALUE_CONTENTS (v); + + srcBitsLeft = bit_size; + nsrc = len; + ntarg = TYPE_LENGTH (type); + sign = 0; + if (bit_size == 0) + { + memset (unpacked, 0, TYPE_LENGTH (type)); + return v; + } + else if (BITS_BIG_ENDIAN) + { + src = len - 1; + if (has_negatives (type) && + ((bytes[0] << bit_offset) & (1 << (HOST_CHAR_BIT - 1)))) + sign = ~0; + + unusedLS = + (HOST_CHAR_BIT - (bit_size + bit_offset) % HOST_CHAR_BIT) + % HOST_CHAR_BIT; + + switch (TYPE_CODE (type)) + { + case TYPE_CODE_ARRAY: + case TYPE_CODE_UNION: + case TYPE_CODE_STRUCT: + /* Non-scalar values must be aligned at a byte boundary. */ + accumSize = + (HOST_CHAR_BIT - bit_size % HOST_CHAR_BIT) % HOST_CHAR_BIT; + /* And are placed at the beginning (most-significant) bytes + * of the target. */ + targ = src; + break; + default: + accumSize = 0; + targ = TYPE_LENGTH (type) - 1; + break; + } + } + else + { + int sign_bit_offset = (bit_size + bit_offset - 1) % 8; + + src = targ = 0; + unusedLS = bit_offset; + accumSize = 0; + + if (has_negatives (type) && (bytes[len - 1] & (1 << sign_bit_offset))) + sign = ~0; + } + + accum = 0; + while (nsrc > 0) + { + /* Mask for removing bits of the next source byte that are not + * part of the value. */ + unsigned int unusedMSMask = + (1 << (srcBitsLeft >= HOST_CHAR_BIT ? HOST_CHAR_BIT : srcBitsLeft)) - + 1; + /* Sign-extend bits for this byte. */ + unsigned int signMask = sign & ~unusedMSMask; + accum |= + (((bytes[src] >> unusedLS) & unusedMSMask) | signMask) << accumSize; + accumSize += HOST_CHAR_BIT - unusedLS; + if (accumSize >= HOST_CHAR_BIT) + { + unpacked[targ] = accum & ~(~0L << HOST_CHAR_BIT); + accumSize -= HOST_CHAR_BIT; + accum >>= HOST_CHAR_BIT; + ntarg -= 1; + targ += delta; + } + srcBitsLeft -= HOST_CHAR_BIT - unusedLS; + unusedLS = 0; + nsrc -= 1; + src += delta; + } + while (ntarg > 0) + { + accum |= sign << accumSize; + unpacked[targ] = accum & ~(~0L << HOST_CHAR_BIT); + accumSize -= HOST_CHAR_BIT; + accum >>= HOST_CHAR_BIT; + ntarg -= 1; + targ += delta; + } + + return v; +} + +/* Move N bits from SOURCE, starting at bit offset SRC_OFFSET to + TARGET, starting at bit offset TARG_OFFSET. SOURCE and TARGET must + not overlap. */ +static void +move_bits (char *target, int targ_offset, char *source, int src_offset, int n) +{ + unsigned int accum, mask; + int accum_bits, chunk_size; + + target += targ_offset / HOST_CHAR_BIT; + targ_offset %= HOST_CHAR_BIT; + source += src_offset / HOST_CHAR_BIT; + src_offset %= HOST_CHAR_BIT; + if (BITS_BIG_ENDIAN) + { + accum = (unsigned char) *source; + source += 1; + accum_bits = HOST_CHAR_BIT - src_offset; + + while (n > 0) + { + int unused_right; + accum = (accum << HOST_CHAR_BIT) + (unsigned char) *source; + accum_bits += HOST_CHAR_BIT; + source += 1; + chunk_size = HOST_CHAR_BIT - targ_offset; + if (chunk_size > n) + chunk_size = n; + unused_right = HOST_CHAR_BIT - (chunk_size + targ_offset); + mask = ((1 << chunk_size) - 1) << unused_right; + *target = + (*target & ~mask) + | ((accum >> (accum_bits - chunk_size - unused_right)) & mask); + n -= chunk_size; + accum_bits -= chunk_size; + target += 1; + targ_offset = 0; + } + } + else + { + accum = (unsigned char) *source >> src_offset; + source += 1; + accum_bits = HOST_CHAR_BIT - src_offset; + + while (n > 0) + { + accum = accum + ((unsigned char) *source << accum_bits); + accum_bits += HOST_CHAR_BIT; + source += 1; + chunk_size = HOST_CHAR_BIT - targ_offset; + if (chunk_size > n) + chunk_size = n; + mask = ((1 << chunk_size) - 1) << targ_offset; + *target = (*target & ~mask) | ((accum << targ_offset) & mask); + n -= chunk_size; + accum_bits -= chunk_size; + accum >>= chunk_size; + target += 1; + targ_offset = 0; + } + } +} + + +/* Store the contents of FROMVAL into the location of TOVAL. + Return a new value with the location of TOVAL and contents of + FROMVAL. Handles assignment into packed fields that have + floating-point or non-scalar types. */ + +static struct value * +ada_value_assign (struct value *toval, struct value *fromval) +{ + struct type *type = VALUE_TYPE (toval); + int bits = VALUE_BITSIZE (toval); + + if (!toval->modifiable) + error ("Left operand of assignment is not a modifiable lvalue."); + + COERCE_REF (toval); + + if (VALUE_LVAL (toval) == lval_memory + && bits > 0 + && (TYPE_CODE (type) == TYPE_CODE_FLT + || TYPE_CODE (type) == TYPE_CODE_STRUCT)) + { + int len = + (VALUE_BITPOS (toval) + bits + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT; + char *buffer = (char *) alloca (len); + struct value *val; + + if (TYPE_CODE (type) == TYPE_CODE_FLT) + fromval = value_cast (type, fromval); + + read_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval), buffer, len); + if (BITS_BIG_ENDIAN) + move_bits (buffer, VALUE_BITPOS (toval), + VALUE_CONTENTS (fromval), + TYPE_LENGTH (VALUE_TYPE (fromval)) * TARGET_CHAR_BIT - + bits, bits); + else + move_bits (buffer, VALUE_BITPOS (toval), VALUE_CONTENTS (fromval), + 0, bits); + write_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval), buffer, + len); + + val = value_copy (toval); + memcpy (VALUE_CONTENTS_RAW (val), VALUE_CONTENTS (fromval), + TYPE_LENGTH (type)); + VALUE_TYPE (val) = type; + + return val; + } + + return value_assign (toval, fromval); +} + + +/* The value of the element of array ARR at the ARITY indices given in IND. + ARR may be either a simple array, GNAT array descriptor, or pointer + thereto. */ + +struct value * +ada_value_subscript (struct value *arr, int arity, struct value **ind) +{ + int k; + struct value *elt; + struct type *elt_type; + + elt = ada_coerce_to_simple_array (arr); + + elt_type = check_typedef (VALUE_TYPE (elt)); + if (TYPE_CODE (elt_type) == TYPE_CODE_ARRAY + && TYPE_FIELD_BITSIZE (elt_type, 0) > 0) + return value_subscript_packed (elt, arity, ind); + + for (k = 0; k < arity; k += 1) + { + if (TYPE_CODE (elt_type) != TYPE_CODE_ARRAY) + error ("too many subscripts (%d expected)", k); + elt = value_subscript (elt, value_pos_atr (ind[k])); + } + return elt; +} + +/* Assuming ARR is a pointer to a standard GDB array of type TYPE, the + value of the element of *ARR at the ARITY indices given in + IND. Does not read the entire array into memory. */ + +struct value * +ada_value_ptr_subscript (struct value *arr, struct type *type, int arity, + struct value **ind) +{ + int k; + + for (k = 0; k < arity; k += 1) + { + LONGEST lwb, upb; + struct value *idx; + + if (TYPE_CODE (type) != TYPE_CODE_ARRAY) + error ("too many subscripts (%d expected)", k); + arr = value_cast (lookup_pointer_type (TYPE_TARGET_TYPE (type)), + value_copy (arr)); + get_discrete_bounds (TYPE_INDEX_TYPE (type), &lwb, &upb); + if (lwb == 0) + idx = ind[k]; + else + idx = value_sub (ind[k], value_from_longest (builtin_type_int, lwb)); + arr = value_add (arr, idx); + type = TYPE_TARGET_TYPE (type); + } + + return value_ind (arr); +} + +/* If type is a record type in the form of a standard GNAT array + descriptor, returns the number of dimensions for type. If arr is a + simple array, returns the number of "array of"s that prefix its + type designation. Otherwise, returns 0. */ + +int +ada_array_arity (struct type *type) +{ + int arity; + + if (type == NULL) + return 0; + + type = desc_base_type (type); + + arity = 0; + if (TYPE_CODE (type) == TYPE_CODE_STRUCT) + return desc_arity (desc_bounds_type (type)); + else + while (TYPE_CODE (type) == TYPE_CODE_ARRAY) + { + arity += 1; + type = check_typedef (TYPE_TARGET_TYPE (type)); + } + + return arity; +} + +/* If TYPE is a record type in the form of a standard GNAT array + descriptor or a simple array type, returns the element type for + TYPE after indexing by NINDICES indices, or by all indices if + NINDICES is -1. Otherwise, returns NULL. */ + +struct type * +ada_array_element_type (struct type *type, int nindices) +{ + type = desc_base_type (type); + + if (TYPE_CODE (type) == TYPE_CODE_STRUCT) + { + int k; + struct type *p_array_type; + + p_array_type = desc_data_type (type); + + k = ada_array_arity (type); + if (k == 0) + return NULL; + + /* Initially p_array_type = elt_type(*)[]...(k times)...[] */ + if (nindices >= 0 && k > nindices) + k = nindices; + p_array_type = TYPE_TARGET_TYPE (p_array_type); + while (k > 0 && p_array_type != NULL) + { + p_array_type = check_typedef (TYPE_TARGET_TYPE (p_array_type)); + k -= 1; + } + return p_array_type; + } + else if (TYPE_CODE (type) == TYPE_CODE_ARRAY) + { + while (nindices != 0 && TYPE_CODE (type) == TYPE_CODE_ARRAY) + { + type = TYPE_TARGET_TYPE (type); + nindices -= 1; + } + return type; + } + + return NULL; +} + +/* The type of nth index in arrays of given type (n numbering from 1). Does + not examine memory. */ + +struct type * +ada_index_type (struct type *type, int n) +{ + type = desc_base_type (type); + + if (n > ada_array_arity (type)) + return NULL; + + if (ada_is_simple_array (type)) + { + int i; + + for (i = 1; i < n; i += 1) + type = TYPE_TARGET_TYPE (type); + + return TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (type, 0)); + } + else + return desc_index_type (desc_bounds_type (type), n); +} + +/* Given that arr is an array type, returns the lower bound of the + Nth index (numbering from 1) if WHICH is 0, and the upper bound if + WHICH is 1. This returns bounds 0 .. -1 if ARR_TYPE is an + array-descriptor type. If TYPEP is non-null, *TYPEP is set to the + bounds type. It works for other arrays with bounds supplied by + run-time quantities other than discriminants. */ + +LONGEST +ada_array_bound_from_type (struct type * arr_type, int n, int which, + struct type ** typep) +{ + struct type *type; + struct type *index_type_desc; + + if (ada_is_packed_array_type (arr_type)) + arr_type = decode_packed_array_type (arr_type); + + if (arr_type == NULL || !ada_is_simple_array (arr_type)) + { + if (typep != NULL) + *typep = builtin_type_int; + return (LONGEST) - which; + } + + if (TYPE_CODE (arr_type) == TYPE_CODE_PTR) + type = TYPE_TARGET_TYPE (arr_type); + else + type = arr_type; + + index_type_desc = ada_find_parallel_type (type, "___XA"); + if (index_type_desc == NULL) + { + struct type *range_type; + struct type *index_type; + + while (n > 1) + { + type = TYPE_TARGET_TYPE (type); + n -= 1; + } + + range_type = TYPE_INDEX_TYPE (type); + index_type = TYPE_TARGET_TYPE (range_type); + if (TYPE_CODE (index_type) == TYPE_CODE_UNDEF) + index_type = builtin_type_long; + if (typep != NULL) + *typep = index_type; + return + (LONGEST) (which == 0 + ? TYPE_LOW_BOUND (range_type) + : TYPE_HIGH_BOUND (range_type)); + } + else + { + struct type *index_type = + to_fixed_range_type (TYPE_FIELD_NAME (index_type_desc, n - 1), + NULL, TYPE_OBJFILE (arr_type)); + if (typep != NULL) + *typep = TYPE_TARGET_TYPE (index_type); + return + (LONGEST) (which == 0 + ? TYPE_LOW_BOUND (index_type) + : TYPE_HIGH_BOUND (index_type)); + } +} + +/* Given that arr is an array value, returns the lower bound of the + nth index (numbering from 1) if which is 0, and the upper bound if + which is 1. This routine will also work for arrays with bounds + supplied by run-time quantities other than discriminants. */ + +struct value * +ada_array_bound (struct value *arr, int n, int which) +{ + struct type *arr_type = VALUE_TYPE (arr); + + if (ada_is_packed_array_type (arr_type)) + return ada_array_bound (decode_packed_array (arr), n, which); + else if (ada_is_simple_array (arr_type)) + { + struct type *type; + LONGEST v = ada_array_bound_from_type (arr_type, n, which, &type); + return value_from_longest (type, v); + } + else + return desc_one_bound (desc_bounds (arr), n, which); +} + +/* Given that arr is an array value, returns the length of the + nth index. This routine will also work for arrays with bounds + supplied by run-time quantities other than discriminants. Does not + work for arrays indexed by enumeration types with representation + clauses at the moment. */ + +struct value * +ada_array_length (struct value *arr, int n) +{ + struct type *arr_type = check_typedef (VALUE_TYPE (arr)); + struct type *index_type_desc; + + if (ada_is_packed_array_type (arr_type)) + return ada_array_length (decode_packed_array (arr), n); + + if (ada_is_simple_array (arr_type)) + { + struct type *type; + LONGEST v = + ada_array_bound_from_type (arr_type, n, 1, &type) - + ada_array_bound_from_type (arr_type, n, 0, NULL) + 1; + return value_from_longest (type, v); + } + else + return + value_from_longest (builtin_type_ada_int, + value_as_long (desc_one_bound (desc_bounds (arr), + n, 1)) + - value_as_long (desc_one_bound (desc_bounds (arr), + n, 0)) + 1); +} + + + /* Name resolution */ + +/* The "demangled" name for the user-definable Ada operator corresponding + to op. */ + +static const char * +ada_op_name (enum exp_opcode op) +{ + int i; + + for (i = 0; ada_opname_table[i].mangled != NULL; i += 1) + { + if (ada_opname_table[i].op == op) + return ada_opname_table[i].demangled; + } + error ("Could not find operator name for opcode"); +} + + +/* Same as evaluate_type (*EXP), but resolves ambiguous symbol + references (OP_UNRESOLVED_VALUES) and converts operators that are + user-defined into appropriate function calls. If CONTEXT_TYPE is + non-null, it provides a preferred result type [at the moment, only + type void has any effect---causing procedures to be preferred over + functions in calls]. A null CONTEXT_TYPE indicates that a non-void + return type is preferred. The variable unresolved_names contains a list + of character strings referenced by expout that should be freed. + May change (expand) *EXP. */ + +void +ada_resolve (struct expression **expp, struct type *context_type) +{ + int pc; + pc = 0; + ada_resolve_subexp (expp, &pc, 1, context_type); +} + +/* Resolve the operator of the subexpression beginning at + position *POS of *EXPP. "Resolving" consists of replacing + OP_UNRESOLVED_VALUE with an appropriate OP_VAR_VALUE, replacing + built-in operators with function calls to user-defined operators, + where appropriate, and (when DEPROCEDURE_P is non-zero), converting + function-valued variables into parameterless calls. May expand + EXP. The CONTEXT_TYPE functions as in ada_resolve, above. */ + +static struct value * +ada_resolve_subexp (struct expression **expp, int *pos, int deprocedure_p, + struct type *context_type) +{ + int pc = *pos; + int i; + struct expression *exp; /* Convenience: == *expp */ + enum exp_opcode op = (*expp)->elts[pc].opcode; + struct value **argvec; /* Vector of operand types (alloca'ed). */ + int nargs; /* Number of operands */ + + argvec = NULL; + nargs = 0; + exp = *expp; + + /* Pass one: resolve operands, saving their types and updating *pos. */ + switch (op) + { + case OP_VAR_VALUE: + /* case OP_UNRESOLVED_VALUE: */ + /* FIXME: OP_UNRESOLVED_VALUE should be defined in expression.h */ + *pos += 4; + break; + + case OP_FUNCALL: + nargs = longest_to_int (exp->elts[pc + 1].longconst) + 1; + /* FIXME: OP_UNRESOLVED_VALUE should be defined in expression.h */ + /* if (exp->elts[pc+3].opcode == OP_UNRESOLVED_VALUE) + { + *pos += 7; + + argvec = (struct value* *) alloca (sizeof (struct value*) * (nargs + 1)); + for (i = 0; i < nargs-1; i += 1) + argvec[i] = ada_resolve_subexp (expp, pos, 1, NULL); + argvec[i] = NULL; + } + else + { + *pos += 3; + ada_resolve_subexp (expp, pos, 0, NULL); + for (i = 1; i < nargs; i += 1) + ada_resolve_subexp (expp, pos, 1, NULL); + } + */ + exp = *expp; + break; + + /* FIXME: UNOP_QUAL should be defined in expression.h */ + /* case UNOP_QUAL: + nargs = 1; + *pos += 3; + ada_resolve_subexp (expp, pos, 1, exp->elts[pc + 1].type); + exp = *expp; + break; + */ + /* FIXME: OP_ATTRIBUTE should be defined in expression.h */ + /* case OP_ATTRIBUTE: + nargs = longest_to_int (exp->elts[pc + 1].longconst) + 1; + *pos += 4; + for (i = 0; i < nargs; i += 1) + ada_resolve_subexp (expp, pos, 1, NULL); + exp = *expp; + break; + */ + case UNOP_ADDR: + nargs = 1; + *pos += 1; + ada_resolve_subexp (expp, pos, 0, NULL); + exp = *expp; + break; + + case BINOP_ASSIGN: + { + struct value *arg1; + nargs = 2; + *pos += 1; + arg1 = ada_resolve_subexp (expp, pos, 0, NULL); + if (arg1 == NULL) + ada_resolve_subexp (expp, pos, 1, NULL); + else + ada_resolve_subexp (expp, pos, 1, VALUE_TYPE (arg1)); + break; + } + + default: + switch (op) + { + default: + error ("Unexpected operator during name resolution"); + case UNOP_CAST: + /* case UNOP_MBR: + nargs = 1; + *pos += 3; + break; + */ + case BINOP_ADD: + case BINOP_SUB: + case BINOP_MUL: + case BINOP_DIV: + case BINOP_REM: + case BINOP_MOD: + case BINOP_EXP: + case BINOP_CONCAT: + case BINOP_LOGICAL_AND: + case BINOP_LOGICAL_OR: + case BINOP_BITWISE_AND: + case BINOP_BITWISE_IOR: + case BINOP_BITWISE_XOR: + + case BINOP_EQUAL: + case BINOP_NOTEQUAL: + case BINOP_LESS: + case BINOP_GTR: + case BINOP_LEQ: + case BINOP_GEQ: + + case BINOP_REPEAT: + case BINOP_SUBSCRIPT: + case BINOP_COMMA: + nargs = 2; + *pos += 1; + break; + + case UNOP_NEG: + case UNOP_PLUS: + case UNOP_LOGICAL_NOT: + case UNOP_ABS: + case UNOP_IND: + nargs = 1; + *pos += 1; + break; + + case OP_LONG: + case OP_DOUBLE: + case OP_VAR_VALUE: + *pos += 4; + break; + + case OP_TYPE: + case OP_BOOL: + case OP_LAST: + case OP_REGISTER: + case OP_INTERNALVAR: + *pos += 3; + break; + + case UNOP_MEMVAL: + *pos += 3; + nargs = 1; + break; + + case STRUCTOP_STRUCT: + case STRUCTOP_PTR: + nargs = 1; + *pos += 4 + BYTES_TO_EXP_ELEM (exp->elts[pc + 1].longconst + 1); + break; + + case OP_ARRAY: + *pos += 4; + nargs = longest_to_int (exp->elts[pc + 2].longconst) + 1; + nargs -= longest_to_int (exp->elts[pc + 1].longconst); + /* A null array contains one dummy element to give the type. */ + /* if (nargs == 0) + nargs = 1; + break; */ + + case TERNOP_SLICE: + /* FIXME: TERNOP_MBR should be defined in expression.h */ + /* case TERNOP_MBR: + *pos += 1; + nargs = 3; + break; + */ + /* FIXME: BINOP_MBR should be defined in expression.h */ + /* case BINOP_MBR: + *pos += 3; + nargs = 2; + break; */ + } + + argvec = + (struct value * *) alloca (sizeof (struct value *) * (nargs + 1)); + for (i = 0; i < nargs; i += 1) + argvec[i] = ada_resolve_subexp (expp, pos, 1, NULL); + argvec[i] = NULL; + exp = *expp; + break; + } + + /* Pass two: perform any resolution on principal operator. */ + switch (op) + { + default: + break; + + /* FIXME: OP_UNRESOLVED_VALUE should be defined in expression.h */ + /* case OP_UNRESOLVED_VALUE: + { + struct symbol** candidate_syms; + struct block** candidate_blocks; + int n_candidates; + + n_candidates = ada_lookup_symbol_list (exp->elts[pc + 2].name, + exp->elts[pc + 1].block, + VAR_NAMESPACE, + &candidate_syms, + &candidate_blocks); + + if (n_candidates > 1) + { */ + /* Types tend to get re-introduced locally, so if there + are any local symbols that are not types, first filter + out all types. *//* + int j; + for (j = 0; j < n_candidates; j += 1) + switch (SYMBOL_CLASS (candidate_syms[j])) + { + case LOC_REGISTER: + case LOC_ARG: + case LOC_REF_ARG: + case LOC_REGPARM: + case LOC_REGPARM_ADDR: + case LOC_LOCAL: + case LOC_LOCAL_ARG: + case LOC_BASEREG: + case LOC_BASEREG_ARG: + goto FoundNonType; + default: + break; + } + FoundNonType: + if (j < n_candidates) + { + j = 0; + while (j < n_candidates) + { + if (SYMBOL_CLASS (candidate_syms[j]) == LOC_TYPEDEF) + { + candidate_syms[j] = candidate_syms[n_candidates-1]; + candidate_blocks[j] = candidate_blocks[n_candidates-1]; + n_candidates -= 1; + } + else + j += 1; + } + } + } + + if (n_candidates == 0) + error ("No definition found for %s", + ada_demangle (exp->elts[pc + 2].name)); + else if (n_candidates == 1) + i = 0; + else if (deprocedure_p + && ! is_nonfunction (candidate_syms, n_candidates)) + { + i = ada_resolve_function (candidate_syms, candidate_blocks, + n_candidates, NULL, 0, + exp->elts[pc + 2].name, context_type); + if (i < 0) + error ("Could not find a match for %s", + ada_demangle (exp->elts[pc + 2].name)); + } + else + { + printf_filtered ("Multiple matches for %s\n", + ada_demangle (exp->elts[pc+2].name)); + user_select_syms (candidate_syms, candidate_blocks, + n_candidates, 1); + i = 0; + } + + exp->elts[pc].opcode = exp->elts[pc + 3].opcode = OP_VAR_VALUE; + exp->elts[pc + 1].block = candidate_blocks[i]; + exp->elts[pc + 2].symbol = candidate_syms[i]; + if (innermost_block == NULL || + contained_in (candidate_blocks[i], innermost_block)) + innermost_block = candidate_blocks[i]; + } */ + /* FALL THROUGH */ + + case OP_VAR_VALUE: + if (deprocedure_p && + TYPE_CODE (SYMBOL_TYPE (exp->elts[pc + 2].symbol)) == + TYPE_CODE_FUNC) + { + replace_operator_with_call (expp, pc, 0, 0, + exp->elts[pc + 2].symbol, + exp->elts[pc + 1].block); + exp = *expp; + } + break; + + case OP_FUNCALL: + { + /* FIXME: OP_UNRESOLVED_VALUE should be defined in expression.h */ + /* if (exp->elts[pc+3].opcode == OP_UNRESOLVED_VALUE) + { + struct symbol** candidate_syms; + struct block** candidate_blocks; + int n_candidates; + + n_candidates = ada_lookup_symbol_list (exp->elts[pc + 5].name, + exp->elts[pc + 4].block, + VAR_NAMESPACE, + &candidate_syms, + &candidate_blocks); + if (n_candidates == 1) + i = 0; + else + { + i = ada_resolve_function (candidate_syms, candidate_blocks, + n_candidates, argvec, nargs-1, + exp->elts[pc + 5].name, context_type); + if (i < 0) + error ("Could not find a match for %s", + ada_demangle (exp->elts[pc + 5].name)); + } + + exp->elts[pc + 3].opcode = exp->elts[pc + 6].opcode = OP_VAR_VALUE; + exp->elts[pc + 4].block = candidate_blocks[i]; + exp->elts[pc + 5].symbol = candidate_syms[i]; + if (innermost_block == NULL || + contained_in (candidate_blocks[i], innermost_block)) + innermost_block = candidate_blocks[i]; + } */ + + } + break; + case BINOP_ADD: + case BINOP_SUB: + case BINOP_MUL: + case BINOP_DIV: + case BINOP_REM: + case BINOP_MOD: + case BINOP_CONCAT: + case BINOP_BITWISE_AND: + case BINOP_BITWISE_IOR: + case BINOP_BITWISE_XOR: + case BINOP_EQUAL: + case BINOP_NOTEQUAL: + case BINOP_LESS: + case BINOP_GTR: + case BINOP_LEQ: + case BINOP_GEQ: + case BINOP_EXP: + case UNOP_NEG: + case UNOP_PLUS: + case UNOP_LOGICAL_NOT: + case UNOP_ABS: + if (possible_user_operator_p (op, argvec)) + { + struct symbol **candidate_syms; + struct block **candidate_blocks; + int n_candidates; + + n_candidates = + ada_lookup_symbol_list (ada_mangle (ada_op_name (op)), + (struct block *) NULL, VAR_NAMESPACE, + &candidate_syms, &candidate_blocks); + i = + ada_resolve_function (candidate_syms, candidate_blocks, + n_candidates, argvec, nargs, + ada_op_name (op), NULL); + if (i < 0) + break; + + replace_operator_with_call (expp, pc, nargs, 1, + candidate_syms[i], candidate_blocks[i]); + exp = *expp; + } + break; + } + + *pos = pc; + return evaluate_subexp_type (exp, pos); +} + +/* Return non-zero if formal type FTYPE matches actual type ATYPE. If + MAY_DEREF is non-zero, the formal may be a pointer and the actual + a non-pointer. */ +/* The term "match" here is rather loose. The match is heuristic and + liberal. FIXME: TOO liberal, in fact. */ + +static int +ada_type_match (struct type *ftype, struct type *atype, int may_deref) +{ + CHECK_TYPEDEF (ftype); + CHECK_TYPEDEF (atype); + + if (TYPE_CODE (ftype) == TYPE_CODE_REF) + ftype = TYPE_TARGET_TYPE (ftype); + if (TYPE_CODE (atype) == TYPE_CODE_REF) + atype = TYPE_TARGET_TYPE (atype); + + if (TYPE_CODE (ftype) == TYPE_CODE_VOID + || TYPE_CODE (atype) == TYPE_CODE_VOID) + return 1; + + switch (TYPE_CODE (ftype)) + { + default: + return 1; + case TYPE_CODE_PTR: + if (TYPE_CODE (atype) == TYPE_CODE_PTR) + return ada_type_match (TYPE_TARGET_TYPE (ftype), + TYPE_TARGET_TYPE (atype), 0); + else + return (may_deref && + ada_type_match (TYPE_TARGET_TYPE (ftype), atype, 0)); + case TYPE_CODE_INT: + case TYPE_CODE_ENUM: + case TYPE_CODE_RANGE: + switch (TYPE_CODE (atype)) + { + case TYPE_CODE_INT: + case TYPE_CODE_ENUM: + case TYPE_CODE_RANGE: + return 1; + default: + return 0; + } + + case TYPE_CODE_ARRAY: + return (TYPE_CODE (atype) == TYPE_CODE_ARRAY + || ada_is_array_descriptor (atype)); + + case TYPE_CODE_STRUCT: + if (ada_is_array_descriptor (ftype)) + return (TYPE_CODE (atype) == TYPE_CODE_ARRAY + || ada_is_array_descriptor (atype)); + else + return (TYPE_CODE (atype) == TYPE_CODE_STRUCT + && !ada_is_array_descriptor (atype)); + + case TYPE_CODE_UNION: + case TYPE_CODE_FLT: + return (TYPE_CODE (atype) == TYPE_CODE (ftype)); + } +} + +/* Return non-zero if the formals of FUNC "sufficiently match" the + vector of actual argument types ACTUALS of size N_ACTUALS. FUNC + may also be an enumeral, in which case it is treated as a 0- + argument function. */ + +static int +ada_args_match (struct symbol *func, struct value **actuals, int n_actuals) +{ + int i; + struct type *func_type = SYMBOL_TYPE (func); + + if (SYMBOL_CLASS (func) == LOC_CONST && + TYPE_CODE (func_type) == TYPE_CODE_ENUM) + return (n_actuals == 0); + else if (func_type == NULL || TYPE_CODE (func_type) != TYPE_CODE_FUNC) + return 0; + + if (TYPE_NFIELDS (func_type) != n_actuals) + return 0; + + for (i = 0; i < n_actuals; i += 1) + { + struct type *ftype = check_typedef (TYPE_FIELD_TYPE (func_type, i)); + struct type *atype = check_typedef (VALUE_TYPE (actuals[i])); + + if (!ada_type_match (TYPE_FIELD_TYPE (func_type, i), + VALUE_TYPE (actuals[i]), 1)) + return 0; + } + return 1; +} + +/* False iff function type FUNC_TYPE definitely does not produce a value + compatible with type CONTEXT_TYPE. Conservatively returns 1 if + FUNC_TYPE is not a valid function type with a non-null return type + or an enumerated type. A null CONTEXT_TYPE indicates any non-void type. */ + +static int +return_match (struct type *func_type, struct type *context_type) +{ + struct type *return_type; + + if (func_type == NULL) + return 1; + + /* FIXME: base_type should be declared in gdbtypes.h, implemented in valarith.c */ + /* if (TYPE_CODE (func_type) == TYPE_CODE_FUNC) + return_type = base_type (TYPE_TARGET_TYPE (func_type)); + else + return_type = base_type (func_type); */ + if (return_type == NULL) + return 1; + + /* FIXME: base_type should be declared in gdbtypes.h, implemented in valarith.c */ + /* context_type = base_type (context_type); */ + + if (TYPE_CODE (return_type) == TYPE_CODE_ENUM) + return context_type == NULL || return_type == context_type; + else if (context_type == NULL) + return TYPE_CODE (return_type) != TYPE_CODE_VOID; + else + return TYPE_CODE (return_type) == TYPE_CODE (context_type); +} + + +/* Return the index in SYMS[0..NSYMS-1] of symbol for the + function (if any) that matches the types of the NARGS arguments in + ARGS. If CONTEXT_TYPE is non-null, and there is at least one match + that returns type CONTEXT_TYPE, then eliminate other matches. If + CONTEXT_TYPE is null, prefer a non-void-returning function. + Asks the user if there is more than one match remaining. Returns -1 + if there is no such symbol or none is selected. NAME is used + solely for messages. May re-arrange and modify SYMS in + the process; the index returned is for the modified vector. BLOCKS + is modified in parallel to SYMS. */ + +int +ada_resolve_function (struct symbol *syms[], struct block *blocks[], + int nsyms, struct value **args, int nargs, + const char *name, struct type *context_type) +{ + int k; + int m; /* Number of hits */ + struct type *fallback; + struct type *return_type; + + return_type = context_type; + if (context_type == NULL) + fallback = builtin_type_void; + else + fallback = NULL; + + m = 0; + while (1) + { + for (k = 0; k < nsyms; k += 1) + { + struct type *type = check_typedef (SYMBOL_TYPE (syms[k])); + + if (ada_args_match (syms[k], args, nargs) + && return_match (SYMBOL_TYPE (syms[k]), return_type)) + { + syms[m] = syms[k]; + if (blocks != NULL) + blocks[m] = blocks[k]; + m += 1; + } + } + if (m > 0 || return_type == fallback) + break; + else + return_type = fallback; + } + + if (m == 0) + return -1; + else if (m > 1) + { + printf_filtered ("Multiple matches for %s\n", name); + user_select_syms (syms, blocks, m, 1); + return 0; + } + return 0; +} + +/* Returns true (non-zero) iff demangled name N0 should appear before N1 */ +/* in a listing of choices during disambiguation (see sort_choices, below). */ +/* The idea is that overloadings of a subprogram name from the */ +/* same package should sort in their source order. We settle for ordering */ +/* such symbols by their trailing number (__N or $N). */ +static int +mangled_ordered_before (char *N0, char *N1) +{ + if (N1 == NULL) + return 0; + else if (N0 == NULL) + return 1; + else + { + int k0, k1; + for (k0 = strlen (N0) - 1; k0 > 0 && isdigit (N0[k0]); k0 -= 1) + ; + for (k1 = strlen (N1) - 1; k1 > 0 && isdigit (N1[k1]); k1 -= 1) + ; + if ((N0[k0] == '_' || N0[k0] == '$') && N0[k0 + 1] != '\000' + && (N1[k1] == '_' || N1[k1] == '$') && N1[k1 + 1] != '\000') + { + int n0, n1; + n0 = k0; + while (N0[n0] == '_' && n0 > 0 && N0[n0 - 1] == '_') + n0 -= 1; + n1 = k1; + while (N1[n1] == '_' && n1 > 0 && N1[n1 - 1] == '_') + n1 -= 1; + if (n0 == n1 && STREQN (N0, N1, n0)) + return (atoi (N0 + k0 + 1) < atoi (N1 + k1 + 1)); + } + return (strcmp (N0, N1) < 0); + } +} + +/* Sort SYMS[0..NSYMS-1] to put the choices in a canonical order by their */ +/* mangled names, rearranging BLOCKS[0..NSYMS-1] according to the same */ +/* permutation. */ +static void +sort_choices (struct symbol *syms[], struct block *blocks[], int nsyms) +{ + int i, j; + for (i = 1; i < nsyms; i += 1) + { + struct symbol *sym = syms[i]; + struct block *block = blocks[i]; + int j; + + for (j = i - 1; j >= 0; j -= 1) + { + if (mangled_ordered_before (SYMBOL_NAME (syms[j]), + SYMBOL_NAME (sym))) + break; + syms[j + 1] = syms[j]; + blocks[j + 1] = blocks[j]; + } + syms[j + 1] = sym; + blocks[j + 1] = block; + } +} + +/* Given a list of NSYMS symbols in SYMS and corresponding blocks in */ +/* BLOCKS, select up to MAX_RESULTS>0 by asking the user (if */ +/* necessary), returning the number selected, and setting the first */ +/* elements of SYMS and BLOCKS to the selected symbols and */ +/* corresponding blocks. Error if no symbols selected. BLOCKS may */ +/* be NULL, in which case it is ignored. */ + +/* NOTE: Adapted from decode_line_2 in symtab.c, with which it ought + to be re-integrated one of these days. */ + +int +user_select_syms (struct symbol *syms[], struct block *blocks[], int nsyms, + int max_results) +{ + int i; + int *chosen = (int *) alloca (sizeof (int) * nsyms); + int n_chosen; + int first_choice = (max_results == 1) ? 1 : 2; + + if (max_results < 1) + error ("Request to select 0 symbols!"); + if (nsyms <= 1) + return nsyms; + + printf_unfiltered ("[0] cancel\n"); + if (max_results > 1) + printf_unfiltered ("[1] all\n"); + + sort_choices (syms, blocks, nsyms); + + for (i = 0; i < nsyms; i += 1) + { + if (syms[i] == NULL) + continue; + + if (SYMBOL_CLASS (syms[i]) == LOC_BLOCK) + { + struct symtab_and_line sal = find_function_start_sal (syms[i], 1); + printf_unfiltered ("[%d] %s at %s:%d\n", + i + first_choice, + SYMBOL_SOURCE_NAME (syms[i]), + sal.symtab == NULL + ? "<no source file available>" + : sal.symtab->filename, sal.line); + continue; + } + else + { + int is_enumeral = + (SYMBOL_CLASS (syms[i]) == LOC_CONST + && SYMBOL_TYPE (syms[i]) != NULL + && TYPE_CODE (SYMBOL_TYPE (syms[i])) == TYPE_CODE_ENUM); + struct symtab *symtab = symtab_for_sym (syms[i]); + + if (SYMBOL_LINE (syms[i]) != 0 && symtab != NULL) + printf_unfiltered ("[%d] %s at %s:%d\n", + i + first_choice, + SYMBOL_SOURCE_NAME (syms[i]), + symtab->filename, SYMBOL_LINE (syms[i])); + else if (is_enumeral && TYPE_NAME (SYMBOL_TYPE (syms[i])) != NULL) + { + printf_unfiltered ("[%d] ", i + first_choice); + ada_print_type (SYMBOL_TYPE (syms[i]), NULL, gdb_stdout, -1, 0); + printf_unfiltered ("'(%s) (enumeral)\n", + SYMBOL_SOURCE_NAME (syms[i])); + } + else if (symtab != NULL) + printf_unfiltered (is_enumeral + ? "[%d] %s in %s (enumeral)\n" + : "[%d] %s at %s:?\n", + i + first_choice, + SYMBOL_SOURCE_NAME (syms[i]), + symtab->filename); + else + printf_unfiltered (is_enumeral + ? "[%d] %s (enumeral)\n" + : "[%d] %s at ?\n", + i + first_choice, + SYMBOL_SOURCE_NAME (syms[i])); + } + } + + n_chosen = get_selections (chosen, nsyms, max_results, max_results > 1, + "overload-choice"); + + for (i = 0; i < n_chosen; i += 1) + { + syms[i] = syms[chosen[i]]; + if (blocks != NULL) + blocks[i] = blocks[chosen[i]]; + } + + return n_chosen; +} + +/* Read and validate a set of numeric choices from the user in the + range 0 .. N_CHOICES-1. Place the results in increasing + order in CHOICES[0 .. N-1], and return N. + + The user types choices as a sequence of numbers on one line + separated by blanks, encoding them as follows: + + + A choice of 0 means to cancel the selection, throwing an error. + + If IS_ALL_CHOICE, a choice of 1 selects the entire set 0 .. N_CHOICES-1. + + The user chooses k by typing k+IS_ALL_CHOICE+1. + + The user is not allowed to choose more than MAX_RESULTS values. + + ANNOTATION_SUFFIX, if present, is used to annotate the input + prompts (for use with the -f switch). */ + +int +get_selections (int *choices, int n_choices, int max_results, + int is_all_choice, char *annotation_suffix) +{ + int i; + char *args; + const char *prompt; + int n_chosen; + int first_choice = is_all_choice ? 2 : 1; + + prompt = getenv ("PS2"); + if (prompt == NULL) + prompt = ">"; + + printf_unfiltered ("%s ", prompt); + gdb_flush (gdb_stdout); + + args = command_line_input ((char *) NULL, 0, annotation_suffix); + + if (args == NULL) + error_no_arg ("one or more choice numbers"); + + n_chosen = 0; + + /* Set choices[0 .. n_chosen-1] to the users' choices in ascending + order, as given in args. Choices are validated. */ + while (1) + { + char *args2; + int choice, j; + + while (isspace (*args)) + args += 1; + if (*args == '\0' && n_chosen == 0) + error_no_arg ("one or more choice numbers"); + else if (*args == '\0') + break; + + choice = strtol (args, &args2, 10); + if (args == args2 || choice < 0 + || choice > n_choices + first_choice - 1) + error ("Argument must be choice number"); + args = args2; + + if (choice == 0) + error ("cancelled"); + + if (choice < first_choice) + { + n_chosen = n_choices; + for (j = 0; j < n_choices; j += 1) + choices[j] = j; + break; + } + choice -= first_choice; + + for (j = n_chosen - 1; j >= 0 && choice < choices[j]; j -= 1) + { + } + + if (j < 0 || choice != choices[j]) + { + int k; + for (k = n_chosen - 1; k > j; k -= 1) + choices[k + 1] = choices[k]; + choices[j + 1] = choice; + n_chosen += 1; + } + } + + if (n_chosen > max_results) + error ("Select no more than %d of the above", max_results); + + return n_chosen; +} + +/* Replace the operator of length OPLEN at position PC in *EXPP with a call */ +/* on the function identified by SYM and BLOCK, and taking NARGS */ +/* arguments. Update *EXPP as needed to hold more space. */ + +static void +replace_operator_with_call (struct expression **expp, int pc, int nargs, + int oplen, struct symbol *sym, + struct block *block) +{ + /* A new expression, with 6 more elements (3 for funcall, 4 for function + symbol, -oplen for operator being replaced). */ + struct expression *newexp = (struct expression *) + xmalloc (sizeof (struct expression) + + EXP_ELEM_TO_BYTES ((*expp)->nelts + 7 - oplen)); + struct expression *exp = *expp; + + newexp->nelts = exp->nelts + 7 - oplen; + newexp->language_defn = exp->language_defn; + memcpy (newexp->elts, exp->elts, EXP_ELEM_TO_BYTES (pc)); + memcpy (newexp->elts + pc + 7, exp->elts + pc + oplen, + EXP_ELEM_TO_BYTES (exp->nelts - pc - oplen)); + + newexp->elts[pc].opcode = newexp->elts[pc + 2].opcode = OP_FUNCALL; + newexp->elts[pc + 1].longconst = (LONGEST) nargs; + + newexp->elts[pc + 3].opcode = newexp->elts[pc + 6].opcode = OP_VAR_VALUE; + newexp->elts[pc + 4].block = block; + newexp->elts[pc + 5].symbol = sym; + + *expp = newexp; + xfree (exp); +} + +/* Type-class predicates */ + +/* True iff TYPE is numeric (i.e., an INT, RANGE (of numeric type), or */ +/* FLOAT.) */ + +static int +numeric_type_p (struct type *type) +{ + if (type == NULL) + return 0; + else + { + switch (TYPE_CODE (type)) + { + case TYPE_CODE_INT: + case TYPE_CODE_FLT: + return 1; + case TYPE_CODE_RANGE: + return (type == TYPE_TARGET_TYPE (type) + || numeric_type_p (TYPE_TARGET_TYPE (type))); + default: + return 0; + } + } +} + +/* True iff TYPE is integral (an INT or RANGE of INTs). */ + +static int +integer_type_p (struct type *type) +{ + if (type == NULL) + return 0; + else + { + switch (TYPE_CODE (type)) + { + case TYPE_CODE_INT: + return 1; + case TYPE_CODE_RANGE: + return (type == TYPE_TARGET_TYPE (type) + || integer_type_p (TYPE_TARGET_TYPE (type))); + default: + return 0; + } + } +} + +/* True iff TYPE is scalar (INT, RANGE, FLOAT, ENUM). */ + +static int +scalar_type_p (struct type *type) +{ + if (type == NULL) + return 0; + else + { + switch (TYPE_CODE (type)) + { + case TYPE_CODE_INT: + case TYPE_CODE_RANGE: + case TYPE_CODE_ENUM: + case TYPE_CODE_FLT: + return 1; + default: + return 0; + } + } +} + +/* True iff TYPE is discrete (INT, RANGE, ENUM). */ + +static int +discrete_type_p (struct type *type) +{ + if (type == NULL) + return 0; + else + { + switch (TYPE_CODE (type)) + { + case TYPE_CODE_INT: + case TYPE_CODE_RANGE: + case TYPE_CODE_ENUM: + return 1; + default: + return 0; + } + } +} + +/* Returns non-zero if OP with operatands in the vector ARGS could be + a user-defined function. Errs on the side of pre-defined operators + (i.e., result 0). */ + +static int +possible_user_operator_p (enum exp_opcode op, struct value *args[]) +{ + struct type *type0 = check_typedef (VALUE_TYPE (args[0])); + struct type *type1 = + (args[1] == NULL) ? NULL : check_typedef (VALUE_TYPE (args[1])); + + switch (op) + { + default: + return 0; + + case BINOP_ADD: + case BINOP_SUB: + case BINOP_MUL: + case BINOP_DIV: + return (!(numeric_type_p (type0) && numeric_type_p (type1))); + + case BINOP_REM: + case BINOP_MOD: + case BINOP_BITWISE_AND: + case BINOP_BITWISE_IOR: + case BINOP_BITWISE_XOR: + return (!(integer_type_p (type0) && integer_type_p (type1))); + + case BINOP_EQUAL: + case BINOP_NOTEQUAL: + case BINOP_LESS: + case BINOP_GTR: + case BINOP_LEQ: + case BINOP_GEQ: + return (!(scalar_type_p (type0) && scalar_type_p (type1))); + + case BINOP_CONCAT: + return ((TYPE_CODE (type0) != TYPE_CODE_ARRAY && + (TYPE_CODE (type0) != TYPE_CODE_PTR || + TYPE_CODE (TYPE_TARGET_TYPE (type0)) + != TYPE_CODE_ARRAY)) + || (TYPE_CODE (type1) != TYPE_CODE_ARRAY && + (TYPE_CODE (type1) != TYPE_CODE_PTR || + TYPE_CODE (TYPE_TARGET_TYPE (type1)) != TYPE_CODE_ARRAY))); + + case BINOP_EXP: + return (!(numeric_type_p (type0) && integer_type_p (type1))); + + case UNOP_NEG: + case UNOP_PLUS: + case UNOP_LOGICAL_NOT: + case UNOP_ABS: + return (!numeric_type_p (type0)); + + } +} + + /* Renaming */ + +/** NOTE: In the following, we assume that a renaming type's name may + * have an ___XD suffix. It would be nice if this went away at some + * point. */ + +/* If TYPE encodes a renaming, returns the renaming suffix, which + * is XR for an object renaming, XRP for a procedure renaming, XRE for + * an exception renaming, and XRS for a subprogram renaming. Returns + * NULL if NAME encodes none of these. */ +const char * +ada_renaming_type (struct type *type) +{ + if (type != NULL && TYPE_CODE (type) == TYPE_CODE_ENUM) + { + const char *name = type_name_no_tag (type); + const char *suffix = (name == NULL) ? NULL : strstr (name, "___XR"); + if (suffix == NULL + || (suffix[5] != '\000' && strchr ("PES_", suffix[5]) == NULL)) + return NULL; + else + return suffix + 3; + } + else + return NULL; +} + +/* Return non-zero iff SYM encodes an object renaming. */ +int +ada_is_object_renaming (struct symbol *sym) +{ + const char *renaming_type = ada_renaming_type (SYMBOL_TYPE (sym)); + return renaming_type != NULL + && (renaming_type[2] == '\0' || renaming_type[2] == '_'); +} + +/* Assuming that SYM encodes a non-object renaming, returns the original + * name of the renamed entity. The name is good until the end of + * parsing. */ +const char * +ada_simple_renamed_entity (struct symbol *sym) +{ + struct type *type; + const char *raw_name; + int len; + char *result; + + type = SYMBOL_TYPE (sym); + if (type == NULL || TYPE_NFIELDS (type) < 1) + error ("Improperly encoded renaming."); + + raw_name = TYPE_FIELD_NAME (type, 0); + len = (raw_name == NULL ? 0 : strlen (raw_name)) - 5; + if (len <= 0) + error ("Improperly encoded renaming."); + + result = xmalloc (len + 1); + /* FIXME: add_name_string_cleanup should be defined in parse.c */ + /* add_name_string_cleanup (result); */ + strncpy (result, raw_name, len); + result[len] = '\000'; + return result; +} + + + /* Evaluation: Function Calls */ + +/* Copy VAL onto the stack, using and updating *SP as the stack + pointer. Return VAL as an lvalue. */ + +static struct value * +place_on_stack (struct value *val, CORE_ADDR *sp) +{ + CORE_ADDR old_sp = *sp; + +#ifdef STACK_ALIGN + *sp = push_bytes (*sp, VALUE_CONTENTS_RAW (val), + STACK_ALIGN (TYPE_LENGTH + (check_typedef (VALUE_TYPE (val))))); +#else + *sp = push_bytes (*sp, VALUE_CONTENTS_RAW (val), + TYPE_LENGTH (check_typedef (VALUE_TYPE (val)))); +#endif + + VALUE_LVAL (val) = lval_memory; + if (INNER_THAN (1, 2)) + VALUE_ADDRESS (val) = *sp; + else + VALUE_ADDRESS (val) = old_sp; + + return val; +} + +/* Return the value ACTUAL, converted to be an appropriate value for a + formal of type FORMAL_TYPE. Use *SP as a stack pointer for + allocating any necessary descriptors (fat pointers), or copies of + values not residing in memory, updating it as needed. */ + +static struct value * +convert_actual (struct value *actual, struct type *formal_type0, + CORE_ADDR *sp) +{ + struct type *actual_type = check_typedef (VALUE_TYPE (actual)); + struct type *formal_type = check_typedef (formal_type0); + struct type *formal_target = + TYPE_CODE (formal_type) == TYPE_CODE_PTR + ? check_typedef (TYPE_TARGET_TYPE (formal_type)) : formal_type; + struct type *actual_target = + TYPE_CODE (actual_type) == TYPE_CODE_PTR + ? check_typedef (TYPE_TARGET_TYPE (actual_type)) : actual_type; + + if (ada_is_array_descriptor (formal_target) + && TYPE_CODE (actual_target) == TYPE_CODE_ARRAY) + return make_array_descriptor (formal_type, actual, sp); + else if (TYPE_CODE (formal_type) == TYPE_CODE_PTR) + { + if (TYPE_CODE (formal_target) == TYPE_CODE_ARRAY + && ada_is_array_descriptor (actual_target)) + return desc_data (actual); + else if (TYPE_CODE (actual_type) != TYPE_CODE_PTR) + { + if (VALUE_LVAL (actual) != lval_memory) + { + struct value *val; + actual_type = check_typedef (VALUE_TYPE (actual)); + val = allocate_value (actual_type); + memcpy ((char *) VALUE_CONTENTS_RAW (val), + (char *) VALUE_CONTENTS (actual), + TYPE_LENGTH (actual_type)); + actual = place_on_stack (val, sp); + } + return value_addr (actual); + } + } + else if (TYPE_CODE (actual_type) == TYPE_CODE_PTR) + return ada_value_ind (actual); + + return actual; +} + + +/* Push a descriptor of type TYPE for array value ARR on the stack at + *SP, updating *SP to reflect the new descriptor. Return either + an lvalue representing the new descriptor, or (if TYPE is a pointer- + to-descriptor type rather than a descriptor type), a struct value* + representing a pointer to this descriptor. */ + +static struct value * +make_array_descriptor (struct type *type, struct value *arr, CORE_ADDR *sp) +{ + struct type *bounds_type = desc_bounds_type (type); + struct type *desc_type = desc_base_type (type); + struct value *descriptor = allocate_value (desc_type); + struct value *bounds = allocate_value (bounds_type); + CORE_ADDR bounds_addr; + int i; + + for (i = ada_array_arity (check_typedef (VALUE_TYPE (arr))); i > 0; i -= 1) + { + modify_general_field (VALUE_CONTENTS (bounds), + value_as_long (ada_array_bound (arr, i, 0)), + desc_bound_bitpos (bounds_type, i, 0), + desc_bound_bitsize (bounds_type, i, 0)); + modify_general_field (VALUE_CONTENTS (bounds), + value_as_long (ada_array_bound (arr, i, 1)), + desc_bound_bitpos (bounds_type, i, 1), + desc_bound_bitsize (bounds_type, i, 1)); + } + + bounds = place_on_stack (bounds, sp); + + modify_general_field (VALUE_CONTENTS (descriptor), + arr, + fat_pntr_data_bitpos (desc_type), + fat_pntr_data_bitsize (desc_type)); + modify_general_field (VALUE_CONTENTS (descriptor), + VALUE_ADDRESS (bounds), + fat_pntr_bounds_bitpos (desc_type), + fat_pntr_bounds_bitsize (desc_type)); + + descriptor = place_on_stack (descriptor, sp); + + if (TYPE_CODE (type) == TYPE_CODE_PTR) + return value_addr (descriptor); + else + return descriptor; +} + + +/* Assuming a dummy frame has been established on the target, perform any + conversions needed for calling function FUNC on the NARGS actual + parameters in ARGS, other than standard C conversions. Does + nothing if FUNC does not have Ada-style prototype data, or if NARGS + does not match the number of arguments expected. Use *SP as a + stack pointer for additional data that must be pushed, updating its + value as needed. */ + +void +ada_convert_actuals (struct value *func, int nargs, struct value *args[], + CORE_ADDR *sp) +{ + int i; + + if (TYPE_NFIELDS (VALUE_TYPE (func)) == 0 + || nargs != TYPE_NFIELDS (VALUE_TYPE (func))) + return; + + for (i = 0; i < nargs; i += 1) + args[i] = + convert_actual (args[i], TYPE_FIELD_TYPE (VALUE_TYPE (func), i), sp); +} + + + /* Symbol Lookup */ + + +/* The vectors of symbols and blocks ultimately returned from */ +/* ada_lookup_symbol_list. */ + +/* Current size of defn_symbols and defn_blocks */ +static size_t defn_vector_size = 0; + +/* Current number of symbols found. */ +static int ndefns = 0; + +static struct symbol **defn_symbols = NULL; +static struct block **defn_blocks = NULL; + +/* Return the result of a standard (literal, C-like) lookup of NAME in + * given NAMESPACE. */ + +static struct symbol * +standard_lookup (const char *name, namespace_enum namespace) +{ + struct symbol *sym; + struct symtab *symtab; + sym = lookup_symbol (name, (struct block *) NULL, namespace, 0, &symtab); + return sym; +} + + +/* Non-zero iff there is at least one non-function/non-enumeral symbol */ +/* in SYMS[0..N-1]. We treat enumerals as functions, since they */ +/* contend in overloading in the same way. */ +static int +is_nonfunction (struct symbol *syms[], int n) +{ + int i; + + for (i = 0; i < n; i += 1) + if (TYPE_CODE (SYMBOL_TYPE (syms[i])) != TYPE_CODE_FUNC + && TYPE_CODE (SYMBOL_TYPE (syms[i])) != TYPE_CODE_ENUM) + return 1; + + return 0; +} + +/* If true (non-zero), then TYPE0 and TYPE1 represent equivalent + struct types. Otherwise, they may not. */ + +static int +equiv_types (struct type *type0, struct type *type1) +{ + if (type0 == type1) + return 1; + if (type0 == NULL || type1 == NULL + || TYPE_CODE (type0) != TYPE_CODE (type1)) + return 0; + if ((TYPE_CODE (type0) == TYPE_CODE_STRUCT + || TYPE_CODE (type0) == TYPE_CODE_ENUM) + && ada_type_name (type0) != NULL && ada_type_name (type1) != NULL + && STREQ (ada_type_name (type0), ada_type_name (type1))) + return 1; + + return 0; +} + +/* True iff SYM0 represents the same entity as SYM1, or one that is + no more defined than that of SYM1. */ + +static int +lesseq_defined_than (struct symbol *sym0, struct symbol *sym1) +{ + if (sym0 == sym1) + return 1; + if (SYMBOL_NAMESPACE (sym0) != SYMBOL_NAMESPACE (sym1) + || SYMBOL_CLASS (sym0) != SYMBOL_CLASS (sym1)) + return 0; + + switch (SYMBOL_CLASS (sym0)) + { + case LOC_UNDEF: + return 1; + case LOC_TYPEDEF: + { + struct type *type0 = SYMBOL_TYPE (sym0); + struct type *type1 = SYMBOL_TYPE (sym1); + char *name0 = SYMBOL_NAME (sym0); + char *name1 = SYMBOL_NAME (sym1); + int len0 = strlen (name0); + return + TYPE_CODE (type0) == TYPE_CODE (type1) + && (equiv_types (type0, type1) + || (len0 < strlen (name1) && STREQN (name0, name1, len0) + && STREQN (name1 + len0, "___XV", 5))); + } + case LOC_CONST: + return SYMBOL_VALUE (sym0) == SYMBOL_VALUE (sym1) + && equiv_types (SYMBOL_TYPE (sym0), SYMBOL_TYPE (sym1)); + default: + return 0; + } +} + +/* Append SYM to the end of defn_symbols, and BLOCK to the end of + defn_blocks, updating ndefns, and expanding defn_symbols and + defn_blocks as needed. Do not include SYM if it is a duplicate. */ + +static void +add_defn_to_vec (struct symbol *sym, struct block *block) +{ + int i; + size_t tmp; + + if (SYMBOL_TYPE (sym) != NULL) + CHECK_TYPEDEF (SYMBOL_TYPE (sym)); + for (i = 0; i < ndefns; i += 1) + { + if (lesseq_defined_than (sym, defn_symbols[i])) + return; + else if (lesseq_defined_than (defn_symbols[i], sym)) + { + defn_symbols[i] = sym; + defn_blocks[i] = block; + return; + } + } + + tmp = defn_vector_size; + GROW_VECT (defn_symbols, tmp, ndefns + 2); + GROW_VECT (defn_blocks, defn_vector_size, ndefns + 2); + + defn_symbols[ndefns] = sym; + defn_blocks[ndefns] = block; + ndefns += 1; +} + +/* Look, in partial_symtab PST, for symbol NAME in given namespace. + Check the global symbols if GLOBAL, the static symbols if not. Do + wild-card match if WILD. */ + +static struct partial_symbol * +ada_lookup_partial_symbol (struct partial_symtab *pst, const char *name, + int global, namespace_enum namespace, int wild) +{ + struct partial_symbol **start; + int name_len = strlen (name); + int length = (global ? pst->n_global_syms : pst->n_static_syms); + int i; + + if (length == 0) + { + return (NULL); + } + + start = (global ? + pst->objfile->global_psymbols.list + pst->globals_offset : + pst->objfile->static_psymbols.list + pst->statics_offset); + + if (wild) + { + for (i = 0; i < length; i += 1) + { + struct partial_symbol *psym = start[i]; + + if (SYMBOL_NAMESPACE (psym) == namespace && + wild_match (name, name_len, SYMBOL_NAME (psym))) + return psym; + } + return NULL; + } + else + { + if (global) + { + int U; + i = 0; + U = length - 1; + while (U - i > 4) + { + int M = (U + i) >> 1; + struct partial_symbol *psym = start[M]; + if (SYMBOL_NAME (psym)[0] < name[0]) + i = M + 1; + else if (SYMBOL_NAME (psym)[0] > name[0]) + U = M - 1; + else if (strcmp (SYMBOL_NAME (psym), name) < 0) + i = M + 1; + else + U = M; + } + } + else + i = 0; + + while (i < length) + { + struct partial_symbol *psym = start[i]; + + if (SYMBOL_NAMESPACE (psym) == namespace) + { + int cmp = strncmp (name, SYMBOL_NAME (psym), name_len); + + if (cmp < 0) + { + if (global) + break; + } + else if (cmp == 0 + && is_name_suffix (SYMBOL_NAME (psym) + name_len)) + return psym; + } + i += 1; + } + + if (global) + { + int U; + i = 0; + U = length - 1; + while (U - i > 4) + { + int M = (U + i) >> 1; + struct partial_symbol *psym = start[M]; + if (SYMBOL_NAME (psym)[0] < '_') + i = M + 1; + else if (SYMBOL_NAME (psym)[0] > '_') + U = M - 1; + else if (strcmp (SYMBOL_NAME (psym), "_ada_") < 0) + i = M + 1; + else + U = M; + } + } + else + i = 0; + + while (i < length) + { + struct partial_symbol *psym = start[i]; + + if (SYMBOL_NAMESPACE (psym) == namespace) + { + int cmp; + + cmp = (int) '_' - (int) SYMBOL_NAME (psym)[0]; + if (cmp == 0) + { + cmp = strncmp ("_ada_", SYMBOL_NAME (psym), 5); + if (cmp == 0) + cmp = strncmp (name, SYMBOL_NAME (psym) + 5, name_len); + } + + if (cmp < 0) + { + if (global) + break; + } + else if (cmp == 0 + && is_name_suffix (SYMBOL_NAME (psym) + name_len + 5)) + return psym; + } + i += 1; + } + + } + return NULL; +} + + +/* Find a symbol table containing symbol SYM or NULL if none. */ +static struct symtab * +symtab_for_sym (struct symbol *sym) +{ + struct symtab *s; + struct objfile *objfile; + struct block *b; + struct symbol *tmp_sym; + int i, j; + + ALL_SYMTABS (objfile, s) + { + switch (SYMBOL_CLASS (sym)) + { + case LOC_CONST: + case LOC_STATIC: + case LOC_TYPEDEF: + case LOC_REGISTER: + case LOC_LABEL: + case LOC_BLOCK: + case LOC_CONST_BYTES: + b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK); + ALL_BLOCK_SYMBOLS (b, i, tmp_sym) if (sym == tmp_sym) + return s; + b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK); + ALL_BLOCK_SYMBOLS (b, i, tmp_sym) if (sym == tmp_sym) + return s; + break; + default: + break; + } + switch (SYMBOL_CLASS (sym)) + { + case LOC_REGISTER: + case LOC_ARG: + case LOC_REF_ARG: + case LOC_REGPARM: + case LOC_REGPARM_ADDR: + case LOC_LOCAL: + case LOC_TYPEDEF: + case LOC_LOCAL_ARG: + case LOC_BASEREG: + case LOC_BASEREG_ARG: + for (j = FIRST_LOCAL_BLOCK; + j < BLOCKVECTOR_NBLOCKS (BLOCKVECTOR (s)); j += 1) + { + b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), j); + ALL_BLOCK_SYMBOLS (b, i, tmp_sym) if (sym == tmp_sym) + return s; + } + break; + default: + break; + } + } + return NULL; +} + +/* Return a minimal symbol matching NAME according to Ada demangling + rules. Returns NULL if there is no such minimal symbol. */ + +struct minimal_symbol * +ada_lookup_minimal_symbol (const char *name) +{ + struct objfile *objfile; + struct minimal_symbol *msymbol; + int wild_match = (strstr (name, "__") == NULL); + + ALL_MSYMBOLS (objfile, msymbol) + { + if (ada_match_name (SYMBOL_NAME (msymbol), name, wild_match) + && MSYMBOL_TYPE (msymbol) != mst_solib_trampoline) + return msymbol; + } + + return NULL; +} + +/* For all subprograms that statically enclose the subprogram of the + * selected frame, add symbols matching identifier NAME in NAMESPACE + * and their blocks to vectors *defn_symbols and *defn_blocks, as for + * ada_add_block_symbols (q.v.). If WILD, treat as NAME with a + * wildcard prefix. At the moment, this function uses a heuristic to + * find the frames of enclosing subprograms: it treats the + * pointer-sized value at location 0 from the local-variable base of a + * frame as a static link, and then searches up the call stack for a + * frame with that same local-variable base. */ +static void +add_symbols_from_enclosing_procs (const char *name, namespace_enum namespace, + int wild_match) +{ +#ifdef i386 + static struct symbol static_link_sym; + static struct symbol *static_link; + + struct cleanup *old_chain = make_cleanup (null_cleanup, NULL); + struct frame_info *frame; + struct frame_info *target_frame; + + if (static_link == NULL) + { + /* Initialize the local variable symbol that stands for the + * static link (when it exists). */ + static_link = &static_link_sym; + SYMBOL_NAME (static_link) = ""; + SYMBOL_LANGUAGE (static_link) = language_unknown; + SYMBOL_CLASS (static_link) = LOC_LOCAL; + SYMBOL_NAMESPACE (static_link) = VAR_NAMESPACE; + SYMBOL_TYPE (static_link) = lookup_pointer_type (builtin_type_void); + SYMBOL_VALUE (static_link) = + -(long) TYPE_LENGTH (SYMBOL_TYPE (static_link)); + } + + frame = selected_frame; + while (frame != NULL && ndefns == 0) + { + struct block *block; + struct value *target_link_val = read_var_value (static_link, frame); + CORE_ADDR target_link; + + if (target_link_val == NULL) + break; + QUIT; + + target_link = target_link_val; + do + { + QUIT; + frame = get_prev_frame (frame); + } + while (frame != NULL && FRAME_LOCALS_ADDRESS (frame) != target_link); + + if (frame == NULL) + break; + + block = get_frame_block (frame, 0); + while (block != NULL && block_function (block) != NULL && ndefns == 0) + { + ada_add_block_symbols (block, name, namespace, NULL, wild_match); + + block = BLOCK_SUPERBLOCK (block); + } + } + + do_cleanups (old_chain); +#endif +} + +/* True if TYPE is definitely an artificial type supplied to a symbol + * for which no debugging information was given in the symbol file. */ +static int +is_nondebugging_type (struct type *type) +{ + char *name = ada_type_name (type); + return (name != NULL && STREQ (name, "<variable, no debug info>")); +} + +/* Remove any non-debugging symbols in SYMS[0 .. NSYMS-1] that definitely + * duplicate other symbols in the list. (The only case I know of where + * this happens is when object files containing stabs-in-ecoff are + * linked with files containing ordinary ecoff debugging symbols (or no + * debugging symbols)). Modifies SYMS to squeeze out deleted symbols, + * and applies the same modification to BLOCKS to maintain the + * correspondence between SYMS[i] and BLOCKS[i]. Returns the number + * of symbols in the modified list. */ +static int +remove_extra_symbols (struct symbol **syms, struct block **blocks, int nsyms) +{ + int i, j; + + i = 0; + while (i < nsyms) + { + if (SYMBOL_NAME (syms[i]) != NULL + && SYMBOL_CLASS (syms[i]) == LOC_STATIC + && is_nondebugging_type (SYMBOL_TYPE (syms[i]))) + { + for (j = 0; j < nsyms; j += 1) + { + if (i != j + && SYMBOL_NAME (syms[j]) != NULL + && STREQ (SYMBOL_NAME (syms[i]), SYMBOL_NAME (syms[j])) + && SYMBOL_CLASS (syms[i]) == SYMBOL_CLASS (syms[j]) + && SYMBOL_VALUE_ADDRESS (syms[i]) + == SYMBOL_VALUE_ADDRESS (syms[j])) + { + int k; + for (k = i + 1; k < nsyms; k += 1) + { + syms[k - 1] = syms[k]; + blocks[k - 1] = blocks[k]; + } + nsyms -= 1; + goto NextSymbol; + } + } + } + i += 1; + NextSymbol: + ; + } + return nsyms; +} + +/* Find symbols in NAMESPACE matching NAME, in BLOCK0 and enclosing + scope and in global scopes, returning the number of matches. Sets + *SYMS to point to a vector of matching symbols, with *BLOCKS + pointing to the vector of corresponding blocks in which those + symbols reside. These two vectors are transient---good only to the + next call of ada_lookup_symbol_list. Any non-function/non-enumeral symbol + match within the nest of blocks whose innermost member is BLOCK0, + is the outermost match returned (no other matches in that or + enclosing blocks is returned). If there are any matches in or + surrounding BLOCK0, then these alone are returned. */ + +int +ada_lookup_symbol_list (const char *name, struct block *block0, + namespace_enum namespace, struct symbol ***syms, + struct block ***blocks) +{ + struct symbol *sym; + struct symtab *s; + struct partial_symtab *ps; + struct blockvector *bv; + struct objfile *objfile; + struct block *b; + struct block *block; + struct minimal_symbol *msymbol; + int wild_match = (strstr (name, "__") == NULL); + int cacheIfUnique; + +#ifdef TIMING + markTimeStart (0); +#endif + + ndefns = 0; + cacheIfUnique = 0; + + /* Search specified block and its superiors. */ + + block = block0; + while (block != NULL) + { + ada_add_block_symbols (block, name, namespace, NULL, wild_match); + + /* If we found a non-function match, assume that's the one. */ + if (is_nonfunction (defn_symbols, ndefns)) + goto done; + + block = BLOCK_SUPERBLOCK (block); + } + + /* If we found ANY matches in the specified BLOCK, we're done. */ + + if (ndefns > 0) + goto done; + + cacheIfUnique = 1; + + /* Now add symbols from all global blocks: symbol tables, minimal symbol + tables, and psymtab's */ + + ALL_SYMTABS (objfile, s) + { + QUIT; + if (!s->primary) + continue; + bv = BLOCKVECTOR (s); + block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK); + ada_add_block_symbols (block, name, namespace, objfile, wild_match); + } + + if (namespace == VAR_NAMESPACE) + { + ALL_MSYMBOLS (objfile, msymbol) + { + if (ada_match_name (SYMBOL_NAME (msymbol), name, wild_match)) + { + switch (MSYMBOL_TYPE (msymbol)) + { + case mst_solib_trampoline: + break; + default: + s = find_pc_symtab (SYMBOL_VALUE_ADDRESS (msymbol)); + if (s != NULL) + { + int old_ndefns = ndefns; + QUIT; + bv = BLOCKVECTOR (s); + block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK); + ada_add_block_symbols (block, + SYMBOL_NAME (msymbol), + namespace, objfile, wild_match); + if (ndefns == old_ndefns) + { + block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK); + ada_add_block_symbols (block, + SYMBOL_NAME (msymbol), + namespace, objfile, + wild_match); + } + } + } + } + } + } + + ALL_PSYMTABS (objfile, ps) + { + QUIT; + if (!ps->readin + && ada_lookup_partial_symbol (ps, name, 1, namespace, wild_match)) + { + s = PSYMTAB_TO_SYMTAB (ps); + if (!s->primary) + continue; + bv = BLOCKVECTOR (s); + block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK); + ada_add_block_symbols (block, name, namespace, objfile, wild_match); + } + } + + /* Now add symbols from all per-file blocks if we've gotten no hits. + (Not strictly correct, but perhaps better than an error). + Do the symtabs first, then check the psymtabs */ + + if (ndefns == 0) + { + + ALL_SYMTABS (objfile, s) + { + QUIT; + if (!s->primary) + continue; + bv = BLOCKVECTOR (s); + block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK); + ada_add_block_symbols (block, name, namespace, objfile, wild_match); + } + + ALL_PSYMTABS (objfile, ps) + { + QUIT; + if (!ps->readin + && ada_lookup_partial_symbol (ps, name, 0, namespace, wild_match)) + { + s = PSYMTAB_TO_SYMTAB (ps); + bv = BLOCKVECTOR (s); + if (!s->primary) + continue; + block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK); + ada_add_block_symbols (block, name, namespace, + objfile, wild_match); + } + } + } + + /* Finally, we try to find NAME as a local symbol in some lexically + enclosing block. We do this last, expecting this case to be + rare. */ + if (ndefns == 0) + { + add_symbols_from_enclosing_procs (name, namespace, wild_match); + if (ndefns > 0) + goto done; + } + +done: + ndefns = remove_extra_symbols (defn_symbols, defn_blocks, ndefns); + + + *syms = defn_symbols; + *blocks = defn_blocks; +#ifdef TIMING + markTimeStop (0); +#endif + return ndefns; +} + +/* Return a symbol in NAMESPACE matching NAME, in BLOCK0 and enclosing + * scope and in global scopes, or NULL if none. NAME is folded to + * lower case first, unless it is surrounded in single quotes. + * Otherwise, the result is as for ada_lookup_symbol_list, but is + * disambiguated by user query if needed. */ + +struct symbol * +ada_lookup_symbol (const char *name, struct block *block0, + namespace_enum namespace) +{ + struct symbol **candidate_syms; + struct block **candidate_blocks; + int n_candidates; + + n_candidates = ada_lookup_symbol_list (name, + block0, namespace, + &candidate_syms, &candidate_blocks); + + if (n_candidates == 0) + return NULL; + else if (n_candidates != 1) + user_select_syms (candidate_syms, candidate_blocks, n_candidates, 1); + + return candidate_syms[0]; +} + + +/* True iff STR is a possible encoded suffix of a normal Ada name + * that is to be ignored for matching purposes. Suffixes of parallel + * names (e.g., XVE) are not included here. Currently, the possible suffixes + * are given by the regular expression: + * (X[nb]*)?(__[0-9]+|\$[0-9]+|___(LJM|X([FDBUP].*|R[^T]?)))?$ + * + */ +static int +is_name_suffix (const char *str) +{ + int k; + if (str[0] == 'X') + { + str += 1; + while (str[0] != '_' && str[0] != '\0') + { + if (str[0] != 'n' && str[0] != 'b') + return 0; + str += 1; + } + } + if (str[0] == '\000') + return 1; + if (str[0] == '_') + { + if (str[1] != '_' || str[2] == '\000') + return 0; + if (str[2] == '_') + { + if (STREQ (str + 3, "LJM")) + return 1; + if (str[3] != 'X') + return 0; + if (str[4] == 'F' || str[4] == 'D' || str[4] == 'B' || + str[4] == 'U' || str[4] == 'P') + return 1; + if (str[4] == 'R' && str[5] != 'T') + return 1; + return 0; + } + for (k = 2; str[k] != '\0'; k += 1) + if (!isdigit (str[k])) + return 0; + return 1; + } + if (str[0] == '$' && str[1] != '\000') + { + for (k = 1; str[k] != '\0'; k += 1) + if (!isdigit (str[k])) + return 0; + return 1; + } + return 0; +} + +/* True if NAME represents a name of the form A1.A2....An, n>=1 and + * PATN[0..PATN_LEN-1] = Ak.Ak+1.....An for some k >= 1. Ignores + * informational suffixes of NAME (i.e., for which is_name_suffix is + * true). */ +static int +wild_match (const char *patn, int patn_len, const char *name) +{ + int name_len; + int s, e; + + name_len = strlen (name); + if (name_len >= patn_len + 5 && STREQN (name, "_ada_", 5) + && STREQN (patn, name + 5, patn_len) + && is_name_suffix (name + patn_len + 5)) + return 1; + + while (name_len >= patn_len) + { + if (STREQN (patn, name, patn_len) && is_name_suffix (name + patn_len)) + return 1; + do + { + name += 1; + name_len -= 1; + } + while (name_len > 0 + && name[0] != '.' && (name[0] != '_' || name[1] != '_')); + if (name_len <= 0) + return 0; + if (name[0] == '_') + { + if (!islower (name[2])) + return 0; + name += 2; + name_len -= 2; + } + else + { + if (!islower (name[1])) + return 0; + name += 1; + name_len -= 1; + } + } + + return 0; +} + + +/* Add symbols from BLOCK matching identifier NAME in NAMESPACE to + vector *defn_symbols, updating *defn_symbols (if necessary), *SZ (the size of + the vector *defn_symbols), and *ndefns (the number of symbols + currently stored in *defn_symbols). If WILD, treat as NAME with a + wildcard prefix. OBJFILE is the section containing BLOCK. */ + +static void +ada_add_block_symbols (struct block *block, const char *name, + namespace_enum namespace, struct objfile *objfile, + int wild) +{ + int i; + int name_len = strlen (name); + /* A matching argument symbol, if any. */ + struct symbol *arg_sym; + /* Set true when we find a matching non-argument symbol */ + int found_sym; + int is_sorted = BLOCK_SHOULD_SORT (block); + struct symbol *sym; + + arg_sym = NULL; + found_sym = 0; + if (wild) + { + struct symbol *sym; + ALL_BLOCK_SYMBOLS (block, i, sym) + { + if (SYMBOL_NAMESPACE (sym) == namespace && + wild_match (name, name_len, SYMBOL_NAME (sym))) + { + switch (SYMBOL_CLASS (sym)) + { + case LOC_ARG: + case LOC_LOCAL_ARG: + case LOC_REF_ARG: + case LOC_REGPARM: + case LOC_REGPARM_ADDR: + case LOC_BASEREG_ARG: + arg_sym = sym; + break; + case LOC_UNRESOLVED: + continue; + default: + found_sym = 1; + fill_in_ada_prototype (sym); + add_defn_to_vec (fixup_symbol_section (sym, objfile), block); + break; + } + } + } + } + else + { + if (is_sorted) + { + int U; + i = 0; + U = BLOCK_NSYMS (block) - 1; + while (U - i > 4) + { + int M = (U + i) >> 1; + struct symbol *sym = BLOCK_SYM (block, M); + if (SYMBOL_NAME (sym)[0] < name[0]) + i = M + 1; + else if (SYMBOL_NAME (sym)[0] > name[0]) + U = M - 1; + else if (strcmp (SYMBOL_NAME (sym), name) < 0) + i = M + 1; + else + U = M; + } + } + else + i = 0; + + for (; i < BLOCK_BUCKETS (block); i += 1) + for (sym = BLOCK_BUCKET (block, i); sym != NULL; sym = sym->hash_next) + { + if (SYMBOL_NAMESPACE (sym) == namespace) + { + int cmp = strncmp (name, SYMBOL_NAME (sym), name_len); + + if (cmp < 0) + { + if (is_sorted) + { + i = BLOCK_BUCKETS (block); + break; + } + } + else if (cmp == 0 + && is_name_suffix (SYMBOL_NAME (sym) + name_len)) + { + switch (SYMBOL_CLASS (sym)) + { + case LOC_ARG: + case LOC_LOCAL_ARG: + case LOC_REF_ARG: + case LOC_REGPARM: + case LOC_REGPARM_ADDR: + case LOC_BASEREG_ARG: + arg_sym = sym; + break; + case LOC_UNRESOLVED: + break; + default: + found_sym = 1; + fill_in_ada_prototype (sym); + add_defn_to_vec (fixup_symbol_section (sym, objfile), + block); + break; + } + } + } + } + } + + if (!found_sym && arg_sym != NULL) + { + fill_in_ada_prototype (arg_sym); + add_defn_to_vec (fixup_symbol_section (arg_sym, objfile), block); + } + + if (!wild) + { + arg_sym = NULL; + found_sym = 0; + if (is_sorted) + { + int U; + i = 0; + U = BLOCK_NSYMS (block) - 1; + while (U - i > 4) + { + int M = (U + i) >> 1; + struct symbol *sym = BLOCK_SYM (block, M); + if (SYMBOL_NAME (sym)[0] < '_') + i = M + 1; + else if (SYMBOL_NAME (sym)[0] > '_') + U = M - 1; + else if (strcmp (SYMBOL_NAME (sym), "_ada_") < 0) + i = M + 1; + else + U = M; + } + } + else + i = 0; + + for (; i < BLOCK_BUCKETS (block); i += 1) + for (sym = BLOCK_BUCKET (block, i); sym != NULL; sym = sym->hash_next) + { + struct symbol *sym = BLOCK_SYM (block, i); + + if (SYMBOL_NAMESPACE (sym) == namespace) + { + int cmp; + + cmp = (int) '_' - (int) SYMBOL_NAME (sym)[0]; + if (cmp == 0) + { + cmp = strncmp ("_ada_", SYMBOL_NAME (sym), 5); + if (cmp == 0) + cmp = strncmp (name, SYMBOL_NAME (sym) + 5, name_len); + } + + if (cmp < 0) + { + if (is_sorted) + { + i = BLOCK_BUCKETS (block); + break; + } + } + else if (cmp == 0 + && is_name_suffix (SYMBOL_NAME (sym) + name_len + 5)) + { + switch (SYMBOL_CLASS (sym)) + { + case LOC_ARG: + case LOC_LOCAL_ARG: + case LOC_REF_ARG: + case LOC_REGPARM: + case LOC_REGPARM_ADDR: + case LOC_BASEREG_ARG: + arg_sym = sym; + break; + case LOC_UNRESOLVED: + break; + default: + found_sym = 1; + fill_in_ada_prototype (sym); + add_defn_to_vec (fixup_symbol_section (sym, objfile), + block); + break; + } + } + } + } + + /* NOTE: This really shouldn't be needed for _ada_ symbols. + They aren't parameters, right? */ + if (!found_sym && arg_sym != NULL) + { + fill_in_ada_prototype (arg_sym); + add_defn_to_vec (fixup_symbol_section (arg_sym, objfile), block); + } + } +} + + + /* Function Types */ + +/* Assuming that SYM is the symbol for a function, fill in its type + with prototype information, if it is not already there. */ + +static void +fill_in_ada_prototype (struct symbol *func) +{ + struct block *b; + int nargs, nsyms; + int i; + struct type *ftype; + struct type *rtype; + size_t max_fields; + struct symbol *sym; + + if (func == NULL + || TYPE_CODE (SYMBOL_TYPE (func)) != TYPE_CODE_FUNC + || TYPE_FIELDS (SYMBOL_TYPE (func)) != NULL) + return; + + /* We make each function type unique, so that each may have its own */ + /* parameter types. This particular way of doing so wastes space: */ + /* it would be nicer to build the argument types while the original */ + /* function type is being built (FIXME). */ + rtype = check_typedef (TYPE_TARGET_TYPE (SYMBOL_TYPE (func))); + ftype = alloc_type (TYPE_OBJFILE (SYMBOL_TYPE (func))); + make_function_type (rtype, &ftype); + SYMBOL_TYPE (func) = ftype; + + b = SYMBOL_BLOCK_VALUE (func); + + nargs = 0; + max_fields = 8; + TYPE_FIELDS (ftype) = + (struct field *) xmalloc (sizeof (struct field) * max_fields); + ALL_BLOCK_SYMBOLS (b, i, sym) + { + GROW_VECT (TYPE_FIELDS (ftype), max_fields, nargs + 1); + + switch (SYMBOL_CLASS (sym)) + { + case LOC_REF_ARG: + case LOC_REGPARM_ADDR: + TYPE_FIELD_BITPOS (ftype, nargs) = nargs; + TYPE_FIELD_BITSIZE (ftype, nargs) = 0; + TYPE_FIELD_TYPE (ftype, nargs) = + lookup_pointer_type (check_typedef (SYMBOL_TYPE (sym))); + TYPE_FIELD_NAME (ftype, nargs) = SYMBOL_NAME (sym); + nargs += 1; + + break; + + case LOC_ARG: + case LOC_REGPARM: + case LOC_LOCAL_ARG: + case LOC_BASEREG_ARG: + TYPE_FIELD_BITPOS (ftype, nargs) = nargs; + TYPE_FIELD_BITSIZE (ftype, nargs) = 0; + TYPE_FIELD_TYPE (ftype, nargs) = check_typedef (SYMBOL_TYPE (sym)); + TYPE_FIELD_NAME (ftype, nargs) = SYMBOL_NAME (sym); + nargs += 1; + + break; + + default: + break; + } + } + + /* Re-allocate fields vector; if there are no fields, make the */ + /* fields pointer non-null anyway, to mark that this function type */ + /* has been filled in. */ + + TYPE_NFIELDS (ftype) = nargs; + if (nargs == 0) + { + static struct field dummy_field = { 0, 0, 0, 0 }; + xfree (TYPE_FIELDS (ftype)); + TYPE_FIELDS (ftype) = &dummy_field; + } + else + { + struct field *fields = + (struct field *) TYPE_ALLOC (ftype, nargs * sizeof (struct field)); + memcpy ((char *) fields, + (char *) TYPE_FIELDS (ftype), nargs * sizeof (struct field)); + xfree (TYPE_FIELDS (ftype)); + TYPE_FIELDS (ftype) = fields; + } +} + + + /* Breakpoint-related */ + +char no_symtab_msg[] = + "No symbol table is loaded. Use the \"file\" command."; + +/* Assuming that LINE is pointing at the beginning of an argument to + 'break', return a pointer to the delimiter for the initial segment + of that name. This is the first ':', ' ', or end of LINE. +*/ +char * +ada_start_decode_line_1 (char *line) +{ + /* [NOTE: strpbrk would be more elegant, but I am reluctant to be + the first to use such a library function in GDB code.] */ + char *p; + for (p = line; *p != '\000' && *p != ' ' && *p != ':'; p += 1) + ; + return p; +} + +/* *SPEC points to a function and line number spec (as in a break + command), following any initial file name specification. + + Return all symbol table/line specfications (sals) consistent with the + information in *SPEC and FILE_TABLE in the + following sense: + + FILE_TABLE is null, or the sal refers to a line in the file + named by FILE_TABLE. + + If *SPEC points to an argument with a trailing ':LINENUM', + then the sal refers to that line (or one following it as closely as + possible). + + If *SPEC does not start with '*', the sal is in a function with + that name. + + Returns with 0 elements if no matching non-minimal symbols found. + + If *SPEC begins with a function name of the form <NAME>, then NAME + is taken as a literal name; otherwise the function name is subject + to the usual mangling. + + *SPEC is updated to point after the function/line number specification. + + FUNFIRSTLINE is non-zero if we desire the first line of real code + in each function (this is ignored in the presence of a LINENUM spec.). + + If CANONICAL is non-NULL, and if any of the sals require a + 'canonical line spec', then *CANONICAL is set to point to an array + of strings, corresponding to and equal in length to the returned + list of sals, such that (*CANONICAL)[i] is non-null and contains a + canonical line spec for the ith returned sal, if needed. If no + canonical line specs are required and CANONICAL is non-null, + *CANONICAL is set to NULL. + + A 'canonical line spec' is simply a name (in the format of the + breakpoint command) that uniquely identifies a breakpoint position, + with no further contextual information or user selection. It is + needed whenever the file name, function name, and line number + information supplied is insufficient for this unique + identification. Currently overloaded functions, the name '*', + or static functions without a filename yield a canonical line spec. + The array and the line spec strings are allocated on the heap; it + is the caller's responsibility to free them. */ + +struct symtabs_and_lines +ada_finish_decode_line_1 (char **spec, struct symtab *file_table, + int funfirstline, char ***canonical) +{ + struct symbol **symbols; + struct block **blocks; + struct block *block; + int n_matches, i, line_num; + struct symtabs_and_lines selected; + struct cleanup *old_chain = make_cleanup (null_cleanup, NULL); + char *name; + + int len; + char *lower_name; + char *unquoted_name; + + if (file_table == NULL) + block = get_selected_block (NULL); + else + block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (file_table), STATIC_BLOCK); + + if (canonical != NULL) + *canonical = (char **) NULL; + + name = *spec; + if (**spec == '*') + *spec += 1; + else + { + while (**spec != '\000' && + !strchr (ada_completer_word_break_characters, **spec)) + *spec += 1; + } + len = *spec - name; + + line_num = -1; + if (file_table != NULL && (*spec)[0] == ':' && isdigit ((*spec)[1])) + { + line_num = strtol (*spec + 1, spec, 10); + while (**spec == ' ' || **spec == '\t') + *spec += 1; + } + + if (name[0] == '*') + { + if (line_num == -1) + error ("Wild-card function with no line number or file name."); + + return all_sals_for_line (file_table->filename, line_num, canonical); + } + + if (name[0] == '\'') + { + name += 1; + len -= 2; + } + + if (name[0] == '<') + { + unquoted_name = (char *) alloca (len - 1); + memcpy (unquoted_name, name + 1, len - 2); + unquoted_name[len - 2] = '\000'; + lower_name = NULL; + } + else + { + unquoted_name = (char *) alloca (len + 1); + memcpy (unquoted_name, name, len); + unquoted_name[len] = '\000'; + lower_name = (char *) alloca (len + 1); + for (i = 0; i < len; i += 1) + lower_name[i] = tolower (name[i]); + lower_name[len] = '\000'; + } + + n_matches = 0; + if (lower_name != NULL) + n_matches = ada_lookup_symbol_list (ada_mangle (lower_name), block, + VAR_NAMESPACE, &symbols, &blocks); + if (n_matches == 0) + n_matches = ada_lookup_symbol_list (unquoted_name, block, + VAR_NAMESPACE, &symbols, &blocks); + if (n_matches == 0 && line_num >= 0) + error ("No line number information found for %s.", unquoted_name); + else if (n_matches == 0) + { +#ifdef HPPA_COMPILER_BUG + /* FIXME: See comment in symtab.c::decode_line_1 */ +#undef volatile + volatile struct symtab_and_line val; +#define volatile /*nothing */ +#else + struct symtab_and_line val; +#endif + struct minimal_symbol *msymbol; + + INIT_SAL (&val); + + msymbol = NULL; + if (lower_name != NULL) + msymbol = ada_lookup_minimal_symbol (ada_mangle (lower_name)); + if (msymbol == NULL) + msymbol = ada_lookup_minimal_symbol (unquoted_name); + if (msymbol != NULL) + { + val.pc = SYMBOL_VALUE_ADDRESS (msymbol); + val.section = SYMBOL_BFD_SECTION (msymbol); + if (funfirstline) + { + val.pc += FUNCTION_START_OFFSET; + SKIP_PROLOGUE (val.pc); + } + selected.sals = (struct symtab_and_line *) + xmalloc (sizeof (struct symtab_and_line)); + selected.sals[0] = val; + selected.nelts = 1; + return selected; + } + + if (!have_full_symbols () && + !have_partial_symbols () && !have_minimal_symbols ()) + error (no_symtab_msg); + + error ("Function \"%s\" not defined.", unquoted_name); + return selected; /* for lint */ + } + + if (line_num >= 0) + { + return + find_sal_from_funcs_and_line (file_table->filename, line_num, + symbols, n_matches); + } + else + { + selected.nelts = + user_select_syms (symbols, blocks, n_matches, n_matches); + } + + selected.sals = (struct symtab_and_line *) + xmalloc (sizeof (struct symtab_and_line) * selected.nelts); + memset (selected.sals, 0, selected.nelts * sizeof (selected.sals[i])); + make_cleanup (xfree, selected.sals); + + i = 0; + while (i < selected.nelts) + { + if (SYMBOL_CLASS (symbols[i]) == LOC_BLOCK) + selected.sals[i] = find_function_start_sal (symbols[i], funfirstline); + else if (SYMBOL_LINE (symbols[i]) != 0) + { + selected.sals[i].symtab = symtab_for_sym (symbols[i]); + selected.sals[i].line = SYMBOL_LINE (symbols[i]); + } + else if (line_num >= 0) + { + /* Ignore this choice */ + symbols[i] = symbols[selected.nelts - 1]; + blocks[i] = blocks[selected.nelts - 1]; + selected.nelts -= 1; + continue; + } + else + error ("Line number not known for symbol \"%s\"", unquoted_name); + i += 1; + } + + if (canonical != NULL && (line_num >= 0 || n_matches > 1)) + { + *canonical = (char **) xmalloc (sizeof (char *) * selected.nelts); + for (i = 0; i < selected.nelts; i += 1) + (*canonical)[i] = + extended_canonical_line_spec (selected.sals[i], + SYMBOL_SOURCE_NAME (symbols[i])); + } + + discard_cleanups (old_chain); + return selected; +} + +/* The (single) sal corresponding to line LINE_NUM in a symbol table + with file name FILENAME that occurs in one of the functions listed + in SYMBOLS[0 .. NSYMS-1]. */ +static struct symtabs_and_lines +find_sal_from_funcs_and_line (const char *filename, int line_num, + struct symbol **symbols, int nsyms) +{ + struct symtabs_and_lines sals; + int best_index, best; + struct linetable *best_linetable; + struct objfile *objfile; + struct symtab *s; + struct symtab *best_symtab; + + read_all_symtabs (filename); + + best_index = 0; + best_linetable = NULL; + best_symtab = NULL; + best = 0; + ALL_SYMTABS (objfile, s) + { + struct linetable *l; + int ind, exact; + + QUIT; + + if (!STREQ (filename, s->filename)) + continue; + l = LINETABLE (s); + ind = find_line_in_linetable (l, line_num, symbols, nsyms, &exact); + if (ind >= 0) + { + if (exact) + { + best_index = ind; + best_linetable = l; + best_symtab = s; + goto done; + } + if (best == 0 || l->item[ind].line < best) + { + best = l->item[ind].line; + best_index = ind; + best_linetable = l; + best_symtab = s; + } + } + } + + if (best == 0) + error ("Line number not found in designated function."); + +done: + + sals.nelts = 1; + sals.sals = (struct symtab_and_line *) xmalloc (sizeof (sals.sals[0])); + + INIT_SAL (&sals.sals[0]); + + sals.sals[0].line = best_linetable->item[best_index].line; + sals.sals[0].pc = best_linetable->item[best_index].pc; + sals.sals[0].symtab = best_symtab; + + return sals; +} + +/* Return the index in LINETABLE of the best match for LINE_NUM whose + pc falls within one of the functions denoted by SYMBOLS[0..NSYMS-1]. + Set *EXACTP to the 1 if the match is exact, and 0 otherwise. */ +static int +find_line_in_linetable (struct linetable *linetable, int line_num, + struct symbol **symbols, int nsyms, int *exactp) +{ + int i, len, best_index, best; + + if (line_num <= 0 || linetable == NULL) + return -1; + + len = linetable->nitems; + for (i = 0, best_index = -1, best = 0; i < len; i += 1) + { + int k; + struct linetable_entry *item = &(linetable->item[i]); + + for (k = 0; k < nsyms; k += 1) + { + if (symbols[k] != NULL && SYMBOL_CLASS (symbols[k]) == LOC_BLOCK + && item->pc >= BLOCK_START (SYMBOL_BLOCK_VALUE (symbols[k])) + && item->pc < BLOCK_END (SYMBOL_BLOCK_VALUE (symbols[k]))) + goto candidate; + } + continue; + + candidate: + + if (item->line == line_num) + { + *exactp = 1; + return i; + } + + if (item->line > line_num && (best == 0 || item->line < best)) + { + best = item->line; + best_index = i; + } + } + + *exactp = 0; + return best_index; +} + +/* Find the smallest k >= LINE_NUM such that k is a line number in + LINETABLE, and k falls strictly within a named function that begins at + or before LINE_NUM. Return -1 if there is no such k. */ +static int +nearest_line_number_in_linetable (struct linetable *linetable, int line_num) +{ + int i, len, best; + + if (line_num <= 0 || linetable == NULL || linetable->nitems == 0) + return -1; + len = linetable->nitems; + + i = 0; + best = INT_MAX; + while (i < len) + { + int k; + struct linetable_entry *item = &(linetable->item[i]); + + if (item->line >= line_num && item->line < best) + { + char *func_name; + CORE_ADDR start, end; + + func_name = NULL; + find_pc_partial_function (item->pc, &func_name, &start, &end); + + if (func_name != NULL && item->pc < end) + { + if (item->line == line_num) + return line_num; + else + { + struct symbol *sym = + standard_lookup (func_name, VAR_NAMESPACE); + if (is_plausible_func_for_line (sym, line_num)) + best = item->line; + else + { + do + i += 1; + while (i < len && linetable->item[i].pc < end); + continue; + } + } + } + } + + i += 1; + } + + return (best == INT_MAX) ? -1 : best; +} + + +/* Return the next higher index, k, into LINETABLE such that k > IND, + entry k in LINETABLE has a line number equal to LINE_NUM, k + corresponds to a PC that is in a function different from that + corresponding to IND, and falls strictly within a named function + that begins at a line at or preceding STARTING_LINE. + Return -1 if there is no such k. + IND == -1 corresponds to no function. */ + +static int +find_next_line_in_linetable (struct linetable *linetable, int line_num, + int starting_line, int ind) +{ + int i, len; + + if (line_num <= 0 || linetable == NULL || ind >= linetable->nitems) + return -1; + len = linetable->nitems; + + if (ind >= 0) + { + CORE_ADDR start, end; + + if (find_pc_partial_function (linetable->item[ind].pc, + (char **) NULL, &start, &end)) + { + while (ind < len && linetable->item[ind].pc < end) + ind += 1; + } + else + ind += 1; + } + else + ind = 0; + + i = ind; + while (i < len) + { + int k; + struct linetable_entry *item = &(linetable->item[i]); + + if (item->line >= line_num) + { + char *func_name; + CORE_ADDR start, end; + + func_name = NULL; + find_pc_partial_function (item->pc, &func_name, &start, &end); + + if (func_name != NULL && item->pc < end) + { + if (item->line == line_num) + { + struct symbol *sym = + standard_lookup (func_name, VAR_NAMESPACE); + if (is_plausible_func_for_line (sym, starting_line)) + return i; + else + { + while ((i + 1) < len && linetable->item[i + 1].pc < end) + i += 1; + } + } + } + } + i += 1; + } + + return -1; +} + +/* True iff function symbol SYM starts somewhere at or before line # + LINE_NUM. */ +static int +is_plausible_func_for_line (struct symbol *sym, int line_num) +{ + struct symtab_and_line start_sal; + + if (sym == NULL) + return 0; + + start_sal = find_function_start_sal (sym, 0); + + return (start_sal.line != 0 && line_num >= start_sal.line); +} + +static void +debug_print_lines (struct linetable *lt) +{ + int i; + + if (lt == NULL) + return; + + fprintf (stderr, "\t"); + for (i = 0; i < lt->nitems; i += 1) + fprintf (stderr, "(%d->%p) ", lt->item[i].line, (void *) lt->item[i].pc); + fprintf (stderr, "\n"); +} + +static void +debug_print_block (struct block *b) +{ + int i; + struct symbol *i; + + fprintf (stderr, "Block: %p; [0x%lx, 0x%lx]", + b, BLOCK_START (b), BLOCK_END (b)); + if (BLOCK_FUNCTION (b) != NULL) + fprintf (stderr, " Function: %s", SYMBOL_NAME (BLOCK_FUNCTION (b))); + fprintf (stderr, "\n"); + fprintf (stderr, "\t Superblock: %p\n", BLOCK_SUPERBLOCK (b)); + fprintf (stderr, "\t Symbols:"); + ALL_BLOCK_SYMBOLS (b, i, sym) + { + if (i > 0 && i % 4 == 0) + fprintf (stderr, "\n\t\t "); + fprintf (stderr, " %s", SYMBOL_NAME (sym)); + } + fprintf (stderr, "\n"); +} + +static void +debug_print_blocks (struct blockvector *bv) +{ + int i; + + if (bv == NULL) + return; + for (i = 0; i < BLOCKVECTOR_NBLOCKS (bv); i += 1) + { + fprintf (stderr, "%6d. ", i); + debug_print_block (BLOCKVECTOR_BLOCK (bv, i)); + } +} + +static void +debug_print_symtab (struct symtab *s) +{ + fprintf (stderr, "Symtab %p\n File: %s; Dir: %s\n", s, + s->filename, s->dirname); + fprintf (stderr, " Blockvector: %p, Primary: %d\n", + BLOCKVECTOR (s), s->primary); + debug_print_blocks (BLOCKVECTOR (s)); + fprintf (stderr, " Line table: %p\n", LINETABLE (s)); + debug_print_lines (LINETABLE (s)); +} + +/* Read in all symbol tables corresponding to partial symbol tables + with file name FILENAME. */ +static void +read_all_symtabs (const char *filename) +{ + struct partial_symtab *ps; + struct objfile *objfile; + + ALL_PSYMTABS (objfile, ps) + { + QUIT; + + if (STREQ (filename, ps->filename)) + PSYMTAB_TO_SYMTAB (ps); + } +} + +/* All sals corresponding to line LINE_NUM in a symbol table from file + FILENAME, as filtered by the user. If CANONICAL is not null, set + it to a corresponding array of canonical line specs. */ +static struct symtabs_and_lines +all_sals_for_line (const char *filename, int line_num, char ***canonical) +{ + struct symtabs_and_lines result; + struct objfile *objfile; + struct symtab *s; + struct cleanup *old_chain = make_cleanup (null_cleanup, NULL); + size_t len; + + read_all_symtabs (filename); + + result.sals = + (struct symtab_and_line *) xmalloc (4 * sizeof (result.sals[0])); + result.nelts = 0; + len = 4; + make_cleanup (free_current_contents, &result.sals); + + ALL_SYMTABS (objfile, s) + { + int ind, target_line_num; + + QUIT; + + if (!STREQ (s->filename, filename)) + continue; + + target_line_num = + nearest_line_number_in_linetable (LINETABLE (s), line_num); + if (target_line_num == -1) + continue; + + ind = -1; + while (1) + { + ind = + find_next_line_in_linetable (LINETABLE (s), + target_line_num, line_num, ind); + + if (ind < 0) + break; + + GROW_VECT (result.sals, len, result.nelts + 1); + INIT_SAL (&result.sals[result.nelts]); + result.sals[result.nelts].line = LINETABLE (s)->item[ind].line; + result.sals[result.nelts].pc = LINETABLE (s)->item[ind].pc; + result.sals[result.nelts].symtab = s; + result.nelts += 1; + } + } + + if (canonical != NULL || result.nelts > 1) + { + int k; + char **func_names = (char **) alloca (result.nelts * sizeof (char *)); + int first_choice = (result.nelts > 1) ? 2 : 1; + int n; + int *choices = (int *) alloca (result.nelts * sizeof (int)); + + for (k = 0; k < result.nelts; k += 1) + { + find_pc_partial_function (result.sals[k].pc, &func_names[k], + (CORE_ADDR *) NULL, (CORE_ADDR *) NULL); + if (func_names[k] == NULL) + error ("Could not find function for one or more breakpoints."); + } + + if (result.nelts > 1) + { + printf_unfiltered ("[0] cancel\n"); + if (result.nelts > 1) + printf_unfiltered ("[1] all\n"); + for (k = 0; k < result.nelts; k += 1) + printf_unfiltered ("[%d] %s\n", k + first_choice, + ada_demangle (func_names[k])); + + n = get_selections (choices, result.nelts, result.nelts, + result.nelts > 1, "instance-choice"); + + for (k = 0; k < n; k += 1) + { + result.sals[k] = result.sals[choices[k]]; + func_names[k] = func_names[choices[k]]; + } + result.nelts = n; + } + + if (canonical != NULL) + { + *canonical = (char **) xmalloc (result.nelts * sizeof (char **)); + make_cleanup (xfree, *canonical); + for (k = 0; k < result.nelts; k += 1) + { + (*canonical)[k] = + extended_canonical_line_spec (result.sals[k], func_names[k]); + if ((*canonical)[k] == NULL) + error ("Could not locate one or more breakpoints."); + make_cleanup (xfree, (*canonical)[k]); + } + } + } + + discard_cleanups (old_chain); + return result; +} + + +/* A canonical line specification of the form FILE:NAME:LINENUM for + symbol table and line data SAL. NULL if insufficient + information. The caller is responsible for releasing any space + allocated. */ + +static char * +extended_canonical_line_spec (struct symtab_and_line sal, const char *name) +{ + char *r; + + if (sal.symtab == NULL || sal.symtab->filename == NULL || sal.line <= 0) + return NULL; + + r = (char *) xmalloc (strlen (name) + strlen (sal.symtab->filename) + + sizeof (sal.line) * 3 + 3); + sprintf (r, "%s:'%s':%d", sal.symtab->filename, name, sal.line); + return r; +} + +#if 0 +int begin_bnum = -1; +#endif +int begin_annotate_level = 0; + +static void +begin_cleanup (void *dummy) +{ + begin_annotate_level = 0; +} + +static void +begin_command (char *args, int from_tty) +{ + struct minimal_symbol *msym; + CORE_ADDR main_program_name_addr; + char main_program_name[1024]; + struct cleanup *old_chain = make_cleanup (begin_cleanup, NULL); + begin_annotate_level = 2; + + /* Check that there is a program to debug */ + if (!have_full_symbols () && !have_partial_symbols ()) + error ("No symbol table is loaded. Use the \"file\" command."); + + /* Check that we are debugging an Ada program */ + /* if (ada_update_initial_language (language_unknown, NULL) != language_ada) + error ("Cannot find the Ada initialization procedure. Is this an Ada main program?"); + */ + /* FIXME: language_ada should be defined in defs.h */ + + /* Get the address of the name of the main procedure */ + msym = lookup_minimal_symbol (ADA_MAIN_PROGRAM_SYMBOL_NAME, NULL, NULL); + + if (msym != NULL) + { + main_program_name_addr = SYMBOL_VALUE_ADDRESS (msym); + if (main_program_name_addr == 0) + error ("Invalid address for Ada main program name."); + + /* Read the name of the main procedure */ + extract_string (main_program_name_addr, main_program_name); + + /* Put a temporary breakpoint in the Ada main program and run */ + do_command ("tbreak ", main_program_name, 0); + do_command ("run ", args, 0); + } + else + { + /* If we could not find the symbol containing the name of the + main program, that means that the compiler that was used to build + was not recent enough. In that case, we fallback to the previous + mechanism, which is a little bit less reliable, but has proved to work + in most cases. The only cases where it will fail is when the user + has set some breakpoints which will be hit before the end of the + begin command processing (eg in the initialization code). + + The begining of the main Ada subprogram is located by breaking + on the adainit procedure. Since we know that the binder generates + the call to this procedure exactly 2 calls before the call to the + Ada main subprogram, it is then easy to put a breakpoint on this + Ada main subprogram once we hit adainit. + */ + do_command ("tbreak adainit", 0); + do_command ("run ", args, 0); + do_command ("up", 0); + do_command ("tbreak +2", 0); + do_command ("continue", 0); + do_command ("step", 0); + } + + do_cleanups (old_chain); +} + +int +is_ada_runtime_file (char *filename) +{ + return (STREQN (filename, "s-", 2) || + STREQN (filename, "a-", 2) || + STREQN (filename, "g-", 2) || STREQN (filename, "i-", 2)); +} + +/* find the first frame that contains debugging information and that is not + part of the Ada run-time, starting from fi and moving upward. */ + +int +find_printable_frame (struct frame_info *fi, int level) +{ + struct symtab_and_line sal; + + for (; fi != NULL; level += 1, fi = get_prev_frame (fi)) + { + /* If fi is not the innermost frame, that normally means that fi->pc + points to *after* the call instruction, and we want to get the line + containing the call, never the next line. But if the next frame is + a signal_handler_caller or a dummy frame, then the next frame was + not entered as the result of a call, and we want to get the line + containing fi->pc. */ + sal = + find_pc_line (fi->pc, + fi->next != NULL + && !fi->next->signal_handler_caller + && !frame_in_dummy (fi->next)); + if (sal.symtab && !is_ada_runtime_file (sal.symtab->filename)) + { +#if defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET) + /* libpthread.so contains some debugging information that prevents us + from finding the right frame */ + + if (sal.symtab->objfile && + STREQ (sal.symtab->objfile->name, "/usr/shlib/libpthread.so")) + continue; +#endif + selected_frame = fi; + break; + } + } + + return level; +} + +void +ada_report_exception_break (struct breakpoint *b) +{ +#ifdef UI_OUT + /* FIXME: break_on_exception should be defined in breakpoint.h */ + /* if (b->break_on_exception == 1) + { + /* Assume that cond has 16 elements, the 15th + being the exception *//* + if (b->cond && b->cond->nelts == 16) + { + ui_out_text (uiout, "on "); + ui_out_field_string (uiout, "exception", + SYMBOL_NAME (b->cond->elts[14].symbol)); + } + else + ui_out_text (uiout, "on all exceptions"); + } + else if (b->break_on_exception == 2) + ui_out_text (uiout, "on unhandled exception"); + else if (b->break_on_exception == 3) + ui_out_text (uiout, "on assert failure"); + #else + if (b->break_on_exception == 1) + { */ + /* Assume that cond has 16 elements, the 15th + being the exception *//* + if (b->cond && b->cond->nelts == 16) + { + fputs_filtered ("on ", gdb_stdout); + fputs_filtered (SYMBOL_NAME + (b->cond->elts[14].symbol), gdb_stdout); + } + else + fputs_filtered ("on all exceptions", gdb_stdout); + } + else if (b->break_on_exception == 2) + fputs_filtered ("on unhandled exception", gdb_stdout); + else if (b->break_on_exception == 3) + fputs_filtered ("on assert failure", gdb_stdout); + */ +#endif +} + +int +ada_is_exception_sym (struct symbol *sym) +{ + char *type_name = type_name_no_tag (SYMBOL_TYPE (sym)); + + return (SYMBOL_CLASS (sym) != LOC_TYPEDEF + && SYMBOL_CLASS (sym) != LOC_BLOCK + && SYMBOL_CLASS (sym) != LOC_CONST + && type_name != NULL && STREQ (type_name, "exception")); +} + +int +ada_maybe_exception_partial_symbol (struct partial_symbol *sym) +{ + return (SYMBOL_CLASS (sym) != LOC_TYPEDEF + && SYMBOL_CLASS (sym) != LOC_BLOCK + && SYMBOL_CLASS (sym) != LOC_CONST); +} + +/* If ARG points to an Ada exception or assert breakpoint, rewrite + into equivalent form. Return resulting argument string. Set + *BREAK_ON_EXCEPTIONP to 1 for ordinary break on exception, 2 for + break on unhandled, 3 for assert, 0 otherwise. */ +char * +ada_breakpoint_rewrite (char *arg, int *break_on_exceptionp) +{ + if (arg == NULL) + return arg; + *break_on_exceptionp = 0; + /* FIXME: language_ada should be defined in defs.h */ + /* if (current_language->la_language == language_ada + && STREQN (arg, "exception", 9) && + (arg[9] == ' ' || arg[9] == '\t' || arg[9] == '\0')) + { + char *tok, *end_tok; + int toklen; + + *break_on_exceptionp = 1; + + tok = arg+9; + while (*tok == ' ' || *tok == '\t') + tok += 1; + + end_tok = tok; + + while (*end_tok != ' ' && *end_tok != '\t' && *end_tok != '\000') + end_tok += 1; + + toklen = end_tok - tok; + + arg = (char*) xmalloc (sizeof ("__gnat_raise_nodefer_with_msg if " + "long_integer(e) = long_integer(&)") + + toklen + 1); + make_cleanup (xfree, arg); + if (toklen == 0) + strcpy (arg, "__gnat_raise_nodefer_with_msg"); + else if (STREQN (tok, "unhandled", toklen)) + { + *break_on_exceptionp = 2; + strcpy (arg, "__gnat_unhandled_exception"); + } + else + { + sprintf (arg, "__gnat_raise_nodefer_with_msg if " + "long_integer(e) = long_integer(&%.*s)", + toklen, tok); + } + } + else if (current_language->la_language == language_ada + && STREQN (arg, "assert", 6) && + (arg[6] == ' ' || arg[6] == '\t' || arg[6] == '\0')) + { + char *tok = arg + 6; + + *break_on_exceptionp = 3; + + arg = (char*) + xmalloc (sizeof ("system__assertions__raise_assert_failure") + + strlen (tok) + 1); + make_cleanup (xfree, arg); + sprintf (arg, "system__assertions__raise_assert_failure%s", tok); + } + */ + return arg; +} + + + /* Field Access */ + +/* True if field number FIELD_NUM in struct or union type TYPE is supposed + to be invisible to users. */ + +int +ada_is_ignored_field (struct type *type, int field_num) +{ + if (field_num < 0 || field_num > TYPE_NFIELDS (type)) + return 1; + else + { + const char *name = TYPE_FIELD_NAME (type, field_num); + return (name == NULL + || (name[0] == '_' && !STREQN (name, "_parent", 7))); + } +} + +/* True iff structure type TYPE has a tag field. */ + +int +ada_is_tagged_type (struct type *type) +{ + if (type == NULL || TYPE_CODE (type) != TYPE_CODE_STRUCT) + return 0; + + return (ada_lookup_struct_elt_type (type, "_tag", 1, NULL) != NULL); +} + +/* The type of the tag on VAL. */ + +struct type * +ada_tag_type (struct value *val) +{ + return ada_lookup_struct_elt_type (VALUE_TYPE (val), "_tag", 0, NULL); +} + +/* The value of the tag on VAL. */ + +struct value * +ada_value_tag (struct value *val) +{ + return ada_value_struct_elt (val, "_tag", "record"); +} + +/* The parent type of TYPE, or NULL if none. */ + +struct type * +ada_parent_type (struct type *type) +{ + int i; + + CHECK_TYPEDEF (type); + + if (type == NULL || TYPE_CODE (type) != TYPE_CODE_STRUCT) + return NULL; + + for (i = 0; i < TYPE_NFIELDS (type); i += 1) + if (ada_is_parent_field (type, i)) + return check_typedef (TYPE_FIELD_TYPE (type, i)); + + return NULL; +} + +/* True iff field number FIELD_NUM of structure type TYPE contains the + parent-type (inherited) fields of a derived type. Assumes TYPE is + a structure type with at least FIELD_NUM+1 fields. */ + +int +ada_is_parent_field (struct type *type, int field_num) +{ + const char *name = TYPE_FIELD_NAME (check_typedef (type), field_num); + return (name != NULL && + (STREQN (name, "PARENT", 6) || STREQN (name, "_parent", 7))); +} + +/* True iff field number FIELD_NUM of structure type TYPE is a + transparent wrapper field (which should be silently traversed when doing + field selection and flattened when printing). Assumes TYPE is a + structure type with at least FIELD_NUM+1 fields. Such fields are always + structures. */ + +int +ada_is_wrapper_field (struct type *type, int field_num) +{ + const char *name = TYPE_FIELD_NAME (type, field_num); + return (name != NULL + && (STREQN (name, "PARENT", 6) || STREQ (name, "REP") + || STREQN (name, "_parent", 7) + || name[0] == 'S' || name[0] == 'R' || name[0] == 'O')); +} + +/* True iff field number FIELD_NUM of structure or union type TYPE + is a variant wrapper. Assumes TYPE is a structure type with at least + FIELD_NUM+1 fields. */ + +int +ada_is_variant_part (struct type *type, int field_num) +{ + struct type *field_type = TYPE_FIELD_TYPE (type, field_num); + return (TYPE_CODE (field_type) == TYPE_CODE_UNION + || (is_dynamic_field (type, field_num) + && TYPE_CODE (TYPE_TARGET_TYPE (field_type)) == + TYPE_CODE_UNION)); +} + +/* Assuming that VAR_TYPE is a variant wrapper (type of the variant part) + whose discriminants are contained in the record type OUTER_TYPE, + returns the type of the controlling discriminant for the variant. */ + +struct type * +ada_variant_discrim_type (struct type *var_type, struct type *outer_type) +{ + char *name = ada_variant_discrim_name (var_type); + struct type *type = ada_lookup_struct_elt_type (outer_type, name, 1, NULL); + if (type == NULL) + return builtin_type_int; + else + return type; +} + +/* Assuming that TYPE is the type of a variant wrapper, and FIELD_NUM is a + valid field number within it, returns 1 iff field FIELD_NUM of TYPE + represents a 'when others' clause; otherwise 0. */ + +int +ada_is_others_clause (struct type *type, int field_num) +{ + const char *name = TYPE_FIELD_NAME (type, field_num); + return (name != NULL && name[0] == 'O'); +} + +/* Assuming that TYPE0 is the type of the variant part of a record, + returns the name of the discriminant controlling the variant. The + value is valid until the next call to ada_variant_discrim_name. */ + +char * +ada_variant_discrim_name (struct type *type0) +{ + static char *result = NULL; + static size_t result_len = 0; + struct type *type; + const char *name; + const char *discrim_end; + const char *discrim_start; + + if (TYPE_CODE (type0) == TYPE_CODE_PTR) + type = TYPE_TARGET_TYPE (type0); + else + type = type0; + + name = ada_type_name (type); + + if (name == NULL || name[0] == '\000') + return ""; + + for (discrim_end = name + strlen (name) - 6; discrim_end != name; + discrim_end -= 1) + { + if (STREQN (discrim_end, "___XVN", 6)) + break; + } + if (discrim_end == name) + return ""; + + for (discrim_start = discrim_end; discrim_start != name + 3; + discrim_start -= 1) + { + if (discrim_start == name + 1) + return ""; + if ((discrim_start > name + 3 && STREQN (discrim_start - 3, "___", 3)) + || discrim_start[-1] == '.') + break; + } + + GROW_VECT (result, result_len, discrim_end - discrim_start + 1); + strncpy (result, discrim_start, discrim_end - discrim_start); + result[discrim_end - discrim_start] = '\0'; + return result; +} + +/* Scan STR for a subtype-encoded number, beginning at position K. Put the + position of the character just past the number scanned in *NEW_K, + if NEW_K!=NULL. Put the scanned number in *R, if R!=NULL. Return 1 + if there was a valid number at the given position, and 0 otherwise. A + "subtype-encoded" number consists of the absolute value in decimal, + followed by the letter 'm' to indicate a negative number. Assumes 0m + does not occur. */ + +int +ada_scan_number (const char str[], int k, LONGEST * R, int *new_k) +{ + ULONGEST RU; + + if (!isdigit (str[k])) + return 0; + + /* Do it the hard way so as not to make any assumption about + the relationship of unsigned long (%lu scan format code) and + LONGEST. */ + RU = 0; + while (isdigit (str[k])) + { + RU = RU * 10 + (str[k] - '0'); + k += 1; + } + + if (str[k] == 'm') + { + if (R != NULL) + *R = (-(LONGEST) (RU - 1)) - 1; + k += 1; + } + else if (R != NULL) + *R = (LONGEST) RU; + + /* NOTE on the above: Technically, C does not say what the results of + - (LONGEST) RU or (LONGEST) -RU are for RU == largest positive + number representable as a LONGEST (although either would probably work + in most implementations). When RU>0, the locution in the then branch + above is always equivalent to the negative of RU. */ + + if (new_k != NULL) + *new_k = k; + return 1; +} + +/* Assuming that TYPE is a variant part wrapper type (a VARIANTS field), + and FIELD_NUM is a valid field number within it, returns 1 iff VAL is + in the range encoded by field FIELD_NUM of TYPE; otherwise 0. */ + +int +ada_in_variant (LONGEST val, struct type *type, int field_num) +{ + const char *name = TYPE_FIELD_NAME (type, field_num); + int p; + + p = 0; + while (1) + { + switch (name[p]) + { + case '\0': + return 0; + case 'S': + { + LONGEST W; + if (!ada_scan_number (name, p + 1, &W, &p)) + return 0; + if (val == W) + return 1; + break; + } + case 'R': + { + LONGEST L, U; + if (!ada_scan_number (name, p + 1, &L, &p) + || name[p] != 'T' || !ada_scan_number (name, p + 1, &U, &p)) + return 0; + if (val >= L && val <= U) + return 1; + break; + } + case 'O': + return 1; + default: + return 0; + } + } +} + +/* Given a value ARG1 (offset by OFFSET bytes) + of a struct or union type ARG_TYPE, + extract and return the value of one of its (non-static) fields. + FIELDNO says which field. Differs from value_primitive_field only + in that it can handle packed values of arbitrary type. */ + +struct value * +ada_value_primitive_field (struct value *arg1, int offset, int fieldno, + struct type *arg_type) +{ + struct value *v; + struct type *type; + + CHECK_TYPEDEF (arg_type); + type = TYPE_FIELD_TYPE (arg_type, fieldno); + + /* Handle packed fields */ + + if (TYPE_FIELD_BITSIZE (arg_type, fieldno) != 0) + { + int bit_pos = TYPE_FIELD_BITPOS (arg_type, fieldno); + int bit_size = TYPE_FIELD_BITSIZE (arg_type, fieldno); + + return ada_value_primitive_packed_val (arg1, VALUE_CONTENTS (arg1), + offset + bit_pos / 8, + bit_pos % 8, bit_size, type); + } + else + return value_primitive_field (arg1, offset, fieldno, arg_type); +} + + +/* Look for a field NAME in ARG. Adjust the address of ARG by OFFSET bytes, + and search in it assuming it has (class) type TYPE. + If found, return value, else return NULL. + + Searches recursively through wrapper fields (e.g., '_parent'). */ + +struct value * +ada_search_struct_field (char *name, struct value *arg, int offset, + struct type *type) +{ + int i; + CHECK_TYPEDEF (type); + + for (i = TYPE_NFIELDS (type) - 1; i >= 0; i -= 1) + { + char *t_field_name = TYPE_FIELD_NAME (type, i); + + if (t_field_name == NULL) + continue; + + else if (field_name_match (t_field_name, name)) + return ada_value_primitive_field (arg, offset, i, type); + + else if (ada_is_wrapper_field (type, i)) + { + struct value *v = ada_search_struct_field (name, arg, + offset + + TYPE_FIELD_BITPOS (type, + i) / + 8, + TYPE_FIELD_TYPE (type, + i)); + if (v != NULL) + return v; + } + + else if (ada_is_variant_part (type, i)) + { + int j; + struct type *field_type = check_typedef (TYPE_FIELD_TYPE (type, i)); + int var_offset = offset + TYPE_FIELD_BITPOS (type, i) / 8; + + for (j = TYPE_NFIELDS (field_type) - 1; j >= 0; j -= 1) + { + struct value *v = ada_search_struct_field (name, arg, + var_offset + + + TYPE_FIELD_BITPOS + (field_type, j) / 8, + TYPE_FIELD_TYPE + (field_type, j)); + if (v != NULL) + return v; + } + } + } + return NULL; +} + +/* Given ARG, a value of type (pointer to a)* structure/union, + extract the component named NAME from the ultimate target structure/union + and return it as a value with its appropriate type. + + The routine searches for NAME among all members of the structure itself + and (recursively) among all members of any wrapper members + (e.g., '_parent'). + + ERR is a name (for use in error messages) that identifies the class + of entity that ARG is supposed to be. */ + +struct value * +ada_value_struct_elt (struct value *arg, char *name, char *err) +{ + struct type *t; + struct value *v; + + arg = ada_coerce_ref (arg); + t = check_typedef (VALUE_TYPE (arg)); + + /* Follow pointers until we get to a non-pointer. */ + + while (TYPE_CODE (t) == TYPE_CODE_PTR || TYPE_CODE (t) == TYPE_CODE_REF) + { + arg = ada_value_ind (arg); + t = check_typedef (VALUE_TYPE (arg)); + } + + if (TYPE_CODE (t) != TYPE_CODE_STRUCT && TYPE_CODE (t) != TYPE_CODE_UNION) + error ("Attempt to extract a component of a value that is not a %s.", + err); + + v = ada_search_struct_field (name, arg, 0, t); + if (v == NULL) + error ("There is no member named %s.", name); + + return v; +} + +/* Given a type TYPE, look up the type of the component of type named NAME. + If DISPP is non-null, add its byte displacement from the beginning of a + structure (pointed to by a value) of type TYPE to *DISPP (does not + work for packed fields). + + Matches any field whose name has NAME as a prefix, possibly + followed by "___". + + TYPE can be either a struct or union, or a pointer or reference to + a struct or union. If it is a pointer or reference, its target + type is automatically used. + + Looks recursively into variant clauses and parent types. + + If NOERR is nonzero, return NULL if NAME is not suitably defined. */ + +struct type * +ada_lookup_struct_elt_type (struct type *type, char *name, int noerr, + int *dispp) +{ + int i; + + if (name == NULL) + goto BadName; + + while (1) + { + CHECK_TYPEDEF (type); + if (TYPE_CODE (type) != TYPE_CODE_PTR + && TYPE_CODE (type) != TYPE_CODE_REF) + break; + type = TYPE_TARGET_TYPE (type); + } + + if (TYPE_CODE (type) != TYPE_CODE_STRUCT && + TYPE_CODE (type) != TYPE_CODE_UNION) + { + target_terminal_ours (); + gdb_flush (gdb_stdout); + fprintf_unfiltered (gdb_stderr, "Type "); + type_print (type, "", gdb_stderr, -1); + error (" is not a structure or union type"); + } + + type = to_static_fixed_type (type); + + for (i = 0; i < TYPE_NFIELDS (type); i += 1) + { + char *t_field_name = TYPE_FIELD_NAME (type, i); + struct type *t; + int disp; + + if (t_field_name == NULL) + continue; + + else if (field_name_match (t_field_name, name)) + { + if (dispp != NULL) + *dispp += TYPE_FIELD_BITPOS (type, i) / 8; + return check_typedef (TYPE_FIELD_TYPE (type, i)); + } + + else if (ada_is_wrapper_field (type, i)) + { + disp = 0; + t = ada_lookup_struct_elt_type (TYPE_FIELD_TYPE (type, i), name, + 1, &disp); + if (t != NULL) + { + if (dispp != NULL) + *dispp += disp + TYPE_FIELD_BITPOS (type, i) / 8; + return t; + } + } + + else if (ada_is_variant_part (type, i)) + { + int j; + struct type *field_type = check_typedef (TYPE_FIELD_TYPE (type, i)); + + for (j = TYPE_NFIELDS (field_type) - 1; j >= 0; j -= 1) + { + disp = 0; + t = ada_lookup_struct_elt_type (TYPE_FIELD_TYPE (field_type, j), + name, 1, &disp); + if (t != NULL) + { + if (dispp != NULL) + *dispp += disp + TYPE_FIELD_BITPOS (type, i) / 8; + return t; + } + } + } + + } + +BadName: + if (!noerr) + { + target_terminal_ours (); + gdb_flush (gdb_stdout); + fprintf_unfiltered (gdb_stderr, "Type "); + type_print (type, "", gdb_stderr, -1); + fprintf_unfiltered (gdb_stderr, " has no component named "); + error ("%s", name == NULL ? "<null>" : name); + } + + return NULL; +} + +/* Assuming that VAR_TYPE is the type of a variant part of a record (a union), + within a value of type OUTER_TYPE that is stored in GDB at + OUTER_VALADDR, determine which variant clause (field number in VAR_TYPE, + numbering from 0) is applicable. Returns -1 if none are. */ + +int +ada_which_variant_applies (struct type *var_type, struct type *outer_type, + char *outer_valaddr) +{ + int others_clause; + int i; + int disp; + struct type *discrim_type; + char *discrim_name = ada_variant_discrim_name (var_type); + LONGEST discrim_val; + + disp = 0; + discrim_type = + ada_lookup_struct_elt_type (outer_type, discrim_name, 1, &disp); + if (discrim_type == NULL) + return -1; + discrim_val = unpack_long (discrim_type, outer_valaddr + disp); + + others_clause = -1; + for (i = 0; i < TYPE_NFIELDS (var_type); i += 1) + { + if (ada_is_others_clause (var_type, i)) + others_clause = i; + else if (ada_in_variant (discrim_val, var_type, i)) + return i; + } + + return others_clause; +} + + + + /* Dynamic-Sized Records */ + +/* Strategy: The type ostensibly attached to a value with dynamic size + (i.e., a size that is not statically recorded in the debugging + data) does not accurately reflect the size or layout of the value. + Our strategy is to convert these values to values with accurate, + conventional types that are constructed on the fly. */ + +/* There is a subtle and tricky problem here. In general, we cannot + determine the size of dynamic records without its data. However, + the 'struct value' data structure, which GDB uses to represent + quantities in the inferior process (the target), requires the size + of the type at the time of its allocation in order to reserve space + for GDB's internal copy of the data. That's why the + 'to_fixed_xxx_type' routines take (target) addresses as parameters, + rather than struct value*s. + + However, GDB's internal history variables ($1, $2, etc.) are + struct value*s containing internal copies of the data that are not, in + general, the same as the data at their corresponding addresses in + the target. Fortunately, the types we give to these values are all + conventional, fixed-size types (as per the strategy described + above), so that we don't usually have to perform the + 'to_fixed_xxx_type' conversions to look at their values. + Unfortunately, there is one exception: if one of the internal + history variables is an array whose elements are unconstrained + records, then we will need to create distinct fixed types for each + element selected. */ + +/* The upshot of all of this is that many routines take a (type, host + address, target address) triple as arguments to represent a value. + The host address, if non-null, is supposed to contain an internal + copy of the relevant data; otherwise, the program is to consult the + target at the target address. */ + +/* Assuming that VAL0 represents a pointer value, the result of + dereferencing it. Differs from value_ind in its treatment of + dynamic-sized types. */ + +struct value * +ada_value_ind (struct value *val0) +{ + struct value *val = unwrap_value (value_ind (val0)); + return ada_to_fixed_value (VALUE_TYPE (val), 0, + VALUE_ADDRESS (val) + VALUE_OFFSET (val), val); +} + +/* The value resulting from dereferencing any "reference to" + * qualifiers on VAL0. */ +static struct value * +ada_coerce_ref (struct value *val0) +{ + if (TYPE_CODE (VALUE_TYPE (val0)) == TYPE_CODE_REF) + { + struct value *val = val0; + COERCE_REF (val); + val = unwrap_value (val); + return ada_to_fixed_value (VALUE_TYPE (val), 0, + VALUE_ADDRESS (val) + VALUE_OFFSET (val), + val); + } + else + return val0; +} + +/* Return OFF rounded upward if necessary to a multiple of + ALIGNMENT (a power of 2). */ + +static unsigned int +align_value (unsigned int off, unsigned int alignment) +{ + return (off + alignment - 1) & ~(alignment - 1); +} + +/* Return the additional bit offset required by field F of template + type TYPE. */ + +static unsigned int +field_offset (struct type *type, int f) +{ + int n = TYPE_FIELD_BITPOS (type, f); + /* Kludge (temporary?) to fix problem with dwarf output. */ + if (n < 0) + return (unsigned int) n & 0xffff; + else + return n; +} + + +/* Return the bit alignment required for field #F of template type TYPE. */ + +static unsigned int +field_alignment (struct type *type, int f) +{ + const char *name = TYPE_FIELD_NAME (type, f); + int len = (name == NULL) ? 0 : strlen (name); + int align_offset; + + if (len < 8 || !isdigit (name[len - 1])) + return TARGET_CHAR_BIT; + + if (isdigit (name[len - 2])) + align_offset = len - 2; + else + align_offset = len - 1; + + if (align_offset < 7 || !STREQN ("___XV", name + align_offset - 6, 5)) + return TARGET_CHAR_BIT; + + return atoi (name + align_offset) * TARGET_CHAR_BIT; +} + +/* Find a type named NAME. Ignores ambiguity. */ +struct type * +ada_find_any_type (const char *name) +{ + struct symbol *sym; + + sym = standard_lookup (name, VAR_NAMESPACE); + if (sym != NULL && SYMBOL_CLASS (sym) == LOC_TYPEDEF) + return SYMBOL_TYPE (sym); + + sym = standard_lookup (name, STRUCT_NAMESPACE); + if (sym != NULL) + return SYMBOL_TYPE (sym); + + return NULL; +} + +/* Because of GNAT encoding conventions, several GDB symbols may match a + given type name. If the type denoted by TYPE0 is to be preferred to + that of TYPE1 for purposes of type printing, return non-zero; + otherwise return 0. */ +int +ada_prefer_type (struct type *type0, struct type *type1) +{ + if (type1 == NULL) + return 1; + else if (type0 == NULL) + return 0; + else if (TYPE_CODE (type1) == TYPE_CODE_VOID) + return 1; + else if (TYPE_CODE (type0) == TYPE_CODE_VOID) + return 0; + else if (ada_is_packed_array_type (type0)) + return 1; + else if (ada_is_array_descriptor (type0) + && !ada_is_array_descriptor (type1)) + return 1; + else if (ada_renaming_type (type0) != NULL + && ada_renaming_type (type1) == NULL) + return 1; + return 0; +} + +/* The name of TYPE, which is either its TYPE_NAME, or, if that is + null, its TYPE_TAG_NAME. Null if TYPE is null. */ +char * +ada_type_name (struct type *type) +{ + if (type == NULL) + return NULL; + else if (TYPE_NAME (type) != NULL) + return TYPE_NAME (type); + else + return TYPE_TAG_NAME (type); +} + +/* Find a parallel type to TYPE whose name is formed by appending + SUFFIX to the name of TYPE. */ + +struct type * +ada_find_parallel_type (struct type *type, const char *suffix) +{ + static char *name; + static size_t name_len = 0; + struct symbol **syms; + struct block **blocks; + int nsyms; + int len; + char *typename = ada_type_name (type); + + if (typename == NULL) + return NULL; + + len = strlen (typename); + + GROW_VECT (name, name_len, len + strlen (suffix) + 1); + + strcpy (name, typename); + strcpy (name + len, suffix); + + return ada_find_any_type (name); +} + + +/* If TYPE is a variable-size record type, return the corresponding template + type describing its fields. Otherwise, return NULL. */ + +static struct type * +dynamic_template_type (struct type *type) +{ + CHECK_TYPEDEF (type); + + if (type == NULL || TYPE_CODE (type) != TYPE_CODE_STRUCT + || ada_type_name (type) == NULL) + return NULL; + else + { + int len = strlen (ada_type_name (type)); + if (len > 6 && STREQ (ada_type_name (type) + len - 6, "___XVE")) + return type; + else + return ada_find_parallel_type (type, "___XVE"); + } +} + +/* Assuming that TEMPL_TYPE is a union or struct type, returns + non-zero iff field FIELD_NUM of TEMPL_TYPE has dynamic size. */ + +static int +is_dynamic_field (struct type *templ_type, int field_num) +{ + const char *name = TYPE_FIELD_NAME (templ_type, field_num); + return name != NULL + && TYPE_CODE (TYPE_FIELD_TYPE (templ_type, field_num)) == TYPE_CODE_PTR + && strstr (name, "___XVL") != NULL; +} + +/* Assuming that TYPE is a struct type, returns non-zero iff TYPE + contains a variant part. */ + +static int +contains_variant_part (struct type *type) +{ + int f; + + if (type == NULL || TYPE_CODE (type) != TYPE_CODE_STRUCT + || TYPE_NFIELDS (type) <= 0) + return 0; + return ada_is_variant_part (type, TYPE_NFIELDS (type) - 1); +} + +/* A record type with no fields, . */ +static struct type * +empty_record (struct objfile *objfile) +{ + struct type *type = alloc_type (objfile); + TYPE_CODE (type) = TYPE_CODE_STRUCT; + TYPE_NFIELDS (type) = 0; + TYPE_FIELDS (type) = NULL; + TYPE_NAME (type) = "<empty>"; + TYPE_TAG_NAME (type) = NULL; + TYPE_FLAGS (type) = 0; + TYPE_LENGTH (type) = 0; + return type; +} + +/* An ordinary record type (with fixed-length fields) that describes + the value of type TYPE at VALADDR or ADDRESS (see comments at + the beginning of this section) VAL according to GNAT conventions. + DVAL0 should describe the (portion of a) record that contains any + necessary discriminants. It should be NULL if VALUE_TYPE (VAL) is + an outer-level type (i.e., as opposed to a branch of a variant.) A + variant field (unless unchecked) is replaced by a particular branch + of the variant. */ +/* NOTE: Limitations: For now, we assume that dynamic fields and + * variants occupy whole numbers of bytes. However, they need not be + * byte-aligned. */ + +static struct type * +template_to_fixed_record_type (struct type *type, char *valaddr, + CORE_ADDR address, struct value *dval0) +{ + struct value *mark = value_mark (); + struct value *dval; + struct type *rtype; + int nfields, bit_len; + long off; + int f; + + nfields = TYPE_NFIELDS (type); + rtype = alloc_type (TYPE_OBJFILE (type)); + TYPE_CODE (rtype) = TYPE_CODE_STRUCT; + INIT_CPLUS_SPECIFIC (rtype); + TYPE_NFIELDS (rtype) = nfields; + TYPE_FIELDS (rtype) = (struct field *) + TYPE_ALLOC (rtype, nfields * sizeof (struct field)); + memset (TYPE_FIELDS (rtype), 0, sizeof (struct field) * nfields); + TYPE_NAME (rtype) = ada_type_name (type); + TYPE_TAG_NAME (rtype) = NULL; + /* FIXME: TYPE_FLAG_FIXED_INSTANCE should be defined in + gdbtypes.h */ + /* TYPE_FLAGS (rtype) |= TYPE_FLAG_FIXED_INSTANCE; */ + + off = 0; + bit_len = 0; + for (f = 0; f < nfields; f += 1) + { + int fld_bit_len, bit_incr; + off = + align_value (off, + field_alignment (type, f)) + TYPE_FIELD_BITPOS (type, f); + /* NOTE: used to use field_offset above, but that causes + * problems with really negative bit positions. So, let's + * rediscover why we needed field_offset and fix it properly. */ + TYPE_FIELD_BITPOS (rtype, f) = off; + TYPE_FIELD_BITSIZE (rtype, f) = 0; + + if (ada_is_variant_part (type, f)) + { + struct type *branch_type; + + if (dval0 == NULL) + dval = value_from_contents_and_address (rtype, valaddr, address); + else + dval = dval0; + + branch_type = + to_fixed_variant_branch_type + (TYPE_FIELD_TYPE (type, f), + cond_offset_host (valaddr, off / TARGET_CHAR_BIT), + cond_offset_target (address, off / TARGET_CHAR_BIT), dval); + if (branch_type == NULL) + TYPE_NFIELDS (rtype) -= 1; + else + { + TYPE_FIELD_TYPE (rtype, f) = branch_type; + TYPE_FIELD_NAME (rtype, f) = "S"; + } + bit_incr = 0; + fld_bit_len = + TYPE_LENGTH (TYPE_FIELD_TYPE (rtype, f)) * TARGET_CHAR_BIT; + } + else if (is_dynamic_field (type, f)) + { + if (dval0 == NULL) + dval = value_from_contents_and_address (rtype, valaddr, address); + else + dval = dval0; + + TYPE_FIELD_TYPE (rtype, f) = + ada_to_fixed_type + (ada_get_base_type + (TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (type, f))), + cond_offset_host (valaddr, off / TARGET_CHAR_BIT), + cond_offset_target (address, off / TARGET_CHAR_BIT), dval); + TYPE_FIELD_NAME (rtype, f) = TYPE_FIELD_NAME (type, f); + bit_incr = fld_bit_len = + TYPE_LENGTH (TYPE_FIELD_TYPE (rtype, f)) * TARGET_CHAR_BIT; + } + else + { + TYPE_FIELD_TYPE (rtype, f) = TYPE_FIELD_TYPE (type, f); + TYPE_FIELD_NAME (rtype, f) = TYPE_FIELD_NAME (type, f); + if (TYPE_FIELD_BITSIZE (type, f) > 0) + bit_incr = fld_bit_len = + TYPE_FIELD_BITSIZE (rtype, f) = TYPE_FIELD_BITSIZE (type, f); + else + bit_incr = fld_bit_len = + TYPE_LENGTH (TYPE_FIELD_TYPE (type, f)) * TARGET_CHAR_BIT; + } + if (off + fld_bit_len > bit_len) + bit_len = off + fld_bit_len; + off += bit_incr; + TYPE_LENGTH (rtype) = bit_len / TARGET_CHAR_BIT; + } + TYPE_LENGTH (rtype) = align_value (TYPE_LENGTH (rtype), TYPE_LENGTH (type)); + + value_free_to_mark (mark); + if (TYPE_LENGTH (rtype) > varsize_limit) + error ("record type with dynamic size is larger than varsize-limit"); + return rtype; +} + +/* As for template_to_fixed_record_type, but uses no run-time values. + As a result, this type can only be approximate, but that's OK, + since it is used only for type determinations. Works on both + structs and unions. + Representation note: to save space, we memoize the result of this + function in the TYPE_TARGET_TYPE of the template type. */ + +static struct type * +template_to_static_fixed_type (struct type *templ_type) +{ + struct type *type; + int nfields; + int f; + + if (TYPE_TARGET_TYPE (templ_type) != NULL) + return TYPE_TARGET_TYPE (templ_type); + + nfields = TYPE_NFIELDS (templ_type); + TYPE_TARGET_TYPE (templ_type) = type = + alloc_type (TYPE_OBJFILE (templ_type)); + TYPE_CODE (type) = TYPE_CODE (templ_type); + INIT_CPLUS_SPECIFIC (type); + TYPE_NFIELDS (type) = nfields; + TYPE_FIELDS (type) = (struct field *) + TYPE_ALLOC (type, nfields * sizeof (struct field)); + memset (TYPE_FIELDS (type), 0, sizeof (struct field) * nfields); + TYPE_NAME (type) = ada_type_name (templ_type); + TYPE_TAG_NAME (type) = NULL; + /* FIXME: TYPE_FLAG_FIXED_INSTANCE should be defined in gdbtypes.h */ + /* TYPE_FLAGS (type) |= TYPE_FLAG_FIXED_INSTANCE; */ + TYPE_LENGTH (type) = 0; + + for (f = 0; f < nfields; f += 1) + { + TYPE_FIELD_BITPOS (type, f) = 0; + TYPE_FIELD_BITSIZE (type, f) = 0; + + if (is_dynamic_field (templ_type, f)) + { + TYPE_FIELD_TYPE (type, f) = + to_static_fixed_type (TYPE_TARGET_TYPE + (TYPE_FIELD_TYPE (templ_type, f))); + TYPE_FIELD_NAME (type, f) = TYPE_FIELD_NAME (templ_type, f); + } + else + { + TYPE_FIELD_TYPE (type, f) = + check_typedef (TYPE_FIELD_TYPE (templ_type, f)); + TYPE_FIELD_NAME (type, f) = TYPE_FIELD_NAME (templ_type, f); + } + } + + return type; +} + +/* A revision of TYPE0 -- a non-dynamic-sized record with a variant + part -- in which the variant part is replaced with the appropriate + branch. */ +static struct type * +to_record_with_fixed_variant_part (struct type *type, char *valaddr, + CORE_ADDR address, struct value *dval) +{ + struct value *mark = value_mark (); + struct type *rtype; + struct type *branch_type; + int nfields = TYPE_NFIELDS (type); + + if (dval == NULL) + return type; + + rtype = alloc_type (TYPE_OBJFILE (type)); + TYPE_CODE (rtype) = TYPE_CODE_STRUCT; + INIT_CPLUS_SPECIFIC (type); + TYPE_NFIELDS (rtype) = TYPE_NFIELDS (type); + TYPE_FIELDS (rtype) = + (struct field *) TYPE_ALLOC (rtype, nfields * sizeof (struct field)); + memcpy (TYPE_FIELDS (rtype), TYPE_FIELDS (type), + sizeof (struct field) * nfields); + TYPE_NAME (rtype) = ada_type_name (type); + TYPE_TAG_NAME (rtype) = NULL; + /* FIXME: TYPE_FLAG_FIXED_INSTANCE should be defined in gdbtypes.h */ + /* TYPE_FLAGS (rtype) |= TYPE_FLAG_FIXED_INSTANCE; */ + TYPE_LENGTH (rtype) = TYPE_LENGTH (type); + + branch_type = + to_fixed_variant_branch_type + (TYPE_FIELD_TYPE (type, nfields - 1), + cond_offset_host (valaddr, + TYPE_FIELD_BITPOS (type, + nfields - 1) / TARGET_CHAR_BIT), + cond_offset_target (address, + TYPE_FIELD_BITPOS (type, + nfields - 1) / TARGET_CHAR_BIT), + dval); + if (branch_type == NULL) + { + TYPE_NFIELDS (rtype) -= 1; + TYPE_LENGTH (rtype) -= + TYPE_LENGTH (TYPE_FIELD_TYPE (type, nfields - 1)); + } + else + { + TYPE_FIELD_TYPE (rtype, nfields - 1) = branch_type; + TYPE_FIELD_NAME (rtype, nfields - 1) = "S"; + TYPE_FIELD_BITSIZE (rtype, nfields - 1) = 0; + TYPE_LENGTH (rtype) += TYPE_LENGTH (branch_type); + -TYPE_LENGTH (TYPE_FIELD_TYPE (type, nfields - 1)); + } + + return rtype; +} + +/* An ordinary record type (with fixed-length fields) that describes + the value at (TYPE0, VALADDR, ADDRESS) [see explanation at + beginning of this section]. Any necessary discriminants' values + should be in DVAL, a record value; it should be NULL if the object + at ADDR itself contains any necessary discriminant values. A + variant field (unless unchecked) is replaced by a particular branch + of the variant. */ + +static struct type * +to_fixed_record_type (struct type *type0, char *valaddr, CORE_ADDR address, + struct value *dval) +{ + struct type *templ_type; + + /* FIXME: TYPE_FLAG_FIXED_INSTANCE should be defined in gdbtypes.h */ + /* if (TYPE_FLAGS (type0) & TYPE_FLAG_FIXED_INSTANCE) + return type0; + */ + templ_type = dynamic_template_type (type0); + + if (templ_type != NULL) + return template_to_fixed_record_type (templ_type, valaddr, address, dval); + else if (contains_variant_part (type0)) + return to_record_with_fixed_variant_part (type0, valaddr, address, dval); + else + { + /* FIXME: TYPE_FLAG_FIXED_INSTANCE should be defined in gdbtypes.h */ + /* TYPE_FLAGS (type0) |= TYPE_FLAG_FIXED_INSTANCE; */ + return type0; + } + +} + +/* An ordinary record type (with fixed-length fields) that describes + the value at (VAR_TYPE0, VALADDR, ADDRESS), where VAR_TYPE0 is a + union type. Any necessary discriminants' values should be in DVAL, + a record value. That is, this routine selects the appropriate + branch of the union at ADDR according to the discriminant value + indicated in the union's type name. */ + +static struct type * +to_fixed_variant_branch_type (struct type *var_type0, char *valaddr, + CORE_ADDR address, struct value *dval) +{ + int which; + struct type *templ_type; + struct type *var_type; + + if (TYPE_CODE (var_type0) == TYPE_CODE_PTR) + var_type = TYPE_TARGET_TYPE (var_type0); + else + var_type = var_type0; + + templ_type = ada_find_parallel_type (var_type, "___XVU"); + + if (templ_type != NULL) + var_type = templ_type; + + which = + ada_which_variant_applies (var_type, + VALUE_TYPE (dval), VALUE_CONTENTS (dval)); + + if (which < 0) + return empty_record (TYPE_OBJFILE (var_type)); + else if (is_dynamic_field (var_type, which)) + return + to_fixed_record_type + (TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (var_type, which)), + valaddr, address, dval); + else if (contains_variant_part (TYPE_FIELD_TYPE (var_type, which))) + return + to_fixed_record_type + (TYPE_FIELD_TYPE (var_type, which), valaddr, address, dval); + else + return TYPE_FIELD_TYPE (var_type, which); +} + +/* Assuming that TYPE0 is an array type describing the type of a value + at ADDR, and that DVAL describes a record containing any + discriminants used in TYPE0, returns a type for the value that + contains no dynamic components (that is, no components whose sizes + are determined by run-time quantities). Unless IGNORE_TOO_BIG is + true, gives an error message if the resulting type's size is over + varsize_limit. +*/ + +static struct type * +to_fixed_array_type (struct type *type0, struct value *dval, + int ignore_too_big) +{ + struct type *index_type_desc; + struct type *result; + + /* FIXME: TYPE_FLAG_FIXED_INSTANCE should be defined in gdbtypes.h */ +/* if (ada_is_packed_array_type (type0) /* revisit? *//* + || (TYPE_FLAGS (type0) & TYPE_FLAG_FIXED_INSTANCE)) + return type0; */ + + index_type_desc = ada_find_parallel_type (type0, "___XA"); + if (index_type_desc == NULL) + { + struct type *elt_type0 = check_typedef (TYPE_TARGET_TYPE (type0)); + /* NOTE: elt_type---the fixed version of elt_type0---should never + * depend on the contents of the array in properly constructed + * debugging data. */ + struct type *elt_type = ada_to_fixed_type (elt_type0, 0, 0, dval); + + if (elt_type0 == elt_type) + result = type0; + else + result = create_array_type (alloc_type (TYPE_OBJFILE (type0)), + elt_type, TYPE_INDEX_TYPE (type0)); + } + else + { + int i; + struct type *elt_type0; + + elt_type0 = type0; + for (i = TYPE_NFIELDS (index_type_desc); i > 0; i -= 1) + elt_type0 = TYPE_TARGET_TYPE (elt_type0); + + /* NOTE: result---the fixed version of elt_type0---should never + * depend on the contents of the array in properly constructed + * debugging data. */ + result = ada_to_fixed_type (check_typedef (elt_type0), 0, 0, dval); + for (i = TYPE_NFIELDS (index_type_desc) - 1; i >= 0; i -= 1) + { + struct type *range_type = + to_fixed_range_type (TYPE_FIELD_NAME (index_type_desc, i), + dval, TYPE_OBJFILE (type0)); + result = create_array_type (alloc_type (TYPE_OBJFILE (type0)), + result, range_type); + } + if (!ignore_too_big && TYPE_LENGTH (result) > varsize_limit) + error ("array type with dynamic size is larger than varsize-limit"); + } + +/* FIXME: TYPE_FLAG_FIXED_INSTANCE should be defined in gdbtypes.h */ +/* TYPE_FLAGS (result) |= TYPE_FLAG_FIXED_INSTANCE; */ + return result; +} + + +/* A standard type (containing no dynamically sized components) + corresponding to TYPE for the value (TYPE, VALADDR, ADDRESS) + DVAL describes a record containing any discriminants used in TYPE0, + and may be NULL if there are none. */ + +struct type * +ada_to_fixed_type (struct type *type, char *valaddr, CORE_ADDR address, + struct value *dval) +{ + CHECK_TYPEDEF (type); + switch (TYPE_CODE (type)) + { + default: + return type; + case TYPE_CODE_STRUCT: + return to_fixed_record_type (type, valaddr, address, NULL); + case TYPE_CODE_ARRAY: + return to_fixed_array_type (type, dval, 0); + case TYPE_CODE_UNION: + if (dval == NULL) + return type; + else + return to_fixed_variant_branch_type (type, valaddr, address, dval); + } +} + +/* A standard (static-sized) type corresponding as well as possible to + TYPE0, but based on no runtime data. */ + +static struct type * +to_static_fixed_type (struct type *type0) +{ + struct type *type; + + if (type0 == NULL) + return NULL; + + /* FIXME: TYPE_FLAG_FIXED_INSTANCE should be defined in gdbtypes.h */ + /* if (TYPE_FLAGS (type0) & TYPE_FLAG_FIXED_INSTANCE) + return type0; + */ + CHECK_TYPEDEF (type0); + + switch (TYPE_CODE (type0)) + { + default: + return type0; + case TYPE_CODE_STRUCT: + type = dynamic_template_type (type0); + if (type != NULL) + return template_to_static_fixed_type (type); + return type0; + case TYPE_CODE_UNION: + type = ada_find_parallel_type (type0, "___XVU"); + if (type != NULL) + return template_to_static_fixed_type (type); + return type0; + } +} + +/* A static approximation of TYPE with all type wrappers removed. */ +static struct type * +static_unwrap_type (struct type *type) +{ + if (ada_is_aligner_type (type)) + { + struct type *type1 = TYPE_FIELD_TYPE (check_typedef (type), 0); + if (ada_type_name (type1) == NULL) + TYPE_NAME (type1) = ada_type_name (type); + + return static_unwrap_type (type1); + } + else + { + struct type *raw_real_type = ada_get_base_type (type); + if (raw_real_type == type) + return type; + else + return to_static_fixed_type (raw_real_type); + } +} + +/* In some cases, incomplete and private types require + cross-references that are not resolved as records (for example, + type Foo; + type FooP is access Foo; + V: FooP; + type Foo is array ...; + ). In these cases, since there is no mechanism for producing + cross-references to such types, we instead substitute for FooP a + stub enumeration type that is nowhere resolved, and whose tag is + the name of the actual type. Call these types "non-record stubs". */ + +/* A type equivalent to TYPE that is not a non-record stub, if one + exists, otherwise TYPE. */ +struct type * +ada_completed_type (struct type *type) +{ + CHECK_TYPEDEF (type); + if (type == NULL || TYPE_CODE (type) != TYPE_CODE_ENUM + || (TYPE_FLAGS (type) & TYPE_FLAG_STUB) == 0 + || TYPE_TAG_NAME (type) == NULL) + return type; + else + { + char *name = TYPE_TAG_NAME (type); + struct type *type1 = ada_find_any_type (name); + return (type1 == NULL) ? type : type1; + } +} + +/* A value representing the data at VALADDR/ADDRESS as described by + type TYPE0, but with a standard (static-sized) type that correctly + describes it. If VAL0 is not NULL and TYPE0 already is a standard + type, then return VAL0 [this feature is simply to avoid redundant + creation of struct values]. */ + +struct value * +ada_to_fixed_value (struct type *type0, char *valaddr, CORE_ADDR address, + struct value *val0) +{ + struct type *type = ada_to_fixed_type (type0, valaddr, address, NULL); + if (type == type0 && val0 != NULL) + return val0; + else + return value_from_contents_and_address (type, valaddr, address); +} + +/* A value representing VAL, but with a standard (static-sized) type + chosen to approximate the real type of VAL as well as possible, but + without consulting any runtime values. For Ada dynamic-sized + types, therefore, the type of the result is likely to be inaccurate. */ + +struct value * +ada_to_static_fixed_value (struct value *val) +{ + struct type *type = + to_static_fixed_type (static_unwrap_type (VALUE_TYPE (val))); + if (type == VALUE_TYPE (val)) + return val; + else + return coerce_unspec_val_to_type (val, 0, type); +} + + + + + +/* Attributes */ + +/* Table mapping attribute numbers to names */ +/* NOTE: Keep up to date with enum ada_attribute definition in ada-lang.h */ + +static const char *attribute_names[] = { + "<?>", + + "first", + "last", + "length", + "image", + "img", + "max", + "min", + "pos" "tag", + "val", + + 0 +}; + +const char * +ada_attribute_name (int n) +{ + if (n > 0 && n < (int) ATR_END) + return attribute_names[n]; + else + return attribute_names[0]; +} + +/* Evaluate the 'POS attribute applied to ARG. */ + +static struct value * +value_pos_atr (struct value *arg) +{ + struct type *type = VALUE_TYPE (arg); + + if (!discrete_type_p (type)) + error ("'POS only defined on discrete types"); + + if (TYPE_CODE (type) == TYPE_CODE_ENUM) + { + int i; + LONGEST v = value_as_long (arg); + + for (i = 0; i < TYPE_NFIELDS (type); i += 1) + { + if (v == TYPE_FIELD_BITPOS (type, i)) + return value_from_longest (builtin_type_ada_int, i); + } + error ("enumeration value is invalid: can't find 'POS"); + } + else + return value_from_longest (builtin_type_ada_int, value_as_long (arg)); +} + +/* Evaluate the TYPE'VAL attribute applied to ARG. */ + +static struct value * +value_val_atr (struct type *type, struct value *arg) +{ + if (!discrete_type_p (type)) + error ("'VAL only defined on discrete types"); + if (!integer_type_p (VALUE_TYPE (arg))) + error ("'VAL requires integral argument"); + + if (TYPE_CODE (type) == TYPE_CODE_ENUM) + { + long pos = value_as_long (arg); + if (pos < 0 || pos >= TYPE_NFIELDS (type)) + error ("argument to 'VAL out of range"); + return value_from_longest (type, TYPE_FIELD_BITPOS (type, pos)); + } + else + return value_from_longest (type, value_as_long (arg)); +} + + + /* Evaluation */ + +/* True if TYPE appears to be an Ada character type. + * [At the moment, this is true only for Character and Wide_Character; + * It is a heuristic test that could stand improvement]. */ + +int +ada_is_character_type (struct type *type) +{ + const char *name = ada_type_name (type); + return + name != NULL + && (TYPE_CODE (type) == TYPE_CODE_CHAR + || TYPE_CODE (type) == TYPE_CODE_INT + || TYPE_CODE (type) == TYPE_CODE_RANGE) + && (STREQ (name, "character") || STREQ (name, "wide_character") + || STREQ (name, "unsigned char")); +} + +/* True if TYPE appears to be an Ada string type. */ + +int +ada_is_string_type (struct type *type) +{ + CHECK_TYPEDEF (type); + if (type != NULL + && TYPE_CODE (type) != TYPE_CODE_PTR + && (ada_is_simple_array (type) || ada_is_array_descriptor (type)) + && ada_array_arity (type) == 1) + { + struct type *elttype = ada_array_element_type (type, 1); + + return ada_is_character_type (elttype); + } + else + return 0; +} + + +/* True if TYPE is a struct type introduced by the compiler to force the + alignment of a value. Such types have a single field with a + distinctive name. */ + +int +ada_is_aligner_type (struct type *type) +{ + CHECK_TYPEDEF (type); + return (TYPE_CODE (type) == TYPE_CODE_STRUCT + && TYPE_NFIELDS (type) == 1 + && STREQ (TYPE_FIELD_NAME (type, 0), "F")); +} + +/* If there is an ___XVS-convention type parallel to SUBTYPE, return + the parallel type. */ + +struct type * +ada_get_base_type (struct type *raw_type) +{ + struct type *real_type_namer; + struct type *raw_real_type; + struct type *real_type; + + if (raw_type == NULL || TYPE_CODE (raw_type) != TYPE_CODE_STRUCT) + return raw_type; + + real_type_namer = ada_find_parallel_type (raw_type, "___XVS"); + if (real_type_namer == NULL + || TYPE_CODE (real_type_namer) != TYPE_CODE_STRUCT + || TYPE_NFIELDS (real_type_namer) != 1) + return raw_type; + + raw_real_type = ada_find_any_type (TYPE_FIELD_NAME (real_type_namer, 0)); + if (raw_real_type == NULL) + return raw_type; + else + return raw_real_type; +} + +/* The type of value designated by TYPE, with all aligners removed. */ + +struct type * +ada_aligned_type (struct type *type) +{ + if (ada_is_aligner_type (type)) + return ada_aligned_type (TYPE_FIELD_TYPE (type, 0)); + else + return ada_get_base_type (type); +} + + +/* The address of the aligned value in an object at address VALADDR + having type TYPE. Assumes ada_is_aligner_type (TYPE). */ + +char * +ada_aligned_value_addr (struct type *type, char *valaddr) +{ + if (ada_is_aligner_type (type)) + return ada_aligned_value_addr (TYPE_FIELD_TYPE (type, 0), + valaddr + + TYPE_FIELD_BITPOS (type, + 0) / TARGET_CHAR_BIT); + else + return valaddr; +} + +/* The printed representation of an enumeration literal with encoded + name NAME. The value is good to the next call of ada_enum_name. */ +const char * +ada_enum_name (const char *name) +{ + char *tmp; + + while (1) + { + if ((tmp = strstr (name, "__")) != NULL) + name = tmp + 2; + else if ((tmp = strchr (name, '.')) != NULL) + name = tmp + 1; + else + break; + } + + if (name[0] == 'Q') + { + static char result[16]; + int v; + if (name[1] == 'U' || name[1] == 'W') + { + if (sscanf (name + 2, "%x", &v) != 1) + return name; + } + else + return name; + + if (isascii (v) && isprint (v)) + sprintf (result, "'%c'", v); + else if (name[1] == 'U') + sprintf (result, "[\"%02x\"]", v); + else + sprintf (result, "[\"%04x\"]", v); + + return result; + } + else + return name; +} + +static struct value * +evaluate_subexp (struct type *expect_type, struct expression *exp, int *pos, + enum noside noside) +{ + return (*exp->language_defn->evaluate_exp) (expect_type, exp, pos, noside); +} + +/* Evaluate the subexpression of EXP starting at *POS as for + evaluate_type, updating *POS to point just past the evaluated + expression. */ + +static struct value * +evaluate_subexp_type (struct expression *exp, int *pos) +{ + return (*exp->language_defn->evaluate_exp) + (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS); +} + +/* If VAL is wrapped in an aligner or subtype wrapper, return the + value it wraps. */ + +static struct value * +unwrap_value (struct value *val) +{ + struct type *type = check_typedef (VALUE_TYPE (val)); + if (ada_is_aligner_type (type)) + { + struct value *v = value_struct_elt (&val, NULL, "F", + NULL, "internal structure"); + struct type *val_type = check_typedef (VALUE_TYPE (v)); + if (ada_type_name (val_type) == NULL) + TYPE_NAME (val_type) = ada_type_name (type); + + return unwrap_value (v); + } + else + { + struct type *raw_real_type = + ada_completed_type (ada_get_base_type (type)); + + if (type == raw_real_type) + return val; + + return + coerce_unspec_val_to_type + (val, 0, ada_to_fixed_type (raw_real_type, 0, + VALUE_ADDRESS (val) + VALUE_OFFSET (val), + NULL)); + } +} + +static struct value * +cast_to_fixed (struct type *type, struct value *arg) +{ + LONGEST val; + + if (type == VALUE_TYPE (arg)) + return arg; + else if (ada_is_fixed_point_type (VALUE_TYPE (arg))) + val = ada_float_to_fixed (type, + ada_fixed_to_float (VALUE_TYPE (arg), + value_as_long (arg))); + else + { + DOUBLEST argd = + value_as_double (value_cast (builtin_type_double, value_copy (arg))); + val = ada_float_to_fixed (type, argd); + } + + return value_from_longest (type, val); +} + +static struct value * +cast_from_fixed_to_double (struct value *arg) +{ + DOUBLEST val = ada_fixed_to_float (VALUE_TYPE (arg), + value_as_long (arg)); + return value_from_double (builtin_type_double, val); +} + +/* Coerce VAL as necessary for assignment to an lval of type TYPE, and + * return the converted value. */ +static struct value * +coerce_for_assign (struct type *type, struct value *val) +{ + struct type *type2 = VALUE_TYPE (val); + if (type == type2) + return val; + + CHECK_TYPEDEF (type2); + CHECK_TYPEDEF (type); + + if (TYPE_CODE (type2) == TYPE_CODE_PTR + && TYPE_CODE (type) == TYPE_CODE_ARRAY) + { + val = ada_value_ind (val); + type2 = VALUE_TYPE (val); + } + + if (TYPE_CODE (type2) == TYPE_CODE_ARRAY + && TYPE_CODE (type) == TYPE_CODE_ARRAY) + { + if (TYPE_LENGTH (type2) != TYPE_LENGTH (type) + || TYPE_LENGTH (TYPE_TARGET_TYPE (type2)) + != TYPE_LENGTH (TYPE_TARGET_TYPE (type2))) + error ("Incompatible types in assignment"); + VALUE_TYPE (val) = type; + } + return val; +} + +struct value * +ada_evaluate_subexp (struct type *expect_type, struct expression *exp, + int *pos, enum noside noside) +{ + enum exp_opcode op; + enum ada_attribute atr; + int tem, tem2, tem3; + int pc; + struct value *arg1 = NULL, *arg2 = NULL, *arg3; + struct type *type; + int nargs; + struct value **argvec; + + pc = *pos; + *pos += 1; + op = exp->elts[pc].opcode; + + switch (op) + { + default: + *pos -= 1; + return + unwrap_value (evaluate_subexp_standard + (expect_type, exp, pos, noside)); + + case UNOP_CAST: + (*pos) += 2; + type = exp->elts[pc + 1].type; + arg1 = evaluate_subexp (type, exp, pos, noside); + if (noside == EVAL_SKIP) + goto nosideret; + if (type != check_typedef (VALUE_TYPE (arg1))) + { + if (ada_is_fixed_point_type (type)) + arg1 = cast_to_fixed (type, arg1); + else if (ada_is_fixed_point_type (VALUE_TYPE (arg1))) + arg1 = value_cast (type, cast_from_fixed_to_double (arg1)); + else if (VALUE_LVAL (arg1) == lval_memory) + { + /* This is in case of the really obscure (and undocumented, + but apparently expected) case of (Foo) Bar.all, where Bar + is an integer constant and Foo is a dynamic-sized type. + If we don't do this, ARG1 will simply be relabeled with + TYPE. */ + if (noside == EVAL_AVOID_SIDE_EFFECTS) + return value_zero (to_static_fixed_type (type), not_lval); + arg1 = + ada_to_fixed_value + (type, 0, VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1), 0); + } + else + arg1 = value_cast (type, arg1); + } + return arg1; + + /* FIXME: UNOP_QUAL should be defined in expression.h */ + /* case UNOP_QUAL: + (*pos) += 2; + type = exp->elts[pc + 1].type; + return ada_evaluate_subexp (type, exp, pos, noside); + */ + case BINOP_ASSIGN: + arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside); + if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS) + return arg1; + if (binop_user_defined_p (op, arg1, arg2)) + return value_x_binop (arg1, arg2, op, OP_NULL, EVAL_NORMAL); + else + { + if (ada_is_fixed_point_type (VALUE_TYPE (arg1))) + arg2 = cast_to_fixed (VALUE_TYPE (arg1), arg2); + else if (ada_is_fixed_point_type (VALUE_TYPE (arg2))) + error + ("Fixed-point values must be assigned to fixed-point variables"); + else + arg2 = coerce_for_assign (VALUE_TYPE (arg1), arg2); + return ada_value_assign (arg1, arg2); + } + + case BINOP_ADD: + arg1 = evaluate_subexp_with_coercion (exp, pos, noside); + arg2 = evaluate_subexp_with_coercion (exp, pos, noside); + if (noside == EVAL_SKIP) + goto nosideret; + if (binop_user_defined_p (op, arg1, arg2)) + return value_x_binop (arg1, arg2, op, OP_NULL, EVAL_NORMAL); + else + { + if ((ada_is_fixed_point_type (VALUE_TYPE (arg1)) + || ada_is_fixed_point_type (VALUE_TYPE (arg2))) + && VALUE_TYPE (arg1) != VALUE_TYPE (arg2)) + error + ("Operands of fixed-point addition must have the same type"); + return value_cast (VALUE_TYPE (arg1), value_add (arg1, arg2)); + } + + case BINOP_SUB: + arg1 = evaluate_subexp_with_coercion (exp, pos, noside); + arg2 = evaluate_subexp_with_coercion (exp, pos, noside); + if (noside == EVAL_SKIP) + goto nosideret; + if (binop_user_defined_p (op, arg1, arg2)) + return value_x_binop (arg1, arg2, op, OP_NULL, EVAL_NORMAL); + else + { + if ((ada_is_fixed_point_type (VALUE_TYPE (arg1)) + || ada_is_fixed_point_type (VALUE_TYPE (arg2))) + && VALUE_TYPE (arg1) != VALUE_TYPE (arg2)) + error + ("Operands of fixed-point subtraction must have the same type"); + return value_cast (VALUE_TYPE (arg1), value_sub (arg1, arg2)); + } + + case BINOP_MUL: + case BINOP_DIV: + arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + if (noside == EVAL_SKIP) + goto nosideret; + if (binop_user_defined_p (op, arg1, arg2)) + return value_x_binop (arg1, arg2, op, OP_NULL, EVAL_NORMAL); + else + if (noside == EVAL_AVOID_SIDE_EFFECTS + && (op == BINOP_DIV || op == BINOP_REM || op == BINOP_MOD)) + return value_zero (VALUE_TYPE (arg1), not_lval); + else + { + if (ada_is_fixed_point_type (VALUE_TYPE (arg1))) + arg1 = cast_from_fixed_to_double (arg1); + if (ada_is_fixed_point_type (VALUE_TYPE (arg2))) + arg2 = cast_from_fixed_to_double (arg2); + return value_binop (arg1, arg2, op); + } + + case UNOP_NEG: + arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + if (noside == EVAL_SKIP) + goto nosideret; + if (unop_user_defined_p (op, arg1)) + return value_x_unop (arg1, op, EVAL_NORMAL); + else if (ada_is_fixed_point_type (VALUE_TYPE (arg1))) + return value_cast (VALUE_TYPE (arg1), value_neg (arg1)); + else + return value_neg (arg1); + + /* FIXME: OP_UNRESOLVED_VALUE should be defined in expression.h */ + /* case OP_UNRESOLVED_VALUE: + /* Only encountered when an unresolved symbol occurs in a + context other than a function call, in which case, it is + illegal. *//* + (*pos) += 3; + if (noside == EVAL_SKIP) + goto nosideret; + else + error ("Unexpected unresolved symbol, %s, during evaluation", + ada_demangle (exp->elts[pc + 2].name)); + */ + case OP_VAR_VALUE: + *pos -= 1; + if (noside == EVAL_SKIP) + { + *pos += 4; + goto nosideret; + } + else if (noside == EVAL_AVOID_SIDE_EFFECTS) + { + *pos += 4; + return value_zero + (to_static_fixed_type + (static_unwrap_type (SYMBOL_TYPE (exp->elts[pc + 2].symbol))), + not_lval); + } + else + { + arg1 = + unwrap_value (evaluate_subexp_standard + (expect_type, exp, pos, noside)); + return ada_to_fixed_value (VALUE_TYPE (arg1), 0, + VALUE_ADDRESS (arg1) + + VALUE_OFFSET (arg1), arg1); + } + + case OP_ARRAY: + (*pos) += 3; + tem2 = longest_to_int (exp->elts[pc + 1].longconst); + tem3 = longest_to_int (exp->elts[pc + 2].longconst); + nargs = tem3 - tem2 + 1; + type = expect_type ? check_typedef (expect_type) : NULL_TYPE; + + argvec = + (struct value * *) alloca (sizeof (struct value *) * (nargs + 1)); + for (tem = 0; tem == 0 || tem < nargs; tem += 1) + /* At least one element gets inserted for the type */ + { + /* Ensure that array expressions are coerced into pointer objects. */ + argvec[tem] = evaluate_subexp_with_coercion (exp, pos, noside); + } + if (noside == EVAL_SKIP) + goto nosideret; + return value_array (tem2, tem3, argvec); + + case OP_FUNCALL: + (*pos) += 2; + + /* Allocate arg vector, including space for the function to be + called in argvec[0] and a terminating NULL */ + nargs = longest_to_int (exp->elts[pc + 1].longconst); + argvec = + (struct value * *) alloca (sizeof (struct value *) * (nargs + 2)); + + /* FIXME: OP_UNRESOLVED_VALUE should be defined in expression.h */ + /* FIXME: name should be defined in expresion.h */ + /* if (exp->elts[*pos].opcode == OP_UNRESOLVED_VALUE) + error ("Unexpected unresolved symbol, %s, during evaluation", + ada_demangle (exp->elts[pc + 5].name)); + */ + if (0) + { + error ("unexpected code path, FIXME"); + } + else + { + for (tem = 0; tem <= nargs; tem += 1) + argvec[tem] = evaluate_subexp (NULL_TYPE, exp, pos, noside); + argvec[tem] = 0; + + if (noside == EVAL_SKIP) + goto nosideret; + } + + if (TYPE_CODE (VALUE_TYPE (argvec[0])) == TYPE_CODE_REF) + argvec[0] = value_addr (argvec[0]); + + if (ada_is_packed_array_type (VALUE_TYPE (argvec[0]))) + argvec[0] = ada_coerce_to_simple_array (argvec[0]); + + type = check_typedef (VALUE_TYPE (argvec[0])); + if (TYPE_CODE (type) == TYPE_CODE_PTR) + { + switch (TYPE_CODE (check_typedef (TYPE_TARGET_TYPE (type)))) + { + case TYPE_CODE_FUNC: + type = check_typedef (TYPE_TARGET_TYPE (type)); + break; + case TYPE_CODE_ARRAY: + break; + case TYPE_CODE_STRUCT: + if (noside != EVAL_AVOID_SIDE_EFFECTS) + argvec[0] = ada_value_ind (argvec[0]); + type = check_typedef (TYPE_TARGET_TYPE (type)); + break; + default: + error ("cannot subscript or call something of type `%s'", + ada_type_name (VALUE_TYPE (argvec[0]))); + break; + } + } + + switch (TYPE_CODE (type)) + { + case TYPE_CODE_FUNC: + if (noside == EVAL_AVOID_SIDE_EFFECTS) + return allocate_value (TYPE_TARGET_TYPE (type)); + return call_function_by_hand (argvec[0], nargs, argvec + 1); + case TYPE_CODE_STRUCT: + { + int arity = ada_array_arity (type); + type = ada_array_element_type (type, nargs); + if (type == NULL) + error ("cannot subscript or call a record"); + if (arity != nargs) + error ("wrong number of subscripts; expecting %d", arity); + if (noside == EVAL_AVOID_SIDE_EFFECTS) + return allocate_value (ada_aligned_type (type)); + return + unwrap_value (ada_value_subscript + (argvec[0], nargs, argvec + 1)); + } + case TYPE_CODE_ARRAY: + if (noside == EVAL_AVOID_SIDE_EFFECTS) + { + type = ada_array_element_type (type, nargs); + if (type == NULL) + error ("element type of array unknown"); + else + return allocate_value (ada_aligned_type (type)); + } + return + unwrap_value (ada_value_subscript + (ada_coerce_to_simple_array (argvec[0]), + nargs, argvec + 1)); + case TYPE_CODE_PTR: /* Pointer to array */ + type = to_fixed_array_type (TYPE_TARGET_TYPE (type), NULL, 1); + if (noside == EVAL_AVOID_SIDE_EFFECTS) + { + type = ada_array_element_type (type, nargs); + if (type == NULL) + error ("element type of array unknown"); + else + return allocate_value (ada_aligned_type (type)); + } + return + unwrap_value (ada_value_ptr_subscript (argvec[0], type, + nargs, argvec + 1)); + + default: + error ("Internal error in evaluate_subexp"); + } + + case TERNOP_SLICE: + { + struct value *array = evaluate_subexp (NULL_TYPE, exp, pos, noside); + int lowbound + = value_as_long (evaluate_subexp (NULL_TYPE, exp, pos, noside)); + int upper + = value_as_long (evaluate_subexp (NULL_TYPE, exp, pos, noside)); + if (noside == EVAL_SKIP) + goto nosideret; + + /* If this is a reference to an array, then dereference it */ + if (TYPE_CODE (VALUE_TYPE (array)) == TYPE_CODE_REF + && TYPE_TARGET_TYPE (VALUE_TYPE (array)) != NULL + && TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (array))) == + TYPE_CODE_ARRAY + && !ada_is_array_descriptor (check_typedef (VALUE_TYPE (array)))) + { + array = ada_coerce_ref (array); + } + + if (noside == EVAL_AVOID_SIDE_EFFECTS && + ada_is_array_descriptor (check_typedef (VALUE_TYPE (array)))) + { + /* Try to dereference the array, in case it is an access to array */ + struct type *arrType = ada_type_of_array (array, 0); + if (arrType != NULL) + array = value_at_lazy (arrType, 0, NULL); + } + if (ada_is_array_descriptor (VALUE_TYPE (array))) + array = ada_coerce_to_simple_array (array); + + /* If at this point we have a pointer to an array, it means that + it is a pointer to a simple (non-ada) array. We just then + dereference it */ + if (TYPE_CODE (VALUE_TYPE (array)) == TYPE_CODE_PTR + && TYPE_TARGET_TYPE (VALUE_TYPE (array)) != NULL + && TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (array))) == + TYPE_CODE_ARRAY) + { + array = ada_value_ind (array); + } + + if (noside == EVAL_AVOID_SIDE_EFFECTS) + /* The following will get the bounds wrong, but only in contexts + where the value is not being requested (FIXME?). */ + return array; + else + return value_slice (array, lowbound, upper - lowbound + 1); + } + + /* FIXME: UNOP_MBR should be defined in expression.h */ + /* case UNOP_MBR: + (*pos) += 2; + arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + type = exp->elts[pc + 1].type; + + if (noside == EVAL_SKIP) + goto nosideret; + + switch (TYPE_CODE (type)) + { + default: + warning ("Membership test incompletely implemented; always returns true"); + return value_from_longest (builtin_type_int, (LONGEST) 1); + + case TYPE_CODE_RANGE: + arg2 = value_from_longest (builtin_type_int, + (LONGEST) TYPE_LOW_BOUND (type)); + arg3 = value_from_longest (builtin_type_int, + (LONGEST) TYPE_HIGH_BOUND (type)); + return + value_from_longest (builtin_type_int, + (value_less (arg1,arg3) + || value_equal (arg1,arg3)) + && (value_less (arg2,arg1) + || value_equal (arg2,arg1))); + } + */ + /* FIXME: BINOP_MBR should be defined in expression.h */ + /* case BINOP_MBR: + (*pos) += 2; + arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + + if (noside == EVAL_SKIP) + goto nosideret; + + if (noside == EVAL_AVOID_SIDE_EFFECTS) + return value_zero (builtin_type_int, not_lval); + + tem = longest_to_int (exp->elts[pc + 1].longconst); + + if (tem < 1 || tem > ada_array_arity (VALUE_TYPE (arg2))) + error ("invalid dimension number to '%s", "range"); + + arg3 = ada_array_bound (arg2, tem, 1); + arg2 = ada_array_bound (arg2, tem, 0); + + return + value_from_longest (builtin_type_int, + (value_less (arg1,arg3) + || value_equal (arg1,arg3)) + && (value_less (arg2,arg1) + || value_equal (arg2,arg1))); + */ + /* FIXME: TERNOP_MBR should be defined in expression.h */ + /* case TERNOP_MBR: + arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + arg3 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + + if (noside == EVAL_SKIP) + goto nosideret; + + return + value_from_longest (builtin_type_int, + (value_less (arg1,arg3) + || value_equal (arg1,arg3)) + && (value_less (arg2,arg1) + || value_equal (arg2,arg1))); + */ + /* FIXME: OP_ATTRIBUTE should be defined in expression.h */ + /* case OP_ATTRIBUTE: + *pos += 3; + atr = (enum ada_attribute) longest_to_int (exp->elts[pc + 2].longconst); + switch (atr) + { + default: + error ("unexpected attribute encountered"); + + case ATR_FIRST: + case ATR_LAST: + case ATR_LENGTH: + { + struct type* type_arg; + if (exp->elts[*pos].opcode == OP_TYPE) + { + evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP); + arg1 = NULL; + type_arg = exp->elts[pc + 5].type; + } + else + { + arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + type_arg = NULL; + } + + if (exp->elts[*pos].opcode != OP_LONG) + error ("illegal operand to '%s", ada_attribute_name (atr)); + tem = longest_to_int (exp->elts[*pos+2].longconst); + *pos += 4; + + if (noside == EVAL_SKIP) + goto nosideret; + + if (type_arg == NULL) + { + arg1 = ada_coerce_ref (arg1); + + if (ada_is_packed_array_type (VALUE_TYPE (arg1))) + arg1 = ada_coerce_to_simple_array (arg1); + + if (tem < 1 || tem > ada_array_arity (VALUE_TYPE (arg1))) + error ("invalid dimension number to '%s", + ada_attribute_name (atr)); + + if (noside == EVAL_AVOID_SIDE_EFFECTS) + { + type = ada_index_type (VALUE_TYPE (arg1), tem); + if (type == NULL) + error ("attempt to take bound of something that is not an array"); + return allocate_value (type); + } + + switch (atr) + { + default: + error ("unexpected attribute encountered"); + case ATR_FIRST: + return ada_array_bound (arg1, tem, 0); + case ATR_LAST: + return ada_array_bound (arg1, tem, 1); + case ATR_LENGTH: + return ada_array_length (arg1, tem); + } + } + else if (TYPE_CODE (type_arg) == TYPE_CODE_RANGE + || TYPE_CODE (type_arg) == TYPE_CODE_INT) + { + struct type* range_type; + char* name = ada_type_name (type_arg); + if (name == NULL) + { + if (TYPE_CODE (type_arg) == TYPE_CODE_RANGE) + range_type = type_arg; + else + error ("unimplemented type attribute"); + } + else + range_type = + to_fixed_range_type (name, NULL, TYPE_OBJFILE (type_arg)); + switch (atr) + { + default: + error ("unexpected attribute encountered"); + case ATR_FIRST: + return value_from_longest (TYPE_TARGET_TYPE (range_type), + TYPE_LOW_BOUND (range_type)); + case ATR_LAST: + return value_from_longest (TYPE_TARGET_TYPE (range_type), + TYPE_HIGH_BOUND (range_type)); + } + } + else if (TYPE_CODE (type_arg) == TYPE_CODE_ENUM) + { + switch (atr) + { + default: + error ("unexpected attribute encountered"); + case ATR_FIRST: + return value_from_longest + (type_arg, TYPE_FIELD_BITPOS (type_arg, 0)); + case ATR_LAST: + return value_from_longest + (type_arg, + TYPE_FIELD_BITPOS (type_arg, + TYPE_NFIELDS (type_arg) - 1)); + } + } + else if (TYPE_CODE (type_arg) == TYPE_CODE_FLT) + error ("unimplemented type attribute"); + else + { + LONGEST low, high; + + if (ada_is_packed_array_type (type_arg)) + type_arg = decode_packed_array_type (type_arg); + + if (tem < 1 || tem > ada_array_arity (type_arg)) + error ("invalid dimension number to '%s", + ada_attribute_name (atr)); + + if (noside == EVAL_AVOID_SIDE_EFFECTS) + { + type = ada_index_type (type_arg, tem); + if (type == NULL) + error ("attempt to take bound of something that is not an array"); + return allocate_value (type); + } + + switch (atr) + { + default: + error ("unexpected attribute encountered"); + case ATR_FIRST: + low = ada_array_bound_from_type (type_arg, tem, 0, &type); + return value_from_longest (type, low); + case ATR_LAST: + high = ada_array_bound_from_type (type_arg, tem, 1, &type); + return value_from_longest (type, high); + case ATR_LENGTH: + low = ada_array_bound_from_type (type_arg, tem, 0, &type); + high = ada_array_bound_from_type (type_arg, tem, 1, NULL); + return value_from_longest (type, high-low+1); + } + } + } + + case ATR_TAG: + arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + if (noside == EVAL_SKIP) + goto nosideret; + + if (noside == EVAL_AVOID_SIDE_EFFECTS) + return + value_zero (ada_tag_type (arg1), not_lval); + + return ada_value_tag (arg1); + + case ATR_MIN: + case ATR_MAX: + evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP); + arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + if (noside == EVAL_SKIP) + goto nosideret; + else if (noside == EVAL_AVOID_SIDE_EFFECTS) + return value_zero (VALUE_TYPE (arg1), not_lval); + else + return value_binop (arg1, arg2, + atr == ATR_MIN ? BINOP_MIN : BINOP_MAX); + + case ATR_MODULUS: + { + struct type* type_arg = exp->elts[pc + 5].type; + evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP); + *pos += 4; + + if (noside == EVAL_SKIP) + goto nosideret; + + if (! ada_is_modular_type (type_arg)) + error ("'modulus must be applied to modular type"); + + return value_from_longest (TYPE_TARGET_TYPE (type_arg), + ada_modulus (type_arg)); + } + + + case ATR_POS: + evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP); + arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + if (noside == EVAL_SKIP) + goto nosideret; + else if (noside == EVAL_AVOID_SIDE_EFFECTS) + return value_zero (builtin_type_ada_int, not_lval); + else + return value_pos_atr (arg1); + + case ATR_SIZE: + arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + if (noside == EVAL_SKIP) + goto nosideret; + else if (noside == EVAL_AVOID_SIDE_EFFECTS) + return value_zero (builtin_type_ada_int, not_lval); + else + return value_from_longest (builtin_type_ada_int, + TARGET_CHAR_BIT + * TYPE_LENGTH (VALUE_TYPE (arg1))); + + case ATR_VAL: + evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP); + arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + type = exp->elts[pc + 5].type; + if (noside == EVAL_SKIP) + goto nosideret; + else if (noside == EVAL_AVOID_SIDE_EFFECTS) + return value_zero (type, not_lval); + else + return value_val_atr (type, arg1); + } */ + case BINOP_EXP: + arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + if (noside == EVAL_SKIP) + goto nosideret; + if (binop_user_defined_p (op, arg1, arg2)) + return unwrap_value (value_x_binop (arg1, arg2, op, OP_NULL, + EVAL_NORMAL)); + else if (noside == EVAL_AVOID_SIDE_EFFECTS) + return value_zero (VALUE_TYPE (arg1), not_lval); + else + return value_binop (arg1, arg2, op); + + case UNOP_PLUS: + arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + if (noside == EVAL_SKIP) + goto nosideret; + if (unop_user_defined_p (op, arg1)) + return unwrap_value (value_x_unop (arg1, op, EVAL_NORMAL)); + else + return arg1; + + case UNOP_ABS: + arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + if (noside == EVAL_SKIP) + goto nosideret; + if (value_less (arg1, value_zero (VALUE_TYPE (arg1), not_lval))) + return value_neg (arg1); + else + return arg1; + + case UNOP_IND: + if (expect_type && TYPE_CODE (expect_type) == TYPE_CODE_PTR) + expect_type = TYPE_TARGET_TYPE (check_typedef (expect_type)); + arg1 = evaluate_subexp (expect_type, exp, pos, noside); + if (noside == EVAL_SKIP) + goto nosideret; + type = check_typedef (VALUE_TYPE (arg1)); + if (noside == EVAL_AVOID_SIDE_EFFECTS) + { + if (ada_is_array_descriptor (type)) + /* GDB allows dereferencing GNAT array descriptors. */ + { + struct type *arrType = ada_type_of_array (arg1, 0); + if (arrType == NULL) + error ("Attempt to dereference null array pointer."); + return value_at_lazy (arrType, 0, NULL); + } + else if (TYPE_CODE (type) == TYPE_CODE_PTR + || TYPE_CODE (type) == TYPE_CODE_REF + /* In C you can dereference an array to get the 1st elt. */ + || TYPE_CODE (type) == TYPE_CODE_ARRAY) + return + value_zero + (to_static_fixed_type + (ada_aligned_type (check_typedef (TYPE_TARGET_TYPE (type)))), + lval_memory); + else if (TYPE_CODE (type) == TYPE_CODE_INT) + /* GDB allows dereferencing an int. */ + return value_zero (builtin_type_int, lval_memory); + else + error ("Attempt to take contents of a non-pointer value."); + } + arg1 = ada_coerce_ref (arg1); + type = check_typedef (VALUE_TYPE (arg1)); + + if (ada_is_array_descriptor (type)) + /* GDB allows dereferencing GNAT array descriptors. */ + return ada_coerce_to_simple_array (arg1); + else + return ada_value_ind (arg1); + + case STRUCTOP_STRUCT: + tem = longest_to_int (exp->elts[pc + 1].longconst); + (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1); + arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + if (noside == EVAL_SKIP) + goto nosideret; + if (noside == EVAL_AVOID_SIDE_EFFECTS) + return value_zero (ada_aligned_type + (ada_lookup_struct_elt_type (VALUE_TYPE (arg1), + &exp->elts[pc + + 2].string, + 0, NULL)), + lval_memory); + else + return unwrap_value (ada_value_struct_elt (arg1, + &exp->elts[pc + 2].string, + "record")); + case OP_TYPE: + /* The value is not supposed to be used. This is here to make it + easier to accommodate expressions that contain types. */ + (*pos) += 2; + if (noside == EVAL_SKIP) + goto nosideret; + else if (noside == EVAL_AVOID_SIDE_EFFECTS) + return allocate_value (builtin_type_void); + else + error ("Attempt to use a type name as an expression"); + + case STRUCTOP_PTR: + tem = longest_to_int (exp->elts[pc + 1].longconst); + (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1); + arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + if (noside == EVAL_SKIP) + goto nosideret; + if (noside == EVAL_AVOID_SIDE_EFFECTS) + return value_zero (ada_aligned_type + (ada_lookup_struct_elt_type (VALUE_TYPE (arg1), + &exp->elts[pc + + 2].string, + 0, NULL)), + lval_memory); + else + return unwrap_value (ada_value_struct_elt (arg1, + &exp->elts[pc + 2].string, + "record access")); + } + +nosideret: + return value_from_longest (builtin_type_long, (LONGEST) 1); +} + + + /* Fixed point */ + +/* If TYPE encodes an Ada fixed-point type, return the suffix of the + type name that encodes the 'small and 'delta information. + Otherwise, return NULL. */ + +static const char * +fixed_type_info (struct type *type) +{ + const char *name = ada_type_name (type); + enum type_code code = (type == NULL) ? TYPE_CODE_UNDEF : TYPE_CODE (type); + + if ((code == TYPE_CODE_INT || code == TYPE_CODE_RANGE) && name != NULL) + { + const char *tail = strstr (name, "___XF_"); + if (tail == NULL) + return NULL; + else + return tail + 5; + } + else if (code == TYPE_CODE_RANGE && TYPE_TARGET_TYPE (type) != type) + return fixed_type_info (TYPE_TARGET_TYPE (type)); + else + return NULL; +} + +/* Returns non-zero iff TYPE represents an Ada fixed-point type. */ + +int +ada_is_fixed_point_type (struct type *type) +{ + return fixed_type_info (type) != NULL; +} + +/* Assuming that TYPE is the representation of an Ada fixed-point + type, return its delta, or -1 if the type is malformed and the + delta cannot be determined. */ + +DOUBLEST +ada_delta (struct type *type) +{ + const char *encoding = fixed_type_info (type); + long num, den; + + if (sscanf (encoding, "_%ld_%ld", &num, &den) < 2) + return -1.0; + else + return (DOUBLEST) num / (DOUBLEST) den; +} + +/* Assuming that ada_is_fixed_point_type (TYPE), return the scaling + factor ('SMALL value) associated with the type. */ + +static DOUBLEST +scaling_factor (struct type *type) +{ + const char *encoding = fixed_type_info (type); + unsigned long num0, den0, num1, den1; + int n; + + n = sscanf (encoding, "_%lu_%lu_%lu_%lu", &num0, &den0, &num1, &den1); + + if (n < 2) + return 1.0; + else if (n == 4) + return (DOUBLEST) num1 / (DOUBLEST) den1; + else + return (DOUBLEST) num0 / (DOUBLEST) den0; +} + + +/* Assuming that X is the representation of a value of fixed-point + type TYPE, return its floating-point equivalent. */ + +DOUBLEST +ada_fixed_to_float (struct type *type, LONGEST x) +{ + return (DOUBLEST) x *scaling_factor (type); +} + +/* The representation of a fixed-point value of type TYPE + corresponding to the value X. */ + +LONGEST +ada_float_to_fixed (struct type *type, DOUBLEST x) +{ + return (LONGEST) (x / scaling_factor (type) + 0.5); +} + + + /* VAX floating formats */ + +/* Non-zero iff TYPE represents one of the special VAX floating-point + types. */ +int +ada_is_vax_floating_type (struct type *type) +{ + int name_len = + (ada_type_name (type) == NULL) ? 0 : strlen (ada_type_name (type)); + return + name_len > 6 + && (TYPE_CODE (type) == TYPE_CODE_INT + || TYPE_CODE (type) == TYPE_CODE_RANGE) + && STREQN (ada_type_name (type) + name_len - 6, "___XF", 5); +} + +/* The type of special VAX floating-point type this is, assuming + ada_is_vax_floating_point */ +int +ada_vax_float_type_suffix (struct type *type) +{ + return ada_type_name (type)[strlen (ada_type_name (type)) - 1]; +} + +/* A value representing the special debugging function that outputs + VAX floating-point values of the type represented by TYPE. Assumes + ada_is_vax_floating_type (TYPE). */ +struct value * +ada_vax_float_print_function (struct type *type) +{ + switch (ada_vax_float_type_suffix (type)) + { + case 'F': + return get_var_value ("DEBUG_STRING_F", 0); + case 'D': + return get_var_value ("DEBUG_STRING_D", 0); + case 'G': + return get_var_value ("DEBUG_STRING_G", 0); + default: + error ("invalid VAX floating-point type"); + } +} + + + /* Range types */ + +/* Scan STR beginning at position K for a discriminant name, and + return the value of that discriminant field of DVAL in *PX. If + PNEW_K is not null, put the position of the character beyond the + name scanned in *PNEW_K. Return 1 if successful; return 0 and do + not alter *PX and *PNEW_K if unsuccessful. */ + +static int +scan_discrim_bound (char *, int k, struct value *dval, LONGEST * px, + int *pnew_k) +{ + static char *bound_buffer = NULL; + static size_t bound_buffer_len = 0; + char *bound; + char *pend; + struct value *bound_val; + + if (dval == NULL || str == NULL || str[k] == '\0') + return 0; + + pend = strstr (str + k, "__"); + if (pend == NULL) + { + bound = str + k; + k += strlen (bound); + } + else + { + GROW_VECT (bound_buffer, bound_buffer_len, pend - (str + k) + 1); + bound = bound_buffer; + strncpy (bound_buffer, str + k, pend - (str + k)); + bound[pend - (str + k)] = '\0'; + k = pend - str; + } + + bound_val = ada_search_struct_field (bound, dval, 0, VALUE_TYPE (dval)); + if (bound_val == NULL) + return 0; + + *px = value_as_long (bound_val); + if (pnew_k != NULL) + *pnew_k = k; + return 1; +} + +/* Value of variable named NAME in the current environment. If + no such variable found, then if ERR_MSG is null, returns 0, and + otherwise causes an error with message ERR_MSG. */ +static struct value * +get_var_value (char *name, char *err_msg) +{ + struct symbol **syms; + struct block **blocks; + int nsyms; + + nsyms = + ada_lookup_symbol_list (name, get_selected_block (NULL), VAR_NAMESPACE, + &syms, &blocks); + + if (nsyms != 1) + { + if (err_msg == NULL) + return 0; + else + error ("%s", err_msg); + } + + return value_of_variable (syms[0], blocks[0]); +} + +/* Value of integer variable named NAME in the current environment. If + no such variable found, then if ERR_MSG is null, returns 0, and sets + *FLAG to 0. If successful, sets *FLAG to 1. */ +LONGEST +get_int_var_value (char *name, char *err_msg, int *flag) +{ + struct value *var_val = get_var_value (name, err_msg); + + if (var_val == 0) + { + if (flag != NULL) + *flag = 0; + return 0; + } + else + { + if (flag != NULL) + *flag = 1; + return value_as_long (var_val); + } +} + + +/* Return a range type whose base type is that of the range type named + NAME in the current environment, and whose bounds are calculated + from NAME according to the GNAT range encoding conventions. + Extract discriminant values, if needed, from DVAL. If a new type + must be created, allocate in OBJFILE's space. The bounds + information, in general, is encoded in NAME, the base type given in + the named range type. */ + +static struct type * +to_fixed_range_type (char *name, struct value *dval, struct objfile *objfile) +{ + struct type *raw_type = ada_find_any_type (name); + struct type *base_type; + LONGEST low, high; + char *subtype_info; + + if (raw_type == NULL) + base_type = builtin_type_int; + else if (TYPE_CODE (raw_type) == TYPE_CODE_RANGE) + base_type = TYPE_TARGET_TYPE (raw_type); + else + base_type = raw_type; + + subtype_info = strstr (name, "___XD"); + if (subtype_info == NULL) + return raw_type; + else + { + static char *name_buf = NULL; + static size_t name_len = 0; + int prefix_len = subtype_info - name; + LONGEST L, U; + struct type *type; + char *bounds_str; + int n; + + GROW_VECT (name_buf, name_len, prefix_len + 5); + strncpy (name_buf, name, prefix_len); + name_buf[prefix_len] = '\0'; + + subtype_info += 5; + bounds_str = strchr (subtype_info, '_'); + n = 1; + + if (*subtype_info == 'L') + { + if (!ada_scan_number (bounds_str, n, &L, &n) + && !scan_discrim_bound (bounds_str, n, dval, &L, &n)) + return raw_type; + if (bounds_str[n] == '_') + n += 2; + else if (bounds_str[n] == '.') /* FIXME? SGI Workshop kludge. */ + n += 1; + subtype_info += 1; + } + else + { + strcpy (name_buf + prefix_len, "___L"); + L = get_int_var_value (name_buf, "Index bound unknown.", NULL); + } + + if (*subtype_info == 'U') + { + if (!ada_scan_number (bounds_str, n, &U, &n) + && !scan_discrim_bound (bounds_str, n, dval, &U, &n)) + return raw_type; + } + else + { + strcpy (name_buf + prefix_len, "___U"); + U = get_int_var_value (name_buf, "Index bound unknown.", NULL); + } + + if (objfile == NULL) + objfile = TYPE_OBJFILE (base_type); + type = create_range_type (alloc_type (objfile), base_type, L, U); + TYPE_NAME (type) = name; + return type; + } +} + +/* True iff NAME is the name of a range type. */ +int +ada_is_range_type_name (const char *name) +{ + return (name != NULL && strstr (name, "___XD")); +} + + + /* Modular types */ + +/* True iff TYPE is an Ada modular type. */ +int +ada_is_modular_type (struct type *type) +{ + /* FIXME: base_type should be declared in gdbtypes.h, implemented in + valarith.c */ + struct type *subranged_type; /* = base_type (type); */ + + return (subranged_type != NULL && TYPE_CODE (type) == TYPE_CODE_RANGE + && TYPE_CODE (subranged_type) != TYPE_CODE_ENUM + && TYPE_UNSIGNED (subranged_type)); +} + +/* Assuming ada_is_modular_type (TYPE), the modulus of TYPE. */ +LONGEST +ada_modulus (struct type * type) +{ + return TYPE_HIGH_BOUND (type) + 1; +} + + + + /* Operators */ + +/* Table mapping opcodes into strings for printing operators + and precedences of the operators. */ + +static const struct op_print ada_op_print_tab[] = { + {":=", BINOP_ASSIGN, PREC_ASSIGN, 1}, + {"or else", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0}, + {"and then", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0}, + {"or", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0}, + {"xor", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0}, + {"and", BINOP_BITWISE_AND, PREC_BITWISE_AND, 0}, + {"=", BINOP_EQUAL, PREC_EQUAL, 0}, + {"/=", BINOP_NOTEQUAL, PREC_EQUAL, 0}, + {"<=", BINOP_LEQ, PREC_ORDER, 0}, + {">=", BINOP_GEQ, PREC_ORDER, 0}, + {">", BINOP_GTR, PREC_ORDER, 0}, + {"<", BINOP_LESS, PREC_ORDER, 0}, + {">>", BINOP_RSH, PREC_SHIFT, 0}, + {"<<", BINOP_LSH, PREC_SHIFT, 0}, + {"+", BINOP_ADD, PREC_ADD, 0}, + {"-", BINOP_SUB, PREC_ADD, 0}, + {"&", BINOP_CONCAT, PREC_ADD, 0}, + {"*", BINOP_MUL, PREC_MUL, 0}, + {"/", BINOP_DIV, PREC_MUL, 0}, + {"rem", BINOP_REM, PREC_MUL, 0}, + {"mod", BINOP_MOD, PREC_MUL, 0}, + {"**", BINOP_EXP, PREC_REPEAT, 0}, + {"@", BINOP_REPEAT, PREC_REPEAT, 0}, + {"-", UNOP_NEG, PREC_PREFIX, 0}, + {"+", UNOP_PLUS, PREC_PREFIX, 0}, + {"not ", UNOP_LOGICAL_NOT, PREC_PREFIX, 0}, + {"not ", UNOP_COMPLEMENT, PREC_PREFIX, 0}, + {"abs ", UNOP_ABS, PREC_PREFIX, 0}, + {".all", UNOP_IND, PREC_SUFFIX, 1}, /* FIXME: postfix .ALL */ + {"'access", UNOP_ADDR, PREC_SUFFIX, 1}, /* FIXME: postfix 'ACCESS */ + {NULL, 0, 0, 0} +}; + + /* Assorted Types and Interfaces */ + +struct type *builtin_type_ada_int; +struct type *builtin_type_ada_short; +struct type *builtin_type_ada_long; +struct type *builtin_type_ada_long_long; +struct type *builtin_type_ada_char; +struct type *builtin_type_ada_float; +struct type *builtin_type_ada_double; +struct type *builtin_type_ada_long_double; +struct type *builtin_type_ada_natural; +struct type *builtin_type_ada_positive; +struct type *builtin_type_ada_system_address; + +struct type **const (ada_builtin_types[]) = +{ + + &builtin_type_ada_int, + &builtin_type_ada_long, + &builtin_type_ada_short, + &builtin_type_ada_char, + &builtin_type_ada_float, + &builtin_type_ada_double, + &builtin_type_ada_long_long, + &builtin_type_ada_long_double, + &builtin_type_ada_natural, &builtin_type_ada_positive, + /* The following types are carried over from C for convenience. */ +&builtin_type_int, + &builtin_type_long, + &builtin_type_short, + &builtin_type_char, + &builtin_type_float, + &builtin_type_double, + &builtin_type_long_long, + &builtin_type_void, + &builtin_type_signed_char, + &builtin_type_unsigned_char, + &builtin_type_unsigned_short, + &builtin_type_unsigned_int, + &builtin_type_unsigned_long, + &builtin_type_unsigned_long_long, + &builtin_type_long_double, + &builtin_type_complex, &builtin_type_double_complex, 0}; + +/* Not really used, but needed in the ada_language_defn. */ +static void +emit_char (int c, struct ui_file *stream, int quoter) +{ + ada_emit_char (c, stream, quoter, 1); +} + +const struct language_defn ada_language_defn = { + "ada", /* Language name */ + /* language_ada, */ + language_unknown, + /* FIXME: language_ada should be defined in defs.h */ + ada_builtin_types, + range_check_off, + type_check_off, + case_sensitive_on, /* Yes, Ada is case-insensitive, but + * that's not quite what this means. */ + ada_parse, + ada_error, + ada_evaluate_subexp, + ada_printchar, /* Print a character constant */ + ada_printstr, /* Function to print string constant */ + emit_char, /* Function to print single char (not used) */ + ada_create_fundamental_type, /* Create fundamental type in this language */ + ada_print_type, /* Print a type using appropriate syntax */ + ada_val_print, /* Print a value using appropriate syntax */ + ada_value_print, /* Print a top-level value */ + {"", "", "", ""}, /* Binary format info */ +#if 0 + {"8#%lo#", "8#", "o", "#"}, /* Octal format info */ + {"%ld", "", "d", ""}, /* Decimal format info */ + {"16#%lx#", "16#", "x", "#"}, /* Hex format info */ +#else + /* Copied from c-lang.c. */ + {"0%lo", "0", "o", ""}, /* Octal format info */ + {"%ld", "", "d", ""}, /* Decimal format info */ + {"0x%lx", "0x", "x", ""}, /* Hex format info */ +#endif + ada_op_print_tab, /* expression operators for printing */ + 1, /* c-style arrays (FIXME?) */ + 0, /* String lower bound (FIXME?) */ + &builtin_type_ada_char, + LANG_MAGIC +}; + +void +_initialize_ada_language (void) +{ + builtin_type_ada_int = + init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT, + 0, "integer", (struct objfile *) NULL); + builtin_type_ada_long = + init_type (TYPE_CODE_INT, TARGET_LONG_BIT / TARGET_CHAR_BIT, + 0, "long_integer", (struct objfile *) NULL); + builtin_type_ada_short = + init_type (TYPE_CODE_INT, TARGET_SHORT_BIT / TARGET_CHAR_BIT, + 0, "short_integer", (struct objfile *) NULL); + builtin_type_ada_char = + init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT, + 0, "character", (struct objfile *) NULL); + builtin_type_ada_float = + init_type (TYPE_CODE_FLT, TARGET_FLOAT_BIT / TARGET_CHAR_BIT, + 0, "float", (struct objfile *) NULL); + builtin_type_ada_double = + init_type (TYPE_CODE_FLT, TARGET_DOUBLE_BIT / TARGET_CHAR_BIT, + 0, "long_float", (struct objfile *) NULL); + builtin_type_ada_long_long = + init_type (TYPE_CODE_INT, TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT, + 0, "long_long_integer", (struct objfile *) NULL); + builtin_type_ada_long_double = + init_type (TYPE_CODE_FLT, TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT, + 0, "long_long_float", (struct objfile *) NULL); + builtin_type_ada_natural = + init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT, + 0, "natural", (struct objfile *) NULL); + builtin_type_ada_positive = + init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT, + 0, "positive", (struct objfile *) NULL); + + + builtin_type_ada_system_address = + lookup_pointer_type (init_type (TYPE_CODE_VOID, 1, 0, "void", + (struct objfile *) NULL)); + TYPE_NAME (builtin_type_ada_system_address) = "system__address"; + + add_language (&ada_language_defn); + + add_show_from_set + (add_set_cmd ("varsize-limit", class_support, var_uinteger, + (char *) &varsize_limit, + "Set maximum bytes in dynamic-sized object.", + &setlist), &showlist); + varsize_limit = 65536; + + add_com ("begin", class_breakpoint, begin_command, + "Start the debugged program, stopping at the beginning of the\n\ +main program. You may specify command-line arguments to give it, as for\n\ +the \"run\" command (q.v.)."); +} + + +/* Create a fundamental Ada type using default reasonable for the current + target machine. + + Some object/debugging file formats (DWARF version 1, COFF, etc) do not + define fundamental types such as "int" or "double". Others (stabs or + DWARF version 2, etc) do define fundamental types. For the formats which + don't provide fundamental types, gdb can create such types using this + function. + + FIXME: Some compilers distinguish explicitly signed integral types + (signed short, signed int, signed long) from "regular" integral types + (short, int, long) in the debugging information. There is some dis- + agreement as to how useful this feature is. In particular, gcc does + not support this. Also, only some debugging formats allow the + distinction to be passed on to a debugger. For now, we always just + use "short", "int", or "long" as the type name, for both the implicit + and explicitly signed types. This also makes life easier for the + gdb test suite since we don't have to account for the differences + in output depending upon what the compiler and debugging format + support. We will probably have to re-examine the issue when gdb + starts taking it's fundamental type information directly from the + debugging information supplied by the compiler. fnf@cygnus.com */ + +static struct type * +ada_create_fundamental_type (struct objfile *objfile, int typeid) +{ + struct type *type = NULL; + + switch (typeid) + { + default: + /* FIXME: For now, if we are asked to produce a type not in this + language, create the equivalent of a C integer type with the + name "<?type?>". When all the dust settles from the type + reconstruction work, this should probably become an error. */ + type = init_type (TYPE_CODE_INT, + TARGET_INT_BIT / TARGET_CHAR_BIT, + 0, "<?type?>", objfile); + warning ("internal error: no Ada fundamental type %d", typeid); + break; + case FT_VOID: + type = init_type (TYPE_CODE_VOID, + TARGET_CHAR_BIT / TARGET_CHAR_BIT, + 0, "void", objfile); + break; + case FT_CHAR: + type = init_type (TYPE_CODE_INT, + TARGET_CHAR_BIT / TARGET_CHAR_BIT, + 0, "character", objfile); + break; + case FT_SIGNED_CHAR: + type = init_type (TYPE_CODE_INT, + TARGET_CHAR_BIT / TARGET_CHAR_BIT, + 0, "signed char", objfile); + break; + case FT_UNSIGNED_CHAR: + type = init_type (TYPE_CODE_INT, + TARGET_CHAR_BIT / TARGET_CHAR_BIT, + TYPE_FLAG_UNSIGNED, "unsigned char", objfile); + break; + case FT_SHORT: + type = init_type (TYPE_CODE_INT, + TARGET_SHORT_BIT / TARGET_CHAR_BIT, + 0, "short_integer", objfile); + break; + case FT_SIGNED_SHORT: + type = init_type (TYPE_CODE_INT, + TARGET_SHORT_BIT / TARGET_CHAR_BIT, + 0, "short_integer", objfile); + break; + case FT_UNSIGNED_SHORT: + type = init_type (TYPE_CODE_INT, + TARGET_SHORT_BIT / TARGET_CHAR_BIT, + TYPE_FLAG_UNSIGNED, "unsigned short", objfile); + break; + case FT_INTEGER: + type = init_type (TYPE_CODE_INT, + TARGET_INT_BIT / TARGET_CHAR_BIT, + 0, "integer", objfile); + break; + case FT_SIGNED_INTEGER: + type = init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT, 0, "integer", objfile); /* FIXME -fnf */ + break; + case FT_UNSIGNED_INTEGER: + type = init_type (TYPE_CODE_INT, + TARGET_INT_BIT / TARGET_CHAR_BIT, + TYPE_FLAG_UNSIGNED, "unsigned int", objfile); + break; + case FT_LONG: + type = init_type (TYPE_CODE_INT, + TARGET_LONG_BIT / TARGET_CHAR_BIT, + 0, "long_integer", objfile); + break; + case FT_SIGNED_LONG: + type = init_type (TYPE_CODE_INT, + TARGET_LONG_BIT / TARGET_CHAR_BIT, + 0, "long_integer", objfile); + break; + case FT_UNSIGNED_LONG: + type = init_type (TYPE_CODE_INT, + TARGET_LONG_BIT / TARGET_CHAR_BIT, + TYPE_FLAG_UNSIGNED, "unsigned long", objfile); + break; + case FT_LONG_LONG: + type = init_type (TYPE_CODE_INT, + TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT, + 0, "long_long_integer", objfile); + break; + case FT_SIGNED_LONG_LONG: + type = init_type (TYPE_CODE_INT, + TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT, + 0, "long_long_integer", objfile); + break; + case FT_UNSIGNED_LONG_LONG: + type = init_type (TYPE_CODE_INT, + TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT, + TYPE_FLAG_UNSIGNED, "unsigned long long", objfile); + break; + case FT_FLOAT: + type = init_type (TYPE_CODE_FLT, + TARGET_FLOAT_BIT / TARGET_CHAR_BIT, + 0, "float", objfile); + break; + case FT_DBL_PREC_FLOAT: + type = init_type (TYPE_CODE_FLT, + TARGET_DOUBLE_BIT / TARGET_CHAR_BIT, + 0, "long_float", objfile); + break; + case FT_EXT_PREC_FLOAT: + type = init_type (TYPE_CODE_FLT, + TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT, + 0, "long_long_float", objfile); + break; + } + return (type); +} + +void +ada_dump_symtab (struct symtab *s) +{ + int i; + fprintf (stderr, "New symtab: [\n"); + fprintf (stderr, " Name: %s/%s;\n", + s->dirname ? s->dirname : "?", s->filename ? s->filename : "?"); + fprintf (stderr, " Format: %s;\n", s->debugformat); + if (s->linetable != NULL) + { + fprintf (stderr, " Line table (section %d):\n", s->block_line_section); + for (i = 0; i < s->linetable->nitems; i += 1) + { + struct linetable_entry *e = s->linetable->item + i; + fprintf (stderr, " %4ld: %8lx\n", (long) e->line, (long) e->pc); + } + } + fprintf (stderr, "]\n"); +} diff --git a/gdb/c-lang.c b/gdb/c-lang.c new file mode 100644 index 0000000..6bbd6d9 --- /dev/null +++ b/gdb/c-lang.c @@ -0,0 +1,652 @@ +/* C language support routines for GDB, the GNU debugger. + Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2002 + 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 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "symtab.h" +#include "gdbtypes.h" +#include "expression.h" +#include "parser-defs.h" +#include "language.h" +#include "c-lang.h" +#include "valprint.h" +#include "macroscope.h" +#include "gdb_assert.h" +#include "charset.h" + +extern void _initialize_c_language (void); +static void c_emit_char (int c, struct ui_file * stream, int quoter); + +/* Print the character C on STREAM as part of the contents of a literal + string whose delimiter is QUOTER. Note that that format for printing + characters and strings is language specific. */ + +static void +c_emit_char (register int c, struct ui_file *stream, int quoter) +{ + const char *escape; + int host_char; + + c &= 0xFF; /* Avoid sign bit follies */ + + escape = c_target_char_has_backslash_escape (c); + if (escape) + { + if (quoter == '"' && strcmp (escape, "0") == 0) + /* Print nulls embedded in double quoted strings as \000 to + prevent ambiguity. */ + fprintf_filtered (stream, "\\000"); + else + fprintf_filtered (stream, "\\%s", escape); + } + else if (target_char_to_host (c, &host_char) + && host_char_print_literally (host_char)) + { + if (host_char == '\\' || host_char == quoter) + fputs_filtered ("\\", stream); + fprintf_filtered (stream, "%c", host_char); + } + else + fprintf_filtered (stream, "\\%.3o", (unsigned int) c); +} + +void +c_printchar (int c, struct ui_file *stream) +{ + fputc_filtered ('\'', stream); + LA_EMIT_CHAR (c, stream, '\''); + fputc_filtered ('\'', stream); +} + +/* Print the character string STRING, printing at most LENGTH characters. + LENGTH is -1 if the string is nul terminated. Each character is WIDTH bytes + long. Printing stops early if the number hits print_max; repeat counts are + printed as appropriate. Print ellipses at the end if we had to stop before + printing LENGTH characters, or if FORCE_ELLIPSES. */ + +void +c_printstr (struct ui_file *stream, char *string, unsigned int length, + int width, int force_ellipses) +{ + register unsigned int i; + unsigned int things_printed = 0; + int in_quotes = 0; + int need_comma = 0; + extern int inspect_it; + + /* If the string was not truncated due to `set print elements', and + the last byte of it is a null, we don't print that, in traditional C + style. */ + if (!force_ellipses + && length > 0 + && (extract_unsigned_integer (string + (length - 1) * width, width) + == '\0')) + length--; + + if (length == 0) + { + fputs_filtered ("\"\"", stream); + return; + } + + for (i = 0; i < length && things_printed < print_max; ++i) + { + /* Position of the character we are examining + to see whether it is repeated. */ + unsigned int rep1; + /* Number of repetitions we have detected so far. */ + unsigned int reps; + unsigned long current_char; + + QUIT; + + if (need_comma) + { + fputs_filtered (", ", stream); + need_comma = 0; + } + + current_char = extract_unsigned_integer (string + i * width, width); + + rep1 = i + 1; + reps = 1; + while (rep1 < length + && extract_unsigned_integer (string + rep1 * width, width) + == current_char) + { + ++rep1; + ++reps; + } + + if (reps > repeat_count_threshold) + { + if (in_quotes) + { + if (inspect_it) + fputs_filtered ("\\\", ", stream); + else + fputs_filtered ("\", ", stream); + in_quotes = 0; + } + LA_PRINT_CHAR (current_char, stream); + fprintf_filtered (stream, " <repeats %u times>", reps); + i = rep1 - 1; + things_printed += repeat_count_threshold; + need_comma = 1; + } + else + { + if (!in_quotes) + { + if (inspect_it) + fputs_filtered ("\\\"", stream); + else + fputs_filtered ("\"", stream); + in_quotes = 1; + } + LA_EMIT_CHAR (current_char, stream, '"'); + ++things_printed; + } + } + + /* Terminate the quotes if necessary. */ + if (in_quotes) + { + if (inspect_it) + fputs_filtered ("\\\"", stream); + else + fputs_filtered ("\"", stream); + } + + if (force_ellipses || i < length) + fputs_filtered ("...", stream); +} + +/* Create a fundamental C type using default reasonable for the current + target machine. + + Some object/debugging file formats (DWARF version 1, COFF, etc) do not + define fundamental types such as "int" or "double". Others (stabs or + DWARF version 2, etc) do define fundamental types. For the formats which + don't provide fundamental types, gdb can create such types using this + function. + + FIXME: Some compilers distinguish explicitly signed integral types + (signed short, signed int, signed long) from "regular" integral types + (short, int, long) in the debugging information. There is some dis- + agreement as to how useful this feature is. In particular, gcc does + not support this. Also, only some debugging formats allow the + distinction to be passed on to a debugger. For now, we always just + use "short", "int", or "long" as the type name, for both the implicit + and explicitly signed types. This also makes life easier for the + gdb test suite since we don't have to account for the differences + in output depending upon what the compiler and debugging format + support. We will probably have to re-examine the issue when gdb + starts taking it's fundamental type information directly from the + debugging information supplied by the compiler. fnf@cygnus.com */ + +struct type * +c_create_fundamental_type (struct objfile *objfile, int typeid) +{ + register struct type *type = NULL; + + switch (typeid) + { + default: + /* FIXME: For now, if we are asked to produce a type not in this + language, create the equivalent of a C integer type with the + name "<?type?>". When all the dust settles from the type + reconstruction work, this should probably become an error. */ + type = init_type (TYPE_CODE_INT, + TARGET_INT_BIT / TARGET_CHAR_BIT, + 0, "<?type?>", objfile); + warning ("internal error: no C/C++ fundamental type %d", typeid); + break; + case FT_VOID: + type = init_type (TYPE_CODE_VOID, + TARGET_CHAR_BIT / TARGET_CHAR_BIT, + 0, "void", objfile); + break; + case FT_BOOLEAN: + type = init_type (TYPE_CODE_BOOL, + TARGET_CHAR_BIT / TARGET_CHAR_BIT, + 0, "bool", objfile); + break; + case FT_CHAR: + type = init_type (TYPE_CODE_INT, + TARGET_CHAR_BIT / TARGET_CHAR_BIT, + TYPE_FLAG_NOSIGN, "char", objfile); + break; + case FT_SIGNED_CHAR: + type = init_type (TYPE_CODE_INT, + TARGET_CHAR_BIT / TARGET_CHAR_BIT, + 0, "signed char", objfile); + break; + case FT_UNSIGNED_CHAR: + type = init_type (TYPE_CODE_INT, + TARGET_CHAR_BIT / TARGET_CHAR_BIT, + TYPE_FLAG_UNSIGNED, "unsigned char", objfile); + break; + case FT_SHORT: + type = init_type (TYPE_CODE_INT, + TARGET_SHORT_BIT / TARGET_CHAR_BIT, + 0, "short", objfile); + break; + case FT_SIGNED_SHORT: + type = init_type (TYPE_CODE_INT, + TARGET_SHORT_BIT / TARGET_CHAR_BIT, + 0, "short", objfile); /* FIXME-fnf */ + break; + case FT_UNSIGNED_SHORT: + type = init_type (TYPE_CODE_INT, + TARGET_SHORT_BIT / TARGET_CHAR_BIT, + TYPE_FLAG_UNSIGNED, "unsigned short", objfile); + break; + case FT_INTEGER: + type = init_type (TYPE_CODE_INT, + TARGET_INT_BIT / TARGET_CHAR_BIT, + 0, "int", objfile); + break; + case FT_SIGNED_INTEGER: + type = init_type (TYPE_CODE_INT, + TARGET_INT_BIT / TARGET_CHAR_BIT, + 0, "int", objfile); /* FIXME -fnf */ + break; + case FT_UNSIGNED_INTEGER: + type = init_type (TYPE_CODE_INT, + TARGET_INT_BIT / TARGET_CHAR_BIT, + TYPE_FLAG_UNSIGNED, "unsigned int", objfile); + break; + case FT_LONG: + type = init_type (TYPE_CODE_INT, + TARGET_LONG_BIT / TARGET_CHAR_BIT, + 0, "long", objfile); + break; + case FT_SIGNED_LONG: + type = init_type (TYPE_CODE_INT, + TARGET_LONG_BIT / TARGET_CHAR_BIT, + 0, "long", objfile); /* FIXME -fnf */ + break; + case FT_UNSIGNED_LONG: + type = init_type (TYPE_CODE_INT, + TARGET_LONG_BIT / TARGET_CHAR_BIT, + TYPE_FLAG_UNSIGNED, "unsigned long", objfile); + break; + case FT_LONG_LONG: + type = init_type (TYPE_CODE_INT, + TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT, + 0, "long long", objfile); + break; + case FT_SIGNED_LONG_LONG: + type = init_type (TYPE_CODE_INT, + TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT, + 0, "signed long long", objfile); + break; + case FT_UNSIGNED_LONG_LONG: + type = init_type (TYPE_CODE_INT, + TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT, + TYPE_FLAG_UNSIGNED, "unsigned long long", objfile); + break; + case FT_FLOAT: + type = init_type (TYPE_CODE_FLT, + TARGET_FLOAT_BIT / TARGET_CHAR_BIT, + 0, "float", objfile); + break; + case FT_DBL_PREC_FLOAT: + type = init_type (TYPE_CODE_FLT, + TARGET_DOUBLE_BIT / TARGET_CHAR_BIT, + 0, "double", objfile); + break; + case FT_EXT_PREC_FLOAT: + type = init_type (TYPE_CODE_FLT, + TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT, + 0, "long double", objfile); + break; + case FT_COMPLEX: + type = init_type (TYPE_CODE_FLT, + 2 * TARGET_FLOAT_BIT / TARGET_CHAR_BIT, + 0, "complex float", objfile); + TYPE_TARGET_TYPE (type) + = init_type (TYPE_CODE_FLT, TARGET_FLOAT_BIT / TARGET_CHAR_BIT, + 0, "float", objfile); + break; + case FT_DBL_PREC_COMPLEX: + type = init_type (TYPE_CODE_FLT, + 2 * TARGET_DOUBLE_BIT / TARGET_CHAR_BIT, + 0, "complex double", objfile); + TYPE_TARGET_TYPE (type) + = init_type (TYPE_CODE_FLT, TARGET_DOUBLE_BIT / TARGET_CHAR_BIT, + 0, "double", objfile); + break; + case FT_EXT_PREC_COMPLEX: + type = init_type (TYPE_CODE_FLT, + 2 * TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT, + 0, "complex long double", objfile); + TYPE_TARGET_TYPE (type) + = init_type (TYPE_CODE_FLT, TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT, + 0, "long double", objfile); + break; + case FT_TEMPLATE_ARG: + type = init_type (TYPE_CODE_TEMPLATE_ARG, + 0, + 0, "<template arg>", objfile); + break; + } + return (type); +} + +/* Preprocessing and parsing C and C++ expressions. */ + + +/* When we find that lexptr (the global var defined in parse.c) is + pointing at a macro invocation, we expand the invocation, and call + scan_macro_expansion to save the old lexptr here and point lexptr + into the expanded text. When we reach the end of that, we call + end_macro_expansion to pop back to the value we saved here. The + macro expansion code promises to return only fully-expanded text, + so we don't need to "push" more than one level. + + This is disgusting, of course. It would be cleaner to do all macro + expansion beforehand, and then hand that to lexptr. But we don't + really know where the expression ends. Remember, in a command like + + (gdb) break *ADDRESS if CONDITION + + we evaluate ADDRESS in the scope of the current frame, but we + evaluate CONDITION in the scope of the breakpoint's location. So + it's simply wrong to try to macro-expand the whole thing at once. */ +static char *macro_original_text; +static char *macro_expanded_text; + + +void +scan_macro_expansion (char *expansion) +{ + /* We'd better not be trying to push the stack twice. */ + gdb_assert (! macro_original_text); + gdb_assert (! macro_expanded_text); + + /* Save the old lexptr value, so we can return to it when we're done + parsing the expanded text. */ + macro_original_text = lexptr; + lexptr = expansion; + + /* Save the expanded text, so we can free it when we're finished. */ + macro_expanded_text = expansion; +} + + +int +scanning_macro_expansion (void) +{ + return macro_original_text != 0; +} + + +void +finished_macro_expansion (void) +{ + /* There'd better be something to pop back to, and we better have + saved a pointer to the start of the expanded text. */ + gdb_assert (macro_original_text); + gdb_assert (macro_expanded_text); + + /* Pop back to the original text. */ + lexptr = macro_original_text; + macro_original_text = 0; + + /* Free the expanded text. */ + xfree (macro_expanded_text); + macro_expanded_text = 0; +} + + +static void +scan_macro_cleanup (void *dummy) +{ + if (macro_original_text) + finished_macro_expansion (); +} + + +/* We set these global variables before calling c_parse, to tell it + how it to find macro definitions for the expression at hand. */ +macro_lookup_ftype *expression_macro_lookup_func; +void *expression_macro_lookup_baton; + + +static struct macro_definition * +null_macro_lookup (const char *name, void *baton) +{ + return 0; +} + + +static int +c_preprocess_and_parse (void) +{ + /* Set up a lookup function for the macro expander. */ + struct macro_scope *scope = 0; + struct cleanup *back_to = make_cleanup (free_current_contents, &scope); + + if (expression_context_block) + scope = sal_macro_scope (find_pc_line (expression_context_pc, 0)); + else + scope = default_macro_scope (); + + if (scope) + { + expression_macro_lookup_func = standard_macro_lookup; + expression_macro_lookup_baton = (void *) scope; + } + else + { + expression_macro_lookup_func = null_macro_lookup; + expression_macro_lookup_baton = 0; + } + + gdb_assert (! macro_original_text); + make_cleanup (scan_macro_cleanup, 0); + + { + int result = c_parse (); + do_cleanups (back_to); + return result; + } +} + + + +/* Table mapping opcodes into strings for printing operators + and precedences of the operators. */ + +const struct op_print c_op_print_tab[] = +{ + {",", BINOP_COMMA, PREC_COMMA, 0}, + {"=", BINOP_ASSIGN, PREC_ASSIGN, 1}, + {"||", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0}, + {"&&", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0}, + {"|", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0}, + {"^", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0}, + {"&", BINOP_BITWISE_AND, PREC_BITWISE_AND, 0}, + {"==", BINOP_EQUAL, PREC_EQUAL, 0}, + {"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0}, + {"<=", BINOP_LEQ, PREC_ORDER, 0}, + {">=", BINOP_GEQ, PREC_ORDER, 0}, + {">", BINOP_GTR, PREC_ORDER, 0}, + {"<", BINOP_LESS, PREC_ORDER, 0}, + {">>", BINOP_RSH, PREC_SHIFT, 0}, + {"<<", BINOP_LSH, PREC_SHIFT, 0}, + {"+", BINOP_ADD, PREC_ADD, 0}, + {"-", BINOP_SUB, PREC_ADD, 0}, + {"*", BINOP_MUL, PREC_MUL, 0}, + {"/", BINOP_DIV, PREC_MUL, 0}, + {"%", BINOP_REM, PREC_MUL, 0}, + {"@", BINOP_REPEAT, PREC_REPEAT, 0}, + {"-", UNOP_NEG, PREC_PREFIX, 0}, + {"!", UNOP_LOGICAL_NOT, PREC_PREFIX, 0}, + {"~", UNOP_COMPLEMENT, PREC_PREFIX, 0}, + {"*", UNOP_IND, PREC_PREFIX, 0}, + {"&", UNOP_ADDR, PREC_PREFIX, 0}, + {"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0}, + {"++", UNOP_PREINCREMENT, PREC_PREFIX, 0}, + {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0}, + {NULL, 0, 0, 0} +}; + +struct type **const (c_builtin_types[]) = +{ + &builtin_type_int, + &builtin_type_long, + &builtin_type_short, + &builtin_type_char, + &builtin_type_float, + &builtin_type_double, + &builtin_type_void, + &builtin_type_long_long, + &builtin_type_signed_char, + &builtin_type_unsigned_char, + &builtin_type_unsigned_short, + &builtin_type_unsigned_int, + &builtin_type_unsigned_long, + &builtin_type_unsigned_long_long, + &builtin_type_long_double, + &builtin_type_complex, + &builtin_type_double_complex, + 0 +}; + +const struct language_defn c_language_defn = +{ + "c", /* Language name */ + language_c, + c_builtin_types, + range_check_off, + type_check_off, + case_sensitive_on, + c_preprocess_and_parse, + c_error, + evaluate_subexp_standard, + c_printchar, /* Print a character constant */ + c_printstr, /* Function to print string constant */ + c_emit_char, /* Print a single char */ + c_create_fundamental_type, /* Create fundamental type in this language */ + c_print_type, /* Print a type using appropriate syntax */ + c_val_print, /* Print a value using appropriate syntax */ + c_value_print, /* Print a top-level value */ + {"", "", "", ""}, /* Binary format info */ + {"0%lo", "0", "o", ""}, /* Octal format info */ + {"%ld", "", "d", ""}, /* Decimal format info */ + {"0x%lx", "0x", "x", ""}, /* Hex format info */ + c_op_print_tab, /* expression operators for printing */ + 1, /* c-style arrays */ + 0, /* String lower bound */ + &builtin_type_char, /* Type of string elements */ + LANG_MAGIC +}; + +struct type **const (cplus_builtin_types[]) = +{ + &builtin_type_int, + &builtin_type_long, + &builtin_type_short, + &builtin_type_char, + &builtin_type_float, + &builtin_type_double, + &builtin_type_void, + &builtin_type_long_long, + &builtin_type_signed_char, + &builtin_type_unsigned_char, + &builtin_type_unsigned_short, + &builtin_type_unsigned_int, + &builtin_type_unsigned_long, + &builtin_type_unsigned_long_long, + &builtin_type_long_double, + &builtin_type_complex, + &builtin_type_double_complex, + &builtin_type_bool, + 0 +}; + +const struct language_defn cplus_language_defn = +{ + "c++", /* Language name */ + language_cplus, + cplus_builtin_types, + range_check_off, + type_check_off, + case_sensitive_on, + c_preprocess_and_parse, + c_error, + evaluate_subexp_standard, + c_printchar, /* Print a character constant */ + c_printstr, /* Function to print string constant */ + c_emit_char, /* Print a single char */ + c_create_fundamental_type, /* Create fundamental type in this language */ + c_print_type, /* Print a type using appropriate syntax */ + c_val_print, /* Print a value using appropriate syntax */ + c_value_print, /* Print a top-level value */ + {"", "", "", ""}, /* Binary format info */ + {"0%lo", "0", "o", ""}, /* Octal format info */ + {"%ld", "", "d", ""}, /* Decimal format info */ + {"0x%lx", "0x", "x", ""}, /* Hex format info */ + c_op_print_tab, /* expression operators for printing */ + 1, /* c-style arrays */ + 0, /* String lower bound */ + &builtin_type_char, /* Type of string elements */ + LANG_MAGIC +}; + +const struct language_defn asm_language_defn = +{ + "asm", /* Language name */ + language_asm, + c_builtin_types, + range_check_off, + type_check_off, + case_sensitive_on, + c_preprocess_and_parse, + c_error, + evaluate_subexp_standard, + c_printchar, /* Print a character constant */ + c_printstr, /* Function to print string constant */ + c_emit_char, /* Print a single char */ + c_create_fundamental_type, /* Create fundamental type in this language */ + c_print_type, /* Print a type using appropriate syntax */ + c_val_print, /* Print a value using appropriate syntax */ + c_value_print, /* Print a top-level value */ + {"", "", "", ""}, /* Binary format info */ + {"0%lo", "0", "o", ""}, /* Octal format info */ + {"%ld", "", "d", ""}, /* Decimal format info */ + {"0x%lx", "0x", "x", ""}, /* Hex format info */ + c_op_print_tab, /* expression operators for printing */ + 1, /* c-style arrays */ + 0, /* String lower bound */ + &builtin_type_char, /* Type of string elements */ + LANG_MAGIC +}; + +void +_initialize_c_language (void) +{ + add_language (&c_language_defn); + add_language (&cplus_language_defn); + add_language (&asm_language_defn); +} diff --git a/gdb/coffread.c b/gdb/coffread.c new file mode 100644 index 0000000..d794a7d --- /dev/null +++ b/gdb/coffread.c @@ -0,0 +1,2166 @@ +/* Read coff symbol tables and convert to internal format, for GDB. + Copyright 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, + 1997, 1998, 1999, 2000, 2001, 2002 + Free Software Foundation, Inc. + Contributed by David D. Johnson, Brown University (ddj@cs.brown.edu). + + 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 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "symtab.h" +#include "gdbtypes.h" +#include "demangle.h" +#include "breakpoint.h" + +#include "bfd.h" +#include "gdb_obstack.h" + +#include "gdb_string.h" +#include <ctype.h> + +#include "coff/internal.h" /* Internal format of COFF symbols in BFD */ +#include "libcoff.h" /* FIXME secret internal data from BFD */ + +#include "symfile.h" +#include "objfiles.h" +#include "buildsym.h" +#include "gdb-stabs.h" +#include "stabsread.h" +#include "complaints.h" +#include "target.h" +#include "gdb_assert.h" + +extern void _initialize_coffread (void); + +struct coff_symfile_info + { + file_ptr min_lineno_offset; /* Where in file lowest line#s are */ + file_ptr max_lineno_offset; /* 1+last byte of line#s in file */ + + CORE_ADDR textaddr; /* Addr of .text section. */ + unsigned int textsize; /* Size of .text section. */ + struct stab_section_list *stabsects; /* .stab sections. */ + asection *stabstrsect; /* Section pointer for .stab section */ + char *stabstrdata; + }; + +/* Translate an external name string into a user-visible name. */ +#define EXTERNAL_NAME(string, abfd) \ + (string[0] == bfd_get_symbol_leading_char(abfd)? string+1: string) + +/* To be an sdb debug type, type must have at least a basic or primary + derived type. Using this rather than checking against T_NULL is + said to prevent core dumps if we try to operate on Michael Bloom + dbx-in-coff file. */ + +#define SDB_TYPE(type) (BTYPE(type) | (type & N_TMASK)) + +/* Core address of start and end of text of current source file. + This comes from a ".text" symbol where x_nlinno > 0. */ + +static CORE_ADDR current_source_start_addr; +static CORE_ADDR current_source_end_addr; + +/* The addresses of the symbol table stream and number of symbols + of the object file we are reading (as copied into core). */ + +static bfd *nlist_bfd_global; +static int nlist_nsyms_global; + + +/* Pointers to scratch storage, used for reading raw symbols and auxents. */ + +static char *temp_sym; +static char *temp_aux; + +/* Local variables that hold the shift and mask values for the + COFF file that we are currently reading. These come back to us + from BFD, and are referenced by their macro names, as well as + internally to the BTYPE, ISPTR, ISFCN, ISARY, ISTAG, and DECREF + macros from include/coff/internal.h . */ + +static unsigned local_n_btmask; +static unsigned local_n_btshft; +static unsigned local_n_tmask; +static unsigned local_n_tshift; + +#define N_BTMASK local_n_btmask +#define N_BTSHFT local_n_btshft +#define N_TMASK local_n_tmask +#define N_TSHIFT local_n_tshift + +/* Local variables that hold the sizes in the file of various COFF structures. + (We only need to know this to read them from the file -- BFD will then + translate the data in them, into `internal_xxx' structs in the right + byte order, alignment, etc.) */ + +static unsigned local_linesz; +static unsigned local_symesz; +static unsigned local_auxesz; + +/* This is set if this is a PE format file. */ + +static int pe_file; + +/* Chain of typedefs of pointers to empty struct/union types. + They are chained thru the SYMBOL_VALUE_CHAIN. */ + +static struct symbol *opaque_type_chain[HASHSIZE]; + +/* Complaints about various problems in the file being read */ + +struct complaint ef_complaint = +{"Unmatched .ef symbol(s) ignored starting at symnum %d", 0, 0}; + +struct complaint ef_stack_complaint = +{"`.ef' symbol without matching `.bf' symbol ignored starting at symnum %d", 0, 0}; + +struct complaint eb_stack_complaint = +{"`.eb' symbol without matching `.bb' symbol ignored starting at symnum %d", 0, 0}; + +struct complaint bf_no_aux_complaint = +{"`.bf' symbol %d has no aux entry", 0, 0}; + +struct complaint ef_no_aux_complaint = +{"`.ef' symbol %d has no aux entry", 0, 0}; + +struct complaint lineno_complaint = +{"Line number pointer %d lower than start of line numbers", 0, 0}; + +struct complaint unexpected_type_complaint = +{"Unexpected type for symbol %s", 0, 0}; + +struct complaint bad_sclass_complaint = +{"Bad n_sclass for symbol %s", 0, 0}; + +struct complaint misordered_blocks_complaint = +{"Blocks out of order at address %x", 0, 0}; + +struct complaint tagndx_bad_complaint = +{"Symbol table entry for %s has bad tagndx value", 0, 0}; + +struct complaint eb_complaint = +{"Mismatched .eb symbol ignored starting at symnum %d", 0, 0}; + +/* Simplified internal version of coff symbol table information */ + +struct coff_symbol + { + char *c_name; + int c_symnum; /* symbol number of this entry */ + int c_naux; /* 0 if syment only, 1 if syment + auxent, etc */ + long c_value; + int c_sclass; + int c_secnum; + unsigned int c_type; + }; + +extern void stabsread_clear_cache (void); + +static struct type *coff_read_struct_type (int, int, int); + +static struct type *decode_base_type (struct coff_symbol *, + unsigned int, union internal_auxent *); + +static struct type *decode_type (struct coff_symbol *, unsigned int, + union internal_auxent *); + +static struct type *decode_function_type (struct coff_symbol *, + unsigned int, + union internal_auxent *); + +static struct type *coff_read_enum_type (int, int, int); + +static struct symbol *process_coff_symbol (struct coff_symbol *, + union internal_auxent *, + struct objfile *); + +static void patch_opaque_types (struct symtab *); + +static void enter_linenos (long, int, int, struct objfile *); + +static void free_linetab (void); + +static void free_linetab_cleanup (void *ignore); + +static int init_lineno (bfd *, long, int); + +static char *getsymname (struct internal_syment *); + +static char *coff_getfilename (union internal_auxent *); + +static void free_stringtab (void); + +static void free_stringtab_cleanup (void *ignore); + +static int init_stringtab (bfd *, long); + +static void read_one_sym (struct coff_symbol *, + struct internal_syment *, union internal_auxent *); + +static void coff_symtab_read (long, unsigned int, struct objfile *); + +/* We are called once per section from coff_symfile_read. We + need to examine each section we are passed, check to see + if it is something we are interested in processing, and + if so, stash away some access information for the section. + + FIXME: The section names should not be hardwired strings (what + should they be? I don't think most object file formats have enough + section flags to specify what kind of debug section it is + -kingdon). */ + +static void +coff_locate_sections (bfd *abfd, asection *sectp, void *csip) +{ + register struct coff_symfile_info *csi; + const char *name; + + csi = (struct coff_symfile_info *) csip; + name = bfd_get_section_name (abfd, sectp); + if (STREQ (name, ".text")) + { + csi->textaddr = bfd_section_vma (abfd, sectp); + csi->textsize += bfd_section_size (abfd, sectp); + } + else if (strncmp (name, ".text", sizeof ".text" - 1) == 0) + { + csi->textsize += bfd_section_size (abfd, sectp); + } + else if (STREQ (name, ".stabstr")) + { + csi->stabstrsect = sectp; + } + else if (strncmp (name, ".stab", sizeof ".stab" - 1) == 0) + { + const char *s; + + /* We can have multiple .stab sections if linked with + --split-by-reloc. */ + for (s = name + sizeof ".stab" - 1; *s != '\0'; s++) + if (!isdigit (*s)) + break; + if (*s == '\0') + { + struct stab_section_list *n, **pn; + + n = ((struct stab_section_list *) + xmalloc (sizeof (struct stab_section_list))); + n->section = sectp; + n->next = NULL; + for (pn = &csi->stabsects; *pn != NULL; pn = &(*pn)->next) + ; + *pn = n; + + /* This will be run after coffstab_build_psymtabs is called + in coff_symfile_read, at which point we no longer need + the information. */ + make_cleanup (xfree, n); + } + } +} + +/* Return the section_offsets* that CS points to. */ +static int cs_to_section (struct coff_symbol *, struct objfile *); + +struct find_targ_sec_arg + { + int targ_index; + asection **resultp; + }; + +static void +find_targ_sec (bfd *abfd, asection *sect, void *obj) +{ + struct find_targ_sec_arg *args = (struct find_targ_sec_arg *) obj; + if (sect->target_index == args->targ_index) + *args->resultp = sect; +} + +/* Return the section number (SECT_OFF_*) that CS points to. */ +static int +cs_to_section (struct coff_symbol *cs, struct objfile *objfile) +{ + asection *sect = NULL; + struct find_targ_sec_arg args; + int off = SECT_OFF_TEXT (objfile); + + args.targ_index = cs->c_secnum; + args.resultp = § + bfd_map_over_sections (objfile->obfd, find_targ_sec, &args); + if (sect != NULL) + { + /* This is the section. Figure out what SECT_OFF_* code it is. */ + if (bfd_get_section_flags (abfd, sect) & SEC_CODE) + off = SECT_OFF_TEXT (objfile); + else if (bfd_get_section_flags (abfd, sect) & SEC_LOAD) + off = SECT_OFF_DATA (objfile); + else + /* Just return the bfd section index. */ + off = sect->index; + } + return off; +} + +/* Return the address of the section of a COFF symbol. */ + +static CORE_ADDR cs_section_address (struct coff_symbol *, bfd *); + +static CORE_ADDR +cs_section_address (struct coff_symbol *cs, bfd *abfd) +{ + asection *sect = NULL; + struct find_targ_sec_arg args; + CORE_ADDR addr = 0; + + args.targ_index = cs->c_secnum; + args.resultp = § + bfd_map_over_sections (abfd, find_targ_sec, &args); + if (sect != NULL) + addr = bfd_get_section_vma (objfile->obfd, sect); + return addr; +} + +/* Look up a coff type-number index. Return the address of the slot + where the type for that index is stored. + The type-number is in INDEX. + + This can be used for finding the type associated with that index + or for associating a new type with the index. */ + +static struct type ** +coff_lookup_type (register int index) +{ + if (index >= type_vector_length) + { + int old_vector_length = type_vector_length; + + type_vector_length *= 2; + if (index /* is still */ >= type_vector_length) + type_vector_length = index * 2; + + type_vector = (struct type **) + xrealloc ((char *) type_vector, + type_vector_length * sizeof (struct type *)); + memset (&type_vector[old_vector_length], 0, + (type_vector_length - old_vector_length) * sizeof (struct type *)); + } + return &type_vector[index]; +} + +/* Make sure there is a type allocated for type number index + and return the type object. + This can create an empty (zeroed) type object. */ + +static struct type * +coff_alloc_type (int index) +{ + register struct type **type_addr = coff_lookup_type (index); + register struct type *type = *type_addr; + + /* If we are referring to a type not known at all yet, + allocate an empty type for it. + We will fill it in later if we find out how. */ + if (type == NULL) + { + type = alloc_type (current_objfile); + *type_addr = type; + } + return type; +} + +/* Start a new symtab for a new source file. + This is called when a COFF ".file" symbol is seen; + it indicates the start of data for one original source file. */ + +static void +coff_start_symtab (char *name) +{ + start_symtab ( + /* We fill in the filename later. start_symtab puts + this pointer into last_source_file and we put it in + subfiles->name, which end_symtab frees; that's why + it must be malloc'd. */ + savestring (name, strlen (name)), + /* We never know the directory name for COFF. */ + NULL, + /* The start address is irrelevant, since we set + last_source_start_addr in coff_end_symtab. */ + 0); + record_debugformat ("COFF"); +} + +/* Save the vital information from when starting to read a file, + for use when closing off the current file. + NAME is the file name the symbols came from, START_ADDR is the first + text address for the file, and SIZE is the number of bytes of text. */ + +static void +complete_symtab (char *name, CORE_ADDR start_addr, unsigned int size) +{ + if (last_source_file != NULL) + xfree (last_source_file); + last_source_file = savestring (name, strlen (name)); + current_source_start_addr = start_addr; + current_source_end_addr = start_addr + size; + + if (current_objfile->ei.entry_point >= current_source_start_addr && + current_objfile->ei.entry_point < current_source_end_addr) + { + current_objfile->ei.entry_file_lowpc = current_source_start_addr; + current_objfile->ei.entry_file_highpc = current_source_end_addr; + } +} + +/* Finish the symbol definitions for one main source file, + close off all the lexical contexts for that file + (creating struct block's for them), then make the + struct symtab for that file and put it in the list of all such. */ + +static void +coff_end_symtab (struct objfile *objfile) +{ + struct symtab *symtab; + + last_source_start_addr = current_source_start_addr; + + symtab = end_symtab (current_source_end_addr, objfile, SECT_OFF_TEXT (objfile)); + + if (symtab != NULL) + free_named_symtabs (symtab->filename); + + /* Reinitialize for beginning of new file. */ + last_source_file = NULL; +} + +static void +record_minimal_symbol (char *name, CORE_ADDR address, + enum minimal_symbol_type type, struct objfile *objfile) +{ + /* We don't want TDESC entry points in the minimal symbol table */ + if (name[0] == '@') + return; + + prim_record_minimal_symbol (name, address, type, objfile); +} + +/* coff_symfile_init () + is the coff-specific initialization routine for reading symbols. + It is passed a struct objfile which contains, among other things, + the BFD for the file whose symbols are being read, and a slot for + a pointer to "private data" which we fill with cookies and other + treats for coff_symfile_read (). + + We will only be called if this is a COFF or COFF-like file. + BFD handles figuring out the format of the file, and code in symtab.c + uses BFD's determination to vector to us. + + The ultimate result is a new symtab (or, FIXME, eventually a psymtab). */ + +static void +coff_symfile_init (struct objfile *objfile) +{ + /* Allocate struct to keep track of stab reading. */ + objfile->sym_stab_info = (struct dbx_symfile_info *) + xmmalloc (objfile->md, sizeof (struct dbx_symfile_info)); + + memset (objfile->sym_stab_info, 0, + sizeof (struct dbx_symfile_info)); + + /* Allocate struct to keep track of the symfile */ + objfile->sym_private = xmmalloc (objfile->md, + sizeof (struct coff_symfile_info)); + + memset (objfile->sym_private, 0, sizeof (struct coff_symfile_info)); + + /* COFF objects may be reordered, so set OBJF_REORDERED. If we + find this causes a significant slowdown in gdb then we could + set it in the debug symbol readers only when necessary. */ + objfile->flags |= OBJF_REORDERED; + + init_entry_point_info (objfile); +} + +/* This function is called for every section; it finds the outer limits + of the line table (minimum and maximum file offset) so that the + mainline code can read the whole thing for efficiency. */ + +/* ARGSUSED */ +static void +find_linenos (bfd *abfd, sec_ptr asect, void *vpinfo) +{ + struct coff_symfile_info *info; + int size, count; + file_ptr offset, maxoff; + +/* WARNING WILL ROBINSON! ACCESSING BFD-PRIVATE DATA HERE! FIXME! */ + count = asect->lineno_count; +/* End of warning */ + + if (count == 0) + return; + size = count * local_linesz; + + info = (struct coff_symfile_info *) vpinfo; +/* WARNING WILL ROBINSON! ACCESSING BFD-PRIVATE DATA HERE! FIXME! */ + offset = asect->line_filepos; +/* End of warning */ + + if (offset < info->min_lineno_offset || info->min_lineno_offset == 0) + info->min_lineno_offset = offset; + + maxoff = offset + size; + if (maxoff > info->max_lineno_offset) + info->max_lineno_offset = maxoff; +} + + +/* The BFD for this file -- only good while we're actively reading + symbols into a psymtab or a symtab. */ + +static bfd *symfile_bfd; + +/* Read a symbol file, after initialization by coff_symfile_init. */ + +/* ARGSUSED */ +static void +coff_symfile_read (struct objfile *objfile, int mainline) +{ + struct coff_symfile_info *info; + struct dbx_symfile_info *dbxinfo; + bfd *abfd = objfile->obfd; + coff_data_type *cdata = coff_data (abfd); + char *name = bfd_get_filename (abfd); + register int val; + unsigned int num_symbols; + int symtab_offset; + int stringtab_offset; + struct cleanup *back_to; + int stabstrsize; + int len; + char * target; + + info = (struct coff_symfile_info *) objfile->sym_private; + dbxinfo = objfile->sym_stab_info; + symfile_bfd = abfd; /* Kludge for swap routines */ + +/* WARNING WILL ROBINSON! ACCESSING BFD-PRIVATE DATA HERE! FIXME! */ + num_symbols = bfd_get_symcount (abfd); /* How many syms */ + symtab_offset = cdata->sym_filepos; /* Symbol table file offset */ + stringtab_offset = symtab_offset + /* String table file offset */ + num_symbols * cdata->local_symesz; + + /* Set a few file-statics that give us specific information about + the particular COFF file format we're reading. */ + local_n_btmask = cdata->local_n_btmask; + local_n_btshft = cdata->local_n_btshft; + local_n_tmask = cdata->local_n_tmask; + local_n_tshift = cdata->local_n_tshift; + local_linesz = cdata->local_linesz; + local_symesz = cdata->local_symesz; + local_auxesz = cdata->local_auxesz; + + /* Allocate space for raw symbol and aux entries, based on their + space requirements as reported by BFD. */ + temp_sym = (char *) xmalloc + (cdata->local_symesz + cdata->local_auxesz); + temp_aux = temp_sym + cdata->local_symesz; + back_to = make_cleanup (free_current_contents, &temp_sym); + + /* We need to know whether this is a PE file, because in PE files, + unlike standard COFF files, symbol values are stored as offsets + from the section address, rather than as absolute addresses. + FIXME: We should use BFD to read the symbol table, and thus avoid + this problem. */ + pe_file = + strncmp (bfd_get_target (objfile->obfd), "pe", 2) == 0 + || strncmp (bfd_get_target (objfile->obfd), "epoc-pe", 7) == 0; + +/* End of warning */ + + info->min_lineno_offset = 0; + info->max_lineno_offset = 0; + + /* Only read line number information if we have symbols. + + On Windows NT, some of the system's DLL's have sections with + PointerToLinenumbers fields that are non-zero, but point at + random places within the image file. (In the case I found, + KERNEL32.DLL's .text section has a line number info pointer that + points into the middle of the string `lib\\i386\kernel32.dll'.) + + However, these DLL's also have no symbols. The line number + tables are meaningless without symbols. And in fact, GDB never + uses the line number information unless there are symbols. So we + can avoid spurious error messages (and maybe run a little + faster!) by not even reading the line number table unless we have + symbols. */ + if (num_symbols > 0) + { + /* Read the line number table, all at once. */ + bfd_map_over_sections (abfd, find_linenos, (void *) info); + + make_cleanup (free_linetab_cleanup, 0 /*ignore*/); + val = init_lineno (abfd, info->min_lineno_offset, + info->max_lineno_offset - info->min_lineno_offset); + if (val < 0) + error ("\"%s\": error reading line numbers\n", name); + } + + /* Now read the string table, all at once. */ + + make_cleanup (free_stringtab_cleanup, 0 /*ignore*/); + val = init_stringtab (abfd, stringtab_offset); + if (val < 0) + error ("\"%s\": can't get string table", name); + + init_minimal_symbol_collection (); + make_cleanup_discard_minimal_symbols (); + + /* Now that the executable file is positioned at symbol table, + process it and define symbols accordingly. */ + + coff_symtab_read ((long) symtab_offset, num_symbols, objfile); + + /* Sort symbols alphabetically within each block. */ + + { + struct symtab *s; + + for (s = objfile->symtabs; s != NULL; s = s->next) + sort_symtab_syms (s); + } + + /* Install any minimal symbols that have been collected as the current + minimal symbols for this objfile. */ + + install_minimal_symbols (objfile); + + bfd_map_over_sections (abfd, coff_locate_sections, (void *) info); + + if (info->stabsects) + { + if (!info->stabstrsect) + { + error (("The debugging information in `%s' is corrupted.\n" + "The file has a `.stabs' section, but no `.stabstr' " + "section."), + name); + } + + /* FIXME: dubious. Why can't we use something normal like + bfd_get_section_contents? */ + bfd_seek (abfd, abfd->where, 0); + + stabstrsize = bfd_section_size (abfd, info->stabstrsect); + + coffstab_build_psymtabs (objfile, + mainline, + info->textaddr, info->textsize, + info->stabsects, + info->stabstrsect->filepos, stabstrsize); + } + if (dwarf2_has_info (abfd)) + { + /* DWARF2 sections. */ + dwarf2_build_psymtabs (objfile, mainline); + } + + do_cleanups (back_to); +} + +static void +coff_new_init (struct objfile *ignore) +{ +} + +/* Perform any local cleanups required when we are done with a particular + objfile. I.E, we are in the process of discarding all symbol information + for an objfile, freeing up all memory held for it, and unlinking the + objfile struct from the global list of known objfiles. */ + +static void +coff_symfile_finish (struct objfile *objfile) +{ + if (objfile->sym_private != NULL) + { + xmfree (objfile->md, objfile->sym_private); + } + + /* Let stabs reader clean up */ + stabsread_clear_cache (); +} + + +/* Given pointers to a symbol table in coff style exec file, + analyze them and create struct symtab's describing the symbols. + NSYMS is the number of symbols in the symbol table. + We read them one at a time using read_one_sym (). */ + +static void +coff_symtab_read (long symtab_offset, unsigned int nsyms, + struct objfile *objfile) +{ + register struct context_stack *new; + struct coff_symbol coff_symbol; + register struct coff_symbol *cs = &coff_symbol; + static struct internal_syment main_sym; + static union internal_auxent main_aux; + struct coff_symbol fcn_cs_saved; + static struct internal_syment fcn_sym_saved; + static union internal_auxent fcn_aux_saved; + struct symtab *s; + /* A .file is open. */ + int in_source_file = 0; + int next_file_symnum = -1; + /* Name of the current file. */ + char *filestring = ""; + int depth = 0; + int fcn_first_line = 0; + CORE_ADDR fcn_first_line_addr = 0; + int fcn_last_line = 0; + int fcn_start_addr = 0; + long fcn_line_ptr = 0; + int val; + CORE_ADDR tmpaddr; + + /* Work around a stdio bug in SunOS4.1.1 (this makes me nervous.... + it's hard to know I've really worked around it. The fix should be + harmless, anyway). The symptom of the bug is that the first + fread (in read_one_sym), will (in my example) actually get data + from file offset 268, when the fseek was to 264 (and ftell shows + 264). This causes all hell to break loose. I was unable to + reproduce this on a short test program which operated on the same + file, performing (I think) the same sequence of operations. + + It stopped happening when I put in this (former) rewind(). + + FIXME: Find out if this has been reported to Sun, whether it has + been fixed in a later release, etc. */ + + bfd_seek (objfile->obfd, 0, 0); + + /* Position to read the symbol table. */ + val = bfd_seek (objfile->obfd, (long) symtab_offset, 0); + if (val < 0) + perror_with_name (objfile->name); + + current_objfile = objfile; + nlist_bfd_global = objfile->obfd; + nlist_nsyms_global = nsyms; + last_source_file = NULL; + memset (opaque_type_chain, 0, sizeof opaque_type_chain); + + if (type_vector) /* Get rid of previous one */ + xfree (type_vector); + type_vector_length = 160; + type_vector = (struct type **) + xmalloc (type_vector_length * sizeof (struct type *)); + memset (type_vector, 0, type_vector_length * sizeof (struct type *)); + + coff_start_symtab (""); + + symnum = 0; + while (symnum < nsyms) + { + QUIT; /* Make this command interruptable. */ + + read_one_sym (cs, &main_sym, &main_aux); + + if (cs->c_symnum == next_file_symnum && cs->c_sclass != C_FILE) + { + if (last_source_file) + coff_end_symtab (objfile); + + coff_start_symtab ("_globals_"); + complete_symtab ("_globals_", 0, 0); + /* done with all files, everything from here on out is globals */ + } + + /* Special case for file with type declarations only, no text. */ + if (!last_source_file && SDB_TYPE (cs->c_type) + && cs->c_secnum == N_DEBUG) + complete_symtab (filestring, 0, 0); + + /* Typedefs should not be treated as symbol definitions. */ + if (ISFCN (cs->c_type) && cs->c_sclass != C_TPDEF) + { + /* Record all functions -- external and static -- in minsyms. */ + tmpaddr = cs->c_value + ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + record_minimal_symbol (cs->c_name, tmpaddr, mst_text, objfile); + + fcn_line_ptr = main_aux.x_sym.x_fcnary.x_fcn.x_lnnoptr; + fcn_start_addr = tmpaddr; + fcn_cs_saved = *cs; + fcn_sym_saved = main_sym; + fcn_aux_saved = main_aux; + continue; + } + + switch (cs->c_sclass) + { + case C_EFCN: + case C_EXTDEF: + case C_ULABEL: + case C_USTATIC: + case C_LINE: + case C_ALIAS: + case C_HIDDEN: + complain (&bad_sclass_complaint, cs->c_name); + break; + + case C_FILE: + /* c_value field contains symnum of next .file entry in table + or symnum of first global after last .file. */ + next_file_symnum = cs->c_value; + if (cs->c_naux > 0) + filestring = coff_getfilename (&main_aux); + else + filestring = ""; + + /* Complete symbol table for last object file + containing debugging information. */ + if (last_source_file) + { + coff_end_symtab (objfile); + coff_start_symtab (filestring); + } + in_source_file = 1; + break; + + /* C_LABEL is used for labels and static functions. Including + it here allows gdb to see static functions when no debug + info is available. */ + case C_LABEL: + /* However, labels within a function can make weird backtraces, + so filter them out (from phdm@macqel.be). */ + if (within_function) + break; + case C_STAT: + case C_THUMBLABEL: + case C_THUMBSTAT: + case C_THUMBSTATFUNC: + if (cs->c_name[0] == '.') + { + if (STREQ (cs->c_name, ".text")) + { + /* FIXME: don't wire in ".text" as section name + or symbol name! */ + /* Check for in_source_file deals with case of + a file with debugging symbols + followed by a later file with no symbols. */ + if (in_source_file) + complete_symtab (filestring, + cs->c_value + ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)), + main_aux.x_scn.x_scnlen); + in_source_file = 0; + } + /* flush rest of '.' symbols */ + break; + } + else if (!SDB_TYPE (cs->c_type) + && cs->c_name[0] == 'L' + && (strncmp (cs->c_name, "LI%", 3) == 0 + || strncmp (cs->c_name, "LF%", 3) == 0 + || strncmp (cs->c_name, "LC%", 3) == 0 + || strncmp (cs->c_name, "LP%", 3) == 0 + || strncmp (cs->c_name, "LPB%", 4) == 0 + || strncmp (cs->c_name, "LBB%", 4) == 0 + || strncmp (cs->c_name, "LBE%", 4) == 0 + || strncmp (cs->c_name, "LPBX%", 5) == 0)) + /* At least on a 3b1, gcc generates swbeg and string labels + that look like this. Ignore them. */ + break; + /* fall in for static symbols that don't start with '.' */ + case C_THUMBEXT: + case C_THUMBEXTFUNC: + case C_EXT: + { + /* Record it in the minimal symbols regardless of + SDB_TYPE. This parallels what we do for other debug + formats, and probably is needed to make + print_address_symbolic work right without the (now + gone) "set fast-symbolic-addr off" kludge. */ + + /* FIXME: should use mst_abs, and not relocate, if absolute. */ + enum minimal_symbol_type ms_type; + int sec; + + if (cs->c_secnum == N_UNDEF) + { + /* This is a common symbol. See if the target + environment knows where it has been relocated to. */ + CORE_ADDR reladdr; + if (target_lookup_symbol (cs->c_name, &reladdr)) + { + /* Error in lookup; ignore symbol. */ + break; + } + tmpaddr = reladdr; + /* The address has already been relocated; make sure that + objfile_relocate doesn't relocate it again. */ + sec = -2; + ms_type = cs->c_sclass == C_EXT + || cs->c_sclass == C_THUMBEXT ? + mst_bss : mst_file_bss; + } + else + { + sec = cs_to_section (cs, objfile); + tmpaddr = cs->c_value; + if (cs->c_sclass == C_EXT || cs->c_sclass == C_THUMBEXTFUNC + || cs->c_sclass == C_THUMBEXT) + tmpaddr += ANOFFSET (objfile->section_offsets, sec); + + if (sec == SECT_OFF_TEXT (objfile)) + { + ms_type = + cs->c_sclass == C_EXT || cs->c_sclass == C_THUMBEXTFUNC + || cs->c_sclass == C_THUMBEXT ? + mst_text : mst_file_text; + tmpaddr = SMASH_TEXT_ADDRESS (tmpaddr); + } + else if (sec == SECT_OFF_DATA (objfile)) + { + ms_type = + cs->c_sclass == C_EXT || cs->c_sclass == C_THUMBEXT ? + mst_data : mst_file_data; + } + else if (sec == SECT_OFF_BSS (objfile)) + { + ms_type = + cs->c_sclass == C_EXT || cs->c_sclass == C_THUMBEXT ? + mst_data : mst_file_data; + } + else + ms_type = mst_unknown; + } + + if (cs->c_name[0] != '@' /* Skip tdesc symbols */ ) + { + struct minimal_symbol *msym; + + /* FIXME: cagney/2001-02-01: The nasty (int) -> (long) + -> (void*) cast is to ensure that that the value of + cs->c_sclass can be correctly stored in a void + pointer in MSYMBOL_INFO. Better solutions + welcome. */ + gdb_assert (sizeof (void *) >= sizeof (cs->c_sclass)); + msym = prim_record_minimal_symbol_and_info + (cs->c_name, tmpaddr, ms_type, (void *) (long) cs->c_sclass, + sec, NULL, objfile); + if (msym) + COFF_MAKE_MSYMBOL_SPECIAL (cs->c_sclass, msym); + } + if (SDB_TYPE (cs->c_type)) + { + struct symbol *sym; + sym = process_coff_symbol + (cs, &main_aux, objfile); + SYMBOL_VALUE (sym) = tmpaddr; + SYMBOL_SECTION (sym) = sec; + } + } + break; + + case C_FCN: + if (STREQ (cs->c_name, ".bf")) + { + within_function = 1; + + /* value contains address of first non-init type code */ + /* main_aux.x_sym.x_misc.x_lnsz.x_lnno + contains line number of '{' } */ + if (cs->c_naux != 1) + complain (&bf_no_aux_complaint, cs->c_symnum); + fcn_first_line = main_aux.x_sym.x_misc.x_lnsz.x_lnno; + fcn_first_line_addr = cs->c_value; + + /* Might want to check that locals are 0 and + context_stack_depth is zero, and complain if not. */ + + depth = 0; + new = push_context (depth, fcn_start_addr); + fcn_cs_saved.c_name = getsymname (&fcn_sym_saved); + new->name = + process_coff_symbol (&fcn_cs_saved, &fcn_aux_saved, objfile); + } + else if (STREQ (cs->c_name, ".ef")) + { + if (!within_function) + error ("Bad coff function information\n"); + /* the value of .ef is the address of epilogue code; + not useful for gdb. */ + /* { main_aux.x_sym.x_misc.x_lnsz.x_lnno + contains number of lines to '}' */ + + if (context_stack_depth <= 0) + { /* We attempted to pop an empty context stack */ + complain (&ef_stack_complaint, cs->c_symnum); + within_function = 0; + break; + } + + new = pop_context (); + /* Stack must be empty now. */ + if (context_stack_depth > 0 || new == NULL) + { + complain (&ef_complaint, cs->c_symnum); + within_function = 0; + break; + } + if (cs->c_naux != 1) + { + complain (&ef_no_aux_complaint, cs->c_symnum); + fcn_last_line = 0x7FFFFFFF; + } + else + { + fcn_last_line = main_aux.x_sym.x_misc.x_lnsz.x_lnno; + } + /* fcn_first_line is the line number of the opening '{'. + Do not record it - because it would affect gdb's idea + of the line number of the first statement of the function - + except for one-line functions, for which it is also the line + number of all the statements and of the closing '}', and + for which we do not have any other statement-line-number. */ + if (fcn_last_line == 1) + record_line (current_subfile, fcn_first_line, + fcn_first_line_addr); + else + enter_linenos (fcn_line_ptr, fcn_first_line, fcn_last_line, + objfile); + + finish_block (new->name, &local_symbols, new->old_blocks, + new->start_addr, +#if defined (FUNCTION_EPILOGUE_SIZE) + /* This macro should be defined only on + machines where the + fcn_aux_saved.x_sym.x_misc.x_fsize + field is always zero. + So use the .bf record information that + points to the epilogue and add the size + of the epilogue. */ + cs->c_value + + FUNCTION_EPILOGUE_SIZE + + ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)), +#else + fcn_cs_saved.c_value + + fcn_aux_saved.x_sym.x_misc.x_fsize + + ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)), +#endif + objfile + ); + within_function = 0; + } + break; + + case C_BLOCK: + if (STREQ (cs->c_name, ".bb")) + { + tmpaddr = cs->c_value; + tmpaddr += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + push_context (++depth, tmpaddr); + } + else if (STREQ (cs->c_name, ".eb")) + { + if (context_stack_depth <= 0) + { /* We attempted to pop an empty context stack */ + complain (&eb_stack_complaint, cs->c_symnum); + break; + } + + new = pop_context (); + if (depth-- != new->depth) + { + complain (&eb_complaint, symnum); + break; + } + if (local_symbols && context_stack_depth > 0) + { + tmpaddr = + cs->c_value + ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + /* Make a block for the local symbols within. */ + finish_block (0, &local_symbols, new->old_blocks, + new->start_addr, tmpaddr, objfile); + } + /* Now pop locals of block just finished. */ + local_symbols = new->locals; + } + break; + + default: + process_coff_symbol (cs, &main_aux, objfile); + break; + } + } + + if (last_source_file) + coff_end_symtab (objfile); + + /* Patch up any opaque types (references to types that are not defined + in the file where they are referenced, e.g. "struct foo *bar"). */ + ALL_OBJFILE_SYMTABS (objfile, s) + patch_opaque_types (s); + + current_objfile = NULL; +} + +/* Routines for reading headers and symbols from executable. */ + +/* Read the next symbol, swap it, and return it in both internal_syment + form, and coff_symbol form. Also return its first auxent, if any, + in internal_auxent form, and skip any other auxents. */ + +static void +read_one_sym (register struct coff_symbol *cs, + register struct internal_syment *sym, + register union internal_auxent *aux) +{ + int i; + + cs->c_symnum = symnum; + bfd_bread (temp_sym, local_symesz, nlist_bfd_global); + bfd_coff_swap_sym_in (symfile_bfd, temp_sym, (char *) sym); + cs->c_naux = sym->n_numaux & 0xff; + if (cs->c_naux >= 1) + { + bfd_bread (temp_aux, local_auxesz, nlist_bfd_global); + bfd_coff_swap_aux_in (symfile_bfd, temp_aux, sym->n_type, sym->n_sclass, + 0, cs->c_naux, (char *) aux); + /* If more than one aux entry, read past it (only the first aux + is important). */ + for (i = 1; i < cs->c_naux; i++) + bfd_bread (temp_aux, local_auxesz, nlist_bfd_global); + } + cs->c_name = getsymname (sym); + cs->c_value = sym->n_value; + cs->c_sclass = (sym->n_sclass & 0xff); + cs->c_secnum = sym->n_scnum; + cs->c_type = (unsigned) sym->n_type; + if (!SDB_TYPE (cs->c_type)) + cs->c_type = 0; + +#if 0 + if (cs->c_sclass & 128) + printf ("thumb symbol %s, class 0x%x\n", cs->c_name, cs->c_sclass); +#endif + + symnum += 1 + cs->c_naux; + + /* The PE file format stores symbol values as offsets within the + section, rather than as absolute addresses. We correct that + here, if the symbol has an appropriate storage class. FIXME: We + should use BFD to read the symbols, rather than duplicating the + work here. */ + if (pe_file) + { + switch (cs->c_sclass) + { + case C_EXT: + case C_THUMBEXT: + case C_THUMBEXTFUNC: + case C_SECTION: + case C_NT_WEAK: + case C_STAT: + case C_THUMBSTAT: + case C_THUMBSTATFUNC: + case C_LABEL: + case C_THUMBLABEL: + case C_BLOCK: + case C_FCN: + case C_EFCN: + if (cs->c_secnum != 0) + cs->c_value += cs_section_address (cs, symfile_bfd); + break; + } + } +} + +/* Support for string table handling */ + +static char *stringtab = NULL; + +static int +init_stringtab (bfd *abfd, long offset) +{ + long length; + int val; + unsigned char lengthbuf[4]; + + free_stringtab (); + + /* If the file is stripped, the offset might be zero, indicating no + string table. Just return with `stringtab' set to null. */ + if (offset == 0) + return 0; + + if (bfd_seek (abfd, offset, 0) < 0) + return -1; + + val = bfd_bread ((char *) lengthbuf, sizeof lengthbuf, abfd); + length = bfd_h_get_32 (symfile_bfd, lengthbuf); + + /* If no string table is needed, then the file may end immediately + after the symbols. Just return with `stringtab' set to null. */ + if (val != sizeof lengthbuf || length < sizeof lengthbuf) + return 0; + + stringtab = (char *) xmalloc (length); + /* This is in target format (probably not very useful, and not currently + used), not host format. */ + memcpy (stringtab, lengthbuf, sizeof lengthbuf); + if (length == sizeof length) /* Empty table -- just the count */ + return 0; + + val = bfd_bread (stringtab + sizeof lengthbuf, length - sizeof lengthbuf, + abfd); + if (val != length - sizeof lengthbuf || stringtab[length - 1] != '\0') + return -1; + + return 0; +} + +static void +free_stringtab (void) +{ + if (stringtab) + xfree (stringtab); + stringtab = NULL; +} + +static void +free_stringtab_cleanup (void *ignore) +{ + free_stringtab (); +} + +static char * +getsymname (struct internal_syment *symbol_entry) +{ + static char buffer[SYMNMLEN + 1]; + char *result; + + if (symbol_entry->_n._n_n._n_zeroes == 0) + { + /* FIXME: Probably should be detecting corrupt symbol files by + seeing whether offset points to within the stringtab. */ + result = stringtab + symbol_entry->_n._n_n._n_offset; + } + else + { + strncpy (buffer, symbol_entry->_n._n_name, SYMNMLEN); + buffer[SYMNMLEN] = '\0'; + result = buffer; + } + return result; +} + +/* Extract the file name from the aux entry of a C_FILE symbol. Return + only the last component of the name. Result is in static storage and + is only good for temporary use. */ + +static char * +coff_getfilename (union internal_auxent *aux_entry) +{ + static char buffer[BUFSIZ]; + register char *temp; + char *result; + + if (aux_entry->x_file.x_n.x_zeroes == 0) + strcpy (buffer, stringtab + aux_entry->x_file.x_n.x_offset); + else + { + strncpy (buffer, aux_entry->x_file.x_fname, FILNMLEN); + buffer[FILNMLEN] = '\0'; + } + result = buffer; + + /* FIXME: We should not be throwing away the information about what + directory. It should go into dirname of the symtab, or some such + place. */ + if ((temp = strrchr (result, '/')) != NULL) + result = temp + 1; + return (result); +} + +/* Support for line number handling. */ + +static char *linetab = NULL; +static long linetab_offset; +static unsigned long linetab_size; + +/* Read in all the line numbers for fast lookups later. Leave them in + external (unswapped) format in memory; we'll swap them as we enter + them into GDB's data structures. */ + +static int +init_lineno (bfd *abfd, long offset, int size) +{ + int val; + + linetab_offset = offset; + linetab_size = size; + + free_linetab (); + + if (size == 0) + return 0; + + if (bfd_seek (abfd, offset, 0) < 0) + return -1; + + /* Allocate the desired table, plus a sentinel */ + linetab = (char *) xmalloc (size + local_linesz); + + val = bfd_bread (linetab, size, abfd); + if (val != size) + return -1; + + /* Terminate it with an all-zero sentinel record */ + memset (linetab + size, 0, local_linesz); + + return 0; +} + +static void +free_linetab (void) +{ + if (linetab) + xfree (linetab); + linetab = NULL; +} + +static void +free_linetab_cleanup (void *ignore) +{ + free_linetab (); +} + +#if !defined (L_LNNO32) +#define L_LNNO32(lp) ((lp)->l_lnno) +#endif + +static void +enter_linenos (long file_offset, register int first_line, + register int last_line, struct objfile *objfile) +{ + register char *rawptr; + struct internal_lineno lptr; + + if (!linetab) + return; + if (file_offset < linetab_offset) + { + complain (&lineno_complaint, file_offset); + if (file_offset > linetab_size) /* Too big to be an offset? */ + return; + file_offset += linetab_offset; /* Try reading at that linetab offset */ + } + + rawptr = &linetab[file_offset - linetab_offset]; + + /* skip first line entry for each function */ + rawptr += local_linesz; + /* line numbers start at one for the first line of the function */ + first_line--; + + for (;;) + { + bfd_coff_swap_lineno_in (symfile_bfd, rawptr, &lptr); + rawptr += local_linesz; + /* The next function, or the sentinel, will have L_LNNO32 zero; we exit. */ + if (L_LNNO32 (&lptr) && L_LNNO32 (&lptr) <= last_line) + record_line (current_subfile, first_line + L_LNNO32 (&lptr), + lptr.l_addr.l_paddr + + ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile))); + else + break; + } +} + +static void +patch_type (struct type *type, struct type *real_type) +{ + register struct type *target = TYPE_TARGET_TYPE (type); + register struct type *real_target = TYPE_TARGET_TYPE (real_type); + int field_size = TYPE_NFIELDS (real_target) * sizeof (struct field); + + TYPE_LENGTH (target) = TYPE_LENGTH (real_target); + TYPE_NFIELDS (target) = TYPE_NFIELDS (real_target); + TYPE_FIELDS (target) = (struct field *) TYPE_ALLOC (target, field_size); + + memcpy (TYPE_FIELDS (target), TYPE_FIELDS (real_target), field_size); + + if (TYPE_NAME (real_target)) + { + if (TYPE_NAME (target)) + xfree (TYPE_NAME (target)); + TYPE_NAME (target) = concat (TYPE_NAME (real_target), NULL); + } +} + +/* Patch up all appropriate typedef symbols in the opaque_type_chains + so that they can be used to print out opaque data structures properly. */ + +static void +patch_opaque_types (struct symtab *s) +{ + register struct block *b; + register int i; + register struct symbol *real_sym; + + /* Go through the per-file symbols only */ + b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK); + ALL_BLOCK_SYMBOLS (b, i, real_sym) + { + /* Find completed typedefs to use to fix opaque ones. + Remove syms from the chain when their types are stored, + but search the whole chain, as there may be several syms + from different files with the same name. */ + if (SYMBOL_CLASS (real_sym) == LOC_TYPEDEF && + SYMBOL_NAMESPACE (real_sym) == VAR_NAMESPACE && + TYPE_CODE (SYMBOL_TYPE (real_sym)) == TYPE_CODE_PTR && + TYPE_LENGTH (TYPE_TARGET_TYPE (SYMBOL_TYPE (real_sym))) != 0) + { + register char *name = SYMBOL_NAME (real_sym); + register int hash = hashname (name); + register struct symbol *sym, *prev; + + prev = 0; + for (sym = opaque_type_chain[hash]; sym;) + { + if (name[0] == SYMBOL_NAME (sym)[0] && + STREQ (name + 1, SYMBOL_NAME (sym) + 1)) + { + if (prev) + { + SYMBOL_VALUE_CHAIN (prev) = SYMBOL_VALUE_CHAIN (sym); + } + else + { + opaque_type_chain[hash] = SYMBOL_VALUE_CHAIN (sym); + } + + patch_type (SYMBOL_TYPE (sym), SYMBOL_TYPE (real_sym)); + + if (prev) + { + sym = SYMBOL_VALUE_CHAIN (prev); + } + else + { + sym = opaque_type_chain[hash]; + } + } + else + { + prev = sym; + sym = SYMBOL_VALUE_CHAIN (sym); + } + } + } + } +} + +static struct symbol * +process_coff_symbol (register struct coff_symbol *cs, + register union internal_auxent *aux, + struct objfile *objfile) +{ + register struct symbol *sym + = (struct symbol *) obstack_alloc (&objfile->symbol_obstack, + sizeof (struct symbol)); + char *name; + + memset (sym, 0, sizeof (struct symbol)); + name = cs->c_name; + name = EXTERNAL_NAME (name, objfile->obfd); + SYMBOL_NAME (sym) = obsavestring (name, strlen (name), + &objfile->symbol_obstack); + SYMBOL_LANGUAGE (sym) = language_auto; + SYMBOL_INIT_DEMANGLED_NAME (sym, &objfile->symbol_obstack); + + /* default assumptions */ + SYMBOL_VALUE (sym) = cs->c_value; + SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; + SYMBOL_SECTION (sym) = cs_to_section (cs, objfile); + + if (ISFCN (cs->c_type)) + { + SYMBOL_VALUE (sym) += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + SYMBOL_TYPE (sym) = + lookup_function_type (decode_function_type (cs, cs->c_type, aux)); + + SYMBOL_CLASS (sym) = LOC_BLOCK; + if (cs->c_sclass == C_STAT || cs->c_sclass == C_THUMBSTAT + || cs->c_sclass == C_THUMBSTATFUNC) + add_symbol_to_list (sym, &file_symbols); + else if (cs->c_sclass == C_EXT || cs->c_sclass == C_THUMBEXT + || cs->c_sclass == C_THUMBEXTFUNC) + add_symbol_to_list (sym, &global_symbols); + } + else + { + SYMBOL_TYPE (sym) = decode_type (cs, cs->c_type, aux); + switch (cs->c_sclass) + { + case C_NULL: + break; + + case C_AUTO: + SYMBOL_CLASS (sym) = LOC_LOCAL; + add_symbol_to_list (sym, &local_symbols); + break; + + case C_THUMBEXT: + case C_THUMBEXTFUNC: + case C_EXT: + SYMBOL_CLASS (sym) = LOC_STATIC; + SYMBOL_VALUE_ADDRESS (sym) = (CORE_ADDR) cs->c_value; + SYMBOL_VALUE_ADDRESS (sym) += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + add_symbol_to_list (sym, &global_symbols); + break; + + case C_THUMBSTAT: + case C_THUMBSTATFUNC: + case C_STAT: + SYMBOL_CLASS (sym) = LOC_STATIC; + SYMBOL_VALUE_ADDRESS (sym) = (CORE_ADDR) cs->c_value; + SYMBOL_VALUE_ADDRESS (sym) += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + if (within_function) + { + /* Static symbol of local scope */ + add_symbol_to_list (sym, &local_symbols); + } + else + { + /* Static symbol at top level of file */ + add_symbol_to_list (sym, &file_symbols); + } + break; + +#ifdef C_GLBLREG /* AMD coff */ + case C_GLBLREG: +#endif + case C_REG: + SYMBOL_CLASS (sym) = LOC_REGISTER; + SYMBOL_VALUE (sym) = SDB_REG_TO_REGNUM (cs->c_value); + add_symbol_to_list (sym, &local_symbols); + break; + + case C_THUMBLABEL: + case C_LABEL: + break; + + case C_ARG: + SYMBOL_CLASS (sym) = LOC_ARG; + add_symbol_to_list (sym, &local_symbols); +#if !defined (BELIEVE_PCC_PROMOTION) + if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) + { + /* If PCC says a parameter is a short or a char, + aligned on an int boundary, realign it to the + "little end" of the int. */ + struct type *temptype; + temptype = lookup_fundamental_type (current_objfile, + FT_INTEGER); + if (TYPE_LENGTH (SYMBOL_TYPE (sym)) < TYPE_LENGTH (temptype) + && TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_INT + && 0 == SYMBOL_VALUE (sym) % TYPE_LENGTH (temptype)) + { + SYMBOL_VALUE (sym) += + TYPE_LENGTH (temptype) + - TYPE_LENGTH (SYMBOL_TYPE (sym)); + } + } +#endif + break; + + case C_REGPARM: + SYMBOL_CLASS (sym) = LOC_REGPARM; + SYMBOL_VALUE (sym) = SDB_REG_TO_REGNUM (cs->c_value); + add_symbol_to_list (sym, &local_symbols); +#if !defined (BELIEVE_PCC_PROMOTION) + /* FIXME: This should retain the current type, since it's just + a register value. gnu@adobe, 26Feb93 */ + { + /* If PCC says a parameter is a short or a char, + it is really an int. */ + struct type *temptype; + temptype = + lookup_fundamental_type (current_objfile, FT_INTEGER); + if (TYPE_LENGTH (SYMBOL_TYPE (sym)) < TYPE_LENGTH (temptype) + && TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_INT) + { + SYMBOL_TYPE (sym) = + (TYPE_UNSIGNED (SYMBOL_TYPE (sym)) + ? lookup_fundamental_type (current_objfile, + FT_UNSIGNED_INTEGER) + : temptype); + } + } +#endif + break; + + case C_TPDEF: + SYMBOL_CLASS (sym) = LOC_TYPEDEF; + SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; + + /* If type has no name, give it one */ + if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0) + { + if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_PTR + || TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_FUNC) + { + /* If we are giving a name to a type such as "pointer to + foo" or "function returning foo", we better not set + the TYPE_NAME. If the program contains "typedef char + *caddr_t;", we don't want all variables of type char + * to print as caddr_t. This is not just a + consequence of GDB's type management; CC and GCC (at + least through version 2.4) both output variables of + either type char * or caddr_t with the type + refering to the C_TPDEF symbol for caddr_t. If a future + compiler cleans this up it GDB is not ready for it + yet, but if it becomes ready we somehow need to + disable this check (without breaking the PCC/GCC2.4 + case). + + Sigh. + + Fortunately, this check seems not to be necessary + for anything except pointers or functions. */ + ; + } + else + TYPE_NAME (SYMBOL_TYPE (sym)) = + concat (SYMBOL_NAME (sym), NULL); + } +#ifdef CXUX_TARGET + /* Ignore vendor section for Harris CX/UX targets. */ + else if (cs->c_name[0] == '$') + break; +#endif /* CXUX_TARGET */ + + /* Keep track of any type which points to empty structured type, + so it can be filled from a definition from another file. A + simple forward reference (TYPE_CODE_UNDEF) is not an + empty structured type, though; the forward references + work themselves out via the magic of coff_lookup_type. */ + if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_PTR && + TYPE_LENGTH (TYPE_TARGET_TYPE (SYMBOL_TYPE (sym))) == 0 && + TYPE_CODE (TYPE_TARGET_TYPE (SYMBOL_TYPE (sym))) != + TYPE_CODE_UNDEF) + { + register int i = hashname (SYMBOL_NAME (sym)); + + SYMBOL_VALUE_CHAIN (sym) = opaque_type_chain[i]; + opaque_type_chain[i] = sym; + } + add_symbol_to_list (sym, &file_symbols); + break; + + case C_STRTAG: + case C_UNTAG: + case C_ENTAG: + SYMBOL_CLASS (sym) = LOC_TYPEDEF; + SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE; + + /* Some compilers try to be helpful by inventing "fake" + names for anonymous enums, structures, and unions, like + "~0fake" or ".0fake". Thanks, but no thanks... */ + if (TYPE_TAG_NAME (SYMBOL_TYPE (sym)) == 0) + if (SYMBOL_NAME (sym) != NULL + && *SYMBOL_NAME (sym) != '~' + && *SYMBOL_NAME (sym) != '.') + TYPE_TAG_NAME (SYMBOL_TYPE (sym)) = + concat (SYMBOL_NAME (sym), NULL); + + add_symbol_to_list (sym, &file_symbols); + break; + + default: + break; + } + } + return sym; +} + +/* Decode a coff type specifier; return the type that is meant. */ + +static struct type * +decode_type (register struct coff_symbol *cs, unsigned int c_type, + register union internal_auxent *aux) +{ + register struct type *type = 0; + unsigned int new_c_type; + + if (c_type & ~N_BTMASK) + { + new_c_type = DECREF (c_type); + if (ISPTR (c_type)) + { + type = decode_type (cs, new_c_type, aux); + type = lookup_pointer_type (type); + } + else if (ISFCN (c_type)) + { + type = decode_type (cs, new_c_type, aux); + type = lookup_function_type (type); + } + else if (ISARY (c_type)) + { + int i, n; + register unsigned short *dim; + struct type *base_type, *index_type, *range_type; + + /* Define an array type. */ + /* auxent refers to array, not base type */ + if (aux->x_sym.x_tagndx.l == 0) + cs->c_naux = 0; + + /* shift the indices down */ + dim = &aux->x_sym.x_fcnary.x_ary.x_dimen[0]; + i = 1; + n = dim[0]; + for (i = 0; *dim && i < DIMNUM - 1; i++, dim++) + *dim = *(dim + 1); + *dim = 0; + + base_type = decode_type (cs, new_c_type, aux); + index_type = lookup_fundamental_type (current_objfile, FT_INTEGER); + range_type = + create_range_type ((struct type *) NULL, index_type, 0, n - 1); + type = + create_array_type ((struct type *) NULL, base_type, range_type); + } + return type; + } + + /* Reference to existing type. This only occurs with the + struct, union, and enum types. EPI a29k coff + fakes us out by producing aux entries with a nonzero + x_tagndx for definitions of structs, unions, and enums, so we + have to check the c_sclass field. SCO 3.2v4 cc gets confused + with pointers to pointers to defined structs, and generates + negative x_tagndx fields. */ + if (cs->c_naux > 0 && aux->x_sym.x_tagndx.l != 0) + { + if (cs->c_sclass != C_STRTAG + && cs->c_sclass != C_UNTAG + && cs->c_sclass != C_ENTAG + && aux->x_sym.x_tagndx.l >= 0) + { + type = coff_alloc_type (aux->x_sym.x_tagndx.l); + return type; + } + else + { + complain (&tagndx_bad_complaint, cs->c_name); + /* And fall through to decode_base_type... */ + } + } + + return decode_base_type (cs, BTYPE (c_type), aux); +} + +/* Decode a coff type specifier for function definition; + return the type that the function returns. */ + +static struct type * +decode_function_type (register struct coff_symbol *cs, unsigned int c_type, + register union internal_auxent *aux) +{ + if (aux->x_sym.x_tagndx.l == 0) + cs->c_naux = 0; /* auxent refers to function, not base type */ + + return decode_type (cs, DECREF (c_type), aux); +} + +/* basic C types */ + +static struct type * +decode_base_type (register struct coff_symbol *cs, unsigned int c_type, + register union internal_auxent *aux) +{ + struct type *type; + + switch (c_type) + { + case T_NULL: + /* shows up with "void (*foo)();" structure members */ + return lookup_fundamental_type (current_objfile, FT_VOID); + +#if 0 +/* DGUX actually defines both T_ARG and T_VOID to the same value. */ +#ifdef T_ARG + case T_ARG: + /* Shows up in DGUX, I think. Not sure where. */ + return lookup_fundamental_type (current_objfile, FT_VOID); /* shouldn't show up here */ +#endif +#endif /* 0 */ + +#ifdef T_VOID + case T_VOID: + /* Intel 960 COFF has this symbol and meaning. */ + return lookup_fundamental_type (current_objfile, FT_VOID); +#endif + + case T_CHAR: + return lookup_fundamental_type (current_objfile, FT_CHAR); + + case T_SHORT: + return lookup_fundamental_type (current_objfile, FT_SHORT); + + case T_INT: + return lookup_fundamental_type (current_objfile, FT_INTEGER); + + case T_LONG: + if (cs->c_sclass == C_FIELD + && aux->x_sym.x_misc.x_lnsz.x_size > TARGET_LONG_BIT) + return lookup_fundamental_type (current_objfile, FT_LONG_LONG); + else + return lookup_fundamental_type (current_objfile, FT_LONG); + + case T_FLOAT: + return lookup_fundamental_type (current_objfile, FT_FLOAT); + + case T_DOUBLE: + return lookup_fundamental_type (current_objfile, FT_DBL_PREC_FLOAT); + + case T_LNGDBL: + return lookup_fundamental_type (current_objfile, FT_EXT_PREC_FLOAT); + + case T_STRUCT: + if (cs->c_naux != 1) + { + /* anonymous structure type */ + type = coff_alloc_type (cs->c_symnum); + TYPE_CODE (type) = TYPE_CODE_STRUCT; + TYPE_NAME (type) = NULL; + /* This used to set the tag to "<opaque>". But I think setting it + to NULL is right, and the printing code can print it as + "struct {...}". */ + TYPE_TAG_NAME (type) = NULL; + INIT_CPLUS_SPECIFIC (type); + TYPE_LENGTH (type) = 0; + TYPE_FIELDS (type) = 0; + TYPE_NFIELDS (type) = 0; + } + else + { + type = coff_read_struct_type (cs->c_symnum, + aux->x_sym.x_misc.x_lnsz.x_size, + aux->x_sym.x_fcnary.x_fcn.x_endndx.l); + } + return type; + + case T_UNION: + if (cs->c_naux != 1) + { + /* anonymous union type */ + type = coff_alloc_type (cs->c_symnum); + TYPE_NAME (type) = NULL; + /* This used to set the tag to "<opaque>". But I think setting it + to NULL is right, and the printing code can print it as + "union {...}". */ + TYPE_TAG_NAME (type) = NULL; + INIT_CPLUS_SPECIFIC (type); + TYPE_LENGTH (type) = 0; + TYPE_FIELDS (type) = 0; + TYPE_NFIELDS (type) = 0; + } + else + { + type = coff_read_struct_type (cs->c_symnum, + aux->x_sym.x_misc.x_lnsz.x_size, + aux->x_sym.x_fcnary.x_fcn.x_endndx.l); + } + TYPE_CODE (type) = TYPE_CODE_UNION; + return type; + + case T_ENUM: + if (cs->c_naux != 1) + { + /* anonymous enum type */ + type = coff_alloc_type (cs->c_symnum); + TYPE_CODE (type) = TYPE_CODE_ENUM; + TYPE_NAME (type) = NULL; + /* This used to set the tag to "<opaque>". But I think setting it + to NULL is right, and the printing code can print it as + "enum {...}". */ + TYPE_TAG_NAME (type) = NULL; + TYPE_LENGTH (type) = 0; + TYPE_FIELDS (type) = 0; + TYPE_NFIELDS (type) = 0; + } + else + { + type = coff_read_enum_type (cs->c_symnum, + aux->x_sym.x_misc.x_lnsz.x_size, + aux->x_sym.x_fcnary.x_fcn.x_endndx.l); + } + return type; + + case T_MOE: + /* shouldn't show up here */ + break; + + case T_UCHAR: + return lookup_fundamental_type (current_objfile, FT_UNSIGNED_CHAR); + + case T_USHORT: + return lookup_fundamental_type (current_objfile, FT_UNSIGNED_SHORT); + + case T_UINT: + return lookup_fundamental_type (current_objfile, FT_UNSIGNED_INTEGER); + + case T_ULONG: + if (cs->c_sclass == C_FIELD + && aux->x_sym.x_misc.x_lnsz.x_size > TARGET_LONG_BIT) + return lookup_fundamental_type (current_objfile, FT_UNSIGNED_LONG_LONG); + else + return lookup_fundamental_type (current_objfile, FT_UNSIGNED_LONG); + } + complain (&unexpected_type_complaint, cs->c_name); + return lookup_fundamental_type (current_objfile, FT_VOID); +} + +/* This page contains subroutines of read_type. */ + +/* Read the description of a structure (or union type) and return an + object describing the type. */ + +static struct type * +coff_read_struct_type (int index, int length, int lastsym) +{ + struct nextfield + { + struct nextfield *next; + struct field field; + }; + + register struct type *type; + register struct nextfield *list = 0; + struct nextfield *new; + int nfields = 0; + register int n; + char *name; + struct coff_symbol member_sym; + register struct coff_symbol *ms = &member_sym; + struct internal_syment sub_sym; + union internal_auxent sub_aux; + int done = 0; + + type = coff_alloc_type (index); + TYPE_CODE (type) = TYPE_CODE_STRUCT; + INIT_CPLUS_SPECIFIC (type); + TYPE_LENGTH (type) = length; + + while (!done && symnum < lastsym && symnum < nlist_nsyms_global) + { + read_one_sym (ms, &sub_sym, &sub_aux); + name = ms->c_name; + name = EXTERNAL_NAME (name, current_objfile->obfd); + + switch (ms->c_sclass) + { + case C_MOS: + case C_MOU: + + /* Get space to record the next field's data. */ + new = (struct nextfield *) alloca (sizeof (struct nextfield)); + new->next = list; + list = new; + + /* Save the data. */ + list->field.name = + obsavestring (name, + strlen (name), + ¤t_objfile->symbol_obstack); + FIELD_TYPE (list->field) = decode_type (ms, ms->c_type, &sub_aux); + FIELD_BITPOS (list->field) = 8 * ms->c_value; + FIELD_BITSIZE (list->field) = 0; + nfields++; + break; + + case C_FIELD: + + /* Get space to record the next field's data. */ + new = (struct nextfield *) alloca (sizeof (struct nextfield)); + new->next = list; + list = new; + + /* Save the data. */ + list->field.name = + obsavestring (name, + strlen (name), + ¤t_objfile->symbol_obstack); + FIELD_TYPE (list->field) = decode_type (ms, ms->c_type, &sub_aux); + FIELD_BITPOS (list->field) = ms->c_value; + FIELD_BITSIZE (list->field) = sub_aux.x_sym.x_misc.x_lnsz.x_size; + nfields++; + break; + + case C_EOS: + done = 1; + break; + } + } + /* Now create the vector of fields, and record how big it is. */ + + TYPE_NFIELDS (type) = nfields; + TYPE_FIELDS (type) = (struct field *) + TYPE_ALLOC (type, sizeof (struct field) * nfields); + + /* Copy the saved-up fields into the field vector. */ + + for (n = nfields; list; list = list->next) + TYPE_FIELD (type, --n) = list->field; + + return type; +} + +/* Read a definition of an enumeration type, + and create and return a suitable type object. + Also defines the symbols that represent the values of the type. */ + +/* ARGSUSED */ +static struct type * +coff_read_enum_type (int index, int length, int lastsym) +{ + register struct symbol *sym; + register struct type *type; + int nsyms = 0; + int done = 0; + struct pending **symlist; + struct coff_symbol member_sym; + register struct coff_symbol *ms = &member_sym; + struct internal_syment sub_sym; + union internal_auxent sub_aux; + struct pending *osyms, *syms; + int o_nsyms; + register int n; + char *name; + int unsigned_enum = 1; + + type = coff_alloc_type (index); + if (within_function) + symlist = &local_symbols; + else + symlist = &file_symbols; + osyms = *symlist; + o_nsyms = osyms ? osyms->nsyms : 0; + + while (!done && symnum < lastsym && symnum < nlist_nsyms_global) + { + read_one_sym (ms, &sub_sym, &sub_aux); + name = ms->c_name; + name = EXTERNAL_NAME (name, current_objfile->obfd); + + switch (ms->c_sclass) + { + case C_MOE: + sym = (struct symbol *) obstack_alloc + (¤t_objfile->symbol_obstack, + sizeof (struct symbol)); + memset (sym, 0, sizeof (struct symbol)); + + SYMBOL_NAME (sym) = + obsavestring (name, strlen (name), + ¤t_objfile->symbol_obstack); + SYMBOL_CLASS (sym) = LOC_CONST; + SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; + SYMBOL_VALUE (sym) = ms->c_value; + add_symbol_to_list (sym, symlist); + nsyms++; + break; + + case C_EOS: + /* Sometimes the linker (on 386/ix 2.0.2 at least) screws + up the count of how many symbols to read. So stop + on .eos. */ + done = 1; + break; + } + } + + /* Now fill in the fields of the type-structure. */ + + if (length > 0) + TYPE_LENGTH (type) = length; + else + TYPE_LENGTH (type) = TARGET_INT_BIT / TARGET_CHAR_BIT; /* Assume ints */ + TYPE_CODE (type) = TYPE_CODE_ENUM; + TYPE_NFIELDS (type) = nsyms; + TYPE_FIELDS (type) = (struct field *) + TYPE_ALLOC (type, sizeof (struct field) * nsyms); + + /* Find the symbols for the values and put them into the type. + The symbols can be found in the symlist that we put them on + to cause them to be defined. osyms contains the old value + of that symlist; everything up to there was defined by us. */ + /* Note that we preserve the order of the enum constants, so + that in something like "enum {FOO, LAST_THING=FOO}" we print + FOO, not LAST_THING. */ + + for (syms = *symlist, n = 0; syms; syms = syms->next) + { + int j = 0; + + if (syms == osyms) + j = o_nsyms; + for (; j < syms->nsyms; j++, n++) + { + struct symbol *xsym = syms->symbol[j]; + SYMBOL_TYPE (xsym) = type; + TYPE_FIELD_NAME (type, n) = SYMBOL_NAME (xsym); + TYPE_FIELD_BITPOS (type, n) = SYMBOL_VALUE (xsym); + if (SYMBOL_VALUE (xsym) < 0) + unsigned_enum = 0; + TYPE_FIELD_BITSIZE (type, n) = 0; + } + if (syms == osyms) + break; + } + + if (unsigned_enum) + TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED; + + return type; +} + +/* Register our ability to parse symbols for coff BFD files. */ + +static struct sym_fns coff_sym_fns = +{ + bfd_target_coff_flavour, + coff_new_init, /* sym_new_init: init anything gbl to entire symtab */ + coff_symfile_init, /* sym_init: read initial info, setup for sym_read() */ + coff_symfile_read, /* sym_read: read a symbol file into symtab */ + coff_symfile_finish, /* sym_finish: finished with file, cleanup */ + default_symfile_offsets, /* sym_offsets: xlate external to internal form */ + NULL /* next: pointer to next struct sym_fns */ +}; + +void +_initialize_coffread (void) +{ + add_symtab_fns (&coff_sym_fns); +} diff --git a/gdb/dbxread.c b/gdb/dbxread.c new file mode 100644 index 0000000..6592b74 --- /dev/null +++ b/gdb/dbxread.c @@ -0,0 +1,3599 @@ +/* Read dbx symbol tables and convert to internal format, for GDB. + Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, + 1996, 1997, 1998, 1999, 2000, 2001, 2002 + 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 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This module provides three functions: dbx_symfile_init, + which initializes to read a symbol file; dbx_new_init, which + discards existing cached information when all symbols are being + discarded; and dbx_symfile_read, which reads a symbol table + from a file. + + dbx_symfile_read only does the minimum work necessary for letting the + user "name" things symbolically; it does not read the entire symtab. + Instead, it reads the external and static symbols and puts them in partial + symbol tables. When more extensive information is requested of a + file, the corresponding partial symbol table is mutated into a full + fledged symbol table by going back and reading the symbols + for real. dbx_psymtab_to_symtab() is the function that does this */ + +#include "defs.h" +#include "gdb_string.h" + +#if defined(USG) || defined(__CYGNUSCLIB__) +#include <sys/types.h> +#include <fcntl.h> +#endif + +#include "gdb_obstack.h" +#include "gdb_stat.h" +#include "symtab.h" +#include "breakpoint.h" +#include "target.h" +#include "gdbcore.h" /* for bfd stuff */ +#include "libaout.h" /* FIXME Secret internal BFD stuff for a.out */ +#include "symfile.h" +#include "objfiles.h" +#include "buildsym.h" +#include "stabsread.h" +#include "gdb-stabs.h" +#include "demangle.h" +#include "language.h" /* Needed for local_hex_string */ +#include "complaints.h" +#include "cp-abi.h" + +#include "aout/aout64.h" +#include "aout/stab_gnu.h" /* We always use GNU stabs, not native, now */ + + +/* This macro returns the size field of a minimal symbol, which is normally + stored in the "info" field. The macro can be overridden for specific + targets (e.g. MIPS16) that use the info field for other purposes. */ +#ifndef MSYMBOL_SIZE +#define MSYMBOL_SIZE(msym) ((long) MSYMBOL_INFO (msym)) +#endif + + +/* We put a pointer to this structure in the read_symtab_private field + of the psymtab. */ + +struct symloc + { + /* Offset within the file symbol table of first local symbol for this + file. */ + + int ldsymoff; + + /* Length (in bytes) of the section of the symbol table devoted to + this file's symbols (actually, the section bracketed may contain + more than just this file's symbols). If ldsymlen is 0, the only + reason for this thing's existence is the dependency list. Nothing + else will happen when it is read in. */ + + int ldsymlen; + + /* The size of each symbol in the symbol file (in external form). */ + + int symbol_size; + + /* Further information needed to locate the symbols if they are in + an ELF file. */ + + int symbol_offset; + int string_offset; + int file_string_offset; + }; + +#define LDSYMOFF(p) (((struct symloc *)((p)->read_symtab_private))->ldsymoff) +#define LDSYMLEN(p) (((struct symloc *)((p)->read_symtab_private))->ldsymlen) +#define SYMLOC(p) ((struct symloc *)((p)->read_symtab_private)) +#define SYMBOL_SIZE(p) (SYMLOC(p)->symbol_size) +#define SYMBOL_OFFSET(p) (SYMLOC(p)->symbol_offset) +#define STRING_OFFSET(p) (SYMLOC(p)->string_offset) +#define FILE_STRING_OFFSET(p) (SYMLOC(p)->file_string_offset) + + +/* Remember what we deduced to be the source language of this psymtab. */ + +static enum language psymtab_language = language_unknown; + +/* The BFD for this file -- implicit parameter to next_symbol_text. */ + +static bfd *symfile_bfd; + +/* The size of each symbol in the symbol file (in external form). + This is set by dbx_symfile_read when building psymtabs, and by + dbx_psymtab_to_symtab when building symtabs. */ + +static unsigned symbol_size; + +/* This is the offset of the symbol table in the executable file. */ + +static unsigned symbol_table_offset; + +/* This is the offset of the string table in the executable file. */ + +static unsigned string_table_offset; + +/* For elf+stab executables, the n_strx field is not a simple index + into the string table. Instead, each .o file has a base offset in + the string table, and the associated symbols contain offsets from + this base. The following two variables contain the base offset for + the current and next .o files. */ + +static unsigned int file_string_table_offset; +static unsigned int next_file_string_table_offset; + +/* .o and NLM files contain unrelocated addresses which are based at + 0. When non-zero, this flag disables some of the special cases for + Solaris elf+stab text addresses at location 0. */ + +static int symfile_relocatable = 0; + +/* If this is nonzero, N_LBRAC, N_RBRAC, and N_SLINE entries are + relative to the function start address. */ + +static int block_address_function_relative = 0; + +/* The lowest text address we have yet encountered. This is needed + because in an a.out file, there is no header field which tells us + what address the program is actually going to be loaded at, so we + need to make guesses based on the symbols (which *are* relocated to + reflect the address it will be loaded at). */ + +static CORE_ADDR lowest_text_address; + +/* Non-zero if there is any line number info in the objfile. Prevents + end_psymtab from discarding an otherwise empty psymtab. */ + +static int has_line_numbers; + +/* Complaints about the symbols we have encountered. */ + +struct complaint lbrac_complaint = +{"bad block start address patched", 0, 0}; + +struct complaint string_table_offset_complaint = +{"bad string table offset in symbol %d", 0, 0}; + +struct complaint unknown_symtype_complaint = +{"unknown symbol type %s", 0, 0}; + +struct complaint unknown_symchar_complaint = +{"unknown symbol descriptor `%c'", 0, 0}; + +struct complaint lbrac_rbrac_complaint = +{"block start larger than block end", 0, 0}; + +struct complaint lbrac_unmatched_complaint = +{"unmatched N_LBRAC before symtab pos %d", 0, 0}; + +struct complaint lbrac_mismatch_complaint = +{"N_LBRAC/N_RBRAC symbol mismatch at symtab pos %d", 0, 0}; + +struct complaint repeated_header_complaint = +{"\"repeated\" header file %s not previously seen, at symtab pos %d", 0, 0}; + +struct complaint unclaimed_bincl_complaint = +{"N_BINCL %s not in entries for any file, at symtab pos %d", 0, 0}; + +struct complaint discarding_local_symbols_complaint = +{"misplaced N_LBRAC entry; discarding local symbols which have no enclosing block", 0, 0}; + +/* find_text_range --- find start and end of loadable code sections + + The find_text_range function finds the shortest address range that + encloses all sections containing executable code, and stores it in + objfile's text_addr and text_size members. + + dbx_symfile_read will use this to finish off the partial symbol + table, in some cases. */ + +static void +find_text_range (bfd * sym_bfd, struct objfile *objfile) +{ + asection *sec; + int found_any = 0; + CORE_ADDR start = 0; + CORE_ADDR end = 0; + + for (sec = sym_bfd->sections; sec; sec = sec->next) + if (bfd_get_section_flags (sym_bfd, sec) & SEC_CODE) + { + CORE_ADDR sec_start = bfd_section_vma (sym_bfd, sec); + CORE_ADDR sec_end = sec_start + bfd_section_size (sym_bfd, sec); + + if (found_any) + { + if (sec_start < start) + start = sec_start; + if (sec_end > end) + end = sec_end; + } + else + { + start = sec_start; + end = sec_end; + } + + found_any = 1; + } + + if (!found_any) + error ("Can't find any code sections in symbol file"); + + DBX_TEXT_ADDR (objfile) = start; + DBX_TEXT_SIZE (objfile) = end - start; +} + + + +/* During initial symbol readin, we need to have a structure to keep + track of which psymtabs have which bincls in them. This structure + is used during readin to setup the list of dependencies within each + partial symbol table. */ + +struct header_file_location +{ + char *name; /* Name of header file */ + int instance; /* See above */ + struct partial_symtab *pst; /* Partial symtab that has the + BINCL/EINCL defs for this file */ +}; + +/* The actual list and controling variables */ +static struct header_file_location *bincl_list, *next_bincl; +static int bincls_allocated; + +/* Local function prototypes */ + +extern void _initialize_dbxread (void); + +static void process_now (struct objfile *); + +static void read_ofile_symtab (struct partial_symtab *); + +static void dbx_psymtab_to_symtab (struct partial_symtab *); + +static void dbx_psymtab_to_symtab_1 (struct partial_symtab *); + +static void read_dbx_dynamic_symtab (struct objfile *objfile); + +static void read_dbx_symtab (struct objfile *); + +static void free_bincl_list (struct objfile *); + +static struct partial_symtab *find_corresponding_bincl_psymtab (char *, int); + +static void add_bincl_to_list (struct partial_symtab *, char *, int); + +static void init_bincl_list (int, struct objfile *); + +static char *dbx_next_symbol_text (struct objfile *); + +static void fill_symbuf (bfd *); + +static void dbx_symfile_init (struct objfile *); + +static void dbx_new_init (struct objfile *); + +static void dbx_symfile_read (struct objfile *, int); + +static void dbx_symfile_finish (struct objfile *); + +static void record_minimal_symbol (char *, CORE_ADDR, int, struct objfile *); + +static void add_new_header_file (char *, int); + +static void add_old_header_file (char *, int); + +static void add_this_object_header_file (int); + +static struct partial_symtab *start_psymtab (struct objfile *, char *, + CORE_ADDR, int, + struct partial_symbol **, + struct partial_symbol **); + +/* Free up old header file tables */ + +void +free_header_files (void) +{ + if (this_object_header_files) + { + xfree (this_object_header_files); + this_object_header_files = NULL; + } + n_allocated_this_object_header_files = 0; +} + +/* Allocate new header file tables */ + +void +init_header_files (void) +{ + n_allocated_this_object_header_files = 10; + this_object_header_files = (int *) xmalloc (10 * sizeof (int)); +} + +/* Add header file number I for this object file + at the next successive FILENUM. */ + +static void +add_this_object_header_file (int i) +{ + if (n_this_object_header_files == n_allocated_this_object_header_files) + { + n_allocated_this_object_header_files *= 2; + this_object_header_files + = (int *) xrealloc ((char *) this_object_header_files, + n_allocated_this_object_header_files * sizeof (int)); + } + + this_object_header_files[n_this_object_header_files++] = i; +} + +/* Add to this file an "old" header file, one already seen in + a previous object file. NAME is the header file's name. + INSTANCE is its instance code, to select among multiple + symbol tables for the same header file. */ + +static void +add_old_header_file (char *name, int instance) +{ + register struct header_file *p = HEADER_FILES (current_objfile); + register int i; + + for (i = 0; i < N_HEADER_FILES (current_objfile); i++) + if (STREQ (p[i].name, name) && instance == p[i].instance) + { + add_this_object_header_file (i); + return; + } + complain (&repeated_header_complaint, name, symnum); +} + +/* Add to this file a "new" header file: definitions for its types follow. + NAME is the header file's name. + Most often this happens only once for each distinct header file, + but not necessarily. If it happens more than once, INSTANCE has + a different value each time, and references to the header file + use INSTANCE values to select among them. + + dbx output contains "begin" and "end" markers for each new header file, + but at this level we just need to know which files there have been; + so we record the file when its "begin" is seen and ignore the "end". */ + +static void +add_new_header_file (char *name, int instance) +{ + register int i; + register struct header_file *hfile; + + /* Make sure there is room for one more header file. */ + + i = N_ALLOCATED_HEADER_FILES (current_objfile); + + if (N_HEADER_FILES (current_objfile) == i) + { + if (i == 0) + { + N_ALLOCATED_HEADER_FILES (current_objfile) = 10; + HEADER_FILES (current_objfile) = (struct header_file *) + xmalloc (10 * sizeof (struct header_file)); + } + else + { + i *= 2; + N_ALLOCATED_HEADER_FILES (current_objfile) = i; + HEADER_FILES (current_objfile) = (struct header_file *) + xrealloc ((char *) HEADER_FILES (current_objfile), + (i * sizeof (struct header_file))); + } + } + + /* Create an entry for this header file. */ + + i = N_HEADER_FILES (current_objfile)++; + hfile = HEADER_FILES (current_objfile) + i; + hfile->name = savestring (name, strlen (name)); + hfile->instance = instance; + hfile->length = 10; + hfile->vector + = (struct type **) xmalloc (10 * sizeof (struct type *)); + memset (hfile->vector, 0, 10 * sizeof (struct type *)); + + add_this_object_header_file (i); +} + +#if 0 +static struct type ** +explicit_lookup_type (int real_filenum, int index) +{ + register struct header_file *f = &HEADER_FILES (current_objfile)[real_filenum]; + + if (index >= f->length) + { + f->length *= 2; + f->vector = (struct type **) + xrealloc (f->vector, f->length * sizeof (struct type *)); + memset (&f->vector[f->length / 2], + '\0', f->length * sizeof (struct type *) / 2); + } + return &f->vector[index]; +} +#endif + +static void +record_minimal_symbol (char *name, CORE_ADDR address, int type, + struct objfile *objfile) +{ + enum minimal_symbol_type ms_type; + int section; + asection *bfd_section; + + switch (type) + { + case N_TEXT | N_EXT: + ms_type = mst_text; + section = SECT_OFF_TEXT (objfile); + bfd_section = DBX_TEXT_SECTION (objfile); + break; + case N_DATA | N_EXT: + ms_type = mst_data; + section = SECT_OFF_DATA (objfile); + bfd_section = DBX_DATA_SECTION (objfile); + break; + case N_BSS | N_EXT: + ms_type = mst_bss; + section = SECT_OFF_BSS (objfile); + bfd_section = DBX_BSS_SECTION (objfile); + break; + case N_ABS | N_EXT: + ms_type = mst_abs; + section = -1; + bfd_section = NULL; + break; +#ifdef N_SETV + case N_SETV | N_EXT: + ms_type = mst_data; + section = SECT_OFF_DATA (objfile); + bfd_section = DBX_DATA_SECTION (objfile); + break; + case N_SETV: + /* I don't think this type actually exists; since a N_SETV is the result + of going over many .o files, it doesn't make sense to have one + file local. */ + ms_type = mst_file_data; + section = SECT_OFF_DATA (objfile); + bfd_section = DBX_DATA_SECTION (objfile); + break; +#endif + case N_TEXT: + case N_NBTEXT: + case N_FN: + case N_FN_SEQ: + ms_type = mst_file_text; + section = SECT_OFF_TEXT (objfile); + bfd_section = DBX_TEXT_SECTION (objfile); + break; + case N_DATA: + ms_type = mst_file_data; + + /* Check for __DYNAMIC, which is used by Sun shared libraries. + Record it as global even if it's local, not global, so + lookup_minimal_symbol can find it. We don't check symbol_leading_char + because for SunOS4 it always is '_'. */ + if (name[8] == 'C' && STREQ ("__DYNAMIC", name)) + ms_type = mst_data; + + /* Same with virtual function tables, both global and static. */ + { + char *tempstring = name; + if (tempstring[0] == bfd_get_symbol_leading_char (objfile->obfd)) + ++tempstring; + if (is_vtable_name (tempstring)) + ms_type = mst_data; + } + section = SECT_OFF_DATA (objfile); + bfd_section = DBX_DATA_SECTION (objfile); + break; + case N_BSS: + ms_type = mst_file_bss; + section = SECT_OFF_BSS (objfile); + bfd_section = DBX_BSS_SECTION (objfile); + break; + default: + ms_type = mst_unknown; + section = -1; + bfd_section = NULL; + break; + } + + if ((ms_type == mst_file_text || ms_type == mst_text) + && address < lowest_text_address) + lowest_text_address = address; + + prim_record_minimal_symbol_and_info + (name, address, ms_type, NULL, section, bfd_section, objfile); +} + +/* Scan and build partial symbols for a symbol file. + We have been initialized by a call to dbx_symfile_init, which + put all the relevant info into a "struct dbx_symfile_info", + hung off the objfile structure. + + MAINLINE is true if we are reading the main symbol + table (as opposed to a shared lib or dynamically loaded file). */ + +static void +dbx_symfile_read (struct objfile *objfile, int mainline) +{ + bfd *sym_bfd; + int val; + struct cleanup *back_to; + + sym_bfd = objfile->obfd; + + /* .o and .nlm files are relocatables with text, data and bss segs based at + 0. This flag disables special (Solaris stabs-in-elf only) fixups for + symbols with a value of 0. */ + + symfile_relocatable = bfd_get_file_flags (sym_bfd) & HAS_RELOC; + + /* This is true for Solaris (and all other systems which put stabs + in sections, hopefully, since it would be silly to do things + differently from Solaris), and false for SunOS4 and other a.out + file formats. */ + block_address_function_relative = + ((0 == strncmp (bfd_get_target (sym_bfd), "elf", 3)) + || (0 == strncmp (bfd_get_target (sym_bfd), "som", 3)) + || (0 == strncmp (bfd_get_target (sym_bfd), "coff", 4)) + || (0 == strncmp (bfd_get_target (sym_bfd), "pe", 2)) + || (0 == strncmp (bfd_get_target (sym_bfd), "epoc-pe", 7)) + || (0 == strncmp (bfd_get_target (sym_bfd), "nlm", 3))); + + val = bfd_seek (sym_bfd, DBX_SYMTAB_OFFSET (objfile), SEEK_SET); + if (val < 0) + perror_with_name (objfile->name); + + /* If we are reinitializing, or if we have never loaded syms yet, init */ + if (mainline + || (objfile->global_psymbols.size == 0 + && objfile->static_psymbols.size == 0)) + init_psymbol_list (objfile, DBX_SYMCOUNT (objfile)); + + symbol_size = DBX_SYMBOL_SIZE (objfile); + symbol_table_offset = DBX_SYMTAB_OFFSET (objfile); + + free_pending_blocks (); + back_to = make_cleanup (really_free_pendings, 0); + + init_minimal_symbol_collection (); + make_cleanup_discard_minimal_symbols (); + + /* Read stabs data from executable file and define symbols. */ + + read_dbx_symtab (objfile); + + /* Add the dynamic symbols. */ + + read_dbx_dynamic_symtab (objfile); + + /* Install any minimal symbols that have been collected as the current + minimal symbols for this objfile. */ + + install_minimal_symbols (objfile); + + do_cleanups (back_to); +} + +/* Initialize anything that needs initializing when a completely new + symbol file is specified (not just adding some symbols from another + file, e.g. a shared library). */ + +static void +dbx_new_init (struct objfile *ignore) +{ + stabsread_new_init (); + buildsym_new_init (); + init_header_files (); +} + + +/* dbx_symfile_init () + is the dbx-specific initialization routine for reading symbols. + It is passed a struct objfile which contains, among other things, + the BFD for the file whose symbols are being read, and a slot for a pointer + to "private data" which we fill with goodies. + + We read the string table into malloc'd space and stash a pointer to it. + + Since BFD doesn't know how to read debug symbols in a format-independent + way (and may never do so...), we have to do it ourselves. We will never + be called unless this is an a.out (or very similar) file. + FIXME, there should be a cleaner peephole into the BFD environment here. */ + +#define DBX_STRINGTAB_SIZE_SIZE sizeof(long) /* FIXME */ + +static void +dbx_symfile_init (struct objfile *objfile) +{ + int val; + bfd *sym_bfd = objfile->obfd; + char *name = bfd_get_filename (sym_bfd); + asection *text_sect; + unsigned char size_temp[DBX_STRINGTAB_SIZE_SIZE]; + + /* Allocate struct to keep track of the symfile */ + objfile->sym_stab_info = (struct dbx_symfile_info *) + xmmalloc (objfile->md, sizeof (struct dbx_symfile_info)); + memset ((PTR) objfile->sym_stab_info, 0, sizeof (struct dbx_symfile_info)); + + DBX_TEXT_SECTION (objfile) = bfd_get_section_by_name (sym_bfd, ".text"); + DBX_DATA_SECTION (objfile) = bfd_get_section_by_name (sym_bfd, ".data"); + DBX_BSS_SECTION (objfile) = bfd_get_section_by_name (sym_bfd, ".bss"); + + /* FIXME POKING INSIDE BFD DATA STRUCTURES */ +#define STRING_TABLE_OFFSET (sym_bfd->origin + obj_str_filepos (sym_bfd)) +#define SYMBOL_TABLE_OFFSET (sym_bfd->origin + obj_sym_filepos (sym_bfd)) + + /* FIXME POKING INSIDE BFD DATA STRUCTURES */ + + DBX_SYMFILE_INFO (objfile)->stab_section_info = NULL; + + text_sect = bfd_get_section_by_name (sym_bfd, ".text"); + if (!text_sect) + error ("Can't find .text section in symbol file"); + DBX_TEXT_ADDR (objfile) = bfd_section_vma (sym_bfd, text_sect); + DBX_TEXT_SIZE (objfile) = bfd_section_size (sym_bfd, text_sect); + + DBX_SYMBOL_SIZE (objfile) = obj_symbol_entry_size (sym_bfd); + DBX_SYMCOUNT (objfile) = bfd_get_symcount (sym_bfd); + DBX_SYMTAB_OFFSET (objfile) = SYMBOL_TABLE_OFFSET; + + /* Read the string table and stash it away in the psymbol_obstack. It is + only needed as long as we need to expand psymbols into full symbols, + so when we blow away the psymbol the string table goes away as well. + Note that gdb used to use the results of attempting to malloc the + string table, based on the size it read, as a form of sanity check + for botched byte swapping, on the theory that a byte swapped string + table size would be so totally bogus that the malloc would fail. Now + that we put in on the psymbol_obstack, we can't do this since gdb gets + a fatal error (out of virtual memory) if the size is bogus. We can + however at least check to see if the size is less than the size of + the size field itself, or larger than the size of the entire file. + Note that all valid string tables have a size greater than zero, since + the bytes used to hold the size are included in the count. */ + + if (STRING_TABLE_OFFSET == 0) + { + /* It appears that with the existing bfd code, STRING_TABLE_OFFSET + will never be zero, even when there is no string table. This + would appear to be a bug in bfd. */ + DBX_STRINGTAB_SIZE (objfile) = 0; + DBX_STRINGTAB (objfile) = NULL; + } + else + { + val = bfd_seek (sym_bfd, STRING_TABLE_OFFSET, SEEK_SET); + if (val < 0) + perror_with_name (name); + + memset ((PTR) size_temp, 0, sizeof (size_temp)); + val = bfd_bread ((PTR) size_temp, sizeof (size_temp), sym_bfd); + if (val < 0) + { + perror_with_name (name); + } + else if (val == 0) + { + /* With the existing bfd code, STRING_TABLE_OFFSET will be set to + EOF if there is no string table, and attempting to read the size + from EOF will read zero bytes. */ + DBX_STRINGTAB_SIZE (objfile) = 0; + DBX_STRINGTAB (objfile) = NULL; + } + else + { + /* Read some data that would appear to be the string table size. + If there really is a string table, then it is probably the right + size. Byteswap if necessary and validate the size. Note that + the minimum is DBX_STRINGTAB_SIZE_SIZE. If we just read some + random data that happened to be at STRING_TABLE_OFFSET, because + bfd can't tell us there is no string table, the sanity checks may + or may not catch this. */ + DBX_STRINGTAB_SIZE (objfile) = bfd_h_get_32 (sym_bfd, size_temp); + + if (DBX_STRINGTAB_SIZE (objfile) < sizeof (size_temp) + || DBX_STRINGTAB_SIZE (objfile) > bfd_get_size (sym_bfd)) + error ("ridiculous string table size (%d bytes).", + DBX_STRINGTAB_SIZE (objfile)); + + DBX_STRINGTAB (objfile) = + (char *) obstack_alloc (&objfile->psymbol_obstack, + DBX_STRINGTAB_SIZE (objfile)); + OBJSTAT (objfile, sz_strtab += DBX_STRINGTAB_SIZE (objfile)); + + /* Now read in the string table in one big gulp. */ + + val = bfd_seek (sym_bfd, STRING_TABLE_OFFSET, SEEK_SET); + if (val < 0) + perror_with_name (name); + val = bfd_bread (DBX_STRINGTAB (objfile), + DBX_STRINGTAB_SIZE (objfile), + sym_bfd); + if (val != DBX_STRINGTAB_SIZE (objfile)) + perror_with_name (name); + } + } +} + +/* Perform any local cleanups required when we are done with a particular + objfile. I.E, we are in the process of discarding all symbol information + for an objfile, freeing up all memory held for it, and unlinking the + objfile struct from the global list of known objfiles. */ + +static void +dbx_symfile_finish (struct objfile *objfile) +{ + if (objfile->sym_stab_info != NULL) + { + if (HEADER_FILES (objfile) != NULL) + { + register int i = N_HEADER_FILES (objfile); + register struct header_file *hfiles = HEADER_FILES (objfile); + + while (--i >= 0) + { + xfree (hfiles[i].name); + xfree (hfiles[i].vector); + } + xfree (hfiles); + } + xmfree (objfile->md, objfile->sym_stab_info); + } + free_header_files (); +} + + +/* Buffer for reading the symbol table entries. */ +static struct external_nlist symbuf[4096]; +static int symbuf_idx; +static int symbuf_end; + +/* cont_elem is used for continuing information in cfront. + It saves information about which types need to be fixed up and + completed after all the stabs are read. */ +struct cont_elem + { + /* sym and stabstring for continuing information in cfront */ + struct symbol *sym; + char *stabs; + /* state dependencies (statics that must be preserved) */ + int sym_idx; + int sym_end; + int symnum; + int (*func) (struct objfile *, struct symbol *, char *); + /* other state dependencies include: + (assumption is that these will not change since process_now FIXME!!) + stringtab_global + n_stabs + objfile + symfile_bfd */ + }; + +static struct cont_elem *cont_list = 0; +static int cont_limit = 0; +static int cont_count = 0; + +/* Arrange for function F to be called with arguments SYM and P later + in the stabs reading process. */ +void +process_later (struct symbol *sym, char *p, + int (*f) (struct objfile *, struct symbol *, char *)) +{ + + /* Allocate more space for the deferred list. */ + if (cont_count >= cont_limit - 1) + { + cont_limit += 32; /* chunk size */ + + cont_list + = (struct cont_elem *) xrealloc (cont_list, + (cont_limit + * sizeof (struct cont_elem))); + if (!cont_list) + error ("Virtual memory exhausted\n"); + } + + /* Save state variables so we can process these stabs later. */ + cont_list[cont_count].sym_idx = symbuf_idx; + cont_list[cont_count].sym_end = symbuf_end; + cont_list[cont_count].symnum = symnum; + cont_list[cont_count].sym = sym; + cont_list[cont_count].stabs = p; + cont_list[cont_count].func = f; + cont_count++; +} + +/* Call deferred funtions in CONT_LIST. */ + +static void +process_now (struct objfile *objfile) +{ + int i; + int save_symbuf_idx; + int save_symbuf_end; + int save_symnum; + struct symbol *sym; + char *stabs; + int err; + int (*func) (struct objfile *, struct symbol *, char *); + + /* Save the state of our caller, we'll want to restore it before + returning. */ + save_symbuf_idx = symbuf_idx; + save_symbuf_end = symbuf_end; + save_symnum = symnum; + + /* Iterate over all the deferred stabs. */ + for (i = 0; i < cont_count; i++) + { + /* Restore the state for this deferred stab. */ + symbuf_idx = cont_list[i].sym_idx; + symbuf_end = cont_list[i].sym_end; + symnum = cont_list[i].symnum; + sym = cont_list[i].sym; + stabs = cont_list[i].stabs; + func = cont_list[i].func; + + /* Call the function to handle this deferrd stab. */ + err = (*func) (objfile, sym, stabs); + if (err) + error ("Internal error: unable to resolve stab.\n"); + } + + /* Restore our caller's state. */ + symbuf_idx = save_symbuf_idx; + symbuf_end = save_symbuf_end; + symnum = save_symnum; + cont_count = 0; +} + + +/* Name of last function encountered. Used in Solaris to approximate + object file boundaries. */ +static char *last_function_name; + +/* The address in memory of the string table of the object file we are + reading (which might not be the "main" object file, but might be a + shared library or some other dynamically loaded thing). This is + set by read_dbx_symtab when building psymtabs, and by + read_ofile_symtab when building symtabs, and is used only by + next_symbol_text. FIXME: If that is true, we don't need it when + building psymtabs, right? */ +static char *stringtab_global; + +/* These variables are used to control fill_symbuf when the stabs + symbols are not contiguous (as may be the case when a COFF file is + linked using --split-by-reloc). */ +static struct stab_section_list *symbuf_sections; +static unsigned int symbuf_left; +static unsigned int symbuf_read; + +/* Refill the symbol table input buffer + and set the variables that control fetching entries from it. + Reports an error if no data available. + This function can read past the end of the symbol table + (into the string table) but this does no harm. */ + +static void +fill_symbuf (bfd *sym_bfd) +{ + unsigned int count; + int nbytes; + + if (symbuf_sections == NULL) + count = sizeof (symbuf); + else + { + if (symbuf_left <= 0) + { + file_ptr filepos = symbuf_sections->section->filepos; + if (bfd_seek (sym_bfd, filepos, SEEK_SET) != 0) + perror_with_name (bfd_get_filename (sym_bfd)); + symbuf_left = bfd_section_size (sym_bfd, symbuf_sections->section); + symbol_table_offset = filepos - symbuf_read; + symbuf_sections = symbuf_sections->next; + } + + count = symbuf_left; + if (count > sizeof (symbuf)) + count = sizeof (symbuf); + } + + nbytes = bfd_bread ((PTR) symbuf, count, sym_bfd); + if (nbytes < 0) + perror_with_name (bfd_get_filename (sym_bfd)); + else if (nbytes == 0) + error ("Premature end of file reading symbol table"); + symbuf_end = nbytes / symbol_size; + symbuf_idx = 0; + symbuf_left -= nbytes; + symbuf_read += nbytes; +} + +#define INTERNALIZE_SYMBOL(intern, extern, abfd) \ + { \ + (intern).n_type = bfd_h_get_8 (abfd, (extern)->e_type); \ + (intern).n_strx = bfd_h_get_32 (abfd, (extern)->e_strx); \ + (intern).n_desc = bfd_h_get_16 (abfd, (extern)->e_desc); \ + if (bfd_get_sign_extend_vma (abfd)) \ + (intern).n_value = bfd_h_get_signed_32 (abfd, (extern)->e_value); \ + else \ + (intern).n_value = bfd_h_get_32 (abfd, (extern)->e_value); \ + } + +/* Invariant: The symbol pointed to by symbuf_idx is the first one + that hasn't been swapped. Swap the symbol at the same time + that symbuf_idx is incremented. */ + +/* dbx allows the text of a symbol name to be continued into the + next symbol name! When such a continuation is encountered + (a \ at the end of the text of a name) + call this function to get the continuation. */ + +static char * +dbx_next_symbol_text (struct objfile *objfile) +{ + struct internal_nlist nlist; + + if (symbuf_idx == symbuf_end) + fill_symbuf (symfile_bfd); + + symnum++; + INTERNALIZE_SYMBOL (nlist, &symbuf[symbuf_idx], symfile_bfd); + OBJSTAT (objfile, n_stabs++); + + symbuf_idx++; + + return nlist.n_strx + stringtab_global + file_string_table_offset; +} + +/* Initialize the list of bincls to contain none and have some + allocated. */ + +static void +init_bincl_list (int number, struct objfile *objfile) +{ + bincls_allocated = number; + next_bincl = bincl_list = (struct header_file_location *) + xmmalloc (objfile->md, bincls_allocated * sizeof (struct header_file_location)); +} + +/* Add a bincl to the list. */ + +static void +add_bincl_to_list (struct partial_symtab *pst, char *name, int instance) +{ + if (next_bincl >= bincl_list + bincls_allocated) + { + int offset = next_bincl - bincl_list; + bincls_allocated *= 2; + bincl_list = (struct header_file_location *) + xmrealloc (pst->objfile->md, (char *) bincl_list, + bincls_allocated * sizeof (struct header_file_location)); + next_bincl = bincl_list + offset; + } + next_bincl->pst = pst; + next_bincl->instance = instance; + next_bincl++->name = name; +} + +/* Given a name, value pair, find the corresponding + bincl in the list. Return the partial symtab associated + with that header_file_location. */ + +static struct partial_symtab * +find_corresponding_bincl_psymtab (char *name, int instance) +{ + struct header_file_location *bincl; + + for (bincl = bincl_list; bincl < next_bincl; bincl++) + if (bincl->instance == instance + && STREQ (name, bincl->name)) + return bincl->pst; + + complain (&repeated_header_complaint, name, symnum); + return (struct partial_symtab *) 0; +} + +/* Free the storage allocated for the bincl list. */ + +static void +free_bincl_list (struct objfile *objfile) +{ + xmfree (objfile->md, (PTR) bincl_list); + bincls_allocated = 0; +} + +static void +do_free_bincl_list_cleanup (void *objfile) +{ + free_bincl_list (objfile); +} + +static struct cleanup * +make_cleanup_free_bincl_list (struct objfile *objfile) +{ + return make_cleanup (do_free_bincl_list_cleanup, objfile); +} + +/* Set namestring based on nlist. If the string table index is invalid, + give a fake name, and print a single error message per symbol file read, + rather than abort the symbol reading or flood the user with messages. */ + +static char * +set_namestring (struct objfile *objfile, struct internal_nlist nlist) +{ + char *namestring; + + if (((unsigned) nlist.n_strx + file_string_table_offset) >= + DBX_STRINGTAB_SIZE (objfile)) + { + complain (&string_table_offset_complaint, symnum); + namestring = "<bad string table offset>"; + } + else + namestring = nlist.n_strx + file_string_table_offset + + DBX_STRINGTAB (objfile); + return namestring; +} + +/* Scan a SunOs dynamic symbol table for symbols of interest and + add them to the minimal symbol table. */ + +static void +read_dbx_dynamic_symtab (struct objfile *objfile) +{ + bfd *abfd = objfile->obfd; + struct cleanup *back_to; + int counter; + long dynsym_size; + long dynsym_count; + asymbol **dynsyms; + asymbol **symptr; + arelent **relptr; + long dynrel_size; + long dynrel_count; + arelent **dynrels; + CORE_ADDR sym_value; + char *name; + + /* Check that the symbol file has dynamic symbols that we know about. + bfd_arch_unknown can happen if we are reading a sun3 symbol file + on a sun4 host (and vice versa) and bfd is not configured + --with-target=all. This would trigger an assertion in bfd/sunos.c, + so we ignore the dynamic symbols in this case. */ + if (bfd_get_flavour (abfd) != bfd_target_aout_flavour + || (bfd_get_file_flags (abfd) & DYNAMIC) == 0 + || bfd_get_arch (abfd) == bfd_arch_unknown) + return; + + dynsym_size = bfd_get_dynamic_symtab_upper_bound (abfd); + if (dynsym_size < 0) + return; + + dynsyms = (asymbol **) xmalloc (dynsym_size); + back_to = make_cleanup (xfree, dynsyms); + + dynsym_count = bfd_canonicalize_dynamic_symtab (abfd, dynsyms); + if (dynsym_count < 0) + { + do_cleanups (back_to); + return; + } + + /* Enter dynamic symbols into the minimal symbol table + if this is a stripped executable. */ + if (bfd_get_symcount (abfd) <= 0) + { + symptr = dynsyms; + for (counter = 0; counter < dynsym_count; counter++, symptr++) + { + asymbol *sym = *symptr; + asection *sec; + int type; + + sec = bfd_get_section (sym); + + /* BFD symbols are section relative. */ + sym_value = sym->value + sec->vma; + + if (bfd_get_section_flags (abfd, sec) & SEC_CODE) + { + sym_value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + type = N_TEXT; + } + else if (bfd_get_section_flags (abfd, sec) & SEC_DATA) + { + sym_value += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile)); + type = N_DATA; + } + else if (bfd_get_section_flags (abfd, sec) & SEC_ALLOC) + { + sym_value += ANOFFSET (objfile->section_offsets, SECT_OFF_BSS (objfile)); + type = N_BSS; + } + else + continue; + + if (sym->flags & BSF_GLOBAL) + type |= N_EXT; + + record_minimal_symbol ((char *) bfd_asymbol_name (sym), sym_value, + type, objfile); + } + } + + /* Symbols from shared libraries have a dynamic relocation entry + that points to the associated slot in the procedure linkage table. + We make a mininal symbol table entry with type mst_solib_trampoline + at the address in the procedure linkage table. */ + dynrel_size = bfd_get_dynamic_reloc_upper_bound (abfd); + if (dynrel_size < 0) + { + do_cleanups (back_to); + return; + } + + dynrels = (arelent **) xmalloc (dynrel_size); + make_cleanup (xfree, dynrels); + + dynrel_count = bfd_canonicalize_dynamic_reloc (abfd, dynrels, dynsyms); + if (dynrel_count < 0) + { + do_cleanups (back_to); + return; + } + + for (counter = 0, relptr = dynrels; + counter < dynrel_count; + counter++, relptr++) + { + arelent *rel = *relptr; + CORE_ADDR address = + rel->address + ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile)); + + switch (bfd_get_arch (abfd)) + { + case bfd_arch_sparc: + if (rel->howto->type != RELOC_JMP_SLOT) + continue; + break; + case bfd_arch_m68k: + /* `16' is the type BFD produces for a jump table relocation. */ + if (rel->howto->type != 16) + continue; + + /* Adjust address in the jump table to point to + the start of the bsr instruction. */ + address -= 2; + break; + default: + continue; + } + + name = (char *) bfd_asymbol_name (*rel->sym_ptr_ptr); + prim_record_minimal_symbol (name, address, mst_solib_trampoline, + objfile); + } + + do_cleanups (back_to); +} + +#ifdef SOFUN_ADDRESS_MAYBE_MISSING +CORE_ADDR +find_stab_function_addr (char *namestring, char *filename, + struct objfile *objfile) +{ + struct minimal_symbol *msym; + char *p; + int n; + + p = strchr (namestring, ':'); + if (p == NULL) + p = namestring; + n = p - namestring; + p = alloca (n + 2); + strncpy (p, namestring, n); + p[n] = 0; + + msym = lookup_minimal_symbol (p, filename, objfile); + if (msym == NULL) + { + /* Sun Fortran appends an underscore to the minimal symbol name, + try again with an appended underscore if the minimal symbol + was not found. */ + p[n] = '_'; + p[n + 1] = 0; + msym = lookup_minimal_symbol (p, filename, objfile); + } + + if (msym == NULL && filename != NULL) + { + /* Try again without the filename. */ + p[n] = 0; + msym = lookup_minimal_symbol (p, NULL, objfile); + } + if (msym == NULL && filename != NULL) + { + /* And try again for Sun Fortran, but without the filename. */ + p[n] = '_'; + p[n + 1] = 0; + msym = lookup_minimal_symbol (p, NULL, objfile); + } + + return msym == NULL ? 0 : SYMBOL_VALUE_ADDRESS (msym); +} +#endif /* SOFUN_ADDRESS_MAYBE_MISSING */ + +/* Setup partial_symtab's describing each source file for which + debugging information is available. */ + +static void +read_dbx_symtab (struct objfile *objfile) +{ + register struct external_nlist *bufp = 0; /* =0 avoids gcc -Wall glitch */ + struct internal_nlist nlist; + CORE_ADDR text_addr; + int text_size; + + register char *namestring; + int nsl; + int past_first_source_file = 0; + CORE_ADDR last_o_file_start = 0; + CORE_ADDR last_function_start = 0; + struct cleanup *back_to; + bfd *abfd; + int textlow_not_set; + + /* Current partial symtab */ + struct partial_symtab *pst; + + /* List of current psymtab's include files */ + char **psymtab_include_list; + int includes_allocated; + int includes_used; + + /* Index within current psymtab dependency list */ + struct partial_symtab **dependency_list; + int dependencies_used, dependencies_allocated; + + text_addr = DBX_TEXT_ADDR (objfile); + text_size = DBX_TEXT_SIZE (objfile); + + /* FIXME. We probably want to change stringtab_global rather than add this + while processing every symbol entry. FIXME. */ + file_string_table_offset = 0; + next_file_string_table_offset = 0; + + stringtab_global = DBX_STRINGTAB (objfile); + + pst = (struct partial_symtab *) 0; + + includes_allocated = 30; + includes_used = 0; + psymtab_include_list = (char **) alloca (includes_allocated * + sizeof (char *)); + + dependencies_allocated = 30; + dependencies_used = 0; + dependency_list = + (struct partial_symtab **) alloca (dependencies_allocated * + sizeof (struct partial_symtab *)); + + /* Init bincl list */ + init_bincl_list (20, objfile); + back_to = make_cleanup_free_bincl_list (objfile); + + last_source_file = NULL; + + lowest_text_address = (CORE_ADDR) -1; + + symfile_bfd = objfile->obfd; /* For next_text_symbol */ + abfd = objfile->obfd; + symbuf_end = symbuf_idx = 0; + next_symbol_text_func = dbx_next_symbol_text; + textlow_not_set = 1; + has_line_numbers = 0; + + for (symnum = 0; symnum < DBX_SYMCOUNT (objfile); symnum++) + { + /* Get the symbol for this run and pull out some info */ + QUIT; /* allow this to be interruptable */ + if (symbuf_idx == symbuf_end) + fill_symbuf (abfd); + bufp = &symbuf[symbuf_idx++]; + + /* + * Special case to speed up readin. + */ + if (bfd_h_get_8 (abfd, bufp->e_type) == N_SLINE) + { + has_line_numbers = 1; + continue; + } + + INTERNALIZE_SYMBOL (nlist, bufp, abfd); + OBJSTAT (objfile, n_stabs++); + + /* Ok. There is a lot of code duplicated in the rest of this + switch statement (for efficiency reasons). Since I don't + like duplicating code, I will do my penance here, and + describe the code which is duplicated: + + *) The assignment to namestring. + *) The call to strchr. + *) The addition of a partial symbol the the two partial + symbol lists. This last is a large section of code, so + I've imbedded it in the following macro. + */ + + switch (nlist.n_type) + { + static struct complaint function_outside_compilation_unit = { + "function `%s' appears to be defined outside of all compilation units", 0, 0 + }; + char *p; + /* + * Standard, external, non-debugger, symbols + */ + + case N_TEXT | N_EXT: + case N_NBTEXT | N_EXT: + nlist.n_value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + goto record_it; + + case N_DATA | N_EXT: + case N_NBDATA | N_EXT: + nlist.n_value += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile)); + goto record_it; + + case N_BSS: + case N_BSS | N_EXT: + case N_NBBSS | N_EXT: + case N_SETV | N_EXT: /* FIXME, is this in BSS? */ + nlist.n_value += ANOFFSET (objfile->section_offsets, SECT_OFF_BSS (objfile)); + goto record_it; + + case N_ABS | N_EXT: + record_it: + namestring = set_namestring (objfile, nlist); + + bss_ext_symbol: + record_minimal_symbol (namestring, nlist.n_value, + nlist.n_type, objfile); /* Always */ + continue; + + /* Standard, local, non-debugger, symbols */ + + case N_NBTEXT: + + /* We need to be able to deal with both N_FN or N_TEXT, + because we have no way of knowing whether the sys-supplied ld + or GNU ld was used to make the executable. Sequents throw + in another wrinkle -- they renumbered N_FN. */ + + case N_FN: + case N_FN_SEQ: + case N_TEXT: + nlist.n_value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + namestring = set_namestring (objfile, nlist); + + if ((namestring[0] == '-' && namestring[1] == 'l') + || (namestring[(nsl = strlen (namestring)) - 1] == 'o' + && namestring[nsl - 2] == '.')) + { + if (objfile->ei.entry_point < nlist.n_value && + objfile->ei.entry_point >= last_o_file_start) + { + objfile->ei.entry_file_lowpc = last_o_file_start; + objfile->ei.entry_file_highpc = nlist.n_value; + } + if (past_first_source_file && pst + /* The gould NP1 uses low values for .o and -l symbols + which are not the address. */ + && nlist.n_value >= pst->textlow) + { + end_psymtab (pst, psymtab_include_list, includes_used, + symnum * symbol_size, + nlist.n_value > pst->texthigh + ? nlist.n_value : pst->texthigh, + dependency_list, dependencies_used, textlow_not_set); + pst = (struct partial_symtab *) 0; + includes_used = 0; + dependencies_used = 0; + } + else + past_first_source_file = 1; + last_o_file_start = nlist.n_value; + } + else + goto record_it; + continue; + + case N_DATA: + nlist.n_value += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile)); + goto record_it; + + case N_UNDF | N_EXT: + if (nlist.n_value != 0) + { + /* This is a "Fortran COMMON" symbol. See if the target + environment knows where it has been relocated to. */ + + CORE_ADDR reladdr; + + namestring = set_namestring (objfile, nlist); + if (target_lookup_symbol (namestring, &reladdr)) + { + continue; /* Error in lookup; ignore symbol for now. */ + } + nlist.n_type ^= (N_BSS ^ N_UNDF); /* Define it as a bss-symbol */ + nlist.n_value = reladdr; + goto bss_ext_symbol; + } + continue; /* Just undefined, not COMMON */ + + case N_UNDF: + if (processing_acc_compilation && nlist.n_strx == 1) + { + /* Deal with relative offsets in the string table + used in ELF+STAB under Solaris. If we want to use the + n_strx field, which contains the name of the file, + we must adjust file_string_table_offset *before* calling + set_namestring(). */ + past_first_source_file = 1; + file_string_table_offset = next_file_string_table_offset; + next_file_string_table_offset = + file_string_table_offset + nlist.n_value; + if (next_file_string_table_offset < file_string_table_offset) + error ("string table offset backs up at %d", symnum); + /* FIXME -- replace error() with complaint. */ + continue; + } + continue; + + /* Lots of symbol types we can just ignore. */ + + case N_ABS: + case N_NBDATA: + case N_NBBSS: + continue; + + /* Keep going . . . */ + + /* + * Special symbol types for GNU + */ + case N_INDR: + case N_INDR | N_EXT: + case N_SETA: + case N_SETA | N_EXT: + case N_SETT: + case N_SETT | N_EXT: + case N_SETD: + case N_SETD | N_EXT: + case N_SETB: + case N_SETB | N_EXT: + case N_SETV: + continue; + + /* + * Debugger symbols + */ + + case N_SO: + { + CORE_ADDR valu; + static int prev_so_symnum = -10; + static int first_so_symnum; + char *p; + int prev_textlow_not_set; + + valu = nlist.n_value + ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + + prev_textlow_not_set = textlow_not_set; + +#ifdef SOFUN_ADDRESS_MAYBE_MISSING + /* A zero value is probably an indication for the SunPRO 3.0 + compiler. end_psymtab explicitly tests for zero, so + don't relocate it. */ + + if (nlist.n_value == 0) + { + textlow_not_set = 1; + valu = 0; + } + else + textlow_not_set = 0; +#else + textlow_not_set = 0; +#endif + past_first_source_file = 1; + + if (prev_so_symnum != symnum - 1) + { /* Here if prev stab wasn't N_SO */ + first_so_symnum = symnum; + + if (pst) + { + end_psymtab (pst, psymtab_include_list, includes_used, + symnum * symbol_size, + valu > pst->texthigh ? valu : pst->texthigh, + dependency_list, dependencies_used, + prev_textlow_not_set); + pst = (struct partial_symtab *) 0; + includes_used = 0; + dependencies_used = 0; + } + } + + prev_so_symnum = symnum; + + /* End the current partial symtab and start a new one */ + + namestring = set_namestring (objfile, nlist); + + /* Null name means end of .o file. Don't start a new one. */ + if (*namestring == '\000') + continue; + + /* Some compilers (including gcc) emit a pair of initial N_SOs. + The first one is a directory name; the second the file name. + If pst exists, is empty, and has a filename ending in '/', + we assume the previous N_SO was a directory name. */ + + p = strrchr (namestring, '/'); + if (p && *(p + 1) == '\000') + continue; /* Simply ignore directory name SOs */ + + /* Some other compilers (C++ ones in particular) emit useless + SOs for non-existant .c files. We ignore all subsequent SOs that + immediately follow the first. */ + + if (!pst) + pst = start_psymtab (objfile, + namestring, valu, + first_so_symnum * symbol_size, + objfile->global_psymbols.next, + objfile->static_psymbols.next); + continue; + } + + case N_BINCL: + { + enum language tmp_language; + /* Add this bincl to the bincl_list for future EXCLs. No + need to save the string; it'll be around until + read_dbx_symtab function returns */ + + namestring = set_namestring (objfile, nlist); + tmp_language = deduce_language_from_filename (namestring); + + /* Only change the psymtab's language if we've learned + something useful (eg. tmp_language is not language_unknown). + In addition, to match what start_subfile does, never change + from C++ to C. */ + if (tmp_language != language_unknown + && (tmp_language != language_c + || psymtab_language != language_cplus)) + psymtab_language = tmp_language; + + if (pst == NULL) + { + /* FIXME: we should not get here without a PST to work on. + Attempt to recover. */ + complain (&unclaimed_bincl_complaint, namestring, symnum); + continue; + } + add_bincl_to_list (pst, namestring, nlist.n_value); + + /* Mark down an include file in the current psymtab */ + + goto record_include_file; + } + + case N_SOL: + { + enum language tmp_language; + /* Mark down an include file in the current psymtab */ + + namestring = set_namestring (objfile, nlist); + tmp_language = deduce_language_from_filename (namestring); + + /* Only change the psymtab's language if we've learned + something useful (eg. tmp_language is not language_unknown). + In addition, to match what start_subfile does, never change + from C++ to C. */ + if (tmp_language != language_unknown + && (tmp_language != language_c + || psymtab_language != language_cplus)) + psymtab_language = tmp_language; + + /* In C++, one may expect the same filename to come round many + times, when code is coming alternately from the main file + and from inline functions in other files. So I check to see + if this is a file we've seen before -- either the main + source file, or a previously included file. + + This seems to be a lot of time to be spending on N_SOL, but + things like "break c-exp.y:435" need to work (I + suppose the psymtab_include_list could be hashed or put + in a binary tree, if profiling shows this is a major hog). */ + if (pst && STREQ (namestring, pst->filename)) + continue; + { + register int i; + for (i = 0; i < includes_used; i++) + if (STREQ (namestring, psymtab_include_list[i])) + { + i = -1; + break; + } + if (i == -1) + continue; + } + + record_include_file: + + psymtab_include_list[includes_used++] = namestring; + if (includes_used >= includes_allocated) + { + char **orig = psymtab_include_list; + + psymtab_include_list = (char **) + alloca ((includes_allocated *= 2) * + sizeof (char *)); + memcpy ((PTR) psymtab_include_list, (PTR) orig, + includes_used * sizeof (char *)); + } + continue; + } + case N_LSYM: /* Typedef or automatic variable. */ + case N_STSYM: /* Data seg var -- static */ + case N_LCSYM: /* BSS " */ + case N_ROSYM: /* Read-only data seg var -- static. */ + case N_NBSTS: /* Gould nobase. */ + case N_NBLCS: /* symbols. */ + case N_FUN: + case N_GSYM: /* Global (extern) variable; can be + data or bss (sigh FIXME). */ + + /* Following may probably be ignored; I'll leave them here + for now (until I do Pascal and Modula 2 extensions). */ + + case N_PC: /* I may or may not need this; I + suspect not. */ + case N_M2C: /* I suspect that I can ignore this here. */ + case N_SCOPE: /* Same. */ + + namestring = set_namestring (objfile, nlist); + + /* See if this is an end of function stab. */ + if (pst && nlist.n_type == N_FUN && *namestring == '\000') + { + CORE_ADDR valu; + + /* It's value is the size (in bytes) of the function for + function relative stabs, or the address of the function's + end for old style stabs. */ + valu = nlist.n_value + last_function_start; + if (pst->texthigh == 0 || valu > pst->texthigh) + pst->texthigh = valu; + break; + } + + p = (char *) strchr (namestring, ':'); + if (!p) + continue; /* Not a debugging symbol. */ + + + + /* Main processing section for debugging symbols which + the initial read through the symbol tables needs to worry + about. If we reach this point, the symbol which we are + considering is definitely one we are interested in. + p must also contain the (valid) index into the namestring + which indicates the debugging type symbol. */ + + switch (p[1]) + { + case 'S': + nlist.n_value += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile)); +#ifdef STATIC_TRANSFORM_NAME + namestring = STATIC_TRANSFORM_NAME (namestring); +#endif + add_psymbol_to_list (namestring, p - namestring, + VAR_NAMESPACE, LOC_STATIC, + &objfile->static_psymbols, + 0, nlist.n_value, + psymtab_language, objfile); + continue; + case 'G': + nlist.n_value += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile)); + /* The addresses in these entries are reported to be + wrong. See the code that reads 'G's for symtabs. */ + add_psymbol_to_list (namestring, p - namestring, + VAR_NAMESPACE, LOC_STATIC, + &objfile->global_psymbols, + 0, nlist.n_value, + psymtab_language, objfile); + continue; + + case 'T': + /* When a 'T' entry is defining an anonymous enum, it + may have a name which is the empty string, or a + single space. Since they're not really defining a + symbol, those shouldn't go in the partial symbol + table. We do pick up the elements of such enums at + 'check_enum:', below. */ + if (p >= namestring + 2 + || (p == namestring + 1 + && namestring[0] != ' ')) + { + add_psymbol_to_list (namestring, p - namestring, + STRUCT_NAMESPACE, LOC_TYPEDEF, + &objfile->static_psymbols, + nlist.n_value, 0, + psymtab_language, objfile); + if (p[2] == 't') + { + /* Also a typedef with the same name. */ + add_psymbol_to_list (namestring, p - namestring, + VAR_NAMESPACE, LOC_TYPEDEF, + &objfile->static_psymbols, + nlist.n_value, 0, + psymtab_language, objfile); + p += 1; + } + /* The semantics of C++ state that "struct foo { ... }" + also defines a typedef for "foo". Unfortuantely, cfront + never makes the typedef when translating from C++ to C. + We make the typedef here so that "ptype foo" works as + expected for cfront translated code. */ + else if (psymtab_language == language_cplus) + { + /* Also a typedef with the same name. */ + add_psymbol_to_list (namestring, p - namestring, + VAR_NAMESPACE, LOC_TYPEDEF, + &objfile->static_psymbols, + nlist.n_value, 0, + psymtab_language, objfile); + } + } + goto check_enum; + case 't': + if (p != namestring) /* a name is there, not just :T... */ + { + add_psymbol_to_list (namestring, p - namestring, + VAR_NAMESPACE, LOC_TYPEDEF, + &objfile->static_psymbols, + nlist.n_value, 0, + psymtab_language, objfile); + } + check_enum: + /* If this is an enumerated type, we need to + add all the enum constants to the partial symbol + table. This does not cover enums without names, e.g. + "enum {a, b} c;" in C, but fortunately those are + rare. There is no way for GDB to find those from the + enum type without spending too much time on it. Thus + to solve this problem, the compiler needs to put out the + enum in a nameless type. GCC2 does this. */ + + /* We are looking for something of the form + <name> ":" ("t" | "T") [<number> "="] "e" + {<constant> ":" <value> ","} ";". */ + + /* Skip over the colon and the 't' or 'T'. */ + p += 2; + /* This type may be given a number. Also, numbers can come + in pairs like (0,26). Skip over it. */ + while ((*p >= '0' && *p <= '9') + || *p == '(' || *p == ',' || *p == ')' + || *p == '=') + p++; + + if (*p++ == 'e') + { + /* The aix4 compiler emits extra crud before the members. */ + if (*p == '-') + { + /* Skip over the type (?). */ + while (*p != ':') + p++; + + /* Skip over the colon. */ + p++; + } + + /* We have found an enumerated type. */ + /* According to comments in read_enum_type + a comma could end it instead of a semicolon. + I don't know where that happens. + Accept either. */ + while (*p && *p != ';' && *p != ',') + { + char *q; + + /* Check for and handle cretinous dbx symbol name + continuation! */ + if (*p == '\\' || (*p == '?' && p[1] == '\0')) + p = next_symbol_text (objfile); + + /* Point to the character after the name + of the enum constant. */ + for (q = p; *q && *q != ':'; q++) + ; + /* Note that the value doesn't matter for + enum constants in psymtabs, just in symtabs. */ + add_psymbol_to_list (p, q - p, + VAR_NAMESPACE, LOC_CONST, + &objfile->static_psymbols, 0, + 0, psymtab_language, objfile); + /* Point past the name. */ + p = q; + /* Skip over the value. */ + while (*p && *p != ',') + p++; + /* Advance past the comma. */ + if (*p) + p++; + } + } + continue; + case 'c': + /* Constant, e.g. from "const" in Pascal. */ + add_psymbol_to_list (namestring, p - namestring, + VAR_NAMESPACE, LOC_CONST, + &objfile->static_psymbols, nlist.n_value, + 0, psymtab_language, objfile); + continue; + + case 'f': + if (! pst) + { + int name_len = p - namestring; + char *name = xmalloc (name_len + 1); + memcpy (name, namestring, name_len); + name[name_len] = '\0'; + complain (&function_outside_compilation_unit, name); + xfree (name); + } + nlist.n_value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + /* Kludges for ELF/STABS with Sun ACC */ + last_function_name = namestring; +#ifdef SOFUN_ADDRESS_MAYBE_MISSING + /* Do not fix textlow==0 for .o or NLM files, as 0 is a legit + value for the bottom of the text seg in those cases. */ + if (nlist.n_value == ANOFFSET (objfile->section_offsets, + SECT_OFF_TEXT (objfile))) + { + CORE_ADDR minsym_valu = + find_stab_function_addr (namestring, pst->filename, objfile); + /* find_stab_function_addr will return 0 if the minimal + symbol wasn't found. (Unfortunately, this might also + be a valid address.) Anyway, if it *does* return 0, + it is likely that the value was set correctly to begin + with... */ + if (minsym_valu != 0) + nlist.n_value = minsym_valu; + } + if (pst && textlow_not_set) + { + pst->textlow = nlist.n_value; + textlow_not_set = 0; + } +#endif + /* End kludge. */ + + /* Keep track of the start of the last function so we + can handle end of function symbols. */ + last_function_start = nlist.n_value; + + /* In reordered executables this function may lie outside + the bounds created by N_SO symbols. If that's the case + use the address of this function as the low bound for + the partial symbol table. */ + if (pst + && (textlow_not_set + || (nlist.n_value < pst->textlow + && (nlist.n_value + != ANOFFSET (objfile->section_offsets, + SECT_OFF_TEXT (objfile)))))) + { + pst->textlow = nlist.n_value; + textlow_not_set = 0; + } + add_psymbol_to_list (namestring, p - namestring, + VAR_NAMESPACE, LOC_BLOCK, + &objfile->static_psymbols, + 0, nlist.n_value, + psymtab_language, objfile); + continue; + + /* Global functions were ignored here, but now they + are put into the global psymtab like one would expect. + They're also in the minimal symbol table. */ + case 'F': + if (! pst) + { + int name_len = p - namestring; + char *name = xmalloc (name_len + 1); + memcpy (name, namestring, name_len); + name[name_len] = '\0'; + complain (&function_outside_compilation_unit, name); + xfree (name); + } + nlist.n_value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + /* Kludges for ELF/STABS with Sun ACC */ + last_function_name = namestring; +#ifdef SOFUN_ADDRESS_MAYBE_MISSING + /* Do not fix textlow==0 for .o or NLM files, as 0 is a legit + value for the bottom of the text seg in those cases. */ + if (nlist.n_value == ANOFFSET (objfile->section_offsets, + SECT_OFF_TEXT (objfile))) + { + CORE_ADDR minsym_valu = + find_stab_function_addr (namestring, pst->filename, objfile); + /* find_stab_function_addr will return 0 if the minimal + symbol wasn't found. (Unfortunately, this might also + be a valid address.) Anyway, if it *does* return 0, + it is likely that the value was set correctly to begin + with... */ + if (minsym_valu != 0) + nlist.n_value = minsym_valu; + } + if (pst && textlow_not_set) + { + pst->textlow = nlist.n_value; + textlow_not_set = 0; + } +#endif + /* End kludge. */ + + /* Keep track of the start of the last function so we + can handle end of function symbols. */ + last_function_start = nlist.n_value; + + /* In reordered executables this function may lie outside + the bounds created by N_SO symbols. If that's the case + use the address of this function as the low bound for + the partial symbol table. */ + if (pst + && (textlow_not_set + || (nlist.n_value < pst->textlow + && (nlist.n_value + != ANOFFSET (objfile->section_offsets, + SECT_OFF_TEXT (objfile)))))) + { + pst->textlow = nlist.n_value; + textlow_not_set = 0; + } + add_psymbol_to_list (namestring, p - namestring, + VAR_NAMESPACE, LOC_BLOCK, + &objfile->global_psymbols, + 0, nlist.n_value, + psymtab_language, objfile); + continue; + + /* Two things show up here (hopefully); static symbols of + local scope (static used inside braces) or extensions + of structure symbols. We can ignore both. */ + case 'V': + case '(': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + case '#': /* for symbol identification (used in live ranges) */ + /* added to support cfront stabs strings */ + case 'Z': /* for definition continuations */ + case 'P': /* for prototypes */ + continue; + + case ':': + /* It is a C++ nested symbol. We don't need to record it + (I don't think); if we try to look up foo::bar::baz, + then symbols for the symtab containing foo should get + read in, I think. */ + /* Someone says sun cc puts out symbols like + /foo/baz/maclib::/usr/local/bin/maclib, + which would get here with a symbol type of ':'. */ + continue; + + default: + /* Unexpected symbol descriptor. The second and subsequent stabs + of a continued stab can show up here. The question is + whether they ever can mimic a normal stab--it would be + nice if not, since we certainly don't want to spend the + time searching to the end of every string looking for + a backslash. */ + + complain (&unknown_symchar_complaint, p[1]); + + /* Ignore it; perhaps it is an extension that we don't + know about. */ + continue; + } + + case N_EXCL: + + namestring = set_namestring (objfile, nlist); + + /* Find the corresponding bincl and mark that psymtab on the + psymtab dependency list */ + { + struct partial_symtab *needed_pst = + find_corresponding_bincl_psymtab (namestring, nlist.n_value); + + /* If this include file was defined earlier in this file, + leave it alone. */ + if (needed_pst == pst) + continue; + + if (needed_pst) + { + int i; + int found = 0; + + for (i = 0; i < dependencies_used; i++) + if (dependency_list[i] == needed_pst) + { + found = 1; + break; + } + + /* If it's already in the list, skip the rest. */ + if (found) + continue; + + dependency_list[dependencies_used++] = needed_pst; + if (dependencies_used >= dependencies_allocated) + { + struct partial_symtab **orig = dependency_list; + dependency_list = + (struct partial_symtab **) + alloca ((dependencies_allocated *= 2) + * sizeof (struct partial_symtab *)); + memcpy ((PTR) dependency_list, (PTR) orig, + (dependencies_used + * sizeof (struct partial_symtab *))); +#ifdef DEBUG_INFO + fprintf_unfiltered (gdb_stderr, "Had to reallocate dependency list.\n"); + fprintf_unfiltered (gdb_stderr, "New dependencies allocated: %d\n", + dependencies_allocated); +#endif + } + } + } + continue; + + case N_ENDM: +#ifdef SOFUN_ADDRESS_MAYBE_MISSING + /* Solaris 2 end of module, finish current partial symbol table. + end_psymtab will set pst->texthigh to the proper value, which + is necessary if a module compiled without debugging info + follows this module. */ + if (pst) + { + end_psymtab (pst, psymtab_include_list, includes_used, + symnum * symbol_size, + (CORE_ADDR) 0, + dependency_list, dependencies_used, textlow_not_set); + pst = (struct partial_symtab *) 0; + includes_used = 0; + dependencies_used = 0; + } +#endif + continue; + + case N_RBRAC: +#ifdef HANDLE_RBRAC + HANDLE_RBRAC (nlist.n_value); + continue; +#endif + case N_EINCL: + case N_DSLINE: + case N_BSLINE: + case N_SSYM: /* Claim: Structure or union element. + Hopefully, I can ignore this. */ + case N_ENTRY: /* Alternate entry point; can ignore. */ + case N_MAIN: /* Can definitely ignore this. */ + case N_CATCH: /* These are GNU C++ extensions */ + case N_EHDECL: /* that can safely be ignored here. */ + case N_LENG: + case N_BCOMM: + case N_ECOMM: + case N_ECOML: + case N_FNAME: + case N_SLINE: + case N_RSYM: + case N_PSYM: + case N_LBRAC: + case N_NSYMS: /* Ultrix 4.0: symbol count */ + case N_DEFD: /* GNU Modula-2 */ + case N_ALIAS: /* SunPro F77: alias name, ignore for now. */ + + case N_OBJ: /* useless types from Solaris */ + case N_OPT: + /* These symbols aren't interesting; don't worry about them */ + + continue; + + default: + /* If we haven't found it yet, ignore it. It's probably some + new type we don't know about yet. */ + complain (&unknown_symtype_complaint, + local_hex_string (nlist.n_type)); + continue; + } + } + + /* If there's stuff to be cleaned up, clean it up. */ + if (DBX_SYMCOUNT (objfile) > 0 /* We have some syms */ + /*FIXME, does this have a bug at start address 0? */ + && last_o_file_start + && objfile->ei.entry_point < nlist.n_value + && objfile->ei.entry_point >= last_o_file_start) + { + objfile->ei.entry_file_lowpc = last_o_file_start; + objfile->ei.entry_file_highpc = nlist.n_value; + } + + if (pst) + { + /* Don't set pst->texthigh lower than it already is. */ + CORE_ADDR text_end = + (lowest_text_address == (CORE_ADDR) -1 + ? (text_addr + ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile))) + : lowest_text_address) + + text_size; + + end_psymtab (pst, psymtab_include_list, includes_used, + symnum * symbol_size, + text_end > pst->texthigh ? text_end : pst->texthigh, + dependency_list, dependencies_used, textlow_not_set); + } + + do_cleanups (back_to); +} + +/* Allocate and partially fill a partial symtab. It will be + completely filled at the end of the symbol list. + + SYMFILE_NAME is the name of the symbol-file we are reading from, and ADDR + is the address relative to which its symbols are (incremental) or 0 + (normal). */ + + +static struct partial_symtab * +start_psymtab (struct objfile *objfile, char *filename, CORE_ADDR textlow, + int ldsymoff, struct partial_symbol **global_syms, + struct partial_symbol **static_syms) +{ + struct partial_symtab *result = + start_psymtab_common (objfile, objfile->section_offsets, + filename, textlow, global_syms, static_syms); + + result->read_symtab_private = (char *) + obstack_alloc (&objfile->psymbol_obstack, sizeof (struct symloc)); + LDSYMOFF (result) = ldsymoff; + result->read_symtab = dbx_psymtab_to_symtab; + SYMBOL_SIZE (result) = symbol_size; + SYMBOL_OFFSET (result) = symbol_table_offset; + STRING_OFFSET (result) = string_table_offset; + FILE_STRING_OFFSET (result) = file_string_table_offset; + + /* If we're handling an ELF file, drag some section-relocation info + for this source file out of the ELF symbol table, to compensate for + Sun brain death. This replaces the section_offsets in this psymtab, + if successful. */ + elfstab_offset_sections (objfile, result); + + /* Deduce the source language from the filename for this psymtab. */ + psymtab_language = deduce_language_from_filename (filename); + + return result; +} + +/* Close off the current usage of PST. + Returns PST or NULL if the partial symtab was empty and thrown away. + + FIXME: List variables and peculiarities of same. */ + +struct partial_symtab * +end_psymtab (struct partial_symtab *pst, char **include_list, int num_includes, + int capping_symbol_offset, CORE_ADDR capping_text, + struct partial_symtab **dependency_list, int number_dependencies, + int textlow_not_set) +{ + int i; + struct objfile *objfile = pst->objfile; + + if (capping_symbol_offset != -1) + LDSYMLEN (pst) = capping_symbol_offset - LDSYMOFF (pst); + pst->texthigh = capping_text; + +#ifdef SOFUN_ADDRESS_MAYBE_MISSING + /* Under Solaris, the N_SO symbols always have a value of 0, + instead of the usual address of the .o file. Therefore, + we have to do some tricks to fill in texthigh and textlow. + The first trick is: if we see a static + or global function, and the textlow for the current pst + is not set (ie: textlow_not_set), then we use that function's + address for the textlow of the pst. */ + + /* Now, to fill in texthigh, we remember the last function seen + in the .o file. Also, there's a hack in + bfd/elf.c and gdb/elfread.c to pass the ELF st_size field + to here via the misc_info field. Therefore, we can fill in + a reliable texthigh by taking the address plus size of the + last function in the file. */ + + if (pst->texthigh == 0 && last_function_name) + { + char *p; + int n; + struct minimal_symbol *minsym; + + p = strchr (last_function_name, ':'); + if (p == NULL) + p = last_function_name; + n = p - last_function_name; + p = alloca (n + 2); + strncpy (p, last_function_name, n); + p[n] = 0; + + minsym = lookup_minimal_symbol (p, pst->filename, objfile); + if (minsym == NULL) + { + /* Sun Fortran appends an underscore to the minimal symbol name, + try again with an appended underscore if the minimal symbol + was not found. */ + p[n] = '_'; + p[n + 1] = 0; + minsym = lookup_minimal_symbol (p, pst->filename, objfile); + } + + if (minsym) + pst->texthigh = SYMBOL_VALUE_ADDRESS (minsym) + MSYMBOL_SIZE (minsym); + + last_function_name = NULL; + } + + /* this test will be true if the last .o file is only data */ + if (textlow_not_set) + pst->textlow = pst->texthigh; + else + { + struct partial_symtab *p1; + + /* If we know our own starting text address, then walk through all other + psymtabs for this objfile, and if any didn't know their ending text + address, set it to our starting address. Take care to not set our + own ending address to our starting address, nor to set addresses on + `dependency' files that have both textlow and texthigh zero. */ + + ALL_OBJFILE_PSYMTABS (objfile, p1) + { + if (p1->texthigh == 0 && p1->textlow != 0 && p1 != pst) + { + p1->texthigh = pst->textlow; + /* if this file has only data, then make textlow match texthigh */ + if (p1->textlow == 0) + p1->textlow = p1->texthigh; + } + } + } + + /* End of kludge for patching Solaris textlow and texthigh. */ +#endif /* SOFUN_ADDRESS_MAYBE_MISSING. */ + + pst->n_global_syms = + objfile->global_psymbols.next - (objfile->global_psymbols.list + pst->globals_offset); + pst->n_static_syms = + objfile->static_psymbols.next - (objfile->static_psymbols.list + pst->statics_offset); + + pst->number_of_dependencies = number_dependencies; + if (number_dependencies) + { + pst->dependencies = (struct partial_symtab **) + obstack_alloc (&objfile->psymbol_obstack, + number_dependencies * sizeof (struct partial_symtab *)); + memcpy (pst->dependencies, dependency_list, + number_dependencies * sizeof (struct partial_symtab *)); + } + else + pst->dependencies = 0; + + for (i = 0; i < num_includes; i++) + { + struct partial_symtab *subpst = + allocate_psymtab (include_list[i], objfile); + + /* Copy the sesction_offsets array from the main psymtab. */ + subpst->section_offsets = pst->section_offsets; + subpst->read_symtab_private = + (char *) obstack_alloc (&objfile->psymbol_obstack, + sizeof (struct symloc)); + LDSYMOFF (subpst) = + LDSYMLEN (subpst) = + subpst->textlow = + subpst->texthigh = 0; + + /* We could save slight bits of space by only making one of these, + shared by the entire set of include files. FIXME-someday. */ + subpst->dependencies = (struct partial_symtab **) + obstack_alloc (&objfile->psymbol_obstack, + sizeof (struct partial_symtab *)); + subpst->dependencies[0] = pst; + subpst->number_of_dependencies = 1; + + subpst->globals_offset = + subpst->n_global_syms = + subpst->statics_offset = + subpst->n_static_syms = 0; + + subpst->readin = 0; + subpst->symtab = 0; + subpst->read_symtab = pst->read_symtab; + } + + sort_pst_symbols (pst); + + /* If there is already a psymtab or symtab for a file of this name, remove it. + (If there is a symtab, more drastic things also happen.) + This happens in VxWorks. */ + free_named_symtabs (pst->filename); + + if (num_includes == 0 + && number_dependencies == 0 + && pst->n_global_syms == 0 + && pst->n_static_syms == 0 + && has_line_numbers == 0) + { + /* Throw away this psymtab, it's empty. We can't deallocate it, since + it is on the obstack, but we can forget to chain it on the list. */ + /* Empty psymtabs happen as a result of header files which don't have + any symbols in them. There can be a lot of them. But this check + is wrong, in that a psymtab with N_SLINE entries but nothing else + is not empty, but we don't realize that. Fixing that without slowing + things down might be tricky. */ + + discard_psymtab (pst); + + /* Indicate that psymtab was thrown away. */ + pst = (struct partial_symtab *) NULL; + } + return pst; +} + +static void +dbx_psymtab_to_symtab_1 (struct partial_symtab *pst) +{ + struct cleanup *old_chain; + int i; + + if (!pst) + return; + + if (pst->readin) + { + fprintf_unfiltered (gdb_stderr, "Psymtab for %s already read in. Shouldn't happen.\n", + pst->filename); + return; + } + + /* Read in all partial symtabs on which this one is dependent */ + for (i = 0; i < pst->number_of_dependencies; i++) + if (!pst->dependencies[i]->readin) + { + /* Inform about additional files that need to be read in. */ + if (info_verbose) + { + fputs_filtered (" ", gdb_stdout); + wrap_here (""); + fputs_filtered ("and ", gdb_stdout); + wrap_here (""); + printf_filtered ("%s...", pst->dependencies[i]->filename); + wrap_here (""); /* Flush output */ + gdb_flush (gdb_stdout); + } + dbx_psymtab_to_symtab_1 (pst->dependencies[i]); + } + + if (LDSYMLEN (pst)) /* Otherwise it's a dummy */ + { + /* Init stuff necessary for reading in symbols */ + stabsread_init (); + buildsym_init (); + old_chain = make_cleanup (really_free_pendings, 0); + file_string_table_offset = FILE_STRING_OFFSET (pst); + symbol_size = SYMBOL_SIZE (pst); + + /* Read in this file's symbols */ + bfd_seek (pst->objfile->obfd, SYMBOL_OFFSET (pst), SEEK_SET); + read_ofile_symtab (pst); + sort_symtab_syms (pst->symtab); + + do_cleanups (old_chain); + } + + pst->readin = 1; +} + +/* Read in all of the symbols for a given psymtab for real. + Be verbose about it if the user wants that. */ + +static void +dbx_psymtab_to_symtab (struct partial_symtab *pst) +{ + bfd *sym_bfd; + + if (!pst) + return; + + if (pst->readin) + { + fprintf_unfiltered (gdb_stderr, "Psymtab for %s already read in. Shouldn't happen.\n", + pst->filename); + return; + } + + if (LDSYMLEN (pst) || pst->number_of_dependencies) + { + /* Print the message now, before reading the string table, + to avoid disconcerting pauses. */ + if (info_verbose) + { + printf_filtered ("Reading in symbols for %s...", pst->filename); + gdb_flush (gdb_stdout); + } + + sym_bfd = pst->objfile->obfd; + + next_symbol_text_func = dbx_next_symbol_text; + + dbx_psymtab_to_symtab_1 (pst); + + /* Match with global symbols. This only needs to be done once, + after all of the symtabs and dependencies have been read in. */ + scan_file_globals (pst->objfile); + + /* Finish up the debug error message. */ + if (info_verbose) + printf_filtered ("done.\n"); + } +} + +/* Read in a defined section of a specific object file's symbols. */ + +static void +read_ofile_symtab (struct partial_symtab *pst) +{ + register char *namestring; + register struct external_nlist *bufp; + struct internal_nlist nlist; + unsigned char type; + unsigned max_symnum; + register bfd *abfd; + struct objfile *objfile; + int sym_offset; /* Offset to start of symbols to read */ + int sym_size; /* Size of symbols to read */ + CORE_ADDR text_offset; /* Start of text segment for symbols */ + int text_size; /* Size of text segment for symbols */ + struct section_offsets *section_offsets; + + objfile = pst->objfile; + sym_offset = LDSYMOFF (pst); + sym_size = LDSYMLEN (pst); + text_offset = pst->textlow; + text_size = pst->texthigh - pst->textlow; + /* This cannot be simply objfile->section_offsets because of + elfstab_offset_sections() which initializes the psymtab section + offsets information in a special way, and that is different from + objfile->section_offsets. */ + section_offsets = pst->section_offsets; + + current_objfile = objfile; + subfile_stack = NULL; + + stringtab_global = DBX_STRINGTAB (objfile); + last_source_file = NULL; + + abfd = objfile->obfd; + symfile_bfd = objfile->obfd; /* Implicit param to next_text_symbol */ + symbuf_end = symbuf_idx = 0; + + /* It is necessary to actually read one symbol *before* the start + of this symtab's symbols, because the GCC_COMPILED_FLAG_SYMBOL + occurs before the N_SO symbol. + + Detecting this in read_dbx_symtab + would slow down initial readin, so we look for it here instead. */ + if (!processing_acc_compilation && sym_offset >= (int) symbol_size) + { + bfd_seek (symfile_bfd, sym_offset - symbol_size, SEEK_CUR); + fill_symbuf (abfd); + bufp = &symbuf[symbuf_idx++]; + INTERNALIZE_SYMBOL (nlist, bufp, abfd); + OBJSTAT (objfile, n_stabs++); + + namestring = set_namestring (objfile, nlist); + + processing_gcc_compilation = 0; + if (nlist.n_type == N_TEXT) + { + const char *tempstring = namestring; + + if (STREQ (namestring, GCC_COMPILED_FLAG_SYMBOL)) + processing_gcc_compilation = 1; + else if (STREQ (namestring, GCC2_COMPILED_FLAG_SYMBOL)) + processing_gcc_compilation = 2; + if (tempstring[0] == bfd_get_symbol_leading_char (symfile_bfd)) + ++tempstring; + if (STREQN (tempstring, "__gnu_compiled", 14)) + processing_gcc_compilation = 2; + } + + /* Try to select a C++ demangling based on the compilation unit + producer. */ + +#if 0 + /* For now, stay with AUTO_DEMANGLING for g++ output, as we don't + know whether it will use the old style or v3 mangling. */ + if (processing_gcc_compilation) + { + if (AUTO_DEMANGLING) + { + set_demangling_style (GNU_DEMANGLING_STYLE_STRING); + } + } +#endif + } + else + { + /* The N_SO starting this symtab is the first symbol, so we + better not check the symbol before it. I'm not this can + happen, but it doesn't hurt to check for it. */ + bfd_seek (symfile_bfd, sym_offset, SEEK_CUR); + processing_gcc_compilation = 0; + } + + if (symbuf_idx == symbuf_end) + fill_symbuf (abfd); + bufp = &symbuf[symbuf_idx]; + if (bfd_h_get_8 (abfd, bufp->e_type) != N_SO) + error ("First symbol in segment of executable not a source symbol"); + + max_symnum = sym_size / symbol_size; + + for (symnum = 0; + symnum < max_symnum; + symnum++) + { + QUIT; /* Allow this to be interruptable */ + if (symbuf_idx == symbuf_end) + fill_symbuf (abfd); + bufp = &symbuf[symbuf_idx++]; + INTERNALIZE_SYMBOL (nlist, bufp, abfd); + OBJSTAT (objfile, n_stabs++); + + type = bfd_h_get_8 (abfd, bufp->e_type); + + namestring = set_namestring (objfile, nlist); + + if (type & N_STAB) + { + process_one_symbol (type, nlist.n_desc, nlist.n_value, + namestring, section_offsets, objfile); + } + /* We skip checking for a new .o or -l file; that should never + happen in this routine. */ + else if (type == N_TEXT) + { + /* I don't think this code will ever be executed, because + the GCC_COMPILED_FLAG_SYMBOL usually is right before + the N_SO symbol which starts this source file. + However, there is no reason not to accept + the GCC_COMPILED_FLAG_SYMBOL anywhere. */ + + if (STREQ (namestring, GCC_COMPILED_FLAG_SYMBOL)) + processing_gcc_compilation = 1; + else if (STREQ (namestring, GCC2_COMPILED_FLAG_SYMBOL)) + processing_gcc_compilation = 2; + +#if 0 + /* For now, stay with AUTO_DEMANGLING for g++ output, as we don't + know whether it will use the old style or v3 mangling. */ + if (AUTO_DEMANGLING) + { + set_demangling_style (GNU_DEMANGLING_STYLE_STRING); + } +#endif + } + else if (type & N_EXT || type == (unsigned char) N_TEXT + || type == (unsigned char) N_NBTEXT + ) + { + /* Global symbol: see if we came across a dbx defintion for + a corresponding symbol. If so, store the value. Remove + syms from the chain when their values are stored, but + search the whole chain, as there may be several syms from + different files with the same name. */ + /* This is probably not true. Since the files will be read + in one at a time, each reference to a global symbol will + be satisfied in each file as it appears. So we skip this + section. */ + ; + } + } + + current_objfile = NULL; + + /* In a Solaris elf file, this variable, which comes from the + value of the N_SO symbol, will still be 0. Luckily, text_offset, + which comes from pst->textlow is correct. */ + if (last_source_start_addr == 0) + last_source_start_addr = text_offset; + + /* In reordered executables last_source_start_addr may not be the + lower bound for this symtab, instead use text_offset which comes + from pst->textlow which is correct. */ + if (last_source_start_addr > text_offset) + last_source_start_addr = text_offset; + + pst->symtab = end_symtab (text_offset + text_size, objfile, SECT_OFF_TEXT (objfile)); + + /* Process items which we had to "process_later" due to dependencies + on other stabs. */ + process_now (objfile); + + end_stabs (); +} + + +/* This handles a single symbol from the symbol-file, building symbols + into a GDB symtab. It takes these arguments and an implicit argument. + + TYPE is the type field of the ".stab" symbol entry. + DESC is the desc field of the ".stab" entry. + VALU is the value field of the ".stab" entry. + NAME is the symbol name, in our address space. + SECTION_OFFSETS is a set of amounts by which the sections of this object + file were relocated when it was loaded into memory. + Note that these section_offsets are not the + objfile->section_offsets but the pst->section_offsets. + All symbols that refer + to memory locations need to be offset by these amounts. + OBJFILE is the object file from which we are reading symbols. + It is used in end_symtab. */ + +void +process_one_symbol (int type, int desc, CORE_ADDR valu, char *name, + struct section_offsets *section_offsets, + struct objfile *objfile) +{ +#ifdef SUN_FIXED_LBRAC_BUG + /* If SUN_FIXED_LBRAC_BUG is defined, then it tells us whether we need + to correct the address of N_LBRAC's. If it is not defined, then + we never need to correct the addresses. */ + + /* This records the last pc address we've seen. We depend on there being + an SLINE or FUN or SO before the first LBRAC, since the variable does + not get reset in between reads of different symbol files. */ + static CORE_ADDR last_pc_address; +#endif + + register struct context_stack *new; + /* This remembers the address of the start of a function. It is used + because in Solaris 2, N_LBRAC, N_RBRAC, and N_SLINE entries are + relative to the current function's start address. On systems + other than Solaris 2, this just holds the SECT_OFF_TEXT value, and is + used to relocate these symbol types rather than SECTION_OFFSETS. */ + static CORE_ADDR function_start_offset; + + /* This holds the address of the start of a function, without the system + peculiarities of function_start_offset. */ + static CORE_ADDR last_function_start; + + /* If this is nonzero, we've seen an N_SLINE since the start of the current + function. Initialized to nonzero to assure that last_function_start + is never used uninitialized. */ + static int sline_found_in_function = 1; + + /* If this is nonzero, we've seen a non-gcc N_OPT symbol for this source + file. Used to detect the SunPRO solaris compiler. */ + static int n_opt_found; + + /* The stab type used for the definition of the last function. + N_STSYM or N_GSYM for SunOS4 acc; N_FUN for other compilers. */ + static int function_stab_type = 0; + + if (!block_address_function_relative) + /* N_LBRAC, N_RBRAC and N_SLINE entries are not relative to the + function start address, so just use the text offset. */ + function_start_offset = ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile)); + + /* Something is wrong if we see real data before + seeing a source file name. */ + + if (last_source_file == NULL && type != (unsigned char) N_SO) + { + /* Ignore any symbols which appear before an N_SO symbol. + Currently no one puts symbols there, but we should deal + gracefully with the case. A complain()t might be in order, + but this should not be an error (). */ + return; + } + + switch (type) + { + case N_FUN: + case N_FNAME: + + if (*name == '\000') + { + /* This N_FUN marks the end of a function. This closes off the + current block. */ + record_line (current_subfile, 0, function_start_offset + valu); + within_function = 0; + new = pop_context (); + + /* Make a block for the local symbols within. */ + finish_block (new->name, &local_symbols, new->old_blocks, + new->start_addr, new->start_addr + valu, + objfile); + + /* May be switching to an assembler file which may not be using + block relative stabs, so reset the offset. */ + if (block_address_function_relative) + function_start_offset = 0; + + break; + } + + sline_found_in_function = 0; + + /* Relocate for dynamic loading */ + valu += ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile)); + valu = SMASH_TEXT_ADDRESS (valu); + last_function_start = valu; + + goto define_a_symbol; + + case N_LBRAC: + /* This "symbol" just indicates the start of an inner lexical + context within a function. */ + + /* Ignore extra outermost context from SunPRO cc and acc. */ + if (n_opt_found && desc == 1) + break; + + if (block_address_function_relative) + /* Relocate for Sun ELF acc fn-relative syms. */ + valu += function_start_offset; + else + /* On most machines, the block addresses are relative to the + N_SO, the linker did not relocate them (sigh). */ + valu += last_source_start_addr; + +#ifdef SUN_FIXED_LBRAC_BUG + if (!SUN_FIXED_LBRAC_BUG && valu < last_pc_address) + { + /* Patch current LBRAC pc value to match last handy pc value */ + complain (&lbrac_complaint); + valu = last_pc_address; + } +#endif + new = push_context (desc, valu); + break; + + case N_RBRAC: + /* This "symbol" just indicates the end of an inner lexical + context that was started with N_LBRAC. */ + + /* Ignore extra outermost context from SunPRO cc and acc. */ + if (n_opt_found && desc == 1) + break; + + if (block_address_function_relative) + /* Relocate for Sun ELF acc fn-relative syms. */ + valu += function_start_offset; + else + /* On most machines, the block addresses are relative to the + N_SO, the linker did not relocate them (sigh). */ + valu += last_source_start_addr; + + new = pop_context (); + if (desc != new->depth) + complain (&lbrac_mismatch_complaint, symnum); + + /* Some compilers put the variable decls inside of an + LBRAC/RBRAC block. This macro should be nonzero if this + is true. DESC is N_DESC from the N_RBRAC symbol. + GCC_P is true if we've detected the GCC_COMPILED_SYMBOL + or the GCC2_COMPILED_SYMBOL. */ +#if !defined (VARIABLES_INSIDE_BLOCK) +#define VARIABLES_INSIDE_BLOCK(desc, gcc_p) 0 +#endif + + /* Can only use new->locals as local symbols here if we're in + gcc or on a machine that puts them before the lbrack. */ + if (!VARIABLES_INSIDE_BLOCK (desc, processing_gcc_compilation)) + { + if (local_symbols != NULL) + { + /* GCC development snapshots from March to December of + 2000 would output N_LSYM entries after N_LBRAC + entries. As a consequence, these symbols are simply + discarded. Complain if this is the case. Note that + there are some compilers which legitimately put local + symbols within an LBRAC/RBRAC block; this complaint + might also help sort out problems in which + VARIABLES_INSIDE_BLOCK is incorrectly defined. */ + complain (&discarding_local_symbols_complaint); + } + local_symbols = new->locals; + } + + if (context_stack_depth + > !VARIABLES_INSIDE_BLOCK (desc, processing_gcc_compilation)) + { + /* This is not the outermost LBRAC...RBRAC pair in the function, + its local symbols preceded it, and are the ones just recovered + from the context stack. Define the block for them (but don't + bother if the block contains no symbols. Should we complain + on blocks without symbols? I can't think of any useful purpose + for them). */ + if (local_symbols != NULL) + { + /* Muzzle a compiler bug that makes end < start. (which + compilers? Is this ever harmful?). */ + if (new->start_addr > valu) + { + complain (&lbrac_rbrac_complaint); + new->start_addr = valu; + } + /* Make a block for the local symbols within. */ + finish_block (0, &local_symbols, new->old_blocks, + new->start_addr, valu, objfile); + } + } + else + { + /* This is the outermost LBRAC...RBRAC pair. There is no + need to do anything; leave the symbols that preceded it + to be attached to the function's own block. We need to + indicate that we just moved outside of the function. */ + within_function = 0; + } + + if (VARIABLES_INSIDE_BLOCK (desc, processing_gcc_compilation)) + /* Now pop locals of block just finished. */ + local_symbols = new->locals; + break; + + case N_FN: + case N_FN_SEQ: + /* This kind of symbol indicates the start of an object file. */ + /* Relocate for dynamic loading */ + valu += ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile)); + break; + + case N_SO: + /* This type of symbol indicates the start of data + for one source file. + Finish the symbol table of the previous source file + (if any) and start accumulating a new symbol table. */ + /* Relocate for dynamic loading */ + valu += ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile)); + + n_opt_found = 0; + +#ifdef SUN_FIXED_LBRAC_BUG + last_pc_address = valu; /* Save for SunOS bug circumcision */ +#endif + +#ifdef PCC_SOL_BROKEN + /* pcc bug, occasionally puts out SO for SOL. */ + if (context_stack_depth > 0) + { + start_subfile (name, NULL); + break; + } +#endif + if (last_source_file) + { + /* Check if previous symbol was also an N_SO (with some + sanity checks). If so, that one was actually the directory + name, and the current one is the real file name. + Patch things up. */ + if (previous_stab_code == (unsigned char) N_SO) + { + patch_subfile_names (current_subfile, name); + break; /* Ignore repeated SOs */ + } + end_symtab (valu, objfile, SECT_OFF_TEXT (objfile)); + end_stabs (); + } + + /* Null name means this just marks the end of text for this .o file. + Don't start a new symtab in this case. */ + if (*name == '\000') + break; + + if (block_address_function_relative) + function_start_offset = 0; + + start_stabs (); + start_symtab (name, NULL, valu); + record_debugformat ("stabs"); + break; + + case N_SOL: + /* This type of symbol indicates the start of data for + a sub-source-file, one whose contents were copied or + included in the compilation of the main source file + (whose name was given in the N_SO symbol.) */ + /* Relocate for dynamic loading */ + valu += ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile)); + start_subfile (name, current_subfile->dirname); + break; + + case N_BINCL: + push_subfile (); + add_new_header_file (name, valu); + start_subfile (name, current_subfile->dirname); + break; + + case N_EINCL: + start_subfile (pop_subfile (), current_subfile->dirname); + break; + + case N_EXCL: + add_old_header_file (name, valu); + break; + + case N_SLINE: + /* This type of "symbol" really just records + one line-number -- core-address correspondence. + Enter it in the line list for this symbol table. */ + + /* Relocate for dynamic loading and for ELF acc fn-relative syms. */ + valu += function_start_offset; + +#ifdef SUN_FIXED_LBRAC_BUG + last_pc_address = valu; /* Save for SunOS bug circumcision */ +#endif + /* If this is the first SLINE note in the function, record it at + the start of the function instead of at the listed location. */ + if (within_function && sline_found_in_function == 0) + { + record_line (current_subfile, desc, last_function_start); + sline_found_in_function = 1; + } + else + record_line (current_subfile, desc, valu); + break; + + case N_BCOMM: + common_block_start (name, objfile); + break; + + case N_ECOMM: + common_block_end (objfile); + break; + + /* The following symbol types need to have the appropriate offset added + to their value; then we process symbol definitions in the name. */ + + case N_STSYM: /* Static symbol in data seg */ + case N_LCSYM: /* Static symbol in BSS seg */ + case N_ROSYM: /* Static symbol in Read-only data seg */ + /* HORRID HACK DEPT. However, it's Sun's furgin' fault. + Solaris2's stabs-in-elf makes *most* symbols relative + but leaves a few absolute (at least for Solaris 2.1 and version + 2.0.1 of the SunPRO compiler). N_STSYM and friends sit on the fence. + .stab "foo:S...",N_STSYM is absolute (ld relocates it) + .stab "foo:V...",N_STSYM is relative (section base subtracted). + This leaves us no choice but to search for the 'S' or 'V'... + (or pass the whole section_offsets stuff down ONE MORE function + call level, which we really don't want to do). */ + { + char *p; + + /* .o files and NLMs have non-zero text seg offsets, but don't need + their static syms offset in this fashion. XXX - This is really a + crock that should be fixed in the solib handling code so that I + don't have to work around it here. */ + + if (!symfile_relocatable) + { + p = strchr (name, ':'); + if (p != 0 && p[1] == 'S') + { + /* The linker relocated it. We don't want to add an + elfstab_offset_sections-type offset, but we *do* want + to add whatever solib.c passed to symbol_file_add as + addr (this is known to affect SunOS4, and I suspect ELF + too). Since elfstab_offset_sections currently does not + muck with the text offset (there is no Ttext.text + symbol), we can get addr from the text offset. If + elfstab_offset_sections ever starts dealing with the + text offset, and we still need to do this, we need to + invent a SECT_OFF_ADDR_KLUDGE or something. */ + valu += ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile)); + goto define_a_symbol; + } + } + /* Since it's not the kludge case, re-dispatch to the right handler. */ + switch (type) + { + case N_STSYM: + goto case_N_STSYM; + case N_LCSYM: + goto case_N_LCSYM; + case N_ROSYM: + goto case_N_ROSYM; + default: + internal_error (__FILE__, __LINE__, "failed internal consistency check"); + } + } + + case_N_STSYM: /* Static symbol in data seg */ + case N_DSLINE: /* Source line number, data seg */ + valu += ANOFFSET (section_offsets, SECT_OFF_DATA (objfile)); + goto define_a_symbol; + + case_N_LCSYM: /* Static symbol in BSS seg */ + case N_BSLINE: /* Source line number, bss seg */ + /* N_BROWS: overlaps with N_BSLINE */ + valu += ANOFFSET (section_offsets, SECT_OFF_BSS (objfile)); + goto define_a_symbol; + + case_N_ROSYM: /* Static symbol in Read-only data seg */ + valu += ANOFFSET (section_offsets, SECT_OFF_RODATA (objfile)); + goto define_a_symbol; + + case N_ENTRY: /* Alternate entry point */ + /* Relocate for dynamic loading */ + valu += ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile)); + goto define_a_symbol; + + /* The following symbol types we don't know how to process. Handle + them in a "default" way, but complain to people who care. */ + default: + case N_CATCH: /* Exception handler catcher */ + case N_EHDECL: /* Exception handler name */ + case N_PC: /* Global symbol in Pascal */ + case N_M2C: /* Modula-2 compilation unit */ + /* N_MOD2: overlaps with N_EHDECL */ + case N_SCOPE: /* Modula-2 scope information */ + case N_ECOML: /* End common (local name) */ + case N_NBTEXT: /* Gould Non-Base-Register symbols??? */ + case N_NBDATA: + case N_NBBSS: + case N_NBSTS: + case N_NBLCS: + complain (&unknown_symtype_complaint, local_hex_string (type)); + /* FALLTHROUGH */ + + /* The following symbol types don't need the address field relocated, + since it is either unused, or is absolute. */ + define_a_symbol: + case N_GSYM: /* Global variable */ + case N_NSYMS: /* Number of symbols (ultrix) */ + case N_NOMAP: /* No map? (ultrix) */ + case N_RSYM: /* Register variable */ + case N_DEFD: /* Modula-2 GNU module dependency */ + case N_SSYM: /* Struct or union element */ + case N_LSYM: /* Local symbol in stack */ + case N_PSYM: /* Parameter variable */ + case N_LENG: /* Length of preceding symbol type */ + if (name) + { + int deftype; + char *colon_pos = strchr (name, ':'); + if (colon_pos == NULL) + deftype = '\0'; + else + deftype = colon_pos[1]; + + switch (deftype) + { + case 'f': + case 'F': + function_stab_type = type; + +#ifdef SOFUN_ADDRESS_MAYBE_MISSING + /* Deal with the SunPRO 3.0 compiler which omits the address + from N_FUN symbols. */ + if (type == N_FUN + && valu == ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile))) + { + CORE_ADDR minsym_valu = + find_stab_function_addr (name, last_source_file, objfile); + + /* find_stab_function_addr will return 0 if the minimal + symbol wasn't found. (Unfortunately, this might also + be a valid address.) Anyway, if it *does* return 0, + it is likely that the value was set correctly to begin + with... */ + if (minsym_valu != 0) + valu = minsym_valu; + } +#endif + +#ifdef SUN_FIXED_LBRAC_BUG + /* The Sun acc compiler, under SunOS4, puts out + functions with N_GSYM or N_STSYM. The problem is + that the address of the symbol is no good (for N_GSYM + it doesn't even attept an address; for N_STSYM it + puts out an address but then it gets relocated + relative to the data segment, not the text segment). + Currently we can't fix this up later as we do for + some types of symbol in scan_file_globals. + Fortunately we do have a way of finding the address - + we know that the value in last_pc_address is either + the one we want (if we're dealing with the first + function in an object file), or somewhere in the + previous function. This means that we can use the + minimal symbol table to get the address. */ + + /* Starting with release 3.0, the Sun acc compiler, + under SunOS4, puts out functions with N_FUN and a value + of zero. This gets relocated to the start of the text + segment of the module, which is no good either. + Under SunOS4 we can deal with this as N_SLINE and N_SO + entries contain valid absolute addresses. + Release 3.0 acc also puts out N_OPT entries, which makes + it possible to discern acc from cc or gcc. */ + + if (type == N_GSYM || type == N_STSYM + || (type == N_FUN + && n_opt_found && !block_address_function_relative)) + { + struct minimal_symbol *m; + int l = colon_pos - name; + + m = lookup_minimal_symbol_by_pc (last_pc_address); + if (m && STREQN (SYMBOL_NAME (m), name, l) + && SYMBOL_NAME (m)[l] == '\0') + /* last_pc_address was in this function */ + valu = SYMBOL_VALUE (m); + else if (m && SYMBOL_NAME (m + 1) + && STREQN (SYMBOL_NAME (m + 1), name, l) + && SYMBOL_NAME (m + 1)[l] == '\0') + /* last_pc_address was in last function */ + valu = SYMBOL_VALUE (m + 1); + else + /* Not found - use last_pc_address (for finish_block) */ + valu = last_pc_address; + } + + last_pc_address = valu; /* Save for SunOS bug circumcision */ +#endif + + if (block_address_function_relative) + /* For Solaris 2.0 compilers, the block addresses and + N_SLINE's are relative to the start of the + function. On normal systems, and when using gcc on + Solaris 2.0, these addresses are just absolute, or + relative to the N_SO, depending on + BLOCK_ADDRESS_ABSOLUTE. */ + function_start_offset = valu; + + within_function = 1; + + if (context_stack_depth > 1) + { + complain (&lbrac_unmatched_complaint, symnum); + break; + } + + if (context_stack_depth > 0) + { + new = pop_context (); + /* Make a block for the local symbols within. */ + finish_block (new->name, &local_symbols, new->old_blocks, + new->start_addr, valu, objfile); + } + + new = push_context (0, valu); + new->name = define_symbol (valu, name, desc, type, objfile); + break; + + default: + define_symbol (valu, name, desc, type, objfile); + break; + } + } + break; + + /* We use N_OPT to carry the gcc2_compiled flag. Sun uses it + for a bunch of other flags, too. Someday we may parse their + flags; for now we ignore theirs and hope they'll ignore ours. */ + case N_OPT: /* Solaris 2: Compiler options */ + if (name) + { + if (STREQ (name, GCC2_COMPILED_FLAG_SYMBOL)) + { + processing_gcc_compilation = 2; +#if 0 /* Works, but is experimental. -fnf */ + /* For now, stay with AUTO_DEMANGLING for g++ output, as we don't + know whether it will use the old style or v3 mangling. */ + if (AUTO_DEMANGLING) + { + set_demangling_style (GNU_DEMANGLING_STYLE_STRING); + } +#endif + } + else + n_opt_found = 1; + } + break; + + case N_MAIN: /* Name of main routine. */ + /* FIXME: If one has a symbol file with N_MAIN and then replaces + it with a symbol file with "main" and without N_MAIN. I'm + not sure exactly what rule to follow but probably something + like: N_MAIN takes precedence over "main" no matter what + objfile it is in; If there is more than one N_MAIN, choose + the one in the symfile_objfile; If there is more than one + N_MAIN within a given objfile, complain() and choose + arbitrarily. (kingdon) */ + if (name != NULL) + set_main_name (name); + break; + + /* The following symbol types can be ignored. */ + case N_OBJ: /* Solaris 2: Object file dir and name */ + /* N_UNDF: Solaris 2: file separator mark */ + /* N_UNDF: -- we will never encounter it, since we only process one + file's symbols at once. */ + case N_ENDM: /* Solaris 2: End of module */ + case N_ALIAS: /* SunPro F77: alias name, ignore for now. */ + break; + } + + /* '#' is a GNU C extension to allow one symbol to refer to another + related symbol. + + Generally this is used so that an alias can refer to its main + symbol. */ + if (name[0] == '#') + { + /* Initialize symbol reference names and determine if this is + a definition. If symbol reference is being defined, go + ahead and add it. Otherwise, just return sym. */ + + char *s = name; + int refnum; + + /* If this stab defines a new reference ID that is not on the + reference list, then put it on the reference list. + + We go ahead and advance NAME past the reference, even though + it is not strictly necessary at this time. */ + refnum = symbol_reference_defined (&s); + if (refnum >= 0) + if (!ref_search (refnum)) + ref_add (refnum, 0, name, valu); + name = s; + } + + + previous_stab_code = type; +} + +/* FIXME: The only difference between this and elfstab_build_psymtabs + is the call to install_minimal_symbols for elf, and the support for + split sections. If the differences are really that small, the code + should be shared. */ + +/* Scan and build partial symbols for an coff symbol file. + The coff file has already been processed to get its minimal symbols. + + This routine is the equivalent of dbx_symfile_init and dbx_symfile_read + rolled into one. + + OBJFILE is the object file we are reading symbols from. + ADDR is the address relative to which the symbols are (e.g. + the base address of the text segment). + MAINLINE is true if we are reading the main symbol + table (as opposed to a shared lib or dynamically loaded file). + TEXTADDR is the address of the text section. + TEXTSIZE is the size of the text section. + STABSECTS is the list of .stab sections in OBJFILE. + STABSTROFFSET and STABSTRSIZE define the location in OBJFILE where the + .stabstr section exists. + + This routine is mostly copied from dbx_symfile_init and dbx_symfile_read, + adjusted for coff details. */ + +void +coffstab_build_psymtabs (struct objfile *objfile, int mainline, + CORE_ADDR textaddr, unsigned int textsize, + struct stab_section_list *stabsects, + file_ptr stabstroffset, unsigned int stabstrsize) +{ + int val; + bfd *sym_bfd = objfile->obfd; + char *name = bfd_get_filename (sym_bfd); + struct dbx_symfile_info *info; + unsigned int stabsize; + + /* There is already a dbx_symfile_info allocated by our caller. + It might even contain some info from the coff symtab to help us. */ + info = objfile->sym_stab_info; + + DBX_TEXT_ADDR (objfile) = textaddr; + DBX_TEXT_SIZE (objfile) = textsize; + +#define COFF_STABS_SYMBOL_SIZE 12 /* XXX FIXME XXX */ + DBX_SYMBOL_SIZE (objfile) = COFF_STABS_SYMBOL_SIZE; + DBX_STRINGTAB_SIZE (objfile) = stabstrsize; + + if (stabstrsize > bfd_get_size (sym_bfd)) + error ("ridiculous string table size: %d bytes", stabstrsize); + DBX_STRINGTAB (objfile) = (char *) + obstack_alloc (&objfile->psymbol_obstack, stabstrsize + 1); + OBJSTAT (objfile, sz_strtab += stabstrsize + 1); + + /* Now read in the string table in one big gulp. */ + + val = bfd_seek (sym_bfd, stabstroffset, SEEK_SET); + if (val < 0) + perror_with_name (name); + val = bfd_bread (DBX_STRINGTAB (objfile), stabstrsize, sym_bfd); + if (val != stabstrsize) + perror_with_name (name); + + stabsread_new_init (); + buildsym_new_init (); + free_header_files (); + init_header_files (); + + processing_acc_compilation = 1; + + /* In a coff file, we've already installed the minimal symbols that came + from the coff (non-stab) symbol table, so always act like an + incremental load here. */ + if (stabsects->next == NULL) + { + stabsize = bfd_section_size (sym_bfd, stabsects->section); + DBX_SYMCOUNT (objfile) = stabsize / DBX_SYMBOL_SIZE (objfile); + DBX_SYMTAB_OFFSET (objfile) = stabsects->section->filepos; + } + else + { + struct stab_section_list *stabsect; + + DBX_SYMCOUNT (objfile) = 0; + for (stabsect = stabsects; stabsect != NULL; stabsect = stabsect->next) + { + stabsize = bfd_section_size (sym_bfd, stabsect->section); + DBX_SYMCOUNT (objfile) += stabsize / DBX_SYMBOL_SIZE (objfile); + } + + DBX_SYMTAB_OFFSET (objfile) = stabsects->section->filepos; + + symbuf_sections = stabsects->next; + symbuf_left = bfd_section_size (sym_bfd, stabsects->section); + symbuf_read = 0; + } + + dbx_symfile_read (objfile, 0); +} + +/* Scan and build partial symbols for an ELF symbol file. + This ELF file has already been processed to get its minimal symbols, + and any DWARF symbols that were in it. + + This routine is the equivalent of dbx_symfile_init and dbx_symfile_read + rolled into one. + + OBJFILE is the object file we are reading symbols from. + ADDR is the address relative to which the symbols are (e.g. + the base address of the text segment). + MAINLINE is true if we are reading the main symbol + table (as opposed to a shared lib or dynamically loaded file). + STABOFFSET and STABSIZE define the location in OBJFILE where the .stab + section exists. + STABSTROFFSET and STABSTRSIZE define the location in OBJFILE where the + .stabstr section exists. + + This routine is mostly copied from dbx_symfile_init and dbx_symfile_read, + adjusted for elf details. */ + +void +elfstab_build_psymtabs (struct objfile *objfile, int mainline, + file_ptr staboffset, unsigned int stabsize, + file_ptr stabstroffset, unsigned int stabstrsize) +{ + int val; + bfd *sym_bfd = objfile->obfd; + char *name = bfd_get_filename (sym_bfd); + struct dbx_symfile_info *info; + + /* There is already a dbx_symfile_info allocated by our caller. + It might even contain some info from the ELF symtab to help us. */ + info = objfile->sym_stab_info; + + /* Find the first and last text address. dbx_symfile_read seems to + want this. */ + find_text_range (sym_bfd, objfile); + +#define ELF_STABS_SYMBOL_SIZE 12 /* XXX FIXME XXX */ + DBX_SYMBOL_SIZE (objfile) = ELF_STABS_SYMBOL_SIZE; + DBX_SYMCOUNT (objfile) = stabsize / DBX_SYMBOL_SIZE (objfile); + DBX_STRINGTAB_SIZE (objfile) = stabstrsize; + DBX_SYMTAB_OFFSET (objfile) = staboffset; + + if (stabstrsize > bfd_get_size (sym_bfd)) + error ("ridiculous string table size: %d bytes", stabstrsize); + DBX_STRINGTAB (objfile) = (char *) + obstack_alloc (&objfile->psymbol_obstack, stabstrsize + 1); + OBJSTAT (objfile, sz_strtab += stabstrsize + 1); + + /* Now read in the string table in one big gulp. */ + + val = bfd_seek (sym_bfd, stabstroffset, SEEK_SET); + if (val < 0) + perror_with_name (name); + val = bfd_bread (DBX_STRINGTAB (objfile), stabstrsize, sym_bfd); + if (val != stabstrsize) + perror_with_name (name); + + stabsread_new_init (); + buildsym_new_init (); + free_header_files (); + init_header_files (); + install_minimal_symbols (objfile); + + processing_acc_compilation = 1; + + /* In an elf file, we've already installed the minimal symbols that came + from the elf (non-stab) symbol table, so always act like an + incremental load here. */ + dbx_symfile_read (objfile, 0); +} + +/* Scan and build partial symbols for a file with special sections for stabs + and stabstrings. The file has already been processed to get its minimal + symbols, and any other symbols that might be necessary to resolve GSYMs. + + This routine is the equivalent of dbx_symfile_init and dbx_symfile_read + rolled into one. + + OBJFILE is the object file we are reading symbols from. + ADDR is the address relative to which the symbols are (e.g. the base address + of the text segment). + MAINLINE is true if we are reading the main symbol table (as opposed to a + shared lib or dynamically loaded file). + STAB_NAME is the name of the section that contains the stabs. + STABSTR_NAME is the name of the section that contains the stab strings. + + This routine is mostly copied from dbx_symfile_init and dbx_symfile_read. */ + +void +stabsect_build_psymtabs (struct objfile *objfile, int mainline, char *stab_name, + char *stabstr_name, char *text_name) +{ + int val; + bfd *sym_bfd = objfile->obfd; + char *name = bfd_get_filename (sym_bfd); + asection *stabsect; + asection *stabstrsect; + asection *text_sect; + + stabsect = bfd_get_section_by_name (sym_bfd, stab_name); + stabstrsect = bfd_get_section_by_name (sym_bfd, stabstr_name); + + if (!stabsect) + return; + + if (!stabstrsect) + error ("stabsect_build_psymtabs: Found stabs (%s), but not string section (%s)", + stab_name, stabstr_name); + + objfile->sym_stab_info = (struct dbx_symfile_info *) + xmalloc (sizeof (struct dbx_symfile_info)); + memset (objfile->sym_stab_info, 0, sizeof (struct dbx_symfile_info)); + + text_sect = bfd_get_section_by_name (sym_bfd, text_name); + if (!text_sect) + error ("Can't find %s section in symbol file", text_name); + DBX_TEXT_ADDR (objfile) = bfd_section_vma (sym_bfd, text_sect); + DBX_TEXT_SIZE (objfile) = bfd_section_size (sym_bfd, text_sect); + + DBX_SYMBOL_SIZE (objfile) = sizeof (struct external_nlist); + DBX_SYMCOUNT (objfile) = bfd_section_size (sym_bfd, stabsect) + / DBX_SYMBOL_SIZE (objfile); + DBX_STRINGTAB_SIZE (objfile) = bfd_section_size (sym_bfd, stabstrsect); + DBX_SYMTAB_OFFSET (objfile) = stabsect->filepos; /* XXX - FIXME: POKING INSIDE BFD DATA STRUCTURES */ + + if (DBX_STRINGTAB_SIZE (objfile) > bfd_get_size (sym_bfd)) + error ("ridiculous string table size: %d bytes", DBX_STRINGTAB_SIZE (objfile)); + DBX_STRINGTAB (objfile) = (char *) + obstack_alloc (&objfile->psymbol_obstack, DBX_STRINGTAB_SIZE (objfile) + 1); + OBJSTAT (objfile, sz_strtab += DBX_STRINGTAB_SIZE (objfile) + 1); + + /* Now read in the string table in one big gulp. */ + + val = bfd_get_section_contents (sym_bfd, /* bfd */ + stabstrsect, /* bfd section */ + DBX_STRINGTAB (objfile), /* input buffer */ + 0, /* offset into section */ + DBX_STRINGTAB_SIZE (objfile)); /* amount to read */ + + if (!val) + perror_with_name (name); + + stabsread_new_init (); + buildsym_new_init (); + free_header_files (); + init_header_files (); + install_minimal_symbols (objfile); + + /* Now, do an incremental load */ + + processing_acc_compilation = 1; + dbx_symfile_read (objfile, 0); +} + +static struct sym_fns aout_sym_fns = +{ + bfd_target_aout_flavour, + dbx_new_init, /* sym_new_init: init anything gbl to entire symtab */ + dbx_symfile_init, /* sym_init: read initial info, setup for sym_read() */ + dbx_symfile_read, /* sym_read: read a symbol file into symtab */ + dbx_symfile_finish, /* sym_finish: finished with file, cleanup */ + default_symfile_offsets, /* sym_offsets: parse user's offsets to internal form */ + NULL /* next: pointer to next struct sym_fns */ +}; + +void +_initialize_dbxread (void) +{ + add_symtab_fns (&aout_sym_fns); +} diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c new file mode 100644 index 0000000..4ef683c --- /dev/null +++ b/gdb/dwarf2read.c @@ -0,0 +1,6938 @@ +/* DWARF 2 debugging format support for GDB. + Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 + Free Software Foundation, Inc. + + Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology, + Inc. with support from Florida State University (under contract + with the Ada Joint Program Office), and Silicon Graphics, Inc. + Initial contribution by Brent Benson, Harris Computer Systems, Inc., + based on Fred Fish's (Cygnus Support) implementation of DWARF 1 + support in dwarfread.c + + 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 2 of the License, or (at + your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "bfd.h" +#include "symtab.h" +#include "gdbtypes.h" +#include "symfile.h" +#include "objfiles.h" +#include "elf/dwarf2.h" +#include "buildsym.h" +#include "demangle.h" +#include "expression.h" +#include "filenames.h" /* for DOSish file names */ +#include "macrotab.h" + +#include "language.h" +#include "complaints.h" +#include "bcache.h" +#include <fcntl.h> +#include "gdb_string.h" +#include "gdb_assert.h" +#include <sys/types.h> + +#ifndef DWARF2_REG_TO_REGNUM +#define DWARF2_REG_TO_REGNUM(REG) (REG) +#endif + +#if 0 +/* .debug_info header for a compilation unit + Because of alignment constraints, this structure has padding and cannot + be mapped directly onto the beginning of the .debug_info section. */ +typedef struct comp_unit_header + { + unsigned int length; /* length of the .debug_info + contribution */ + unsigned short version; /* version number -- 2 for DWARF + version 2 */ + unsigned int abbrev_offset; /* offset into .debug_abbrev section */ + unsigned char addr_size; /* byte size of an address -- 4 */ + } +_COMP_UNIT_HEADER; +#define _ACTUAL_COMP_UNIT_HEADER_SIZE 11 +#endif + +/* .debug_pubnames header + Because of alignment constraints, this structure has padding and cannot + be mapped directly onto the beginning of the .debug_info section. */ +typedef struct pubnames_header + { + unsigned int length; /* length of the .debug_pubnames + contribution */ + unsigned char version; /* version number -- 2 for DWARF + version 2 */ + unsigned int info_offset; /* offset into .debug_info section */ + unsigned int info_size; /* byte size of .debug_info section + portion */ + } +_PUBNAMES_HEADER; +#define _ACTUAL_PUBNAMES_HEADER_SIZE 13 + +/* .debug_pubnames header + Because of alignment constraints, this structure has padding and cannot + be mapped directly onto the beginning of the .debug_info section. */ +typedef struct aranges_header + { + unsigned int length; /* byte len of the .debug_aranges + contribution */ + unsigned short version; /* version number -- 2 for DWARF + version 2 */ + unsigned int info_offset; /* offset into .debug_info section */ + unsigned char addr_size; /* byte size of an address */ + unsigned char seg_size; /* byte size of segment descriptor */ + } +_ARANGES_HEADER; +#define _ACTUAL_ARANGES_HEADER_SIZE 12 + +/* .debug_line statement program prologue + Because of alignment constraints, this structure has padding and cannot + be mapped directly onto the beginning of the .debug_info section. */ +typedef struct statement_prologue + { + unsigned int total_length; /* byte length of the statement + information */ + unsigned short version; /* version number -- 2 for DWARF + version 2 */ + unsigned int prologue_length; /* # bytes between prologue & + stmt program */ + unsigned char minimum_instruction_length; /* byte size of + smallest instr */ + unsigned char default_is_stmt; /* initial value of is_stmt + register */ + char line_base; + unsigned char line_range; + unsigned char opcode_base; /* number assigned to first special + opcode */ + unsigned char *standard_opcode_lengths; + } +_STATEMENT_PROLOGUE; + +/* offsets and sizes of debugging sections */ + +static file_ptr dwarf_info_offset; +static file_ptr dwarf_abbrev_offset; +static file_ptr dwarf_line_offset; +static file_ptr dwarf_pubnames_offset; +static file_ptr dwarf_aranges_offset; +static file_ptr dwarf_loc_offset; +static file_ptr dwarf_macinfo_offset; +static file_ptr dwarf_str_offset; +file_ptr dwarf_frame_offset; +file_ptr dwarf_eh_frame_offset; + +static unsigned int dwarf_info_size; +static unsigned int dwarf_abbrev_size; +static unsigned int dwarf_line_size; +static unsigned int dwarf_pubnames_size; +static unsigned int dwarf_aranges_size; +static unsigned int dwarf_loc_size; +static unsigned int dwarf_macinfo_size; +static unsigned int dwarf_str_size; +unsigned int dwarf_frame_size; +unsigned int dwarf_eh_frame_size; + +/* names of the debugging sections */ + +#define INFO_SECTION ".debug_info" +#define ABBREV_SECTION ".debug_abbrev" +#define LINE_SECTION ".debug_line" +#define PUBNAMES_SECTION ".debug_pubnames" +#define ARANGES_SECTION ".debug_aranges" +#define LOC_SECTION ".debug_loc" +#define MACINFO_SECTION ".debug_macinfo" +#define STR_SECTION ".debug_str" +#define FRAME_SECTION ".debug_frame" +#define EH_FRAME_SECTION ".eh_frame" + +/* local data types */ + +/* The data in a compilation unit header, after target2host + translation, looks like this. */ +struct comp_unit_head + { + unsigned long length; + short version; + unsigned int abbrev_offset; + unsigned char addr_size; + unsigned char signed_addr_p; + unsigned int offset_size; /* size of file offsets; either 4 or 8 */ + unsigned int initial_length_size; /* size of the length field; either + 4 or 12 */ + }; + +/* The line number information for a compilation unit (found in the + .debug_line section) begins with a "statement program header", + which contains the following information. */ +struct line_header +{ + unsigned int total_length; + unsigned short version; + unsigned int header_length; + unsigned char minimum_instruction_length; + unsigned char default_is_stmt; + int line_base; + unsigned char line_range; + unsigned char opcode_base; + + /* standard_opcode_lengths[i] is the number of operands for the + standard opcode whose value is i. This means that + standard_opcode_lengths[0] is unused, and the last meaningful + element is standard_opcode_lengths[opcode_base - 1]. */ + unsigned char *standard_opcode_lengths; + + /* The include_directories table. NOTE! These strings are not + allocated with xmalloc; instead, they are pointers into + debug_line_buffer. If you try to free them, `free' will get + indigestion. */ + unsigned int num_include_dirs, include_dirs_size; + char **include_dirs; + + /* The file_names table. NOTE! These strings are not allocated + with xmalloc; instead, they are pointers into debug_line_buffer. + Don't try to free them directly. */ + unsigned int num_file_names, file_names_size; + struct file_entry + { + char *name; + unsigned int dir_index; + unsigned int mod_time; + unsigned int length; + } *file_names; + + /* The start and end of the statement program following this + header. These point into dwarf_line_buffer. */ + char *statement_program_start, *statement_program_end; +}; + +/* When we construct a partial symbol table entry we only + need this much information. */ +struct partial_die_info + { + enum dwarf_tag tag; + unsigned char has_children; + unsigned char is_external; + unsigned char is_declaration; + unsigned char has_type; + unsigned int offset; + unsigned int abbrev; + char *name; + int has_pc_info; + CORE_ADDR lowpc; + CORE_ADDR highpc; + struct dwarf_block *locdesc; + unsigned int language; + char *sibling; + }; + +/* This data structure holds the information of an abbrev. */ +struct abbrev_info + { + unsigned int number; /* number identifying abbrev */ + enum dwarf_tag tag; /* dwarf tag */ + int has_children; /* boolean */ + unsigned int num_attrs; /* number of attributes */ + struct attr_abbrev *attrs; /* an array of attribute descriptions */ + struct abbrev_info *next; /* next in chain */ + }; + +struct attr_abbrev + { + enum dwarf_attribute name; + enum dwarf_form form; + }; + +/* This data structure holds a complete die structure. */ +struct die_info + { + enum dwarf_tag tag; /* Tag indicating type of die */ + unsigned short has_children; /* Does the die have children */ + unsigned int abbrev; /* Abbrev number */ + unsigned int offset; /* Offset in .debug_info section */ + unsigned int num_attrs; /* Number of attributes */ + struct attribute *attrs; /* An array of attributes */ + struct die_info *next_ref; /* Next die in ref hash table */ + struct die_info *next; /* Next die in linked list */ + struct type *type; /* Cached type information */ + }; + +/* Attributes have a name and a value */ +struct attribute + { + enum dwarf_attribute name; + enum dwarf_form form; + union + { + char *str; + struct dwarf_block *blk; + unsigned long unsnd; + long int snd; + CORE_ADDR addr; + } + u; + }; + +struct function_range +{ + const char *name; + CORE_ADDR lowpc, highpc; + int seen_line; + struct function_range *next; +}; + +static struct function_range *cu_first_fn, *cu_last_fn, *cu_cached_fn; + +/* Get at parts of an attribute structure */ + +#define DW_STRING(attr) ((attr)->u.str) +#define DW_UNSND(attr) ((attr)->u.unsnd) +#define DW_BLOCK(attr) ((attr)->u.blk) +#define DW_SND(attr) ((attr)->u.snd) +#define DW_ADDR(attr) ((attr)->u.addr) + +/* Blocks are a bunch of untyped bytes. */ +struct dwarf_block + { + unsigned int size; + char *data; + }; + +/* We only hold one compilation unit's abbrevs in + memory at any one time. */ +#ifndef ABBREV_HASH_SIZE +#define ABBREV_HASH_SIZE 121 +#endif +#ifndef ATTR_ALLOC_CHUNK +#define ATTR_ALLOC_CHUNK 4 +#endif + +static struct abbrev_info *dwarf2_abbrevs[ABBREV_HASH_SIZE]; + +/* A hash table of die offsets for following references. */ +#ifndef REF_HASH_SIZE +#define REF_HASH_SIZE 1021 +#endif + +static struct die_info *die_ref_table[REF_HASH_SIZE]; + +/* Obstack for allocating temporary storage used during symbol reading. */ +static struct obstack dwarf2_tmp_obstack; + +/* Offset to the first byte of the current compilation unit header, + for resolving relative reference dies. */ +static unsigned int cu_header_offset; + +/* Allocate fields for structs, unions and enums in this size. */ +#ifndef DW_FIELD_ALLOC_CHUNK +#define DW_FIELD_ALLOC_CHUNK 4 +#endif + +/* The language we are debugging. */ +static enum language cu_language; +static const struct language_defn *cu_language_defn; + +/* Actually data from the sections. */ +static char *dwarf_info_buffer; +static char *dwarf_abbrev_buffer; +static char *dwarf_line_buffer; +static char *dwarf_str_buffer; +static char *dwarf_macinfo_buffer; + +/* A zeroed version of a partial die for initialization purposes. */ +static struct partial_die_info zeroed_partial_die; + +/* The generic symbol table building routines have separate lists for + file scope symbols and all all other scopes (local scopes). So + we need to select the right one to pass to add_symbol_to_list(). + We do it by keeping a pointer to the correct list in list_in_scope. + + FIXME: The original dwarf code just treated the file scope as the first + local scope, and all other local scopes as nested local scopes, and worked + fine. Check to see if we really need to distinguish these + in buildsym.c. */ +static struct pending **list_in_scope = &file_symbols; + +/* FIXME: decode_locdesc sets these variables to describe the location + to the caller. These ought to be a structure or something. If + none of the flags are set, the object lives at the address returned + by decode_locdesc. */ + +static int optimized_out; /* No ops in location in expression, + so object was optimized out. */ +static int isreg; /* Object lives in register. + decode_locdesc's return value is + the register number. */ +static int offreg; /* Object's address is the sum of the + register specified by basereg, plus + the offset returned. */ +static int basereg; /* See `offreg'. */ +static int isderef; /* Value described by flags above is + the address of a pointer to the object. */ +static int islocal; /* Variable is at the returned offset + from the frame start, but there's + no identified frame pointer for + this function, so we can't say + which register it's relative to; + use LOC_LOCAL. */ + +/* DW_AT_frame_base values for the current function. + frame_base_reg is -1 if DW_AT_frame_base is missing, otherwise it + contains the register number for the frame register. + frame_base_offset is the offset from the frame register to the + virtual stack frame. */ +static int frame_base_reg; +static CORE_ADDR frame_base_offset; + +/* This value is added to each symbol value. FIXME: Generalize to + the section_offsets structure used by dbxread (once this is done, + pass the appropriate section number to end_symtab). */ +static CORE_ADDR baseaddr; /* Add to each symbol value */ + +/* We put a pointer to this structure in the read_symtab_private field + of the psymtab. + The complete dwarf information for an objfile is kept in the + psymbol_obstack, so that absolute die references can be handled. + Most of the information in this structure is related to an entire + object file and could be passed via the sym_private field of the objfile. + It is however conceivable that dwarf2 might not be the only type + of symbols read from an object file. */ + +struct dwarf2_pinfo + { + /* Pointer to start of dwarf info buffer for the objfile. */ + + char *dwarf_info_buffer; + + /* Offset in dwarf_info_buffer for this compilation unit. */ + + unsigned long dwarf_info_offset; + + /* Pointer to start of dwarf abbreviation buffer for the objfile. */ + + char *dwarf_abbrev_buffer; + + /* Size of dwarf abbreviation section for the objfile. */ + + unsigned int dwarf_abbrev_size; + + /* Pointer to start of dwarf line buffer for the objfile. */ + + char *dwarf_line_buffer; + + /* Size of dwarf_line_buffer, in bytes. */ + + unsigned int dwarf_line_size; + + /* Pointer to start of dwarf string buffer for the objfile. */ + + char *dwarf_str_buffer; + + /* Size of dwarf string section for the objfile. */ + + unsigned int dwarf_str_size; + + /* Pointer to start of dwarf macro buffer for the objfile. */ + + char *dwarf_macinfo_buffer; + + /* Size of dwarf macinfo section for the objfile. */ + + unsigned int dwarf_macinfo_size; + + }; + +#define PST_PRIVATE(p) ((struct dwarf2_pinfo *)(p)->read_symtab_private) +#define DWARF_INFO_BUFFER(p) (PST_PRIVATE(p)->dwarf_info_buffer) +#define DWARF_INFO_OFFSET(p) (PST_PRIVATE(p)->dwarf_info_offset) +#define DWARF_ABBREV_BUFFER(p) (PST_PRIVATE(p)->dwarf_abbrev_buffer) +#define DWARF_ABBREV_SIZE(p) (PST_PRIVATE(p)->dwarf_abbrev_size) +#define DWARF_LINE_BUFFER(p) (PST_PRIVATE(p)->dwarf_line_buffer) +#define DWARF_LINE_SIZE(p) (PST_PRIVATE(p)->dwarf_line_size) +#define DWARF_STR_BUFFER(p) (PST_PRIVATE(p)->dwarf_str_buffer) +#define DWARF_STR_SIZE(p) (PST_PRIVATE(p)->dwarf_str_size) +#define DWARF_MACINFO_BUFFER(p) (PST_PRIVATE(p)->dwarf_macinfo_buffer) +#define DWARF_MACINFO_SIZE(p) (PST_PRIVATE(p)->dwarf_macinfo_size) + +/* Maintain an array of referenced fundamental types for the current + compilation unit being read. For DWARF version 1, we have to construct + the fundamental types on the fly, since no information about the + fundamental types is supplied. Each such fundamental type is created by + calling a language dependent routine to create the type, and then a + pointer to that type is then placed in the array at the index specified + by it's FT_<TYPENAME> value. The array has a fixed size set by the + FT_NUM_MEMBERS compile time constant, which is the number of predefined + fundamental types gdb knows how to construct. */ +static struct type *ftypes[FT_NUM_MEMBERS]; /* Fundamental types */ + +/* FIXME: We might want to set this from BFD via bfd_arch_bits_per_byte, + but this would require a corresponding change in unpack_field_as_long + and friends. */ +static int bits_per_byte = 8; + +/* The routines that read and process dies for a C struct or C++ class + pass lists of data member fields and lists of member function fields + in an instance of a field_info structure, as defined below. */ +struct field_info + { + /* List of data member and baseclasses fields. */ + struct nextfield + { + struct nextfield *next; + int accessibility; + int virtuality; + struct field field; + } + *fields; + + /* Number of fields. */ + int nfields; + + /* Number of baseclasses. */ + int nbaseclasses; + + /* Set if the accesibility of one of the fields is not public. */ + int non_public_fields; + + /* Member function fields array, entries are allocated in the order they + are encountered in the object file. */ + struct nextfnfield + { + struct nextfnfield *next; + struct fn_field fnfield; + } + *fnfields; + + /* Member function fieldlist array, contains name of possibly overloaded + member function, number of overloaded member functions and a pointer + to the head of the member function field chain. */ + struct fnfieldlist + { + char *name; + int length; + struct nextfnfield *head; + } + *fnfieldlists; + + /* Number of entries in the fnfieldlists array. */ + int nfnfields; + }; + +/* Various complaints about symbol reading that don't abort the process */ + +static struct complaint dwarf2_const_ignored = +{ + "type qualifier 'const' ignored", 0, 0 +}; +static struct complaint dwarf2_volatile_ignored = +{ + "type qualifier 'volatile' ignored", 0, 0 +}; +static struct complaint dwarf2_non_const_array_bound_ignored = +{ + "non-constant array bounds form '%s' ignored", 0, 0 +}; +static struct complaint dwarf2_missing_line_number_section = +{ + "missing .debug_line section", 0, 0 +}; +static struct complaint dwarf2_statement_list_fits_in_line_number_section = +{ + "statement list doesn't fit in .debug_line section", 0, 0 +}; +static struct complaint dwarf2_mangled_line_number_section = +{ + "mangled .debug_line section", 0, 0 +}; +static struct complaint dwarf2_unsupported_die_ref_attr = +{ + "unsupported die ref attribute form: '%s'", 0, 0 +}; +static struct complaint dwarf2_unsupported_stack_op = +{ + "unsupported stack op: '%s'", 0, 0 +}; +static struct complaint dwarf2_complex_location_expr = +{ + "location expression too complex", 0, 0 +}; +static struct complaint dwarf2_unsupported_tag = +{ + "unsupported tag: '%s'", 0, 0 +}; +static struct complaint dwarf2_unsupported_at_encoding = +{ + "unsupported DW_AT_encoding: '%s'", 0, 0 +}; +static struct complaint dwarf2_unsupported_at_frame_base = +{ + "unsupported DW_AT_frame_base for function '%s'", 0, 0 +}; +static struct complaint dwarf2_unexpected_tag = +{ + "unexepected tag in read_type_die: '%s'", 0, 0 +}; +static struct complaint dwarf2_missing_at_frame_base = +{ + "DW_AT_frame_base missing for DW_OP_fbreg", 0, 0 +}; +static struct complaint dwarf2_bad_static_member_name = +{ + "unrecognized static data member name '%s'", 0, 0 +}; +static struct complaint dwarf2_unsupported_accessibility = +{ + "unsupported accessibility %d", 0, 0 +}; +static struct complaint dwarf2_bad_member_name_complaint = +{ + "cannot extract member name from '%s'", 0, 0 +}; +static struct complaint dwarf2_missing_member_fn_type_complaint = +{ + "member function type missing for '%s'", 0, 0 +}; +static struct complaint dwarf2_vtbl_not_found_complaint = +{ + "virtual function table pointer not found when defining class '%s'", 0, 0 +}; +static struct complaint dwarf2_absolute_sibling_complaint = +{ + "ignoring absolute DW_AT_sibling", 0, 0 +}; +static struct complaint dwarf2_const_value_length_mismatch = +{ + "const value length mismatch for '%s', got %d, expected %d", 0, 0 +}; +static struct complaint dwarf2_unsupported_const_value_attr = +{ + "unsupported const value attribute form: '%s'", 0, 0 +}; +static struct complaint dwarf2_misplaced_line_number = +{ + "misplaced first line number at 0x%lx for '%s'", 0, 0 +}; +static struct complaint dwarf2_line_header_too_long = +{ + "line number info header doesn't fit in `.debug_line' section", 0, 0 +}; +static struct complaint dwarf2_missing_macinfo_section = +{ + "missing .debug_macinfo section", 0, 0 +}; +static struct complaint dwarf2_macros_too_long = +{ + "macro info runs off end of `.debug_macinfo' section", 0, 0 +}; +static struct complaint dwarf2_macros_not_terminated = +{ + "no terminating 0-type entry for macros in `.debug_macinfo' section", 0, 0 +}; +static struct complaint dwarf2_macro_outside_file = +{ + "debug info gives macro %s outside of any file: %s", 0, 0 +}; +static struct complaint dwarf2_macro_unmatched_end_file = +{ + "macro debug info has an unmatched `close_file' directive", 0, 0 +}; +static struct complaint dwarf2_macro_malformed_definition = +{ + "macro debug info contains a malformed macro definition:\n`%s'", 0, 0 +}; +static struct complaint dwarf2_macro_spaces_in_definition = +{ + "macro definition contains spaces in formal argument list:\n`%s'", 0, 0 +}; +static struct complaint dwarf2_invalid_attrib_class = +{ + "invalid attribute class or form for '%s' in '%s'", 0, 0 +}; + +/* local function prototypes */ + +static void dwarf2_locate_sections (bfd *, asection *, PTR); + +#if 0 +static void dwarf2_build_psymtabs_easy (struct objfile *, int); +#endif + +static void dwarf2_build_psymtabs_hard (struct objfile *, int); + +static char *scan_partial_symbols (char *, struct objfile *, + CORE_ADDR *, CORE_ADDR *, + const struct comp_unit_head *); + +static void add_partial_symbol (struct partial_die_info *, struct objfile *, + const struct comp_unit_head *); + +static void dwarf2_psymtab_to_symtab (struct partial_symtab *); + +static void psymtab_to_symtab_1 (struct partial_symtab *); + +char *dwarf2_read_section (struct objfile *, file_ptr, unsigned int); + +static void dwarf2_read_abbrevs (bfd *, unsigned int); + +static void dwarf2_empty_abbrev_table (PTR); + +static struct abbrev_info *dwarf2_lookup_abbrev (unsigned int); + +static char *read_partial_die (struct partial_die_info *, + bfd *, char *, + const struct comp_unit_head *); + +static char *read_full_die (struct die_info **, bfd *, char *, + const struct comp_unit_head *); + +static char *read_attribute (struct attribute *, struct attr_abbrev *, + bfd *, char *, const struct comp_unit_head *); + +static char *read_attribute_value (struct attribute *, unsigned, + bfd *, char *, const struct comp_unit_head *); + +static unsigned int read_1_byte (bfd *, char *); + +static int read_1_signed_byte (bfd *, char *); + +static unsigned int read_2_bytes (bfd *, char *); + +static unsigned int read_4_bytes (bfd *, char *); + +static unsigned long read_8_bytes (bfd *, char *); + +static CORE_ADDR read_address (bfd *, char *ptr, const struct comp_unit_head *, + int *bytes_read); + +static LONGEST read_initial_length (bfd *, char *, + struct comp_unit_head *, int *bytes_read); + +static LONGEST read_offset (bfd *, char *, const struct comp_unit_head *, + int *bytes_read); + +static char *read_n_bytes (bfd *, char *, unsigned int); + +static char *read_string (bfd *, char *, unsigned int *); + +static char *read_indirect_string (bfd *, char *, const struct comp_unit_head *, + unsigned int *); + +static unsigned long read_unsigned_leb128 (bfd *, char *, unsigned int *); + +static long read_signed_leb128 (bfd *, char *, unsigned int *); + +static void set_cu_language (unsigned int); + +static struct attribute *dwarf_attr (struct die_info *, unsigned int); + +static int die_is_declaration (struct die_info *); + +static void free_line_header (struct line_header *lh); + +static struct line_header *(dwarf_decode_line_header + (unsigned int offset, + bfd *abfd, + const struct comp_unit_head *cu_header)); + +static void dwarf_decode_lines (struct line_header *, char *, bfd *, + const struct comp_unit_head *); + +static void dwarf2_start_subfile (char *, char *); + +static struct symbol *new_symbol (struct die_info *, struct type *, + struct objfile *, const struct comp_unit_head *); + +static void dwarf2_const_value (struct attribute *, struct symbol *, + struct objfile *, const struct comp_unit_head *); + +static void dwarf2_const_value_data (struct attribute *attr, + struct symbol *sym, + int bits); + +static struct type *die_type (struct die_info *, struct objfile *, + const struct comp_unit_head *); + +static struct type *die_containing_type (struct die_info *, struct objfile *, + const struct comp_unit_head *); + +#if 0 +static struct type *type_at_offset (unsigned int, struct objfile *); +#endif + +static struct type *tag_type_to_type (struct die_info *, struct objfile *, + const struct comp_unit_head *); + +static void read_type_die (struct die_info *, struct objfile *, + const struct comp_unit_head *); + +static void read_typedef (struct die_info *, struct objfile *, + const struct comp_unit_head *); + +static void read_base_type (struct die_info *, struct objfile *); + +static void read_file_scope (struct die_info *, struct objfile *, + const struct comp_unit_head *); + +static void read_func_scope (struct die_info *, struct objfile *, + const struct comp_unit_head *); + +static void read_lexical_block_scope (struct die_info *, struct objfile *, + const struct comp_unit_head *); + +static int dwarf2_get_pc_bounds (struct die_info *, + CORE_ADDR *, CORE_ADDR *, struct objfile *); + +static void dwarf2_add_field (struct field_info *, struct die_info *, + struct objfile *, const struct comp_unit_head *); + +static void dwarf2_attach_fields_to_type (struct field_info *, + struct type *, struct objfile *); + +static void dwarf2_add_member_fn (struct field_info *, + struct die_info *, struct type *, + struct objfile *objfile, + const struct comp_unit_head *); + +static void dwarf2_attach_fn_fields_to_type (struct field_info *, + struct type *, struct objfile *); + +static void read_structure_scope (struct die_info *, struct objfile *, + const struct comp_unit_head *); + +static void read_common_block (struct die_info *, struct objfile *, + const struct comp_unit_head *); + +static void read_enumeration (struct die_info *, struct objfile *, + const struct comp_unit_head *); + +static struct type *dwarf_base_type (int, int, struct objfile *); + +static CORE_ADDR decode_locdesc (struct dwarf_block *, struct objfile *, + const struct comp_unit_head *); + +static void read_array_type (struct die_info *, struct objfile *, + const struct comp_unit_head *); + +static void read_tag_pointer_type (struct die_info *, struct objfile *, + const struct comp_unit_head *); + +static void read_tag_ptr_to_member_type (struct die_info *, struct objfile *, + const struct comp_unit_head *); + +static void read_tag_reference_type (struct die_info *, struct objfile *, + const struct comp_unit_head *); + +static void read_tag_const_type (struct die_info *, struct objfile *, + const struct comp_unit_head *); + +static void read_tag_volatile_type (struct die_info *, struct objfile *, + const struct comp_unit_head *); + +static void read_tag_string_type (struct die_info *, struct objfile *); + +static void read_subroutine_type (struct die_info *, struct objfile *, + const struct comp_unit_head *); + +static struct die_info *read_comp_unit (char *, bfd *, + const struct comp_unit_head *); + +static void free_die_list (struct die_info *); + +static struct cleanup *make_cleanup_free_die_list (struct die_info *); + +static void process_die (struct die_info *, struct objfile *, + const struct comp_unit_head *); + +static char *dwarf2_linkage_name (struct die_info *); + +static char *dwarf_tag_name (unsigned int); + +static char *dwarf_attr_name (unsigned int); + +static char *dwarf_form_name (unsigned int); + +static char *dwarf_stack_op_name (unsigned int); + +static char *dwarf_bool_name (unsigned int); + +static char *dwarf_type_encoding_name (unsigned int); + +#if 0 +static char *dwarf_cfi_name (unsigned int); + +struct die_info *copy_die (struct die_info *); +#endif + +static struct die_info *sibling_die (struct die_info *); + +static void dump_die (struct die_info *); + +static void dump_die_list (struct die_info *); + +static void store_in_ref_table (unsigned int, struct die_info *); + +static void dwarf2_empty_hash_tables (void); + +static unsigned int dwarf2_get_ref_die_offset (struct attribute *); + +static struct die_info *follow_die_ref (unsigned int); + +static struct type *dwarf2_fundamental_type (struct objfile *, int); + +/* memory allocation interface */ + +static void dwarf2_free_tmp_obstack (PTR); + +static struct dwarf_block *dwarf_alloc_block (void); + +static struct abbrev_info *dwarf_alloc_abbrev (void); + +static struct die_info *dwarf_alloc_die (void); + +static void initialize_cu_func_list (void); + +static void add_to_cu_func_list (const char *, CORE_ADDR, CORE_ADDR); + +static void dwarf_decode_macros (struct line_header *, unsigned int, + char *, bfd *, const struct comp_unit_head *, + struct objfile *); + +static int attr_form_is_block (struct attribute *); + +/* Try to locate the sections we need for DWARF 2 debugging + information and return true if we have enough to do something. */ + +int +dwarf2_has_info (bfd *abfd) +{ + dwarf_info_offset = 0; + dwarf_abbrev_offset = 0; + dwarf_line_offset = 0; + dwarf_str_offset = 0; + dwarf_macinfo_offset = 0; + dwarf_frame_offset = 0; + dwarf_eh_frame_offset = 0; + bfd_map_over_sections (abfd, dwarf2_locate_sections, NULL); + if (dwarf_info_offset && dwarf_abbrev_offset) + { + return 1; + } + else + { + return 0; + } +} + +/* This function is mapped across the sections and remembers the + offset and size of each of the debugging sections we are interested + in. */ + +static void +dwarf2_locate_sections (bfd *ignore_abfd, asection *sectp, PTR ignore_ptr) +{ + if (STREQ (sectp->name, INFO_SECTION)) + { + dwarf_info_offset = sectp->filepos; + dwarf_info_size = bfd_get_section_size_before_reloc (sectp); + } + else if (STREQ (sectp->name, ABBREV_SECTION)) + { + dwarf_abbrev_offset = sectp->filepos; + dwarf_abbrev_size = bfd_get_section_size_before_reloc (sectp); + } + else if (STREQ (sectp->name, LINE_SECTION)) + { + dwarf_line_offset = sectp->filepos; + dwarf_line_size = bfd_get_section_size_before_reloc (sectp); + } + else if (STREQ (sectp->name, PUBNAMES_SECTION)) + { + dwarf_pubnames_offset = sectp->filepos; + dwarf_pubnames_size = bfd_get_section_size_before_reloc (sectp); + } + else if (STREQ (sectp->name, ARANGES_SECTION)) + { + dwarf_aranges_offset = sectp->filepos; + dwarf_aranges_size = bfd_get_section_size_before_reloc (sectp); + } + else if (STREQ (sectp->name, LOC_SECTION)) + { + dwarf_loc_offset = sectp->filepos; + dwarf_loc_size = bfd_get_section_size_before_reloc (sectp); + } + else if (STREQ (sectp->name, MACINFO_SECTION)) + { + dwarf_macinfo_offset = sectp->filepos; + dwarf_macinfo_size = bfd_get_section_size_before_reloc (sectp); + } + else if (STREQ (sectp->name, STR_SECTION)) + { + dwarf_str_offset = sectp->filepos; + dwarf_str_size = bfd_get_section_size_before_reloc (sectp); + } + else if (STREQ (sectp->name, FRAME_SECTION)) + { + dwarf_frame_offset = sectp->filepos; + dwarf_frame_size = bfd_get_section_size_before_reloc (sectp); + } + else if (STREQ (sectp->name, EH_FRAME_SECTION)) + { + dwarf_eh_frame_offset = sectp->filepos; + dwarf_eh_frame_size = bfd_get_section_size_before_reloc (sectp); + } +} + +/* Build a partial symbol table. */ + +void +dwarf2_build_psymtabs (struct objfile *objfile, int mainline) +{ + + /* We definitely need the .debug_info and .debug_abbrev sections */ + + dwarf_info_buffer = dwarf2_read_section (objfile, + dwarf_info_offset, + dwarf_info_size); + dwarf_abbrev_buffer = dwarf2_read_section (objfile, + dwarf_abbrev_offset, + dwarf_abbrev_size); + + if (dwarf_line_offset) + dwarf_line_buffer = dwarf2_read_section (objfile, + dwarf_line_offset, + dwarf_line_size); + else + dwarf_line_buffer = NULL; + + if (dwarf_str_offset) + dwarf_str_buffer = dwarf2_read_section (objfile, + dwarf_str_offset, + dwarf_str_size); + else + dwarf_str_buffer = NULL; + + if (dwarf_macinfo_offset) + dwarf_macinfo_buffer = dwarf2_read_section (objfile, + dwarf_macinfo_offset, + dwarf_macinfo_size); + else + dwarf_macinfo_buffer = NULL; + + if (mainline + || (objfile->global_psymbols.size == 0 + && objfile->static_psymbols.size == 0)) + { + init_psymbol_list (objfile, 1024); + } + +#if 0 + if (dwarf_aranges_offset && dwarf_pubnames_offset) + { + /* Things are significantly easier if we have .debug_aranges and + .debug_pubnames sections */ + + dwarf2_build_psymtabs_easy (objfile, mainline); + } + else +#endif + /* only test this case for now */ + { + /* In this case we have to work a bit harder */ + dwarf2_build_psymtabs_hard (objfile, mainline); + } +} + +#if 0 +/* Build the partial symbol table from the information in the + .debug_pubnames and .debug_aranges sections. */ + +static void +dwarf2_build_psymtabs_easy (struct objfile *objfile, int mainline) +{ + bfd *abfd = objfile->obfd; + char *aranges_buffer, *pubnames_buffer; + char *aranges_ptr, *pubnames_ptr; + unsigned int entry_length, version, info_offset, info_size; + + pubnames_buffer = dwarf2_read_section (objfile, + dwarf_pubnames_offset, + dwarf_pubnames_size); + pubnames_ptr = pubnames_buffer; + while ((pubnames_ptr - pubnames_buffer) < dwarf_pubnames_size) + { + struct comp_unit_head cu_header; + int bytes_read; + + entry_length = read_initial_length (abfd, pubnames_ptr, &cu_header, + &bytes_read); + pubnames_ptr += bytes_read; + version = read_1_byte (abfd, pubnames_ptr); + pubnames_ptr += 1; + info_offset = read_4_bytes (abfd, pubnames_ptr); + pubnames_ptr += 4; + info_size = read_4_bytes (abfd, pubnames_ptr); + pubnames_ptr += 4; + } + + aranges_buffer = dwarf2_read_section (objfile, + dwarf_aranges_offset, + dwarf_aranges_size); + +} +#endif + +/* Read in the comp unit header information from the debug_info at + info_ptr. */ + +static char * +read_comp_unit_head (struct comp_unit_head *cu_header, + char *info_ptr, bfd *abfd) +{ + int signed_addr; + int bytes_read; + cu_header->length = read_initial_length (abfd, info_ptr, cu_header, + &bytes_read); + info_ptr += bytes_read; + cu_header->version = read_2_bytes (abfd, info_ptr); + info_ptr += 2; + cu_header->abbrev_offset = read_offset (abfd, info_ptr, cu_header, + &bytes_read); + info_ptr += bytes_read; + cu_header->addr_size = read_1_byte (abfd, info_ptr); + info_ptr += 1; + signed_addr = bfd_get_sign_extend_vma (abfd); + if (signed_addr < 0) + internal_error (__FILE__, __LINE__, + "read_comp_unit_head: dwarf from non elf file"); + cu_header->signed_addr_p = signed_addr; + return info_ptr; +} + +/* Build the partial symbol table by doing a quick pass through the + .debug_info and .debug_abbrev sections. */ + +static void +dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline) +{ + /* Instead of reading this into a big buffer, we should probably use + mmap() on architectures that support it. (FIXME) */ + bfd *abfd = objfile->obfd; + char *info_ptr, *abbrev_ptr; + char *beg_of_comp_unit; + struct partial_die_info comp_unit_die; + struct partial_symtab *pst; + struct cleanup *back_to; + CORE_ADDR lowpc, highpc; + + info_ptr = dwarf_info_buffer; + abbrev_ptr = dwarf_abbrev_buffer; + + /* We use dwarf2_tmp_obstack for objects that don't need to survive + the partial symbol scan, like attribute values. + + We could reduce our peak memory consumption during partial symbol + table construction by freeing stuff from this obstack more often + --- say, after processing each compilation unit, or each die --- + but it turns out that this saves almost nothing. For an + executable with 11Mb of Dwarf 2 data, I found about 64k allocated + on dwarf2_tmp_obstack. Some investigation showed: + + 1) 69% of the attributes used forms DW_FORM_addr, DW_FORM_data*, + DW_FORM_flag, DW_FORM_[su]data, and DW_FORM_ref*. These are + all fixed-length values not requiring dynamic allocation. + + 2) 30% of the attributes used the form DW_FORM_string. For + DW_FORM_string, read_attribute simply hands back a pointer to + the null-terminated string in dwarf_info_buffer, so no dynamic + allocation is needed there either. + + 3) The remaining 1% of the attributes all used DW_FORM_block1. + 75% of those were DW_AT_frame_base location lists for + functions; the rest were DW_AT_location attributes, probably + for the global variables. + + Anyway, what this all means is that the memory the dwarf2 + reader uses as temporary space reading partial symbols is about + 0.5% as much as we use for dwarf_*_buffer. That's noise. */ + + obstack_init (&dwarf2_tmp_obstack); + back_to = make_cleanup (dwarf2_free_tmp_obstack, NULL); + + /* Since the objects we're extracting from dwarf_info_buffer vary in + length, only the individual functions to extract them (like + read_comp_unit_head and read_partial_die) can really know whether + the buffer is large enough to hold another complete object. + + At the moment, they don't actually check that. If + dwarf_info_buffer holds just one extra byte after the last + compilation unit's dies, then read_comp_unit_head will happily + read off the end of the buffer. read_partial_die is similarly + casual. Those functions should be fixed. + + For this loop condition, simply checking whether there's any data + left at all should be sufficient. */ + while (info_ptr < dwarf_info_buffer + dwarf_info_size) + { + struct comp_unit_head cu_header; + beg_of_comp_unit = info_ptr; + info_ptr = read_comp_unit_head (&cu_header, info_ptr, abfd); + + if (cu_header.version != 2) + { + error ("Dwarf Error: wrong version in compilation unit header."); + return; + } + if (cu_header.abbrev_offset >= dwarf_abbrev_size) + { + error ("Dwarf Error: bad offset (0x%lx) in compilation unit header (offset 0x%lx + 6).", + (long) cu_header.abbrev_offset, + (long) (beg_of_comp_unit - dwarf_info_buffer)); + return; + } + if (beg_of_comp_unit + cu_header.length + cu_header.initial_length_size + > dwarf_info_buffer + dwarf_info_size) + { + error ("Dwarf Error: bad length (0x%lx) in compilation unit header (offset 0x%lx + 0).", + (long) cu_header.length, + (long) (beg_of_comp_unit - dwarf_info_buffer)); + return; + } + /* Read the abbrevs for this compilation unit into a table */ + dwarf2_read_abbrevs (abfd, cu_header.abbrev_offset); + make_cleanup (dwarf2_empty_abbrev_table, NULL); + + /* Read the compilation unit die */ + info_ptr = read_partial_die (&comp_unit_die, abfd, info_ptr, + &cu_header); + + /* Set the language we're debugging */ + set_cu_language (comp_unit_die.language); + + /* Allocate a new partial symbol table structure */ + pst = start_psymtab_common (objfile, objfile->section_offsets, + comp_unit_die.name ? comp_unit_die.name : "", + comp_unit_die.lowpc, + objfile->global_psymbols.next, + objfile->static_psymbols.next); + + pst->read_symtab_private = (char *) + obstack_alloc (&objfile->psymbol_obstack, sizeof (struct dwarf2_pinfo)); + cu_header_offset = beg_of_comp_unit - dwarf_info_buffer; + DWARF_INFO_BUFFER (pst) = dwarf_info_buffer; + DWARF_INFO_OFFSET (pst) = beg_of_comp_unit - dwarf_info_buffer; + DWARF_ABBREV_BUFFER (pst) = dwarf_abbrev_buffer; + DWARF_ABBREV_SIZE (pst) = dwarf_abbrev_size; + DWARF_LINE_BUFFER (pst) = dwarf_line_buffer; + DWARF_LINE_SIZE (pst) = dwarf_line_size; + DWARF_STR_BUFFER (pst) = dwarf_str_buffer; + DWARF_STR_SIZE (pst) = dwarf_str_size; + DWARF_MACINFO_BUFFER (pst) = dwarf_macinfo_buffer; + DWARF_MACINFO_SIZE (pst) = dwarf_macinfo_size; + baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + + /* Store the function that reads in the rest of the symbol table */ + pst->read_symtab = dwarf2_psymtab_to_symtab; + + /* Check if comp unit has_children. + If so, read the rest of the partial symbols from this comp unit. + If not, there's no more debug_info for this comp unit. */ + if (comp_unit_die.has_children) + { + info_ptr = scan_partial_symbols (info_ptr, objfile, &lowpc, &highpc, + &cu_header); + + /* If the compilation unit didn't have an explicit address range, + then use the information extracted from its child dies. */ + if (! comp_unit_die.has_pc_info) + { + comp_unit_die.lowpc = lowpc; + comp_unit_die.highpc = highpc; + } + } + pst->textlow = comp_unit_die.lowpc + baseaddr; + pst->texthigh = comp_unit_die.highpc + baseaddr; + + pst->n_global_syms = objfile->global_psymbols.next - + (objfile->global_psymbols.list + pst->globals_offset); + pst->n_static_syms = objfile->static_psymbols.next - + (objfile->static_psymbols.list + pst->statics_offset); + sort_pst_symbols (pst); + + /* If there is already a psymtab or symtab for a file of this + name, remove it. (If there is a symtab, more drastic things + also happen.) This happens in VxWorks. */ + free_named_symtabs (pst->filename); + + info_ptr = beg_of_comp_unit + cu_header.length + + cu_header.initial_length_size; + } + do_cleanups (back_to); +} + +/* Read in all interesting dies to the end of the compilation unit. */ + +static char * +scan_partial_symbols (char *info_ptr, struct objfile *objfile, + CORE_ADDR *lowpc, CORE_ADDR *highpc, + const struct comp_unit_head *cu_header) +{ + bfd *abfd = objfile->obfd; + struct partial_die_info pdi; + + /* This function is called after we've read in the comp_unit_die in + order to read its children. We start the nesting level at 1 since + we have pushed 1 level down in order to read the comp unit's children. + The comp unit itself is at level 0, so we stop reading when we pop + back to that level. */ + + int nesting_level = 1; + + *lowpc = ((CORE_ADDR) -1); + *highpc = ((CORE_ADDR) 0); + + while (nesting_level) + { + info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu_header); + + if (pdi.name) + { + switch (pdi.tag) + { + case DW_TAG_subprogram: + if (pdi.has_pc_info) + { + if (pdi.lowpc < *lowpc) + { + *lowpc = pdi.lowpc; + } + if (pdi.highpc > *highpc) + { + *highpc = pdi.highpc; + } + if ((pdi.is_external || nesting_level == 1) + && !pdi.is_declaration) + { + add_partial_symbol (&pdi, objfile, cu_header); + } + } + break; + case DW_TAG_variable: + case DW_TAG_typedef: + case DW_TAG_class_type: + case DW_TAG_structure_type: + case DW_TAG_union_type: + case DW_TAG_enumeration_type: + if ((pdi.is_external || nesting_level == 1) + && !pdi.is_declaration) + { + add_partial_symbol (&pdi, objfile, cu_header); + } + break; + case DW_TAG_enumerator: + /* File scope enumerators are added to the partial symbol + table. */ + if (nesting_level == 2) + add_partial_symbol (&pdi, objfile, cu_header); + break; + case DW_TAG_base_type: + /* File scope base type definitions are added to the partial + symbol table. */ + if (nesting_level == 1) + add_partial_symbol (&pdi, objfile, cu_header); + break; + default: + break; + } + } + + /* If the die has a sibling, skip to the sibling. + Do not skip enumeration types, we want to record their + enumerators. */ + if (pdi.sibling && pdi.tag != DW_TAG_enumeration_type) + { + info_ptr = pdi.sibling; + } + else if (pdi.has_children) + { + /* Die has children, but the optional DW_AT_sibling attribute + is missing. */ + nesting_level++; + } + + if (pdi.tag == 0) + { + nesting_level--; + } + } + + /* If we didn't find a lowpc, set it to highpc to avoid complaints + from `maint check'. */ + if (*lowpc == ((CORE_ADDR) -1)) + *lowpc = *highpc; + return info_ptr; +} + +static void +add_partial_symbol (struct partial_die_info *pdi, struct objfile *objfile, + const struct comp_unit_head *cu_header) +{ + CORE_ADDR addr = 0; + + switch (pdi->tag) + { + case DW_TAG_subprogram: + if (pdi->is_external) + { + /*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr, + mst_text, objfile); */ + add_psymbol_to_list (pdi->name, strlen (pdi->name), + VAR_NAMESPACE, LOC_BLOCK, + &objfile->global_psymbols, + 0, pdi->lowpc + baseaddr, cu_language, objfile); + } + else + { + /*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr, + mst_file_text, objfile); */ + add_psymbol_to_list (pdi->name, strlen (pdi->name), + VAR_NAMESPACE, LOC_BLOCK, + &objfile->static_psymbols, + 0, pdi->lowpc + baseaddr, cu_language, objfile); + } + break; + case DW_TAG_variable: + if (pdi->is_external) + { + /* Global Variable. + Don't enter into the minimal symbol tables as there is + a minimal symbol table entry from the ELF symbols already. + Enter into partial symbol table if it has a location + descriptor or a type. + If the location descriptor is missing, new_symbol will create + a LOC_UNRESOLVED symbol, the address of the variable will then + be determined from the minimal symbol table whenever the variable + is referenced. + The address for the partial symbol table entry is not + used by GDB, but it comes in handy for debugging partial symbol + table building. */ + + if (pdi->locdesc) + addr = decode_locdesc (pdi->locdesc, objfile, cu_header); + if (pdi->locdesc || pdi->has_type) + add_psymbol_to_list (pdi->name, strlen (pdi->name), + VAR_NAMESPACE, LOC_STATIC, + &objfile->global_psymbols, + 0, addr + baseaddr, cu_language, objfile); + } + else + { + /* Static Variable. Skip symbols without location descriptors. */ + if (pdi->locdesc == NULL) + return; + addr = decode_locdesc (pdi->locdesc, objfile, cu_header); + /*prim_record_minimal_symbol (pdi->name, addr + baseaddr, + mst_file_data, objfile); */ + add_psymbol_to_list (pdi->name, strlen (pdi->name), + VAR_NAMESPACE, LOC_STATIC, + &objfile->static_psymbols, + 0, addr + baseaddr, cu_language, objfile); + } + break; + case DW_TAG_typedef: + case DW_TAG_base_type: + add_psymbol_to_list (pdi->name, strlen (pdi->name), + VAR_NAMESPACE, LOC_TYPEDEF, + &objfile->static_psymbols, + 0, (CORE_ADDR) 0, cu_language, objfile); + break; + case DW_TAG_class_type: + case DW_TAG_structure_type: + case DW_TAG_union_type: + case DW_TAG_enumeration_type: + /* Skip aggregate types without children, these are external + references. */ + if (pdi->has_children == 0) + return; + add_psymbol_to_list (pdi->name, strlen (pdi->name), + STRUCT_NAMESPACE, LOC_TYPEDEF, + &objfile->static_psymbols, + 0, (CORE_ADDR) 0, cu_language, objfile); + + if (cu_language == language_cplus) + { + /* For C++, these implicitly act as typedefs as well. */ + add_psymbol_to_list (pdi->name, strlen (pdi->name), + VAR_NAMESPACE, LOC_TYPEDEF, + &objfile->static_psymbols, + 0, (CORE_ADDR) 0, cu_language, objfile); + } + break; + case DW_TAG_enumerator: + add_psymbol_to_list (pdi->name, strlen (pdi->name), + VAR_NAMESPACE, LOC_CONST, + &objfile->static_psymbols, + 0, (CORE_ADDR) 0, cu_language, objfile); + break; + default: + break; + } +} + +/* Expand this partial symbol table into a full symbol table. */ + +static void +dwarf2_psymtab_to_symtab (struct partial_symtab *pst) +{ + /* FIXME: This is barely more than a stub. */ + if (pst != NULL) + { + if (pst->readin) + { + warning ("bug: psymtab for %s is already read in.", pst->filename); + } + else + { + if (info_verbose) + { + printf_filtered ("Reading in symbols for %s...", pst->filename); + gdb_flush (gdb_stdout); + } + + psymtab_to_symtab_1 (pst); + + /* Finish up the debug error message. */ + if (info_verbose) + printf_filtered ("done.\n"); + } + } +} + +static void +psymtab_to_symtab_1 (struct partial_symtab *pst) +{ + struct objfile *objfile = pst->objfile; + bfd *abfd = objfile->obfd; + struct comp_unit_head cu_header; + struct die_info *dies; + unsigned long offset; + CORE_ADDR lowpc, highpc; + struct die_info *child_die; + char *info_ptr; + struct symtab *symtab; + struct cleanup *back_to; + + /* Set local variables from the partial symbol table info. */ + offset = DWARF_INFO_OFFSET (pst); + dwarf_info_buffer = DWARF_INFO_BUFFER (pst); + dwarf_abbrev_buffer = DWARF_ABBREV_BUFFER (pst); + dwarf_abbrev_size = DWARF_ABBREV_SIZE (pst); + dwarf_line_buffer = DWARF_LINE_BUFFER (pst); + dwarf_line_size = DWARF_LINE_SIZE (pst); + dwarf_str_buffer = DWARF_STR_BUFFER (pst); + dwarf_str_size = DWARF_STR_SIZE (pst); + dwarf_macinfo_buffer = DWARF_MACINFO_BUFFER (pst); + dwarf_macinfo_size = DWARF_MACINFO_SIZE (pst); + baseaddr = ANOFFSET (pst->section_offsets, SECT_OFF_TEXT (objfile)); + cu_header_offset = offset; + info_ptr = dwarf_info_buffer + offset; + + obstack_init (&dwarf2_tmp_obstack); + back_to = make_cleanup (dwarf2_free_tmp_obstack, NULL); + + buildsym_init (); + make_cleanup (really_free_pendings, NULL); + + /* read in the comp_unit header */ + info_ptr = read_comp_unit_head (&cu_header, info_ptr, abfd); + + /* Read the abbrevs for this compilation unit */ + dwarf2_read_abbrevs (abfd, cu_header.abbrev_offset); + make_cleanup (dwarf2_empty_abbrev_table, NULL); + + dies = read_comp_unit (info_ptr, abfd, &cu_header); + + make_cleanup_free_die_list (dies); + + /* Do line number decoding in read_file_scope () */ + process_die (dies, objfile, &cu_header); + + if (!dwarf2_get_pc_bounds (dies, &lowpc, &highpc, objfile)) + { + /* 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. */ + highpc = 0; + if (dies->has_children) + { + child_die = dies->next; + while (child_die && child_die->tag) + { + if (child_die->tag == DW_TAG_subprogram) + { + CORE_ADDR low, high; + + if (dwarf2_get_pc_bounds (child_die, &low, &high, objfile)) + { + highpc = max (highpc, high); + } + } + child_die = sibling_die (child_die); + } + } + } + symtab = end_symtab (highpc + baseaddr, objfile, SECT_OFF_TEXT (objfile)); + + /* Set symtab language to language from DW_AT_language. + If the compilation is from a C file generated by language preprocessors, + do not set the language if it was already deduced by start_subfile. */ + if (symtab != NULL + && !(cu_language == language_c && symtab->language != language_c)) + { + symtab->language = cu_language; + } + pst->symtab = symtab; + pst->readin = 1; + sort_symtab_syms (pst->symtab); + + do_cleanups (back_to); +} + +/* Process a die and its children. */ + +static void +process_die (struct die_info *die, struct objfile *objfile, + const struct comp_unit_head *cu_header) +{ + switch (die->tag) + { + case DW_TAG_padding: + break; + case DW_TAG_compile_unit: + read_file_scope (die, objfile, cu_header); + break; + case DW_TAG_subprogram: + read_subroutine_type (die, objfile, cu_header); + read_func_scope (die, objfile, cu_header); + break; + case DW_TAG_inlined_subroutine: + /* FIXME: These are ignored for now. + They could be used to set breakpoints on all inlined instances + of a function and make GDB `next' properly over inlined functions. */ + break; + case DW_TAG_lexical_block: + read_lexical_block_scope (die, objfile, cu_header); + break; + case DW_TAG_class_type: + case DW_TAG_structure_type: + case DW_TAG_union_type: + read_structure_scope (die, objfile, cu_header); + break; + case DW_TAG_enumeration_type: + read_enumeration (die, objfile, cu_header); + break; + case DW_TAG_subroutine_type: + read_subroutine_type (die, objfile, cu_header); + break; + case DW_TAG_array_type: + read_array_type (die, objfile, cu_header); + break; + case DW_TAG_pointer_type: + read_tag_pointer_type (die, objfile, cu_header); + break; + case DW_TAG_ptr_to_member_type: + read_tag_ptr_to_member_type (die, objfile, cu_header); + break; + case DW_TAG_reference_type: + read_tag_reference_type (die, objfile, cu_header); + break; + case DW_TAG_string_type: + read_tag_string_type (die, objfile); + break; + case DW_TAG_base_type: + read_base_type (die, objfile); + if (dwarf_attr (die, DW_AT_name)) + { + /* Add a typedef symbol for the base type definition. */ + new_symbol (die, die->type, objfile, cu_header); + } + break; + case DW_TAG_common_block: + read_common_block (die, objfile, cu_header); + break; + case DW_TAG_common_inclusion: + break; + default: + new_symbol (die, NULL, objfile, cu_header); + break; + } +} + +static void +initialize_cu_func_list (void) +{ + cu_first_fn = cu_last_fn = cu_cached_fn = NULL; +} + +static void +read_file_scope (struct die_info *die, struct objfile *objfile, + const struct comp_unit_head *cu_header) +{ + struct cleanup *back_to = make_cleanup (null_cleanup, 0); + CORE_ADDR lowpc = ((CORE_ADDR) -1); + CORE_ADDR highpc = ((CORE_ADDR) 0); + struct attribute *attr; + char *name = "<unknown>"; + char *comp_dir = NULL; + struct die_info *child_die; + bfd *abfd = objfile->obfd; + struct line_header *line_header = 0; + + if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile)) + { + if (die->has_children) + { + child_die = die->next; + while (child_die && child_die->tag) + { + if (child_die->tag == DW_TAG_subprogram) + { + CORE_ADDR low, high; + + if (dwarf2_get_pc_bounds (child_die, &low, &high, objfile)) + { + lowpc = min (lowpc, low); + highpc = max (highpc, high); + } + } + child_die = sibling_die (child_die); + } + } + } + + /* If we didn't find a lowpc, set it to highpc to avoid complaints + from finish_block. */ + if (lowpc == ((CORE_ADDR) -1)) + lowpc = highpc; + lowpc += baseaddr; + highpc += baseaddr; + + attr = dwarf_attr (die, DW_AT_name); + if (attr) + { + name = DW_STRING (attr); + } + attr = dwarf_attr (die, DW_AT_comp_dir); + if (attr) + { + comp_dir = DW_STRING (attr); + if (comp_dir) + { + /* Irix 6.2 native cc prepends <machine>.: 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 (objfile->ei.entry_point >= lowpc && + objfile->ei.entry_point < highpc) + { + objfile->ei.entry_file_lowpc = lowpc; + objfile->ei.entry_file_highpc = highpc; + } + + attr = dwarf_attr (die, DW_AT_language); + if (attr) + { + set_cu_language (DW_UNSND (attr)); + } + + /* We assume that we're processing GCC output. */ + processing_gcc_compilation = 2; +#if 0 + /* FIXME:Do something here. */ + if (dip->at_producer != NULL) + { + handle_producer (dip->at_producer); + } +#endif + + /* The compilation unit may be in a different language or objfile, + zero out all remembered fundamental types. */ + memset (ftypes, 0, FT_NUM_MEMBERS * sizeof (struct type *)); + + start_symtab (name, comp_dir, lowpc); + record_debugformat ("DWARF 2"); + + initialize_cu_func_list (); + + /* Process all dies in compilation unit. */ + if (die->has_children) + { + child_die = die->next; + while (child_die && child_die->tag) + { + process_die (child_die, objfile, cu_header); + child_die = sibling_die (child_die); + } + } + + /* Decode line number information if present. */ + attr = dwarf_attr (die, DW_AT_stmt_list); + if (attr) + { + unsigned int line_offset = DW_UNSND (attr); + line_header = dwarf_decode_line_header (line_offset, + abfd, cu_header); + if (line_header) + { + make_cleanup ((make_cleanup_ftype *) free_line_header, + (void *) line_header); + dwarf_decode_lines (line_header, comp_dir, abfd, cu_header); + } + } + + /* Decode macro information, if present. Dwarf 2 macro information + refers to information in the line number info statement program + header, so we can only read it if we've read the header + successfully. */ + attr = dwarf_attr (die, DW_AT_macro_info); + if (attr && line_header) + { + unsigned int macro_offset = DW_UNSND (attr); + dwarf_decode_macros (line_header, macro_offset, + comp_dir, abfd, cu_header, objfile); + } + do_cleanups (back_to); +} + +static void +add_to_cu_func_list (const char *name, CORE_ADDR lowpc, CORE_ADDR highpc) +{ + struct function_range *thisfn; + + thisfn = (struct function_range *) + obstack_alloc (&dwarf2_tmp_obstack, sizeof (struct function_range)); + thisfn->name = name; + thisfn->lowpc = lowpc; + thisfn->highpc = highpc; + thisfn->seen_line = 0; + thisfn->next = NULL; + + if (cu_last_fn == NULL) + cu_first_fn = thisfn; + else + cu_last_fn->next = thisfn; + + cu_last_fn = thisfn; +} + +static void +read_func_scope (struct die_info *die, struct objfile *objfile, + const struct comp_unit_head *cu_header) +{ + register struct context_stack *new; + CORE_ADDR lowpc; + CORE_ADDR highpc; + struct die_info *child_die; + struct attribute *attr; + char *name; + + name = dwarf2_linkage_name (die); + + /* Ignore functions with missing or empty names and functions with + missing or invalid low and high pc attributes. */ + if (name == NULL || !dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile)) + return; + + lowpc += baseaddr; + highpc += baseaddr; + + /* Record the function range for dwarf_decode_lines. */ + add_to_cu_func_list (name, lowpc, highpc); + + if (objfile->ei.entry_point >= lowpc && + objfile->ei.entry_point < highpc) + { + objfile->ei.entry_func_lowpc = lowpc; + objfile->ei.entry_func_highpc = highpc; + } + + /* Decode DW_AT_frame_base location descriptor if present, keep result + for DW_OP_fbreg operands in decode_locdesc. */ + frame_base_reg = -1; + frame_base_offset = 0; + attr = dwarf_attr (die, DW_AT_frame_base); + if (attr) + { + CORE_ADDR addr; + + /* Support the .debug_loc offsets */ + if (attr_form_is_block (attr)) + { + addr = decode_locdesc (DW_BLOCK (attr), objfile, cu_header); + } + else if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8) + { + complain (&dwarf2_complex_location_expr); + addr = 0; + } + else + { + complain (&dwarf2_invalid_attrib_class, "DW_AT_frame_base", name); + addr = 0; + } + + if (isderef) + complain (&dwarf2_unsupported_at_frame_base, name); + else if (isreg) + frame_base_reg = addr; + else if (offreg) + { + frame_base_reg = basereg; + frame_base_offset = addr; + } + else + complain (&dwarf2_unsupported_at_frame_base, name); + } + + new = push_context (0, lowpc); + new->name = new_symbol (die, die->type, objfile, cu_header); + list_in_scope = &local_symbols; + + if (die->has_children) + { + child_die = die->next; + while (child_die && child_die->tag) + { + process_die (child_die, objfile, cu_header); + child_die = sibling_die (child_die); + } + } + + new = pop_context (); + /* Make a block for the local symbols within. */ + finish_block (new->name, &local_symbols, new->old_blocks, + lowpc, highpc, objfile); + list_in_scope = &file_symbols; +} + +/* Process all the DIES contained within a lexical block scope. Start + a new scope, process the dies, and then close the scope. */ + +static void +read_lexical_block_scope (struct die_info *die, struct objfile *objfile, + const struct comp_unit_head *cu_header) +{ + register struct context_stack *new; + CORE_ADDR lowpc, highpc; + struct die_info *child_die; + + /* Ignore blocks with missing or invalid low and high pc attributes. */ + if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile)) + return; + lowpc += baseaddr; + highpc += baseaddr; + + push_context (0, lowpc); + if (die->has_children) + { + child_die = die->next; + while (child_die && child_die->tag) + { + process_die (child_die, objfile, cu_header); + child_die = sibling_die (child_die); + } + } + new = pop_context (); + + if (local_symbols != NULL) + { + finish_block (0, &local_symbols, new->old_blocks, new->start_addr, + highpc, objfile); + } + local_symbols = new->locals; +} + +/* Get low and high pc attributes from a die. + Return 1 if the attributes are present and valid, otherwise, return 0. */ + +static int +dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, CORE_ADDR *highpc, + struct objfile *objfile) +{ + struct attribute *attr; + CORE_ADDR low; + CORE_ADDR high; + + attr = dwarf_attr (die, DW_AT_low_pc); + if (attr) + low = DW_ADDR (attr); + else + return 0; + attr = dwarf_attr (die, DW_AT_high_pc); + if (attr) + high = DW_ADDR (attr); + else + return 0; + + if (high < low) + return 0; + + /* When using the GNU linker, .gnu.linkonce. sections are used to + eliminate duplicate copies of functions and vtables and such. + The linker will arbitrarily choose one and discard the others. + The AT_*_pc values for such functions refer to local labels in + these sections. If the section from that file was discarded, the + labels are not in the output, so the relocs get a value of 0. + If this is a discarded function, mark the pc bounds as invalid, + so that GDB will ignore it. */ + if (low == 0 && (bfd_get_file_flags (objfile->obfd) & HAS_RELOC) == 0) + return 0; + + *lowpc = low; + *highpc = high; + return 1; +} + +/* Add an aggregate field to the field list. */ + +static void +dwarf2_add_field (struct field_info *fip, struct die_info *die, + struct objfile *objfile, + const struct comp_unit_head *cu_header) +{ + struct nextfield *new_field; + struct attribute *attr; + struct field *fp; + char *fieldname = ""; + + /* Allocate a new field list entry and link it in. */ + new_field = (struct nextfield *) xmalloc (sizeof (struct nextfield)); + make_cleanup (xfree, new_field); + memset (new_field, 0, sizeof (struct nextfield)); + new_field->next = fip->fields; + fip->fields = new_field; + fip->nfields++; + + /* Handle accessibility and virtuality of field. + The default accessibility for members is public, the default + accessibility for inheritance is private. */ + if (die->tag != DW_TAG_inheritance) + new_field->accessibility = DW_ACCESS_public; + else + new_field->accessibility = DW_ACCESS_private; + new_field->virtuality = DW_VIRTUALITY_none; + + attr = dwarf_attr (die, DW_AT_accessibility); + if (attr) + new_field->accessibility = DW_UNSND (attr); + if (new_field->accessibility != DW_ACCESS_public) + fip->non_public_fields = 1; + attr = dwarf_attr (die, DW_AT_virtuality); + if (attr) + new_field->virtuality = DW_UNSND (attr); + + fp = &new_field->field; + if (die->tag == DW_TAG_member) + { + /* Get type of field. */ + fp->type = die_type (die, objfile, cu_header); + + /* Get bit size of field (zero if none). */ + attr = dwarf_attr (die, DW_AT_bit_size); + if (attr) + { + FIELD_BITSIZE (*fp) = DW_UNSND (attr); + } + else + { + FIELD_BITSIZE (*fp) = 0; + } + + /* Get bit offset of field. */ + attr = dwarf_attr (die, DW_AT_data_member_location); + if (attr) + { + FIELD_BITPOS (*fp) = + decode_locdesc (DW_BLOCK (attr), objfile, cu_header) * bits_per_byte; + } + else + FIELD_BITPOS (*fp) = 0; + attr = dwarf_attr (die, DW_AT_bit_offset); + if (attr) + { + if (BITS_BIG_ENDIAN) + { + /* For big endian bits, the DW_AT_bit_offset gives the + additional bit offset from the MSB of the containing + anonymous object to the MSB of the field. We don't + have to do anything special since we don't need to + know the size of the anonymous object. */ + FIELD_BITPOS (*fp) += DW_UNSND (attr); + } + else + { + /* For little endian bits, compute the bit offset to the + MSB of the anonymous object, subtract off the number of + bits from the MSB of the field to the MSB of the + object, and then subtract off the number of bits of + the field itself. The result is the bit offset of + the LSB of the field. */ + int anonymous_size; + int bit_offset = DW_UNSND (attr); + + attr = dwarf_attr (die, DW_AT_byte_size); + if (attr) + { + /* The size of the anonymous object containing + the bit field is explicit, so use the + indicated size (in bytes). */ + anonymous_size = DW_UNSND (attr); + } + else + { + /* The size of the anonymous object containing + the bit field must be inferred from the type + attribute of the data member containing the + bit field. */ + anonymous_size = TYPE_LENGTH (fp->type); + } + FIELD_BITPOS (*fp) += anonymous_size * bits_per_byte + - bit_offset - FIELD_BITSIZE (*fp); + } + } + + /* Get name of field. */ + attr = dwarf_attr (die, DW_AT_name); + if (attr && DW_STRING (attr)) + fieldname = DW_STRING (attr); + fp->name = obsavestring (fieldname, strlen (fieldname), + &objfile->type_obstack); + + /* Change accessibility for artificial fields (e.g. virtual table + pointer or virtual base class pointer) to private. */ + if (dwarf_attr (die, DW_AT_artificial)) + { + new_field->accessibility = DW_ACCESS_private; + fip->non_public_fields = 1; + } + } + else if (die->tag == DW_TAG_variable) + { + char *physname; + + /* C++ static member. + Get name of field. */ + attr = dwarf_attr (die, DW_AT_name); + if (attr && DW_STRING (attr)) + fieldname = DW_STRING (attr); + else + return; + + /* Get physical name. */ + physname = dwarf2_linkage_name (die); + + SET_FIELD_PHYSNAME (*fp, obsavestring (physname, strlen (physname), + &objfile->type_obstack)); + FIELD_TYPE (*fp) = die_type (die, objfile, cu_header); + FIELD_NAME (*fp) = obsavestring (fieldname, strlen (fieldname), + &objfile->type_obstack); + } + else if (die->tag == DW_TAG_inheritance) + { + /* C++ base class field. */ + attr = dwarf_attr (die, DW_AT_data_member_location); + if (attr) + FIELD_BITPOS (*fp) = (decode_locdesc (DW_BLOCK (attr), objfile, cu_header) + * bits_per_byte); + FIELD_BITSIZE (*fp) = 0; + FIELD_TYPE (*fp) = die_type (die, objfile, cu_header); + FIELD_NAME (*fp) = type_name_no_tag (fp->type); + fip->nbaseclasses++; + } +} + +/* Create the vector of fields, and attach it to the type. */ + +static void +dwarf2_attach_fields_to_type (struct field_info *fip, struct type *type, + struct objfile *objfile) +{ + int nfields = fip->nfields; + + /* Record the field count, allocate space for the array of fields, + and create blank accessibility bitfields if necessary. */ + TYPE_NFIELDS (type) = nfields; + TYPE_FIELDS (type) = (struct field *) + TYPE_ALLOC (type, sizeof (struct field) * nfields); + memset (TYPE_FIELDS (type), 0, sizeof (struct field) * nfields); + + if (fip->non_public_fields) + { + ALLOCATE_CPLUS_STRUCT_TYPE (type); + + TYPE_FIELD_PRIVATE_BITS (type) = + (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields)); + B_CLRALL (TYPE_FIELD_PRIVATE_BITS (type), nfields); + + TYPE_FIELD_PROTECTED_BITS (type) = + (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields)); + B_CLRALL (TYPE_FIELD_PROTECTED_BITS (type), nfields); + + TYPE_FIELD_IGNORE_BITS (type) = + (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields)); + B_CLRALL (TYPE_FIELD_IGNORE_BITS (type), nfields); + } + + /* If the type has baseclasses, allocate and clear a bit vector for + TYPE_FIELD_VIRTUAL_BITS. */ + if (fip->nbaseclasses) + { + int num_bytes = B_BYTES (fip->nbaseclasses); + char *pointer; + + ALLOCATE_CPLUS_STRUCT_TYPE (type); + pointer = (char *) TYPE_ALLOC (type, num_bytes); + TYPE_FIELD_VIRTUAL_BITS (type) = (B_TYPE *) pointer; + B_CLRALL (TYPE_FIELD_VIRTUAL_BITS (type), fip->nbaseclasses); + TYPE_N_BASECLASSES (type) = fip->nbaseclasses; + } + + /* Copy the saved-up fields into the field vector. Start from the head + of the list, adding to the tail of the field array, so that they end + up in the same order in the array in which they were added to the list. */ + while (nfields-- > 0) + { + TYPE_FIELD (type, nfields) = fip->fields->field; + switch (fip->fields->accessibility) + { + case DW_ACCESS_private: + SET_TYPE_FIELD_PRIVATE (type, nfields); + break; + + case DW_ACCESS_protected: + SET_TYPE_FIELD_PROTECTED (type, nfields); + break; + + case DW_ACCESS_public: + break; + + default: + /* Unknown accessibility. Complain and treat it as public. */ + { + complain (&dwarf2_unsupported_accessibility, + fip->fields->accessibility); + } + break; + } + if (nfields < fip->nbaseclasses) + { + switch (fip->fields->virtuality) + { + case DW_VIRTUALITY_virtual: + case DW_VIRTUALITY_pure_virtual: + SET_TYPE_FIELD_VIRTUAL (type, nfields); + break; + } + } + fip->fields = fip->fields->next; + } +} + +/* Add a member function to the proper fieldlist. */ + +static void +dwarf2_add_member_fn (struct field_info *fip, struct die_info *die, + struct type *type, struct objfile *objfile, + const struct comp_unit_head *cu_header) +{ + struct attribute *attr; + struct fnfieldlist *flp; + int i; + struct fn_field *fnp; + char *fieldname; + char *physname; + struct nextfnfield *new_fnfield; + + /* Get name of member function. */ + attr = dwarf_attr (die, DW_AT_name); + if (attr && DW_STRING (attr)) + fieldname = DW_STRING (attr); + else + return; + + /* Get the mangled name. */ + physname = dwarf2_linkage_name (die); + + /* Look up member function name in fieldlist. */ + for (i = 0; i < fip->nfnfields; i++) + { + if (STREQ (fip->fnfieldlists[i].name, fieldname)) + break; + } + + /* Create new list element if necessary. */ + if (i < fip->nfnfields) + flp = &fip->fnfieldlists[i]; + else + { + if ((fip->nfnfields % DW_FIELD_ALLOC_CHUNK) == 0) + { + fip->fnfieldlists = (struct fnfieldlist *) + xrealloc (fip->fnfieldlists, + (fip->nfnfields + DW_FIELD_ALLOC_CHUNK) + * sizeof (struct fnfieldlist)); + if (fip->nfnfields == 0) + make_cleanup (free_current_contents, &fip->fnfieldlists); + } + flp = &fip->fnfieldlists[fip->nfnfields]; + flp->name = fieldname; + flp->length = 0; + flp->head = NULL; + fip->nfnfields++; + } + + /* Create a new member function field and chain it to the field list + entry. */ + new_fnfield = (struct nextfnfield *) xmalloc (sizeof (struct nextfnfield)); + make_cleanup (xfree, new_fnfield); + memset (new_fnfield, 0, sizeof (struct nextfnfield)); + new_fnfield->next = flp->head; + flp->head = new_fnfield; + flp->length++; + + /* Fill in the member function field info. */ + fnp = &new_fnfield->fnfield; + fnp->physname = obsavestring (physname, strlen (physname), + &objfile->type_obstack); + fnp->type = alloc_type (objfile); + if (die->type && TYPE_CODE (die->type) == TYPE_CODE_FUNC) + { + struct type *return_type = TYPE_TARGET_TYPE (die->type); + int nparams = TYPE_NFIELDS (die->type); + + /* TYPE is the domain of this method, and DIE->TYPE is the type + of the method itself (TYPE_CODE_METHOD). */ + smash_to_method_type (fnp->type, type, + TYPE_TARGET_TYPE (die->type), + TYPE_FIELDS (die->type), + TYPE_NFIELDS (die->type), + TYPE_VARARGS (die->type)); + + /* Handle static member functions. + Dwarf2 has no clean way to discern C++ static and non-static + member functions. G++ helps GDB by marking the first + parameter for non-static member functions (which is the + this pointer) as artificial. We obtain this information + from read_subroutine_type via TYPE_FIELD_ARTIFICIAL. */ + if (nparams == 0 || TYPE_FIELD_ARTIFICIAL (die->type, 0) == 0) + fnp->voffset = VOFFSET_STATIC; + } + else + complain (&dwarf2_missing_member_fn_type_complaint, physname); + + /* Get fcontext from DW_AT_containing_type if present. */ + if (dwarf_attr (die, DW_AT_containing_type) != NULL) + fnp->fcontext = die_containing_type (die, objfile, cu_header); + + /* dwarf2 doesn't have stubbed physical names, so the setting of is_const + and is_volatile is irrelevant, as it is needed by gdb_mangle_name only. */ + + /* Get accessibility. */ + attr = dwarf_attr (die, DW_AT_accessibility); + if (attr) + { + switch (DW_UNSND (attr)) + { + case DW_ACCESS_private: + fnp->is_private = 1; + break; + case DW_ACCESS_protected: + fnp->is_protected = 1; + break; + } + } + + /* Check for artificial methods. */ + attr = dwarf_attr (die, DW_AT_artificial); + if (attr && DW_UNSND (attr) != 0) + fnp->is_artificial = 1; + + /* Get index in virtual function table if it is a virtual member function. */ + attr = dwarf_attr (die, DW_AT_vtable_elem_location); + if (attr) + { + /* Support the .debug_loc offsets */ + if (attr_form_is_block (attr)) + { + fnp->voffset = decode_locdesc (DW_BLOCK (attr), objfile, cu_header) + 2; + } + else if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8) + { + complain (&dwarf2_complex_location_expr); + } + else + { + complain (&dwarf2_invalid_attrib_class, "DW_AT_vtable_elem_location", + fieldname); + } + } +} + +/* Create the vector of member function fields, and attach it to the type. */ + +static void +dwarf2_attach_fn_fields_to_type (struct field_info *fip, struct type *type, + struct objfile *objfile) +{ + struct fnfieldlist *flp; + int total_length = 0; + int i; + + ALLOCATE_CPLUS_STRUCT_TYPE (type); + TYPE_FN_FIELDLISTS (type) = (struct fn_fieldlist *) + TYPE_ALLOC (type, sizeof (struct fn_fieldlist) * fip->nfnfields); + + for (i = 0, flp = fip->fnfieldlists; i < fip->nfnfields; i++, flp++) + { + struct nextfnfield *nfp = flp->head; + struct fn_fieldlist *fn_flp = &TYPE_FN_FIELDLIST (type, i); + int k; + + TYPE_FN_FIELDLIST_NAME (type, i) = flp->name; + TYPE_FN_FIELDLIST_LENGTH (type, i) = flp->length; + fn_flp->fn_fields = (struct fn_field *) + TYPE_ALLOC (type, sizeof (struct fn_field) * flp->length); + for (k = flp->length; (k--, nfp); nfp = nfp->next) + fn_flp->fn_fields[k] = nfp->fnfield; + + total_length += flp->length; + } + + TYPE_NFN_FIELDS (type) = fip->nfnfields; + TYPE_NFN_FIELDS_TOTAL (type) = total_length; +} + +/* Called when we find the DIE that starts a structure or union scope + (definition) to process all dies that define the members of the + structure or union. + + NOTE: we need to call struct_type regardless of whether or not the + DIE has an at_name attribute, since it might be an anonymous + structure or union. This gets the type entered into our set of + user defined types. + + However, if the structure is incomplete (an opaque struct/union) + then suppress creating a symbol table entry for it since gdb only + wants to find the one with the complete definition. Note that if + it is complete, we just call new_symbol, which does it's own + checking about whether the struct/union is anonymous or not (and + suppresses creating a symbol table entry itself). */ + +static void +read_structure_scope (struct die_info *die, struct objfile *objfile, + const struct comp_unit_head *cu_header) +{ + struct type *type; + struct attribute *attr; + + type = alloc_type (objfile); + + INIT_CPLUS_SPECIFIC (type); + attr = dwarf_attr (die, DW_AT_name); + if (attr && DW_STRING (attr)) + { + TYPE_TAG_NAME (type) = obsavestring (DW_STRING (attr), + strlen (DW_STRING (attr)), + &objfile->type_obstack); + } + + if (die->tag == DW_TAG_structure_type) + { + TYPE_CODE (type) = TYPE_CODE_STRUCT; + } + else if (die->tag == DW_TAG_union_type) + { + TYPE_CODE (type) = TYPE_CODE_UNION; + } + else + { + /* FIXME: TYPE_CODE_CLASS is currently defined to TYPE_CODE_STRUCT + in gdbtypes.h. */ + TYPE_CODE (type) = TYPE_CODE_CLASS; + } + + attr = dwarf_attr (die, DW_AT_byte_size); + if (attr) + { + TYPE_LENGTH (type) = DW_UNSND (attr); + } + else + { + TYPE_LENGTH (type) = 0; + } + + /* We need to add the type field to the die immediately so we don't + infinitely recurse when dealing with pointers to the structure + type within the structure itself. */ + die->type = type; + + if (die->has_children && ! die_is_declaration (die)) + { + struct field_info fi; + struct die_info *child_die; + struct cleanup *back_to = make_cleanup (null_cleanup, NULL); + + memset (&fi, 0, sizeof (struct field_info)); + + child_die = die->next; + + while (child_die && child_die->tag) + { + if (child_die->tag == DW_TAG_member) + { + dwarf2_add_field (&fi, child_die, objfile, cu_header); + } + else if (child_die->tag == DW_TAG_variable) + { + /* C++ static member. */ + dwarf2_add_field (&fi, child_die, objfile, cu_header); + } + else if (child_die->tag == DW_TAG_subprogram) + { + /* C++ member function. */ + process_die (child_die, objfile, cu_header); + dwarf2_add_member_fn (&fi, child_die, type, objfile, cu_header); + } + else if (child_die->tag == DW_TAG_inheritance) + { + /* C++ base class field. */ + dwarf2_add_field (&fi, child_die, objfile, cu_header); + } + else + { + process_die (child_die, objfile, cu_header); + } + child_die = sibling_die (child_die); + } + + /* Attach fields and member functions to the type. */ + if (fi.nfields) + dwarf2_attach_fields_to_type (&fi, type, objfile); + if (fi.nfnfields) + { + dwarf2_attach_fn_fields_to_type (&fi, type, objfile); + + /* Get the type which refers to the base class (possibly this + class itself) which contains the vtable pointer for the current + class from the DW_AT_containing_type attribute. */ + + if (dwarf_attr (die, DW_AT_containing_type) != NULL) + { + struct type *t = die_containing_type (die, objfile, cu_header); + + TYPE_VPTR_BASETYPE (type) = t; + if (type == t) + { + static const char vptr_name[] = + {'_', 'v', 'p', 't', 'r', '\0'}; + int i; + + /* Our own class provides vtbl ptr. */ + for (i = TYPE_NFIELDS (t) - 1; + i >= TYPE_N_BASECLASSES (t); + --i) + { + char *fieldname = TYPE_FIELD_NAME (t, i); + + if (STREQN (fieldname, vptr_name, strlen (vptr_name) - 1) + && is_cplus_marker (fieldname[strlen (vptr_name)])) + { + TYPE_VPTR_FIELDNO (type) = i; + break; + } + } + + /* Complain if virtual function table field not found. */ + if (i < TYPE_N_BASECLASSES (t)) + complain (&dwarf2_vtbl_not_found_complaint, + TYPE_TAG_NAME (type) ? TYPE_TAG_NAME (type) : ""); + } + else + { + TYPE_VPTR_FIELDNO (type) = TYPE_VPTR_FIELDNO (t); + } + } + } + + new_symbol (die, type, objfile, cu_header); + + do_cleanups (back_to); + } + else + { + /* No children, must be stub. */ + TYPE_FLAGS (type) |= TYPE_FLAG_STUB; + } +} + +/* Given a pointer to a die which begins an enumeration, process all + the dies that define the members of the enumeration. + + This will be much nicer in draft 6 of the DWARF spec when our + members will be dies instead squished into the DW_AT_element_list + attribute. + + NOTE: We reverse the order of the element list. */ + +static void +read_enumeration (struct die_info *die, struct objfile *objfile, + const struct comp_unit_head *cu_header) +{ + struct die_info *child_die; + struct type *type; + struct field *fields; + struct attribute *attr; + struct symbol *sym; + int num_fields; + int unsigned_enum = 1; + + type = alloc_type (objfile); + + TYPE_CODE (type) = TYPE_CODE_ENUM; + attr = dwarf_attr (die, DW_AT_name); + if (attr && DW_STRING (attr)) + { + TYPE_TAG_NAME (type) = obsavestring (DW_STRING (attr), + strlen (DW_STRING (attr)), + &objfile->type_obstack); + } + + attr = dwarf_attr (die, DW_AT_byte_size); + if (attr) + { + TYPE_LENGTH (type) = DW_UNSND (attr); + } + else + { + TYPE_LENGTH (type) = 0; + } + + num_fields = 0; + fields = NULL; + if (die->has_children) + { + child_die = die->next; + while (child_die && child_die->tag) + { + if (child_die->tag != DW_TAG_enumerator) + { + process_die (child_die, objfile, cu_header); + } + else + { + attr = dwarf_attr (child_die, DW_AT_name); + if (attr) + { + sym = new_symbol (child_die, type, objfile, cu_header); + if (SYMBOL_VALUE (sym) < 0) + unsigned_enum = 0; + + if ((num_fields % DW_FIELD_ALLOC_CHUNK) == 0) + { + fields = (struct field *) + xrealloc (fields, + (num_fields + DW_FIELD_ALLOC_CHUNK) + * sizeof (struct field)); + } + + FIELD_NAME (fields[num_fields]) = SYMBOL_NAME (sym); + FIELD_TYPE (fields[num_fields]) = NULL; + FIELD_BITPOS (fields[num_fields]) = SYMBOL_VALUE (sym); + FIELD_BITSIZE (fields[num_fields]) = 0; + + num_fields++; + } + } + + child_die = sibling_die (child_die); + } + + if (num_fields) + { + TYPE_NFIELDS (type) = num_fields; + TYPE_FIELDS (type) = (struct field *) + TYPE_ALLOC (type, sizeof (struct field) * num_fields); + memcpy (TYPE_FIELDS (type), fields, + sizeof (struct field) * num_fields); + xfree (fields); + } + if (unsigned_enum) + TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED; + } + die->type = type; + new_symbol (die, type, objfile, cu_header); +} + +/* 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. */ + +static void +read_array_type (struct die_info *die, struct objfile *objfile, + const struct comp_unit_head *cu_header) +{ + struct die_info *child_die; + struct type *type = NULL; + struct type *element_type, *range_type, *index_type; + struct type **range_types = NULL; + struct attribute *attr; + int ndim = 0; + struct cleanup *back_to; + + /* Return if we've already decoded this type. */ + if (die->type) + { + return; + } + + element_type = die_type (die, objfile, cu_header); + + /* Irix 6.2 native cc creates array types without children for + arrays with unspecified length. */ + if (die->has_children == 0) + { + index_type = dwarf2_fundamental_type (objfile, FT_INTEGER); + range_type = create_range_type (NULL, index_type, 0, -1); + die->type = create_array_type (NULL, element_type, range_type); + return; + } + + back_to = make_cleanup (null_cleanup, NULL); + child_die = die->next; + while (child_die && child_die->tag) + { + if (child_die->tag == DW_TAG_subrange_type) + { + unsigned int low, high; + + /* Default bounds to an array with unspecified length. */ + low = 0; + high = -1; + if (cu_language == language_fortran) + { + /* FORTRAN implies a lower bound of 1, if not given. */ + low = 1; + } + + index_type = die_type (child_die, objfile, cu_header); + attr = dwarf_attr (child_die, DW_AT_lower_bound); + if (attr) + { + if (attr->form == DW_FORM_sdata) + { + low = DW_SND (attr); + } + else if (attr->form == DW_FORM_udata + || attr->form == DW_FORM_data1 + || attr->form == DW_FORM_data2 + || attr->form == DW_FORM_data4 + || attr->form == DW_FORM_data8) + { + low = DW_UNSND (attr); + } + else + { + complain (&dwarf2_non_const_array_bound_ignored, + dwarf_form_name (attr->form)); +#ifdef FORTRAN_HACK + die->type = lookup_pointer_type (element_type); + return; +#else + low = 0; +#endif + } + } + attr = dwarf_attr (child_die, DW_AT_upper_bound); + if (attr) + { + if (attr->form == DW_FORM_sdata) + { + high = DW_SND (attr); + } + else if (attr->form == DW_FORM_udata + || attr->form == DW_FORM_data1 + || attr->form == DW_FORM_data2 + || attr->form == DW_FORM_data4 + || attr->form == DW_FORM_data8) + { + high = DW_UNSND (attr); + } + else if (attr->form == DW_FORM_block1) + { + /* GCC encodes arrays with unspecified or dynamic length + with a DW_FORM_block1 attribute. + FIXME: GDB does not yet know how to handle dynamic + arrays properly, treat them as arrays with unspecified + length for now. */ + high = -1; + } + else + { + complain (&dwarf2_non_const_array_bound_ignored, + dwarf_form_name (attr->form)); +#ifdef FORTRAN_HACK + die->type = lookup_pointer_type (element_type); + return; +#else + high = 1; +#endif + } + } + + /* Create a range type and save it for array type creation. */ + if ((ndim % DW_FIELD_ALLOC_CHUNK) == 0) + { + range_types = (struct type **) + xrealloc (range_types, (ndim + DW_FIELD_ALLOC_CHUNK) + * sizeof (struct type *)); + if (ndim == 0) + make_cleanup (free_current_contents, &range_types); + } + range_types[ndim++] = create_range_type (NULL, index_type, low, high); + } + child_die = sibling_die (child_die); + } + + /* Dwarf2 dimensions are output from left to right, create the + necessary array types in backwards order. */ + type = element_type; + while (ndim-- > 0) + type = create_array_type (NULL, type, range_types[ndim]); + + /* Understand Dwarf2 support for vector types (like they occur on + the PowerPC w/ AltiVec). Gcc just adds another attribute to the + array type. This is not part of the Dwarf2/3 standard yet, but a + custom vendor extension. The main difference between a regular + array and the vector variant is that vectors are passed by value + to functions. */ + attr = dwarf_attr (die, DW_AT_GNU_vector); + if (attr) + TYPE_FLAGS (type) |= TYPE_FLAG_VECTOR; + + do_cleanups (back_to); + + /* Install the type in the die. */ + die->type = type; +} + +/* First cut: install each common block member as a global variable. */ + +static void +read_common_block (struct die_info *die, struct objfile *objfile, + const struct comp_unit_head *cu_header) +{ + struct die_info *child_die; + struct attribute *attr; + struct symbol *sym; + CORE_ADDR base = (CORE_ADDR) 0; + + attr = dwarf_attr (die, DW_AT_location); + if (attr) + { + /* Support the .debug_loc offsets */ + if (attr_form_is_block (attr)) + { + base = decode_locdesc (DW_BLOCK (attr), objfile, cu_header); + } + else if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8) + { + complain (&dwarf2_complex_location_expr); + } + else + { + complain (&dwarf2_invalid_attrib_class, "DW_AT_location", + "common block member"); + } + } + if (die->has_children) + { + child_die = die->next; + while (child_die && child_die->tag) + { + sym = new_symbol (child_die, NULL, objfile, cu_header); + attr = dwarf_attr (child_die, DW_AT_data_member_location); + if (attr) + { + SYMBOL_VALUE_ADDRESS (sym) = + base + decode_locdesc (DW_BLOCK (attr), objfile, cu_header); + add_symbol_to_list (sym, &global_symbols); + } + child_die = sibling_die (child_die); + } + } +} + +/* Extract all information from a DW_TAG_pointer_type DIE and add to + the user defined type vector. */ + +static void +read_tag_pointer_type (struct die_info *die, struct objfile *objfile, + const struct comp_unit_head *cu_header) +{ + struct type *type; + struct attribute *attr; + + if (die->type) + { + return; + } + + type = lookup_pointer_type (die_type (die, objfile, cu_header)); + attr = dwarf_attr (die, DW_AT_byte_size); + if (attr) + { + TYPE_LENGTH (type) = DW_UNSND (attr); + } + else + { + TYPE_LENGTH (type) = cu_header->addr_size; + } + die->type = type; +} + +/* Extract all information from a DW_TAG_ptr_to_member_type DIE and add to + the user defined type vector. */ + +static void +read_tag_ptr_to_member_type (struct die_info *die, struct objfile *objfile, + const struct comp_unit_head *cu_header) +{ + struct type *type; + struct type *to_type; + struct type *domain; + + if (die->type) + { + return; + } + + type = alloc_type (objfile); + to_type = die_type (die, objfile, cu_header); + domain = die_containing_type (die, objfile, cu_header); + smash_to_member_type (type, domain, to_type); + + die->type = type; +} + +/* Extract all information from a DW_TAG_reference_type DIE and add to + the user defined type vector. */ + +static void +read_tag_reference_type (struct die_info *die, struct objfile *objfile, + const struct comp_unit_head *cu_header) +{ + struct type *type; + struct attribute *attr; + + if (die->type) + { + return; + } + + type = lookup_reference_type (die_type (die, objfile, cu_header)); + attr = dwarf_attr (die, DW_AT_byte_size); + if (attr) + { + TYPE_LENGTH (type) = DW_UNSND (attr); + } + else + { + TYPE_LENGTH (type) = cu_header->addr_size; + } + die->type = type; +} + +static void +read_tag_const_type (struct die_info *die, struct objfile *objfile, + const struct comp_unit_head *cu_header) +{ + struct type *base_type; + + if (die->type) + { + return; + } + + base_type = die_type (die, objfile, cu_header); + die->type = make_cv_type (1, TYPE_VOLATILE (base_type), base_type, 0); +} + +static void +read_tag_volatile_type (struct die_info *die, struct objfile *objfile, + const struct comp_unit_head *cu_header) +{ + struct type *base_type; + + if (die->type) + { + return; + } + + base_type = die_type (die, objfile, cu_header); + die->type = make_cv_type (TYPE_CONST (base_type), 1, base_type, 0); +} + +/* Extract all information from a DW_TAG_string_type DIE and add to + the user defined type vector. It isn't really a user defined type, + but it behaves like one, with other DIE's using an AT_user_def_type + attribute to reference it. */ + +static void +read_tag_string_type (struct die_info *die, struct objfile *objfile) +{ + struct type *type, *range_type, *index_type, *char_type; + struct attribute *attr; + unsigned int length; + + if (die->type) + { + return; + } + + attr = dwarf_attr (die, DW_AT_string_length); + if (attr) + { + length = DW_UNSND (attr); + } + else + { + /* check for the DW_AT_byte_size attribute */ + attr = dwarf_attr (die, DW_AT_byte_size); + if (attr) + { + length = DW_UNSND (attr); + } + else + { + length = 1; + } + } + index_type = dwarf2_fundamental_type (objfile, FT_INTEGER); + range_type = create_range_type (NULL, index_type, 1, length); + if (cu_language == language_fortran) + { + /* Need to create a unique string type for bounds + information */ + type = create_string_type (0, range_type); + } + else + { + char_type = dwarf2_fundamental_type (objfile, FT_CHAR); + type = create_string_type (char_type, range_type); + } + die->type = type; +} + +/* Handle DIES due to C code like: + + struct foo + { + int (*funcp)(int a, long l); + int b; + }; + + ('funcp' generates a DW_TAG_subroutine_type DIE) + */ + +static void +read_subroutine_type (struct die_info *die, struct objfile *objfile, + const struct comp_unit_head *cu_header) +{ + struct type *type; /* Type that this function returns */ + struct type *ftype; /* Function that returns above type */ + struct attribute *attr; + + /* Decode the type that this subroutine returns */ + if (die->type) + { + return; + } + type = die_type (die, objfile, cu_header); + ftype = lookup_function_type (type); + + /* All functions in C++ have prototypes. */ + attr = dwarf_attr (die, DW_AT_prototyped); + if ((attr && (DW_UNSND (attr) != 0)) + || cu_language == language_cplus) + TYPE_FLAGS (ftype) |= TYPE_FLAG_PROTOTYPED; + + if (die->has_children) + { + struct die_info *child_die; + int nparams = 0; + int iparams = 0; + + /* Count the number of parameters. + FIXME: GDB currently ignores vararg functions, but knows about + vararg member functions. */ + child_die = die->next; + while (child_die && child_die->tag) + { + if (child_die->tag == DW_TAG_formal_parameter) + nparams++; + else if (child_die->tag == DW_TAG_unspecified_parameters) + TYPE_FLAGS (ftype) |= TYPE_FLAG_VARARGS; + child_die = sibling_die (child_die); + } + + /* Allocate storage for parameters and fill them in. */ + TYPE_NFIELDS (ftype) = nparams; + TYPE_FIELDS (ftype) = (struct field *) + TYPE_ALLOC (ftype, nparams * sizeof (struct field)); + + child_die = die->next; + while (child_die && child_die->tag) + { + if (child_die->tag == DW_TAG_formal_parameter) + { + /* Dwarf2 has no clean way to discern C++ static and non-static + member functions. G++ helps GDB by marking the first + parameter for non-static member functions (which is the + this pointer) as artificial. We pass this information + to dwarf2_add_member_fn via TYPE_FIELD_ARTIFICIAL. */ + attr = dwarf_attr (child_die, DW_AT_artificial); + if (attr) + TYPE_FIELD_ARTIFICIAL (ftype, iparams) = DW_UNSND (attr); + else + TYPE_FIELD_ARTIFICIAL (ftype, iparams) = 0; + TYPE_FIELD_TYPE (ftype, iparams) = die_type (child_die, objfile, + cu_header); + iparams++; + } + child_die = sibling_die (child_die); + } + } + + die->type = ftype; +} + +static void +read_typedef (struct die_info *die, struct objfile *objfile, + const struct comp_unit_head *cu_header) +{ + struct attribute *attr; + char *name = NULL; + + if (!die->type) + { + attr = dwarf_attr (die, DW_AT_name); + if (attr && DW_STRING (attr)) + { + name = DW_STRING (attr); + } + die->type = init_type (TYPE_CODE_TYPEDEF, 0, TYPE_FLAG_TARGET_STUB, name, objfile); + TYPE_TARGET_TYPE (die->type) = die_type (die, objfile, cu_header); + } +} + +/* Find a representation of a given base type and install + it in the TYPE field of the die. */ + +static void +read_base_type (struct die_info *die, struct objfile *objfile) +{ + struct type *type; + struct attribute *attr; + int encoding = 0, size = 0; + + /* If we've already decoded this die, this is a no-op. */ + if (die->type) + { + return; + } + + attr = dwarf_attr (die, DW_AT_encoding); + if (attr) + { + encoding = DW_UNSND (attr); + } + attr = dwarf_attr (die, DW_AT_byte_size); + if (attr) + { + size = DW_UNSND (attr); + } + attr = dwarf_attr (die, DW_AT_name); + if (attr && DW_STRING (attr)) + { + enum type_code code = TYPE_CODE_INT; + int type_flags = 0; + + switch (encoding) + { + case DW_ATE_address: + /* Turn DW_ATE_address into a void * pointer. */ + code = TYPE_CODE_PTR; + type_flags |= TYPE_FLAG_UNSIGNED; + break; + case DW_ATE_boolean: + code = TYPE_CODE_BOOL; + type_flags |= TYPE_FLAG_UNSIGNED; + break; + case DW_ATE_complex_float: + code = TYPE_CODE_COMPLEX; + break; + case DW_ATE_float: + code = TYPE_CODE_FLT; + break; + case DW_ATE_signed: + case DW_ATE_signed_char: + break; + case DW_ATE_unsigned: + case DW_ATE_unsigned_char: + type_flags |= TYPE_FLAG_UNSIGNED; + break; + default: + complain (&dwarf2_unsupported_at_encoding, + dwarf_type_encoding_name (encoding)); + break; + } + type = init_type (code, size, type_flags, DW_STRING (attr), objfile); + if (encoding == DW_ATE_address) + TYPE_TARGET_TYPE (type) = dwarf2_fundamental_type (objfile, FT_VOID); + else if (encoding == DW_ATE_complex_float) + { + if (size == 32) + TYPE_TARGET_TYPE (type) + = dwarf2_fundamental_type (objfile, FT_EXT_PREC_FLOAT); + else if (size == 16) + TYPE_TARGET_TYPE (type) + = dwarf2_fundamental_type (objfile, FT_DBL_PREC_FLOAT); + else if (size == 8) + TYPE_TARGET_TYPE (type) + = dwarf2_fundamental_type (objfile, FT_FLOAT); + } + } + else + { + type = dwarf_base_type (encoding, size, objfile); + } + die->type = type; +} + +/* Read a whole compilation unit into a linked list of dies. */ + +static struct die_info * +read_comp_unit (char *info_ptr, bfd *abfd, + const struct comp_unit_head *cu_header) +{ + struct die_info *first_die, *last_die, *die; + char *cur_ptr; + int nesting_level; + + /* Reset die reference table; we are + building new ones now. */ + dwarf2_empty_hash_tables (); + + cur_ptr = info_ptr; + nesting_level = 0; + first_die = last_die = NULL; + do + { + cur_ptr = read_full_die (&die, abfd, cur_ptr, cu_header); + if (die->has_children) + { + nesting_level++; + } + if (die->tag == 0) + { + nesting_level--; + } + + die->next = NULL; + + /* Enter die in reference hash table */ + store_in_ref_table (die->offset, die); + + if (!first_die) + { + first_die = last_die = die; + } + else + { + last_die->next = die; + last_die = die; + } + } + while (nesting_level > 0); + return first_die; +} + +/* Free a linked list of dies. */ + +static void +free_die_list (struct die_info *dies) +{ + struct die_info *die, *next; + + die = dies; + while (die) + { + next = die->next; + xfree (die->attrs); + xfree (die); + die = next; + } +} + +static void +do_free_die_list_cleanup (void *dies) +{ + free_die_list (dies); +} + +static struct cleanup * +make_cleanup_free_die_list (struct die_info *dies) +{ + return make_cleanup (do_free_die_list_cleanup, dies); +} + + +/* Read the contents of the section at OFFSET and of size SIZE from the + object file specified by OBJFILE into the psymbol_obstack and return it. */ + +char * +dwarf2_read_section (struct objfile *objfile, file_ptr offset, + unsigned int size) +{ + bfd *abfd = objfile->obfd; + char *buf; + + if (size == 0) + return NULL; + + buf = (char *) obstack_alloc (&objfile->psymbol_obstack, size); + if ((bfd_seek (abfd, offset, SEEK_SET) != 0) || + (bfd_bread (buf, size, abfd) != size)) + { + buf = NULL; + error ("Dwarf Error: Can't read DWARF data from '%s'", + bfd_get_filename (abfd)); + } + return buf; +} + +/* In DWARF version 2, the description of the debugging information is + stored in a separate .debug_abbrev section. Before we read any + dies from a section we read in all abbreviations and install them + in a hash table. */ + +static void +dwarf2_read_abbrevs (bfd *abfd, unsigned int offset) +{ + char *abbrev_ptr; + struct abbrev_info *cur_abbrev; + unsigned int abbrev_number, bytes_read, abbrev_name; + unsigned int abbrev_form, hash_number; + + /* empty the table */ + dwarf2_empty_abbrev_table (NULL); + + abbrev_ptr = dwarf_abbrev_buffer + offset; + abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read); + abbrev_ptr += bytes_read; + + /* loop until we reach an abbrev number of 0 */ + while (abbrev_number) + { + cur_abbrev = dwarf_alloc_abbrev (); + + /* read in abbrev header */ + cur_abbrev->number = abbrev_number; + cur_abbrev->tag = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read); + abbrev_ptr += bytes_read; + cur_abbrev->has_children = read_1_byte (abfd, abbrev_ptr); + abbrev_ptr += 1; + + /* now read in declarations */ + abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read); + abbrev_ptr += bytes_read; + abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read); + abbrev_ptr += bytes_read; + while (abbrev_name) + { + if ((cur_abbrev->num_attrs % ATTR_ALLOC_CHUNK) == 0) + { + cur_abbrev->attrs = (struct attr_abbrev *) + xrealloc (cur_abbrev->attrs, + (cur_abbrev->num_attrs + ATTR_ALLOC_CHUNK) + * sizeof (struct attr_abbrev)); + } + cur_abbrev->attrs[cur_abbrev->num_attrs].name = abbrev_name; + cur_abbrev->attrs[cur_abbrev->num_attrs++].form = abbrev_form; + abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read); + abbrev_ptr += bytes_read; + abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read); + abbrev_ptr += bytes_read; + } + + hash_number = abbrev_number % ABBREV_HASH_SIZE; + cur_abbrev->next = dwarf2_abbrevs[hash_number]; + dwarf2_abbrevs[hash_number] = cur_abbrev; + + /* Get next abbreviation. + Under Irix6 the abbreviations for a compilation unit are not + always properly terminated with an abbrev number of 0. + Exit loop if we encounter an abbreviation which we have + already read (which means we are about to read the abbreviations + for the next compile unit) or if the end of the abbreviation + table is reached. */ + if ((unsigned int) (abbrev_ptr - dwarf_abbrev_buffer) + >= dwarf_abbrev_size) + break; + abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read); + abbrev_ptr += bytes_read; + if (dwarf2_lookup_abbrev (abbrev_number) != NULL) + break; + } +} + +/* Empty the abbrev table for a new compilation unit. */ + +/* ARGSUSED */ +static void +dwarf2_empty_abbrev_table (PTR ignore) +{ + int i; + struct abbrev_info *abbrev, *next; + + for (i = 0; i < ABBREV_HASH_SIZE; ++i) + { + next = NULL; + abbrev = dwarf2_abbrevs[i]; + while (abbrev) + { + next = abbrev->next; + xfree (abbrev->attrs); + xfree (abbrev); + abbrev = next; + } + dwarf2_abbrevs[i] = NULL; + } +} + +/* Lookup an abbrev_info structure in the abbrev hash table. */ + +static struct abbrev_info * +dwarf2_lookup_abbrev (unsigned int number) +{ + unsigned int hash_number; + struct abbrev_info *abbrev; + + hash_number = number % ABBREV_HASH_SIZE; + abbrev = dwarf2_abbrevs[hash_number]; + + while (abbrev) + { + if (abbrev->number == number) + return abbrev; + else + abbrev = abbrev->next; + } + return NULL; +} + +/* Read a minimal amount of information into the minimal die structure. */ + +static char * +read_partial_die (struct partial_die_info *part_die, bfd *abfd, + char *info_ptr, const struct comp_unit_head *cu_header) +{ + unsigned int abbrev_number, bytes_read, i; + struct abbrev_info *abbrev; + struct attribute attr; + struct attribute spec_attr; + int found_spec_attr = 0; + int has_low_pc_attr = 0; + int has_high_pc_attr = 0; + + *part_die = zeroed_partial_die; + abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read); + info_ptr += bytes_read; + if (!abbrev_number) + return info_ptr; + + abbrev = dwarf2_lookup_abbrev (abbrev_number); + if (!abbrev) + { + error ("Dwarf Error: Could not find abbrev number %d.", abbrev_number); + } + part_die->offset = info_ptr - dwarf_info_buffer; + part_die->tag = abbrev->tag; + part_die->has_children = abbrev->has_children; + part_die->abbrev = abbrev_number; + + for (i = 0; i < abbrev->num_attrs; ++i) + { + info_ptr = read_attribute (&attr, &abbrev->attrs[i], abfd, + info_ptr, cu_header); + + /* Store the data if it is of an attribute we want to keep in a + partial symbol table. */ + switch (attr.name) + { + case DW_AT_name: + + /* Prefer DW_AT_MIPS_linkage_name over DW_AT_name. */ + if (part_die->name == NULL) + part_die->name = DW_STRING (&attr); + break; + case DW_AT_MIPS_linkage_name: + part_die->name = DW_STRING (&attr); + break; + case DW_AT_low_pc: + has_low_pc_attr = 1; + part_die->lowpc = DW_ADDR (&attr); + break; + case DW_AT_high_pc: + has_high_pc_attr = 1; + part_die->highpc = DW_ADDR (&attr); + break; + case DW_AT_location: + /* Support the .debug_loc offsets */ + if (attr_form_is_block (&attr)) + { + part_die->locdesc = DW_BLOCK (&attr); + } + else if (attr.form == DW_FORM_data4 || attr.form == DW_FORM_data8) + { + complain (&dwarf2_complex_location_expr); + } + else + { + complain (&dwarf2_invalid_attrib_class, "DW_AT_location", + "partial symbol information"); + } + break; + case DW_AT_language: + part_die->language = DW_UNSND (&attr); + break; + case DW_AT_external: + part_die->is_external = DW_UNSND (&attr); + break; + case DW_AT_declaration: + part_die->is_declaration = DW_UNSND (&attr); + break; + case DW_AT_type: + part_die->has_type = 1; + break; + case DW_AT_abstract_origin: + case DW_AT_specification: + found_spec_attr = 1; + spec_attr = attr; + break; + case DW_AT_sibling: + /* Ignore absolute siblings, they might point outside of + the current compile unit. */ + if (attr.form == DW_FORM_ref_addr) + complain (&dwarf2_absolute_sibling_complaint); + else + part_die->sibling = + dwarf_info_buffer + dwarf2_get_ref_die_offset (&attr); + break; + default: + break; + } + } + + /* If we found a reference attribute and the die has no name, try + to find a name in the referred to die. */ + + if (found_spec_attr && part_die->name == NULL) + { + struct partial_die_info spec_die; + char *spec_ptr; + int dummy; + + spec_ptr = dwarf_info_buffer + dwarf2_get_ref_die_offset (&spec_attr); + read_partial_die (&spec_die, abfd, spec_ptr, cu_header); + if (spec_die.name) + { + part_die->name = spec_die.name; + + /* Copy DW_AT_external attribute if it is set. */ + if (spec_die.is_external) + part_die->is_external = spec_die.is_external; + } + } + + /* When using the GNU linker, .gnu.linkonce. sections are used to + eliminate duplicate copies of functions and vtables and such. + The linker will arbitrarily choose one and discard the others. + The AT_*_pc values for such functions refer to local labels in + these sections. If the section from that file was discarded, the + labels are not in the output, so the relocs get a value of 0. + If this is a discarded function, mark the pc bounds as invalid, + so that GDB will ignore it. */ + if (has_low_pc_attr && has_high_pc_attr + && part_die->lowpc < part_die->highpc + && (part_die->lowpc != 0 + || (bfd_get_file_flags (abfd) & HAS_RELOC))) + part_die->has_pc_info = 1; + return info_ptr; +} + +/* Read the die from the .debug_info section buffer. And set diep to + point to a newly allocated die with its information. */ + +static char * +read_full_die (struct die_info **diep, bfd *abfd, char *info_ptr, + const struct comp_unit_head *cu_header) +{ + unsigned int abbrev_number, bytes_read, i, offset; + struct abbrev_info *abbrev; + struct die_info *die; + + offset = info_ptr - dwarf_info_buffer; + abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read); + info_ptr += bytes_read; + if (!abbrev_number) + { + die = dwarf_alloc_die (); + die->tag = 0; + die->abbrev = abbrev_number; + die->type = NULL; + *diep = die; + return info_ptr; + } + + abbrev = dwarf2_lookup_abbrev (abbrev_number); + if (!abbrev) + { + error ("Dwarf Error: could not find abbrev number %d.", abbrev_number); + } + die = dwarf_alloc_die (); + die->offset = offset; + die->tag = abbrev->tag; + die->has_children = abbrev->has_children; + die->abbrev = abbrev_number; + die->type = NULL; + + die->num_attrs = abbrev->num_attrs; + die->attrs = (struct attribute *) + xmalloc (die->num_attrs * sizeof (struct attribute)); + + for (i = 0; i < abbrev->num_attrs; ++i) + { + info_ptr = read_attribute (&die->attrs[i], &abbrev->attrs[i], + abfd, info_ptr, cu_header); + } + + *diep = die; + return info_ptr; +} + +/* Read an attribute value described by an attribute form. */ + +static char * +read_attribute_value (struct attribute *attr, unsigned form, + bfd *abfd, char *info_ptr, + const struct comp_unit_head *cu_header) +{ + unsigned int bytes_read; + struct dwarf_block *blk; + + attr->form = form; + switch (form) + { + case DW_FORM_addr: + case DW_FORM_ref_addr: + DW_ADDR (attr) = read_address (abfd, info_ptr, cu_header, &bytes_read); + info_ptr += bytes_read; + break; + case DW_FORM_block2: + blk = dwarf_alloc_block (); + blk->size = read_2_bytes (abfd, info_ptr); + info_ptr += 2; + blk->data = read_n_bytes (abfd, info_ptr, blk->size); + info_ptr += blk->size; + DW_BLOCK (attr) = blk; + break; + case DW_FORM_block4: + blk = dwarf_alloc_block (); + blk->size = read_4_bytes (abfd, info_ptr); + info_ptr += 4; + blk->data = read_n_bytes (abfd, info_ptr, blk->size); + info_ptr += blk->size; + DW_BLOCK (attr) = blk; + break; + case DW_FORM_data2: + DW_UNSND (attr) = read_2_bytes (abfd, info_ptr); + info_ptr += 2; + break; + case DW_FORM_data4: + DW_UNSND (attr) = read_4_bytes (abfd, info_ptr); + info_ptr += 4; + break; + case DW_FORM_data8: + DW_UNSND (attr) = read_8_bytes (abfd, info_ptr); + info_ptr += 8; + break; + case DW_FORM_string: + DW_STRING (attr) = read_string (abfd, info_ptr, &bytes_read); + info_ptr += bytes_read; + break; + case DW_FORM_strp: + DW_STRING (attr) = read_indirect_string (abfd, info_ptr, cu_header, + &bytes_read); + info_ptr += bytes_read; + break; + case DW_FORM_block: + blk = dwarf_alloc_block (); + blk->size = read_unsigned_leb128 (abfd, info_ptr, &bytes_read); + info_ptr += bytes_read; + blk->data = read_n_bytes (abfd, info_ptr, blk->size); + info_ptr += blk->size; + DW_BLOCK (attr) = blk; + break; + case DW_FORM_block1: + blk = dwarf_alloc_block (); + blk->size = read_1_byte (abfd, info_ptr); + info_ptr += 1; + blk->data = read_n_bytes (abfd, info_ptr, blk->size); + info_ptr += blk->size; + DW_BLOCK (attr) = blk; + break; + case DW_FORM_data1: + DW_UNSND (attr) = read_1_byte (abfd, info_ptr); + info_ptr += 1; + break; + case DW_FORM_flag: + DW_UNSND (attr) = read_1_byte (abfd, info_ptr); + info_ptr += 1; + break; + case DW_FORM_sdata: + DW_SND (attr) = read_signed_leb128 (abfd, info_ptr, &bytes_read); + info_ptr += bytes_read; + break; + case DW_FORM_udata: + DW_UNSND (attr) = read_unsigned_leb128 (abfd, info_ptr, &bytes_read); + info_ptr += bytes_read; + break; + case DW_FORM_ref1: + DW_UNSND (attr) = read_1_byte (abfd, info_ptr); + info_ptr += 1; + break; + case DW_FORM_ref2: + DW_UNSND (attr) = read_2_bytes (abfd, info_ptr); + info_ptr += 2; + break; + case DW_FORM_ref4: + DW_UNSND (attr) = read_4_bytes (abfd, info_ptr); + info_ptr += 4; + break; + case DW_FORM_ref8: + DW_UNSND (attr) = read_8_bytes (abfd, info_ptr); + info_ptr += 8; + break; + case DW_FORM_ref_udata: + DW_UNSND (attr) = read_unsigned_leb128 (abfd, info_ptr, &bytes_read); + info_ptr += bytes_read; + break; + case DW_FORM_indirect: + form = read_unsigned_leb128 (abfd, info_ptr, &bytes_read); + info_ptr += bytes_read; + info_ptr = read_attribute_value (attr, form, abfd, info_ptr, cu_header); + break; + default: + error ("Dwarf Error: Cannot handle %s in DWARF reader.", + dwarf_form_name (form)); + } + return info_ptr; +} + +/* Read an attribute described by an abbreviated attribute. */ + +static char * +read_attribute (struct attribute *attr, struct attr_abbrev *abbrev, + bfd *abfd, char *info_ptr, + const struct comp_unit_head *cu_header) +{ + attr->name = abbrev->name; + return read_attribute_value (attr, abbrev->form, abfd, info_ptr, cu_header); +} + +/* read dwarf information from a buffer */ + +static unsigned int +read_1_byte (bfd *abfd, char *buf) +{ + return bfd_get_8 (abfd, (bfd_byte *) buf); +} + +static int +read_1_signed_byte (bfd *abfd, char *buf) +{ + return bfd_get_signed_8 (abfd, (bfd_byte *) buf); +} + +static unsigned int +read_2_bytes (bfd *abfd, char *buf) +{ + return bfd_get_16 (abfd, (bfd_byte *) buf); +} + +static int +read_2_signed_bytes (bfd *abfd, char *buf) +{ + return bfd_get_signed_16 (abfd, (bfd_byte *) buf); +} + +static unsigned int +read_4_bytes (bfd *abfd, char *buf) +{ + return bfd_get_32 (abfd, (bfd_byte *) buf); +} + +static int +read_4_signed_bytes (bfd *abfd, char *buf) +{ + return bfd_get_signed_32 (abfd, (bfd_byte *) buf); +} + +static unsigned long +read_8_bytes (bfd *abfd, char *buf) +{ + return bfd_get_64 (abfd, (bfd_byte *) buf); +} + +static CORE_ADDR +read_address (bfd *abfd, char *buf, const struct comp_unit_head *cu_header, + int *bytes_read) +{ + CORE_ADDR retval = 0; + + if (cu_header->signed_addr_p) + { + switch (cu_header->addr_size) + { + case 2: + retval = bfd_get_signed_16 (abfd, (bfd_byte *) buf); + break; + case 4: + retval = bfd_get_signed_32 (abfd, (bfd_byte *) buf); + break; + case 8: + retval = bfd_get_signed_64 (abfd, (bfd_byte *) buf); + break; + default: + internal_error (__FILE__, __LINE__, + "read_address: bad switch, signed"); + } + } + else + { + switch (cu_header->addr_size) + { + case 2: + retval = bfd_get_16 (abfd, (bfd_byte *) buf); + break; + case 4: + retval = bfd_get_32 (abfd, (bfd_byte *) buf); + break; + case 8: + retval = bfd_get_64 (abfd, (bfd_byte *) buf); + break; + default: + internal_error (__FILE__, __LINE__, + "read_address: bad switch, unsigned"); + } + } + + *bytes_read = cu_header->addr_size; + return retval; +} + +/* Read the initial length from a section. The (draft) DWARF 3 + specification allows the initial length to take up either 4 bytes + or 12 bytes. If the first 4 bytes are 0xffffffff, then the next 8 + bytes describe the length and all offsets will be 8 bytes in length + instead of 4. + + An older, non-standard 64-bit format is also handled by this + function. The older format in question stores the initial length + as an 8-byte quantity without an escape value. Lengths greater + than 2^32 aren't very common which means that the initial 4 bytes + is almost always zero. Since a length value of zero doesn't make + sense for the 32-bit format, this initial zero can be considered to + be an escape value which indicates the presence of the older 64-bit + format. As written, the code can't detect (old format) lengths + greater than 4GB. If it becomes necessary to handle lengths somewhat + larger than 4GB, we could allow other small values (such as the + non-sensical values of 1, 2, and 3) to also be used as escape values + indicating the presence of the old format. + + The value returned via bytes_read should be used to increment + the relevant pointer after calling read_initial_length(). + + As a side effect, this function sets the fields initial_length_size + and offset_size in cu_header to the values appropriate for the + length field. (The format of the initial length field determines + the width of file offsets to be fetched later with fetch_offset().) + + [ Note: read_initial_length() and read_offset() are based on the + document entitled "DWARF Debugging Information Format", revision + 3, draft 8, dated November 19, 2001. This document was obtained + from: + + http://reality.sgiweb.org/davea/dwarf3-draft8-011125.pdf + + This document is only a draft and is subject to change. (So beware.) + + Details regarding the older, non-standard 64-bit format were + determined empirically by examining 64-bit ELF files produced + by the SGI toolchain on an IRIX 6.5 machine. + + - Kevin, July 16, 2002 + ] */ + +static LONGEST +read_initial_length (bfd *abfd, char *buf, struct comp_unit_head *cu_header, + int *bytes_read) +{ + LONGEST retval = 0; + + retval = bfd_get_32 (abfd, (bfd_byte *) buf); + + if (retval == 0xffffffff) + { + retval = bfd_get_64 (abfd, (bfd_byte *) buf + 4); + *bytes_read = 12; + if (cu_header != NULL) + { + cu_header->initial_length_size = 12; + cu_header->offset_size = 8; + } + } + else if (retval == 0) + { + /* Handle (non-standard) 64-bit DWARF2 formats such as that used + by IRIX. */ + retval = bfd_get_64 (abfd, (bfd_byte *) buf); + *bytes_read = 8; + if (cu_header != NULL) + { + cu_header->initial_length_size = 8; + cu_header->offset_size = 8; + } + } + else + { + *bytes_read = 4; + if (cu_header != NULL) + { + cu_header->initial_length_size = 4; + cu_header->offset_size = 4; + } + } + + return retval; +} + +/* Read an offset from the data stream. The size of the offset is + given by cu_header->offset_size. */ + +static LONGEST +read_offset (bfd *abfd, char *buf, const struct comp_unit_head *cu_header, + int *bytes_read) +{ + LONGEST retval = 0; + + switch (cu_header->offset_size) + { + case 4: + retval = bfd_get_32 (abfd, (bfd_byte *) buf); + *bytes_read = 4; + break; + case 8: + retval = bfd_get_64 (abfd, (bfd_byte *) buf); + *bytes_read = 8; + break; + default: + internal_error (__FILE__, __LINE__, + "read_offset: bad switch"); + } + + return retval; +} + +static char * +read_n_bytes (bfd *abfd, char *buf, unsigned int size) +{ + /* If the size of a host char is 8 bits, we can return a pointer + to the buffer, otherwise we have to copy the data to a buffer + allocated on the temporary obstack. */ + gdb_assert (HOST_CHAR_BIT == 8); + return buf; +} + +static char * +read_string (bfd *abfd, char *buf, unsigned int *bytes_read_ptr) +{ + /* If the size of a host char is 8 bits, we can return a pointer + to the string, otherwise we have to copy the string to a buffer + allocated on the temporary obstack. */ + gdb_assert (HOST_CHAR_BIT == 8); + if (*buf == '\0') + { + *bytes_read_ptr = 1; + return NULL; + } + *bytes_read_ptr = strlen (buf) + 1; + return buf; +} + +static char * +read_indirect_string (bfd *abfd, char *buf, + const struct comp_unit_head *cu_header, + unsigned int *bytes_read_ptr) +{ + LONGEST str_offset = read_offset (abfd, buf, cu_header, + (int *) bytes_read_ptr); + + if (dwarf_str_buffer == NULL) + { + error ("DW_FORM_strp used without .debug_str section"); + return NULL; + } + if (str_offset >= dwarf_str_size) + { + error ("DW_FORM_strp pointing outside of .debug_str section"); + return NULL; + } + gdb_assert (HOST_CHAR_BIT == 8); + if (dwarf_str_buffer[str_offset] == '\0') + return NULL; + return dwarf_str_buffer + str_offset; +} + +static unsigned long +read_unsigned_leb128 (bfd *abfd, char *buf, unsigned int *bytes_read_ptr) +{ + unsigned long result; + unsigned int num_read; + int i, shift; + unsigned char byte; + + result = 0; + shift = 0; + num_read = 0; + i = 0; + while (1) + { + byte = bfd_get_8 (abfd, (bfd_byte *) buf); + buf++; + num_read++; + result |= ((unsigned long)(byte & 127) << shift); + if ((byte & 128) == 0) + { + break; + } + shift += 7; + } + *bytes_read_ptr = num_read; + return result; +} + +static long +read_signed_leb128 (bfd *abfd, char *buf, unsigned int *bytes_read_ptr) +{ + long result; + int i, shift, size, num_read; + unsigned char byte; + + result = 0; + shift = 0; + size = 32; + num_read = 0; + i = 0; + while (1) + { + byte = bfd_get_8 (abfd, (bfd_byte *) buf); + buf++; + num_read++; + result |= ((long)(byte & 127) << shift); + shift += 7; + if ((byte & 128) == 0) + { + break; + } + } + if ((shift < size) && (byte & 0x40)) + { + result |= -(1 << shift); + } + *bytes_read_ptr = num_read; + return result; +} + +static void +set_cu_language (unsigned int lang) +{ + switch (lang) + { + case DW_LANG_C89: + case DW_LANG_C: + cu_language = language_c; + break; + case DW_LANG_C_plus_plus: + cu_language = language_cplus; + break; + case DW_LANG_Fortran77: + case DW_LANG_Fortran90: + case DW_LANG_Fortran95: + cu_language = language_fortran; + break; + case DW_LANG_Mips_Assembler: + cu_language = language_asm; + break; + case DW_LANG_Java: + cu_language = language_java; + break; + case DW_LANG_Ada83: + case DW_LANG_Ada95: + case DW_LANG_Cobol74: + case DW_LANG_Cobol85: + case DW_LANG_Pascal83: + case DW_LANG_Modula2: + default: + cu_language = language_unknown; + break; + } + cu_language_defn = language_def (cu_language); +} + +/* Return the named attribute or NULL if not there. */ + +static struct attribute * +dwarf_attr (struct die_info *die, unsigned int name) +{ + unsigned int i; + struct attribute *spec = NULL; + + for (i = 0; i < die->num_attrs; ++i) + { + if (die->attrs[i].name == name) + { + return &die->attrs[i]; + } + if (die->attrs[i].name == DW_AT_specification + || die->attrs[i].name == DW_AT_abstract_origin) + spec = &die->attrs[i]; + } + if (spec) + { + struct die_info *ref_die = + follow_die_ref (dwarf2_get_ref_die_offset (spec)); + + if (ref_die) + return dwarf_attr (ref_die, name); + } + + return NULL; +} + +static int +die_is_declaration (struct die_info *die) +{ + return (dwarf_attr (die, DW_AT_declaration) + && ! dwarf_attr (die, DW_AT_specification)); +} + + +/* Free the line_header structure *LH, and any arrays and strings it + refers to. */ +static void +free_line_header (struct line_header *lh) +{ + if (lh->standard_opcode_lengths) + xfree (lh->standard_opcode_lengths); + + /* Remember that all the lh->file_names[i].name pointers are + pointers into debug_line_buffer, and don't need to be freed. */ + if (lh->file_names) + xfree (lh->file_names); + + /* Similarly for the include directory names. */ + if (lh->include_dirs) + xfree (lh->include_dirs); + + xfree (lh); +} + + +/* Add an entry to LH's include directory table. */ +static void +add_include_dir (struct line_header *lh, char *include_dir) +{ + /* Grow the array if necessary. */ + if (lh->include_dirs_size == 0) + { + lh->include_dirs_size = 1; /* for testing */ + lh->include_dirs = xmalloc (lh->include_dirs_size + * sizeof (*lh->include_dirs)); + } + else if (lh->num_include_dirs >= lh->include_dirs_size) + { + lh->include_dirs_size *= 2; + lh->include_dirs = xrealloc (lh->include_dirs, + (lh->include_dirs_size + * sizeof (*lh->include_dirs))); + } + + lh->include_dirs[lh->num_include_dirs++] = include_dir; +} + + +/* Add an entry to LH's file name table. */ +static void +add_file_name (struct line_header *lh, + char *name, + unsigned int dir_index, + unsigned int mod_time, + unsigned int length) +{ + struct file_entry *fe; + + /* Grow the array if necessary. */ + if (lh->file_names_size == 0) + { + lh->file_names_size = 1; /* for testing */ + lh->file_names = xmalloc (lh->file_names_size + * sizeof (*lh->file_names)); + } + else if (lh->num_file_names >= lh->file_names_size) + { + lh->file_names_size *= 2; + lh->file_names = xrealloc (lh->file_names, + (lh->file_names_size + * sizeof (*lh->file_names))); + } + + fe = &lh->file_names[lh->num_file_names++]; + fe->name = name; + fe->dir_index = dir_index; + fe->mod_time = mod_time; + fe->length = length; +} + + +/* Read the statement program header starting at OFFSET in + dwarf_line_buffer, according to the endianness of ABFD. Return a + pointer to a struct line_header, allocated using xmalloc. + + NOTE: the strings in the include directory and file name tables of + the returned object point into debug_line_buffer, and must not be + freed. */ +static struct line_header * +dwarf_decode_line_header (unsigned int offset, bfd *abfd, + const struct comp_unit_head *cu_header) +{ + struct cleanup *back_to; + struct line_header *lh; + char *line_ptr; + int bytes_read; + int i; + char *cur_dir, *cur_file; + + if (dwarf_line_buffer == NULL) + { + complain (&dwarf2_missing_line_number_section); + return 0; + } + + /* Make sure that at least there's room for the total_length field. That + could be 12 bytes long, but we're just going to fudge that. */ + if (offset + 4 >= dwarf_line_size) + { + complain (&dwarf2_statement_list_fits_in_line_number_section); + return 0; + } + + lh = xmalloc (sizeof (*lh)); + memset (lh, 0, sizeof (*lh)); + back_to = make_cleanup ((make_cleanup_ftype *) free_line_header, + (void *) lh); + + line_ptr = dwarf_line_buffer + offset; + + /* read in the header */ + lh->total_length = read_initial_length (abfd, line_ptr, NULL, &bytes_read); + line_ptr += bytes_read; + if (line_ptr + lh->total_length > dwarf_line_buffer + dwarf_line_size) + { + complain (&dwarf2_statement_list_fits_in_line_number_section); + return 0; + } + lh->statement_program_end = line_ptr + lh->total_length; + lh->version = read_2_bytes (abfd, line_ptr); + line_ptr += 2; + lh->header_length = read_offset (abfd, line_ptr, cu_header, &bytes_read); + line_ptr += bytes_read; + lh->minimum_instruction_length = read_1_byte (abfd, line_ptr); + line_ptr += 1; + lh->default_is_stmt = read_1_byte (abfd, line_ptr); + line_ptr += 1; + lh->line_base = read_1_signed_byte (abfd, line_ptr); + line_ptr += 1; + lh->line_range = read_1_byte (abfd, line_ptr); + line_ptr += 1; + lh->opcode_base = read_1_byte (abfd, line_ptr); + line_ptr += 1; + lh->standard_opcode_lengths + = (unsigned char *) xmalloc (lh->opcode_base * sizeof (unsigned char)); + + lh->standard_opcode_lengths[0] = 1; /* This should never be used anyway. */ + for (i = 1; i < lh->opcode_base; ++i) + { + lh->standard_opcode_lengths[i] = read_1_byte (abfd, line_ptr); + line_ptr += 1; + } + + /* Read directory table */ + while ((cur_dir = read_string (abfd, line_ptr, &bytes_read)) != NULL) + { + line_ptr += bytes_read; + add_include_dir (lh, cur_dir); + } + line_ptr += bytes_read; + + /* Read file name table */ + while ((cur_file = read_string (abfd, line_ptr, &bytes_read)) != NULL) + { + unsigned int dir_index, mod_time, length; + + line_ptr += bytes_read; + dir_index = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); + line_ptr += bytes_read; + mod_time = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); + line_ptr += bytes_read; + length = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); + line_ptr += bytes_read; + + add_file_name (lh, cur_file, dir_index, mod_time, length); + } + line_ptr += bytes_read; + lh->statement_program_start = line_ptr; + + if (line_ptr > dwarf_line_buffer + dwarf_line_size) + complain (&dwarf2_line_header_too_long); + + discard_cleanups (back_to); + return lh; +} + +/* This function exists to work around a bug in certain compilers + (particularly GCC 2.95), in which the first line number marker of a + function does not show up until after the prologue, right before + the second line number marker. This function shifts ADDRESS down + to the beginning of the function if necessary, and is called on + addresses passed to record_line. */ + +static CORE_ADDR +check_cu_functions (CORE_ADDR address) +{ + struct function_range *fn; + + /* Find the function_range containing address. */ + if (!cu_first_fn) + return address; + + if (!cu_cached_fn) + cu_cached_fn = cu_first_fn; + + fn = cu_cached_fn; + while (fn) + if (fn->lowpc <= address && fn->highpc > address) + goto found; + else + fn = fn->next; + + fn = cu_first_fn; + while (fn && fn != cu_cached_fn) + if (fn->lowpc <= address && fn->highpc > address) + goto found; + else + fn = fn->next; + + return address; + + found: + if (fn->seen_line) + return address; + if (address != fn->lowpc) + complain (&dwarf2_misplaced_line_number, + (unsigned long) address, fn->name); + fn->seen_line = 1; + return fn->lowpc; +} + +/* Decode the line number information for the compilation unit whose + line number info is at OFFSET in the .debug_line section. + The compilation directory of the file is passed in COMP_DIR. */ + +static void +dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd, + const struct comp_unit_head *cu_header) +{ + char *line_ptr; + char *line_end; + unsigned int i, bytes_read; + char *cur_dir; + unsigned char op_code, extended_op, adj_opcode; + + line_ptr = lh->statement_program_start; + line_end = lh->statement_program_end; + + /* Read the statement sequences until there's nothing left. */ + while (line_ptr < line_end) + { + /* state machine registers */ + CORE_ADDR address = 0; + unsigned int file = 1; + unsigned int line = 1; + unsigned int column = 0; + int is_stmt = lh->default_is_stmt; + int basic_block = 0; + int end_sequence = 0; + + /* Start a subfile for the current file of the state machine. */ + if (lh->num_file_names >= file) + { + /* lh->include_dirs and lh->file_names are 0-based, but the + directory and file name numbers in the statement program + are 1-based. */ + struct file_entry *fe = &lh->file_names[file - 1]; + char *dir; + if (fe->dir_index) + dir = lh->include_dirs[fe->dir_index - 1]; + else + dir = comp_dir; + dwarf2_start_subfile (fe->name, dir); + } + + /* Decode the table. */ + while (!end_sequence) + { + op_code = read_1_byte (abfd, line_ptr); + line_ptr += 1; + + if (op_code >= lh->opcode_base) + { /* Special operand. */ + adj_opcode = op_code - lh->opcode_base; + address += (adj_opcode / lh->line_range) + * lh->minimum_instruction_length; + line += lh->line_base + (adj_opcode % lh->line_range); + /* append row to matrix using current values */ + address = check_cu_functions (address); + record_line (current_subfile, line, address); + basic_block = 1; + } + else switch (op_code) + { + case DW_LNS_extended_op: + line_ptr += 1; /* ignore length */ + extended_op = read_1_byte (abfd, line_ptr); + line_ptr += 1; + switch (extended_op) + { + case DW_LNE_end_sequence: + end_sequence = 1; + record_line (current_subfile, 0, address); + break; + case DW_LNE_set_address: + address = read_address (abfd, line_ptr, cu_header, &bytes_read); + line_ptr += bytes_read; + address += baseaddr; + break; + case DW_LNE_define_file: + { + char *cur_file; + unsigned int dir_index, mod_time, length; + + cur_file = read_string (abfd, line_ptr, &bytes_read); + line_ptr += bytes_read; + dir_index = + read_unsigned_leb128 (abfd, line_ptr, &bytes_read); + line_ptr += bytes_read; + mod_time = + read_unsigned_leb128 (abfd, line_ptr, &bytes_read); + line_ptr += bytes_read; + length = + read_unsigned_leb128 (abfd, line_ptr, &bytes_read); + line_ptr += bytes_read; + add_file_name (lh, cur_file, dir_index, mod_time, length); + } + break; + default: + complain (&dwarf2_mangled_line_number_section); + return; + } + break; + case DW_LNS_copy: + address = check_cu_functions (address); + record_line (current_subfile, line, address); + basic_block = 0; + break; + case DW_LNS_advance_pc: + address += lh->minimum_instruction_length + * read_unsigned_leb128 (abfd, line_ptr, &bytes_read); + line_ptr += bytes_read; + break; + case DW_LNS_advance_line: + line += read_signed_leb128 (abfd, line_ptr, &bytes_read); + line_ptr += bytes_read; + break; + case DW_LNS_set_file: + { + /* lh->include_dirs and lh->file_names are 0-based, + but the directory and file name numbers in the + statement program are 1-based. */ + struct file_entry *fe; + char *dir; + file = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); + line_ptr += bytes_read; + fe = &lh->file_names[file - 1]; + if (fe->dir_index) + dir = lh->include_dirs[fe->dir_index - 1]; + else + dir = comp_dir; + dwarf2_start_subfile (fe->name, dir); + } + break; + case DW_LNS_set_column: + column = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); + line_ptr += bytes_read; + break; + case DW_LNS_negate_stmt: + is_stmt = (!is_stmt); + break; + case DW_LNS_set_basic_block: + basic_block = 1; + break; + /* Add to the address register of the state machine the + address increment value corresponding to special opcode + 255. Ie, this value is scaled by the minimum instruction + length since special opcode 255 would have scaled the + the increment. */ + case DW_LNS_const_add_pc: + address += (lh->minimum_instruction_length + * ((255 - lh->opcode_base) / lh->line_range)); + break; + case DW_LNS_fixed_advance_pc: + address += read_2_bytes (abfd, line_ptr); + line_ptr += 2; + break; + default: + { /* Unknown standard opcode, ignore it. */ + int i; + for (i = 0; i < lh->standard_opcode_lengths[op_code]; i++) + { + (void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read); + line_ptr += bytes_read; + } + } + } + } + } +} + +/* Start a subfile for DWARF. FILENAME is the name of the file and + DIRNAME the name of the source directory which contains FILENAME + or NULL if not known. + This routine tries to keep line numbers from identical absolute and + relative file names in a common subfile. + + Using the `list' example from the GDB testsuite, which resides in + /srcdir and compiling it with Irix6.2 cc in /compdir using a filename + of /srcdir/list0.c yields the following debugging information for list0.c: + + DW_AT_name: /srcdir/list0.c + DW_AT_comp_dir: /compdir + files.files[0].name: list0.h + files.files[0].dir: /srcdir + files.files[1].name: list0.c + files.files[1].dir: /srcdir + + The line number information for list0.c has to end up in a single + subfile, so that `break /srcdir/list0.c:1' works as expected. */ + +static void +dwarf2_start_subfile (char *filename, char *dirname) +{ + /* If the filename isn't absolute, try to match an existing subfile + with the full pathname. */ + + if (!IS_ABSOLUTE_PATH (filename) && dirname != NULL) + { + struct subfile *subfile; + char *fullname = concat (dirname, "/", filename, NULL); + + for (subfile = subfiles; subfile; subfile = subfile->next) + { + if (FILENAME_CMP (subfile->name, fullname) == 0) + { + current_subfile = subfile; + xfree (fullname); + return; + } + } + xfree (fullname); + } + start_subfile (filename, dirname); +} + +/* Given a pointer to a DWARF information entry, figure out if we need + to make a symbol table entry for it, and if so, create a new entry + and return a pointer to it. + If TYPE is NULL, determine symbol type from the die, otherwise + used the passed type. */ + +static struct symbol * +new_symbol (struct die_info *die, struct type *type, struct objfile *objfile, + const struct comp_unit_head *cu_header) +{ + struct symbol *sym = NULL; + char *name; + struct attribute *attr = NULL; + struct attribute *attr2 = NULL; + CORE_ADDR addr = 0; + + name = dwarf2_linkage_name (die); + if (name) + { + sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack, + sizeof (struct symbol)); + OBJSTAT (objfile, n_syms++); + memset (sym, 0, sizeof (struct symbol)); + SYMBOL_NAME (sym) = obsavestring (name, strlen (name), + &objfile->symbol_obstack); + + /* Default assumptions. + Use the passed type or decode it from the die. */ + SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; + SYMBOL_CLASS (sym) = LOC_STATIC; + if (type != NULL) + SYMBOL_TYPE (sym) = type; + else + SYMBOL_TYPE (sym) = die_type (die, objfile, cu_header); + attr = dwarf_attr (die, DW_AT_decl_line); + if (attr) + { + SYMBOL_LINE (sym) = DW_UNSND (attr); + } + + /* If this symbol is from a C++ compilation, then attempt to + cache the demangled form for future reference. This is a + typical time versus space tradeoff, that was decided in favor + of time because it sped up C++ symbol lookups by a factor of + about 20. */ + + SYMBOL_LANGUAGE (sym) = cu_language; + SYMBOL_INIT_DEMANGLED_NAME (sym, &objfile->symbol_obstack); + switch (die->tag) + { + case DW_TAG_label: + attr = dwarf_attr (die, DW_AT_low_pc); + if (attr) + { + SYMBOL_VALUE_ADDRESS (sym) = DW_ADDR (attr) + baseaddr; + } + SYMBOL_CLASS (sym) = LOC_LABEL; + break; + case DW_TAG_subprogram: + /* SYMBOL_BLOCK_VALUE (sym) will be filled in later by + finish_block. */ + SYMBOL_CLASS (sym) = LOC_BLOCK; + attr2 = dwarf_attr (die, DW_AT_external); + if (attr2 && (DW_UNSND (attr2) != 0)) + { + add_symbol_to_list (sym, &global_symbols); + } + else + { + add_symbol_to_list (sym, list_in_scope); + } + break; + case DW_TAG_variable: + /* Compilation with minimal debug info may result in variables + with missing type entries. Change the misleading `void' type + to something sensible. */ + if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_VOID) + SYMBOL_TYPE (sym) = init_type (TYPE_CODE_INT, + TARGET_INT_BIT / HOST_CHAR_BIT, 0, + "<variable, no debug info>", + objfile); + attr = dwarf_attr (die, DW_AT_const_value); + if (attr) + { + dwarf2_const_value (attr, sym, objfile, cu_header); + attr2 = dwarf_attr (die, DW_AT_external); + if (attr2 && (DW_UNSND (attr2) != 0)) + add_symbol_to_list (sym, &global_symbols); + else + add_symbol_to_list (sym, list_in_scope); + break; + } + attr = dwarf_attr (die, DW_AT_location); + if (attr) + { + attr2 = dwarf_attr (die, DW_AT_external); + if (attr2 && (DW_UNSND (attr2) != 0)) + { + /* Support the .debug_loc offsets */ + if (attr_form_is_block (attr)) + { + SYMBOL_VALUE_ADDRESS (sym) = + decode_locdesc (DW_BLOCK (attr), objfile, cu_header); + } + else if (attr->form == DW_FORM_data4 + || attr->form == DW_FORM_data8) + { + complain (&dwarf2_complex_location_expr); + } + else + { + complain (&dwarf2_invalid_attrib_class, "DW_AT_location", + "external variable"); + } + add_symbol_to_list (sym, &global_symbols); + + /* In shared libraries the address of the variable + in the location descriptor might still be relocatable, + so its value could be zero. + Enter the symbol as a LOC_UNRESOLVED symbol, if its + value is zero, the address of the variable will then + be determined from the minimal symbol table whenever + the variable is referenced. */ + if (SYMBOL_VALUE_ADDRESS (sym)) + { + fixup_symbol_section (sym, objfile); + SYMBOL_VALUE_ADDRESS (sym) += + ANOFFSET (objfile->section_offsets, + SYMBOL_SECTION (sym)); + SYMBOL_CLASS (sym) = LOC_STATIC; + } + else + SYMBOL_CLASS (sym) = LOC_UNRESOLVED; + } + else + { + /* Support the .debug_loc offsets */ + if (attr_form_is_block (attr)) + { + SYMBOL_VALUE (sym) = addr = + decode_locdesc (DW_BLOCK (attr), objfile, cu_header); + } + else if (attr->form == DW_FORM_data4 + || attr->form == DW_FORM_data8) + { + complain (&dwarf2_complex_location_expr); + } + else + { + complain (&dwarf2_invalid_attrib_class, "DW_AT_location", + "external variable"); + addr = 0; + } + add_symbol_to_list (sym, list_in_scope); + if (optimized_out) + { + SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT; + } + else if (isreg) + { + SYMBOL_CLASS (sym) = LOC_REGISTER; + SYMBOL_VALUE (sym) = + DWARF2_REG_TO_REGNUM (SYMBOL_VALUE (sym)); + } + else if (offreg) + { + SYMBOL_CLASS (sym) = LOC_BASEREG; + SYMBOL_BASEREG (sym) = DWARF2_REG_TO_REGNUM (basereg); + } + else if (islocal) + { + SYMBOL_CLASS (sym) = LOC_LOCAL; + } + else + { + fixup_symbol_section (sym, objfile); + SYMBOL_VALUE_ADDRESS (sym) = + addr + ANOFFSET (objfile->section_offsets, + SYMBOL_SECTION (sym)); + SYMBOL_CLASS (sym) = LOC_STATIC; + } + } + } + else + { + /* We do not know the address of this symbol. + If it is an external symbol and we have type information + for it, enter the symbol as a LOC_UNRESOLVED symbol. + The address of the variable will then be determined from + the minimal symbol table whenever the variable is + referenced. */ + attr2 = dwarf_attr (die, DW_AT_external); + if (attr2 && (DW_UNSND (attr2) != 0) + && dwarf_attr (die, DW_AT_type) != NULL) + { + SYMBOL_CLASS (sym) = LOC_UNRESOLVED; + add_symbol_to_list (sym, &global_symbols); + } + } + break; + case DW_TAG_formal_parameter: + attr = dwarf_attr (die, DW_AT_location); + if (attr) + { + SYMBOL_VALUE (sym) = + decode_locdesc (DW_BLOCK (attr), objfile, cu_header); + if (isreg) + { + SYMBOL_CLASS (sym) = LOC_REGPARM; + SYMBOL_VALUE (sym) = + DWARF2_REG_TO_REGNUM (SYMBOL_VALUE (sym)); + } + else if (offreg) + { + if (isderef) + { + if (basereg != frame_base_reg) + complain (&dwarf2_complex_location_expr); + SYMBOL_CLASS (sym) = LOC_REF_ARG; + } + else + { + SYMBOL_CLASS (sym) = LOC_BASEREG_ARG; + SYMBOL_BASEREG (sym) = DWARF2_REG_TO_REGNUM (basereg); + } + } + else + { + SYMBOL_CLASS (sym) = LOC_ARG; + } + } + attr = dwarf_attr (die, DW_AT_const_value); + if (attr) + { + dwarf2_const_value (attr, sym, objfile, cu_header); + } + add_symbol_to_list (sym, list_in_scope); + break; + case DW_TAG_unspecified_parameters: + /* From varargs functions; gdb doesn't seem to have any + interest in this information, so just ignore it for now. + (FIXME?) */ + break; + case DW_TAG_class_type: + case DW_TAG_structure_type: + case DW_TAG_union_type: + case DW_TAG_enumeration_type: + SYMBOL_CLASS (sym) = LOC_TYPEDEF; + SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE; + add_symbol_to_list (sym, list_in_scope); + + /* The semantics of C++ state that "struct foo { ... }" also + defines a typedef for "foo". Synthesize a typedef symbol so + that "ptype foo" works as expected. */ + if (cu_language == language_cplus) + { + struct symbol *typedef_sym = (struct symbol *) + obstack_alloc (&objfile->symbol_obstack, + sizeof (struct symbol)); + *typedef_sym = *sym; + SYMBOL_NAMESPACE (typedef_sym) = VAR_NAMESPACE; + if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0) + TYPE_NAME (SYMBOL_TYPE (sym)) = + obsavestring (SYMBOL_NAME (sym), + strlen (SYMBOL_NAME (sym)), + &objfile->type_obstack); + add_symbol_to_list (typedef_sym, list_in_scope); + } + break; + case DW_TAG_typedef: + case DW_TAG_base_type: + SYMBOL_CLASS (sym) = LOC_TYPEDEF; + SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; + add_symbol_to_list (sym, list_in_scope); + break; + case DW_TAG_enumerator: + attr = dwarf_attr (die, DW_AT_const_value); + if (attr) + { + dwarf2_const_value (attr, sym, objfile, cu_header); + } + add_symbol_to_list (sym, list_in_scope); + break; + default: + /* Not a tag we recognize. Hopefully we aren't processing + trash data, but since we must specifically ignore things + we don't recognize, there is nothing else we should do at + this point. */ + complain (&dwarf2_unsupported_tag, dwarf_tag_name (die->tag)); + break; + } + } + return (sym); +} + +/* Copy constant value from an attribute to a symbol. */ + +static void +dwarf2_const_value (struct attribute *attr, struct symbol *sym, + struct objfile *objfile, + const struct comp_unit_head *cu_header) +{ + struct dwarf_block *blk; + + switch (attr->form) + { + case DW_FORM_addr: + if (TYPE_LENGTH (SYMBOL_TYPE (sym)) != cu_header->addr_size) + complain (&dwarf2_const_value_length_mismatch, SYMBOL_NAME (sym), + cu_header->addr_size, TYPE_LENGTH (SYMBOL_TYPE (sym))); + SYMBOL_VALUE_BYTES (sym) = (char *) + obstack_alloc (&objfile->symbol_obstack, cu_header->addr_size); + store_address (SYMBOL_VALUE_BYTES (sym), cu_header->addr_size, + DW_ADDR (attr)); + SYMBOL_CLASS (sym) = LOC_CONST_BYTES; + break; + case DW_FORM_block1: + case DW_FORM_block2: + case DW_FORM_block4: + case DW_FORM_block: + blk = DW_BLOCK (attr); + if (TYPE_LENGTH (SYMBOL_TYPE (sym)) != blk->size) + complain (&dwarf2_const_value_length_mismatch, SYMBOL_NAME (sym), + blk->size, TYPE_LENGTH (SYMBOL_TYPE (sym))); + SYMBOL_VALUE_BYTES (sym) = (char *) + obstack_alloc (&objfile->symbol_obstack, blk->size); + memcpy (SYMBOL_VALUE_BYTES (sym), blk->data, blk->size); + SYMBOL_CLASS (sym) = LOC_CONST_BYTES; + break; + + /* The DW_AT_const_value attributes are supposed to carry the + symbol's value "represented as it would be on the target + architecture." By the time we get here, it's already been + converted to host endianness, so we just need to sign- or + zero-extend it as appropriate. */ + case DW_FORM_data1: + dwarf2_const_value_data (attr, sym, 8); + break; + case DW_FORM_data2: + dwarf2_const_value_data (attr, sym, 16); + break; + case DW_FORM_data4: + dwarf2_const_value_data (attr, sym, 32); + break; + case DW_FORM_data8: + dwarf2_const_value_data (attr, sym, 64); + break; + + case DW_FORM_sdata: + SYMBOL_VALUE (sym) = DW_SND (attr); + SYMBOL_CLASS (sym) = LOC_CONST; + break; + + case DW_FORM_udata: + SYMBOL_VALUE (sym) = DW_UNSND (attr); + SYMBOL_CLASS (sym) = LOC_CONST; + break; + + default: + complain (&dwarf2_unsupported_const_value_attr, + dwarf_form_name (attr->form)); + SYMBOL_VALUE (sym) = 0; + SYMBOL_CLASS (sym) = LOC_CONST; + break; + } +} + + +/* Given an attr with a DW_FORM_dataN value in host byte order, sign- + or zero-extend it as appropriate for the symbol's type. */ +static void +dwarf2_const_value_data (struct attribute *attr, + struct symbol *sym, + int bits) +{ + LONGEST l = DW_UNSND (attr); + + if (bits < sizeof (l) * 8) + { + if (TYPE_UNSIGNED (SYMBOL_TYPE (sym))) + l &= ((LONGEST) 1 << bits) - 1; + else + l = (l << (sizeof (l) * 8 - bits)) >> (sizeof (l) * 8 - bits); + } + + SYMBOL_VALUE (sym) = l; + SYMBOL_CLASS (sym) = LOC_CONST; +} + + +/* Return the type of the die in question using its DW_AT_type attribute. */ + +static struct type * +die_type (struct die_info *die, struct objfile *objfile, + const struct comp_unit_head *cu_header) +{ + struct type *type; + struct attribute *type_attr; + struct die_info *type_die; + unsigned int ref; + + type_attr = dwarf_attr (die, DW_AT_type); + if (!type_attr) + { + /* A missing DW_AT_type represents a void type. */ + return dwarf2_fundamental_type (objfile, FT_VOID); + } + else + { + ref = dwarf2_get_ref_die_offset (type_attr); + type_die = follow_die_ref (ref); + if (!type_die) + { + error ("Dwarf Error: Cannot find referent at offset %d.", ref); + return NULL; + } + } + type = tag_type_to_type (type_die, objfile, cu_header); + if (!type) + { + dump_die (type_die); + error ("Dwarf Error: Problem turning type die at offset into gdb type."); + } + return type; +} + +/* Return the containing type of the die in question using its + DW_AT_containing_type attribute. */ + +static struct type * +die_containing_type (struct die_info *die, struct objfile *objfile, + const struct comp_unit_head *cu_header) +{ + struct type *type = NULL; + struct attribute *type_attr; + struct die_info *type_die = NULL; + unsigned int ref; + + type_attr = dwarf_attr (die, DW_AT_containing_type); + if (type_attr) + { + ref = dwarf2_get_ref_die_offset (type_attr); + type_die = follow_die_ref (ref); + if (!type_die) + { + error ("Dwarf Error: Cannot find referent at offset %d.", ref); + return NULL; + } + type = tag_type_to_type (type_die, objfile, cu_header); + } + if (!type) + { + if (type_die) + dump_die (type_die); + error ("Dwarf Error: Problem turning containing type into gdb type."); + } + return type; +} + +#if 0 +static struct type * +type_at_offset (unsigned int offset, struct objfile *objfile) +{ + struct die_info *die; + struct type *type; + + die = follow_die_ref (offset); + if (!die) + { + error ("Dwarf Error: Cannot find type referent at offset %d.", offset); + return NULL; + } + type = tag_type_to_type (die, objfile); + return type; +} +#endif + +static struct type * +tag_type_to_type (struct die_info *die, struct objfile *objfile, + const struct comp_unit_head *cu_header) +{ + if (die->type) + { + return die->type; + } + else + { + read_type_die (die, objfile, cu_header); + if (!die->type) + { + dump_die (die); + error ("Dwarf Error: Cannot find type of die."); + } + return die->type; + } +} + +static void +read_type_die (struct die_info *die, struct objfile *objfile, + const struct comp_unit_head *cu_header) +{ + switch (die->tag) + { + case DW_TAG_class_type: + case DW_TAG_structure_type: + case DW_TAG_union_type: + read_structure_scope (die, objfile, cu_header); + break; + case DW_TAG_enumeration_type: + read_enumeration (die, objfile, cu_header); + break; + case DW_TAG_subprogram: + case DW_TAG_subroutine_type: + read_subroutine_type (die, objfile, cu_header); + break; + case DW_TAG_array_type: + read_array_type (die, objfile, cu_header); + break; + case DW_TAG_pointer_type: + read_tag_pointer_type (die, objfile, cu_header); + break; + case DW_TAG_ptr_to_member_type: + read_tag_ptr_to_member_type (die, objfile, cu_header); + break; + case DW_TAG_reference_type: + read_tag_reference_type (die, objfile, cu_header); + break; + case DW_TAG_const_type: + read_tag_const_type (die, objfile, cu_header); + break; + case DW_TAG_volatile_type: + read_tag_volatile_type (die, objfile, cu_header); + break; + case DW_TAG_string_type: + read_tag_string_type (die, objfile); + break; + case DW_TAG_typedef: + read_typedef (die, objfile, cu_header); + break; + case DW_TAG_base_type: + read_base_type (die, objfile); + break; + default: + complain (&dwarf2_unexpected_tag, dwarf_tag_name (die->tag)); + break; + } +} + +static struct type * +dwarf_base_type (int encoding, int size, struct objfile *objfile) +{ + /* FIXME - this should not produce a new (struct type *) + every time. It should cache base types. */ + struct type *type; + switch (encoding) + { + case DW_ATE_address: + type = dwarf2_fundamental_type (objfile, FT_VOID); + return type; + case DW_ATE_boolean: + type = dwarf2_fundamental_type (objfile, FT_BOOLEAN); + return type; + case DW_ATE_complex_float: + if (size == 16) + { + type = dwarf2_fundamental_type (objfile, FT_DBL_PREC_COMPLEX); + } + else + { + type = dwarf2_fundamental_type (objfile, FT_COMPLEX); + } + return type; + case DW_ATE_float: + if (size == 8) + { + type = dwarf2_fundamental_type (objfile, FT_DBL_PREC_FLOAT); + } + else + { + type = dwarf2_fundamental_type (objfile, FT_FLOAT); + } + return type; + case DW_ATE_signed: + switch (size) + { + case 1: + type = dwarf2_fundamental_type (objfile, FT_SIGNED_CHAR); + break; + case 2: + type = dwarf2_fundamental_type (objfile, FT_SIGNED_SHORT); + break; + default: + case 4: + type = dwarf2_fundamental_type (objfile, FT_SIGNED_INTEGER); + break; + } + return type; + case DW_ATE_signed_char: + type = dwarf2_fundamental_type (objfile, FT_SIGNED_CHAR); + return type; + case DW_ATE_unsigned: + switch (size) + { + case 1: + type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_CHAR); + break; + case 2: + type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_SHORT); + break; + default: + case 4: + type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_INTEGER); + break; + } + return type; + case DW_ATE_unsigned_char: + type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_CHAR); + return type; + default: + type = dwarf2_fundamental_type (objfile, FT_SIGNED_INTEGER); + return type; + } +} + +#if 0 +struct die_info * +copy_die (struct die_info *old_die) +{ + struct die_info *new_die; + int i, num_attrs; + + new_die = (struct die_info *) xmalloc (sizeof (struct die_info)); + memset (new_die, 0, sizeof (struct die_info)); + + new_die->tag = old_die->tag; + new_die->has_children = old_die->has_children; + new_die->abbrev = old_die->abbrev; + new_die->offset = old_die->offset; + new_die->type = NULL; + + num_attrs = old_die->num_attrs; + new_die->num_attrs = num_attrs; + new_die->attrs = (struct attribute *) + xmalloc (num_attrs * sizeof (struct attribute)); + + for (i = 0; i < old_die->num_attrs; ++i) + { + new_die->attrs[i].name = old_die->attrs[i].name; + new_die->attrs[i].form = old_die->attrs[i].form; + new_die->attrs[i].u.addr = old_die->attrs[i].u.addr; + } + + new_die->next = NULL; + return new_die; +} +#endif + +/* Return sibling of die, NULL if no sibling. */ + +static struct die_info * +sibling_die (struct die_info *die) +{ + int nesting_level = 0; + + if (!die->has_children) + { + if (die->next && (die->next->tag == 0)) + { + return NULL; + } + else + { + return die->next; + } + } + else + { + do + { + if (die->has_children) + { + nesting_level++; + } + if (die->tag == 0) + { + nesting_level--; + } + die = die->next; + } + while (nesting_level); + if (die && (die->tag == 0)) + { + return NULL; + } + else + { + return die; + } + } +} + +/* Get linkage name of a die, return NULL if not found. */ + +static char * +dwarf2_linkage_name (struct die_info *die) +{ + struct attribute *attr; + + attr = dwarf_attr (die, DW_AT_MIPS_linkage_name); + if (attr && DW_STRING (attr)) + return DW_STRING (attr); + attr = dwarf_attr (die, DW_AT_name); + if (attr && DW_STRING (attr)) + return DW_STRING (attr); + return NULL; +} + +/* Convert a DIE tag into its string name. */ + +static char * +dwarf_tag_name (register unsigned tag) +{ + switch (tag) + { + case DW_TAG_padding: + return "DW_TAG_padding"; + case DW_TAG_array_type: + return "DW_TAG_array_type"; + case DW_TAG_class_type: + return "DW_TAG_class_type"; + case DW_TAG_entry_point: + return "DW_TAG_entry_point"; + case DW_TAG_enumeration_type: + return "DW_TAG_enumeration_type"; + case DW_TAG_formal_parameter: + return "DW_TAG_formal_parameter"; + case DW_TAG_imported_declaration: + return "DW_TAG_imported_declaration"; + case DW_TAG_label: + return "DW_TAG_label"; + case DW_TAG_lexical_block: + return "DW_TAG_lexical_block"; + case DW_TAG_member: + return "DW_TAG_member"; + case DW_TAG_pointer_type: + return "DW_TAG_pointer_type"; + case DW_TAG_reference_type: + return "DW_TAG_reference_type"; + case DW_TAG_compile_unit: + return "DW_TAG_compile_unit"; + case DW_TAG_string_type: + return "DW_TAG_string_type"; + case DW_TAG_structure_type: + return "DW_TAG_structure_type"; + case DW_TAG_subroutine_type: + return "DW_TAG_subroutine_type"; + case DW_TAG_typedef: + return "DW_TAG_typedef"; + case DW_TAG_union_type: + return "DW_TAG_union_type"; + case DW_TAG_unspecified_parameters: + return "DW_TAG_unspecified_parameters"; + case DW_TAG_variant: + return "DW_TAG_variant"; + case DW_TAG_common_block: + return "DW_TAG_common_block"; + case DW_TAG_common_inclusion: + return "DW_TAG_common_inclusion"; + case DW_TAG_inheritance: + return "DW_TAG_inheritance"; + case DW_TAG_inlined_subroutine: + return "DW_TAG_inlined_subroutine"; + case DW_TAG_module: + return "DW_TAG_module"; + case DW_TAG_ptr_to_member_type: + return "DW_TAG_ptr_to_member_type"; + case DW_TAG_set_type: + return "DW_TAG_set_type"; + case DW_TAG_subrange_type: + return "DW_TAG_subrange_type"; + case DW_TAG_with_stmt: + return "DW_TAG_with_stmt"; + case DW_TAG_access_declaration: + return "DW_TAG_access_declaration"; + case DW_TAG_base_type: + return "DW_TAG_base_type"; + case DW_TAG_catch_block: + return "DW_TAG_catch_block"; + case DW_TAG_const_type: + return "DW_TAG_const_type"; + case DW_TAG_constant: + return "DW_TAG_constant"; + case DW_TAG_enumerator: + return "DW_TAG_enumerator"; + case DW_TAG_file_type: + return "DW_TAG_file_type"; + case DW_TAG_friend: + return "DW_TAG_friend"; + case DW_TAG_namelist: + return "DW_TAG_namelist"; + case DW_TAG_namelist_item: + return "DW_TAG_namelist_item"; + case DW_TAG_packed_type: + return "DW_TAG_packed_type"; + case DW_TAG_subprogram: + return "DW_TAG_subprogram"; + case DW_TAG_template_type_param: + return "DW_TAG_template_type_param"; + case DW_TAG_template_value_param: + return "DW_TAG_template_value_param"; + case DW_TAG_thrown_type: + return "DW_TAG_thrown_type"; + case DW_TAG_try_block: + return "DW_TAG_try_block"; + case DW_TAG_variant_part: + return "DW_TAG_variant_part"; + case DW_TAG_variable: + return "DW_TAG_variable"; + case DW_TAG_volatile_type: + return "DW_TAG_volatile_type"; + case DW_TAG_MIPS_loop: + return "DW_TAG_MIPS_loop"; + case DW_TAG_format_label: + return "DW_TAG_format_label"; + case DW_TAG_function_template: + return "DW_TAG_function_template"; + case DW_TAG_class_template: + return "DW_TAG_class_template"; + default: + return "DW_TAG_<unknown>"; + } +} + +/* Convert a DWARF attribute code into its string name. */ + +static char * +dwarf_attr_name (register unsigned attr) +{ + switch (attr) + { + case DW_AT_sibling: + return "DW_AT_sibling"; + case DW_AT_location: + return "DW_AT_location"; + case DW_AT_name: + return "DW_AT_name"; + case DW_AT_ordering: + return "DW_AT_ordering"; + case DW_AT_subscr_data: + return "DW_AT_subscr_data"; + case DW_AT_byte_size: + return "DW_AT_byte_size"; + case DW_AT_bit_offset: + return "DW_AT_bit_offset"; + case DW_AT_bit_size: + return "DW_AT_bit_size"; + case DW_AT_element_list: + return "DW_AT_element_list"; + case DW_AT_stmt_list: + return "DW_AT_stmt_list"; + case DW_AT_low_pc: + return "DW_AT_low_pc"; + case DW_AT_high_pc: + return "DW_AT_high_pc"; + case DW_AT_language: + return "DW_AT_language"; + case DW_AT_member: + return "DW_AT_member"; + case DW_AT_discr: + return "DW_AT_discr"; + case DW_AT_discr_value: + return "DW_AT_discr_value"; + case DW_AT_visibility: + return "DW_AT_visibility"; + case DW_AT_import: + return "DW_AT_import"; + case DW_AT_string_length: + return "DW_AT_string_length"; + case DW_AT_common_reference: + return "DW_AT_common_reference"; + case DW_AT_comp_dir: + return "DW_AT_comp_dir"; + case DW_AT_const_value: + return "DW_AT_const_value"; + case DW_AT_containing_type: + return "DW_AT_containing_type"; + case DW_AT_default_value: + return "DW_AT_default_value"; + case DW_AT_inline: + return "DW_AT_inline"; + case DW_AT_is_optional: + return "DW_AT_is_optional"; + case DW_AT_lower_bound: + return "DW_AT_lower_bound"; + case DW_AT_producer: + return "DW_AT_producer"; + case DW_AT_prototyped: + return "DW_AT_prototyped"; + case DW_AT_return_addr: + return "DW_AT_return_addr"; + case DW_AT_start_scope: + return "DW_AT_start_scope"; + case DW_AT_stride_size: + return "DW_AT_stride_size"; + case DW_AT_upper_bound: + return "DW_AT_upper_bound"; + case DW_AT_abstract_origin: + return "DW_AT_abstract_origin"; + case DW_AT_accessibility: + return "DW_AT_accessibility"; + case DW_AT_address_class: + return "DW_AT_address_class"; + case DW_AT_artificial: + return "DW_AT_artificial"; + case DW_AT_base_types: + return "DW_AT_base_types"; + case DW_AT_calling_convention: + return "DW_AT_calling_convention"; + case DW_AT_count: + return "DW_AT_count"; + case DW_AT_data_member_location: + return "DW_AT_data_member_location"; + case DW_AT_decl_column: + return "DW_AT_decl_column"; + case DW_AT_decl_file: + return "DW_AT_decl_file"; + case DW_AT_decl_line: + return "DW_AT_decl_line"; + case DW_AT_declaration: + return "DW_AT_declaration"; + case DW_AT_discr_list: + return "DW_AT_discr_list"; + case DW_AT_encoding: + return "DW_AT_encoding"; + case DW_AT_external: + return "DW_AT_external"; + case DW_AT_frame_base: + return "DW_AT_frame_base"; + case DW_AT_friend: + return "DW_AT_friend"; + case DW_AT_identifier_case: + return "DW_AT_identifier_case"; + case DW_AT_macro_info: + return "DW_AT_macro_info"; + case DW_AT_namelist_items: + return "DW_AT_namelist_items"; + case DW_AT_priority: + return "DW_AT_priority"; + case DW_AT_segment: + return "DW_AT_segment"; + case DW_AT_specification: + return "DW_AT_specification"; + case DW_AT_static_link: + return "DW_AT_static_link"; + case DW_AT_type: + return "DW_AT_type"; + case DW_AT_use_location: + return "DW_AT_use_location"; + case DW_AT_variable_parameter: + return "DW_AT_variable_parameter"; + case DW_AT_virtuality: + return "DW_AT_virtuality"; + case DW_AT_vtable_elem_location: + return "DW_AT_vtable_elem_location"; + +#ifdef MIPS + case DW_AT_MIPS_fde: + return "DW_AT_MIPS_fde"; + case DW_AT_MIPS_loop_begin: + return "DW_AT_MIPS_loop_begin"; + case DW_AT_MIPS_tail_loop_begin: + return "DW_AT_MIPS_tail_loop_begin"; + case DW_AT_MIPS_epilog_begin: + return "DW_AT_MIPS_epilog_begin"; + case DW_AT_MIPS_loop_unroll_factor: + return "DW_AT_MIPS_loop_unroll_factor"; + case DW_AT_MIPS_software_pipeline_depth: + return "DW_AT_MIPS_software_pipeline_depth"; + case DW_AT_MIPS_linkage_name: + return "DW_AT_MIPS_linkage_name"; +#endif + + case DW_AT_sf_names: + return "DW_AT_sf_names"; + case DW_AT_src_info: + return "DW_AT_src_info"; + case DW_AT_mac_info: + return "DW_AT_mac_info"; + case DW_AT_src_coords: + return "DW_AT_src_coords"; + case DW_AT_body_begin: + return "DW_AT_body_begin"; + case DW_AT_body_end: + return "DW_AT_body_end"; + case DW_AT_GNU_vector: + return "DW_AT_GNU_vector"; + default: + return "DW_AT_<unknown>"; + } +} + +/* Convert a DWARF value form code into its string name. */ + +static char * +dwarf_form_name (register unsigned form) +{ + switch (form) + { + case DW_FORM_addr: + return "DW_FORM_addr"; + case DW_FORM_block2: + return "DW_FORM_block2"; + case DW_FORM_block4: + return "DW_FORM_block4"; + case DW_FORM_data2: + return "DW_FORM_data2"; + case DW_FORM_data4: + return "DW_FORM_data4"; + case DW_FORM_data8: + return "DW_FORM_data8"; + case DW_FORM_string: + return "DW_FORM_string"; + case DW_FORM_block: + return "DW_FORM_block"; + case DW_FORM_block1: + return "DW_FORM_block1"; + case DW_FORM_data1: + return "DW_FORM_data1"; + case DW_FORM_flag: + return "DW_FORM_flag"; + case DW_FORM_sdata: + return "DW_FORM_sdata"; + case DW_FORM_strp: + return "DW_FORM_strp"; + case DW_FORM_udata: + return "DW_FORM_udata"; + case DW_FORM_ref_addr: + return "DW_FORM_ref_addr"; + case DW_FORM_ref1: + return "DW_FORM_ref1"; + case DW_FORM_ref2: + return "DW_FORM_ref2"; + case DW_FORM_ref4: + return "DW_FORM_ref4"; + case DW_FORM_ref8: + return "DW_FORM_ref8"; + case DW_FORM_ref_udata: + return "DW_FORM_ref_udata"; + case DW_FORM_indirect: + return "DW_FORM_indirect"; + default: + return "DW_FORM_<unknown>"; + } +} + +/* Convert a DWARF stack opcode into its string name. */ + +static char * +dwarf_stack_op_name (register unsigned op) +{ + switch (op) + { + case DW_OP_addr: + return "DW_OP_addr"; + case DW_OP_deref: + return "DW_OP_deref"; + case DW_OP_const1u: + return "DW_OP_const1u"; + case DW_OP_const1s: + return "DW_OP_const1s"; + case DW_OP_const2u: + return "DW_OP_const2u"; + case DW_OP_const2s: + return "DW_OP_const2s"; + case DW_OP_const4u: + return "DW_OP_const4u"; + case DW_OP_const4s: + return "DW_OP_const4s"; + case DW_OP_const8u: + return "DW_OP_const8u"; + case DW_OP_const8s: + return "DW_OP_const8s"; + case DW_OP_constu: + return "DW_OP_constu"; + case DW_OP_consts: + return "DW_OP_consts"; + case DW_OP_dup: + return "DW_OP_dup"; + case DW_OP_drop: + return "DW_OP_drop"; + case DW_OP_over: + return "DW_OP_over"; + case DW_OP_pick: + return "DW_OP_pick"; + case DW_OP_swap: + return "DW_OP_swap"; + case DW_OP_rot: + return "DW_OP_rot"; + case DW_OP_xderef: + return "DW_OP_xderef"; + case DW_OP_abs: + return "DW_OP_abs"; + case DW_OP_and: + return "DW_OP_and"; + case DW_OP_div: + return "DW_OP_div"; + case DW_OP_minus: + return "DW_OP_minus"; + case DW_OP_mod: + return "DW_OP_mod"; + case DW_OP_mul: + return "DW_OP_mul"; + case DW_OP_neg: + return "DW_OP_neg"; + case DW_OP_not: + return "DW_OP_not"; + case DW_OP_or: + return "DW_OP_or"; + case DW_OP_plus: + return "DW_OP_plus"; + case DW_OP_plus_uconst: + return "DW_OP_plus_uconst"; + case DW_OP_shl: + return "DW_OP_shl"; + case DW_OP_shr: + return "DW_OP_shr"; + case DW_OP_shra: + return "DW_OP_shra"; + case DW_OP_xor: + return "DW_OP_xor"; + case DW_OP_bra: + return "DW_OP_bra"; + case DW_OP_eq: + return "DW_OP_eq"; + case DW_OP_ge: + return "DW_OP_ge"; + case DW_OP_gt: + return "DW_OP_gt"; + case DW_OP_le: + return "DW_OP_le"; + case DW_OP_lt: + return "DW_OP_lt"; + case DW_OP_ne: + return "DW_OP_ne"; + case DW_OP_skip: + return "DW_OP_skip"; + case DW_OP_lit0: + return "DW_OP_lit0"; + case DW_OP_lit1: + return "DW_OP_lit1"; + case DW_OP_lit2: + return "DW_OP_lit2"; + case DW_OP_lit3: + return "DW_OP_lit3"; + case DW_OP_lit4: + return "DW_OP_lit4"; + case DW_OP_lit5: + return "DW_OP_lit5"; + case DW_OP_lit6: + return "DW_OP_lit6"; + case DW_OP_lit7: + return "DW_OP_lit7"; + case DW_OP_lit8: + return "DW_OP_lit8"; + case DW_OP_lit9: + return "DW_OP_lit9"; + case DW_OP_lit10: + return "DW_OP_lit10"; + case DW_OP_lit11: + return "DW_OP_lit11"; + case DW_OP_lit12: + return "DW_OP_lit12"; + case DW_OP_lit13: + return "DW_OP_lit13"; + case DW_OP_lit14: + return "DW_OP_lit14"; + case DW_OP_lit15: + return "DW_OP_lit15"; + case DW_OP_lit16: + return "DW_OP_lit16"; + case DW_OP_lit17: + return "DW_OP_lit17"; + case DW_OP_lit18: + return "DW_OP_lit18"; + case DW_OP_lit19: + return "DW_OP_lit19"; + case DW_OP_lit20: + return "DW_OP_lit20"; + case DW_OP_lit21: + return "DW_OP_lit21"; + case DW_OP_lit22: + return "DW_OP_lit22"; + case DW_OP_lit23: + return "DW_OP_lit23"; + case DW_OP_lit24: + return "DW_OP_lit24"; + case DW_OP_lit25: + return "DW_OP_lit25"; + case DW_OP_lit26: + return "DW_OP_lit26"; + case DW_OP_lit27: + return "DW_OP_lit27"; + case DW_OP_lit28: + return "DW_OP_lit28"; + case DW_OP_lit29: + return "DW_OP_lit29"; + case DW_OP_lit30: + return "DW_OP_lit30"; + case DW_OP_lit31: + return "DW_OP_lit31"; + case DW_OP_reg0: + return "DW_OP_reg0"; + case DW_OP_reg1: + return "DW_OP_reg1"; + case DW_OP_reg2: + return "DW_OP_reg2"; + case DW_OP_reg3: + return "DW_OP_reg3"; + case DW_OP_reg4: + return "DW_OP_reg4"; + case DW_OP_reg5: + return "DW_OP_reg5"; + case DW_OP_reg6: + return "DW_OP_reg6"; + case DW_OP_reg7: + return "DW_OP_reg7"; + case DW_OP_reg8: + return "DW_OP_reg8"; + case DW_OP_reg9: + return "DW_OP_reg9"; + case DW_OP_reg10: + return "DW_OP_reg10"; + case DW_OP_reg11: + return "DW_OP_reg11"; + case DW_OP_reg12: + return "DW_OP_reg12"; + case DW_OP_reg13: + return "DW_OP_reg13"; + case DW_OP_reg14: + return "DW_OP_reg14"; + case DW_OP_reg15: + return "DW_OP_reg15"; + case DW_OP_reg16: + return "DW_OP_reg16"; + case DW_OP_reg17: + return "DW_OP_reg17"; + case DW_OP_reg18: + return "DW_OP_reg18"; + case DW_OP_reg19: + return "DW_OP_reg19"; + case DW_OP_reg20: + return "DW_OP_reg20"; + case DW_OP_reg21: + return "DW_OP_reg21"; + case DW_OP_reg22: + return "DW_OP_reg22"; + case DW_OP_reg23: + return "DW_OP_reg23"; + case DW_OP_reg24: + return "DW_OP_reg24"; + case DW_OP_reg25: + return "DW_OP_reg25"; + case DW_OP_reg26: + return "DW_OP_reg26"; + case DW_OP_reg27: + return "DW_OP_reg27"; + case DW_OP_reg28: + return "DW_OP_reg28"; + case DW_OP_reg29: + return "DW_OP_reg29"; + case DW_OP_reg30: + return "DW_OP_reg30"; + case DW_OP_reg31: + return "DW_OP_reg31"; + case DW_OP_breg0: + return "DW_OP_breg0"; + case DW_OP_breg1: + return "DW_OP_breg1"; + case DW_OP_breg2: + return "DW_OP_breg2"; + case DW_OP_breg3: + return "DW_OP_breg3"; + case DW_OP_breg4: + return "DW_OP_breg4"; + case DW_OP_breg5: + return "DW_OP_breg5"; + case DW_OP_breg6: + return "DW_OP_breg6"; + case DW_OP_breg7: + return "DW_OP_breg7"; + case DW_OP_breg8: + return "DW_OP_breg8"; + case DW_OP_breg9: + return "DW_OP_breg9"; + case DW_OP_breg10: + return "DW_OP_breg10"; + case DW_OP_breg11: + return "DW_OP_breg11"; + case DW_OP_breg12: + return "DW_OP_breg12"; + case DW_OP_breg13: + return "DW_OP_breg13"; + case DW_OP_breg14: + return "DW_OP_breg14"; + case DW_OP_breg15: + return "DW_OP_breg15"; + case DW_OP_breg16: + return "DW_OP_breg16"; + case DW_OP_breg17: + return "DW_OP_breg17"; + case DW_OP_breg18: + return "DW_OP_breg18"; + case DW_OP_breg19: + return "DW_OP_breg19"; + case DW_OP_breg20: + return "DW_OP_breg20"; + case DW_OP_breg21: + return "DW_OP_breg21"; + case DW_OP_breg22: + return "DW_OP_breg22"; + case DW_OP_breg23: + return "DW_OP_breg23"; + case DW_OP_breg24: + return "DW_OP_breg24"; + case DW_OP_breg25: + return "DW_OP_breg25"; + case DW_OP_breg26: + return "DW_OP_breg26"; + case DW_OP_breg27: + return "DW_OP_breg27"; + case DW_OP_breg28: + return "DW_OP_breg28"; + case DW_OP_breg29: + return "DW_OP_breg29"; + case DW_OP_breg30: + return "DW_OP_breg30"; + case DW_OP_breg31: + return "DW_OP_breg31"; + case DW_OP_regx: + return "DW_OP_regx"; + case DW_OP_fbreg: + return "DW_OP_fbreg"; + case DW_OP_bregx: + return "DW_OP_bregx"; + case DW_OP_piece: + return "DW_OP_piece"; + case DW_OP_deref_size: + return "DW_OP_deref_size"; + case DW_OP_xderef_size: + return "DW_OP_xderef_size"; + case DW_OP_nop: + return "DW_OP_nop"; + default: + return "OP_<unknown>"; + } +} + +static char * +dwarf_bool_name (unsigned mybool) +{ + if (mybool) + return "TRUE"; + else + return "FALSE"; +} + +/* Convert a DWARF type code into its string name. */ + +static char * +dwarf_type_encoding_name (register unsigned enc) +{ + switch (enc) + { + case DW_ATE_address: + return "DW_ATE_address"; + case DW_ATE_boolean: + return "DW_ATE_boolean"; + case DW_ATE_complex_float: + return "DW_ATE_complex_float"; + case DW_ATE_float: + return "DW_ATE_float"; + case DW_ATE_signed: + return "DW_ATE_signed"; + case DW_ATE_signed_char: + return "DW_ATE_signed_char"; + case DW_ATE_unsigned: + return "DW_ATE_unsigned"; + case DW_ATE_unsigned_char: + return "DW_ATE_unsigned_char"; + default: + return "DW_ATE_<unknown>"; + } +} + +/* Convert a DWARF call frame info operation to its string name. */ + +#if 0 +static char * +dwarf_cfi_name (register unsigned cfi_opc) +{ + switch (cfi_opc) + { + case DW_CFA_advance_loc: + return "DW_CFA_advance_loc"; + case DW_CFA_offset: + return "DW_CFA_offset"; + case DW_CFA_restore: + return "DW_CFA_restore"; + case DW_CFA_nop: + return "DW_CFA_nop"; + case DW_CFA_set_loc: + return "DW_CFA_set_loc"; + case DW_CFA_advance_loc1: + return "DW_CFA_advance_loc1"; + case DW_CFA_advance_loc2: + return "DW_CFA_advance_loc2"; + case DW_CFA_advance_loc4: + return "DW_CFA_advance_loc4"; + case DW_CFA_offset_extended: + return "DW_CFA_offset_extended"; + case DW_CFA_restore_extended: + return "DW_CFA_restore_extended"; + case DW_CFA_undefined: + return "DW_CFA_undefined"; + case DW_CFA_same_value: + return "DW_CFA_same_value"; + case DW_CFA_register: + return "DW_CFA_register"; + case DW_CFA_remember_state: + return "DW_CFA_remember_state"; + case DW_CFA_restore_state: + return "DW_CFA_restore_state"; + case DW_CFA_def_cfa: + return "DW_CFA_def_cfa"; + case DW_CFA_def_cfa_register: + return "DW_CFA_def_cfa_register"; + case DW_CFA_def_cfa_offset: + return "DW_CFA_def_cfa_offset"; + + /* DWARF 3 */ + case DW_CFA_def_cfa_expression: + return "DW_CFA_def_cfa_expression"; + case DW_CFA_expression: + return "DW_CFA_expression"; + case DW_CFA_offset_extended_sf: + return "DW_CFA_offset_extended_sf"; + case DW_CFA_def_cfa_sf: + return "DW_CFA_def_cfa_sf"; + case DW_CFA_def_cfa_offset_sf: + return "DW_CFA_def_cfa_offset_sf"; + + /* SGI/MIPS specific */ + case DW_CFA_MIPS_advance_loc8: + return "DW_CFA_MIPS_advance_loc8"; + + /* GNU extensions */ + case DW_CFA_GNU_window_save: + return "DW_CFA_GNU_window_save"; + case DW_CFA_GNU_args_size: + return "DW_CFA_GNU_args_size"; + case DW_CFA_GNU_negative_offset_extended: + return "DW_CFA_GNU_negative_offset_extended"; + + default: + return "DW_CFA_<unknown>"; + } +} +#endif + +static void +dump_die (struct die_info *die) +{ + unsigned int i; + + fprintf_unfiltered (gdb_stderr, "Die: %s (abbrev = %d, offset = %d)\n", + dwarf_tag_name (die->tag), die->abbrev, die->offset); + fprintf_unfiltered (gdb_stderr, "\thas children: %s\n", + dwarf_bool_name (die->has_children)); + + fprintf_unfiltered (gdb_stderr, "\tattributes:\n"); + for (i = 0; i < die->num_attrs; ++i) + { + fprintf_unfiltered (gdb_stderr, "\t\t%s (%s) ", + dwarf_attr_name (die->attrs[i].name), + dwarf_form_name (die->attrs[i].form)); + switch (die->attrs[i].form) + { + case DW_FORM_ref_addr: + case DW_FORM_addr: + fprintf_unfiltered (gdb_stderr, "address: "); + print_address_numeric (DW_ADDR (&die->attrs[i]), 1, gdb_stderr); + break; + case DW_FORM_block2: + case DW_FORM_block4: + case DW_FORM_block: + case DW_FORM_block1: + fprintf_unfiltered (gdb_stderr, "block: size %d", DW_BLOCK (&die->attrs[i])->size); + break; + case DW_FORM_data1: + case DW_FORM_data2: + case DW_FORM_data4: + case DW_FORM_data8: + case DW_FORM_ref1: + case DW_FORM_ref2: + case DW_FORM_ref4: + case DW_FORM_udata: + case DW_FORM_sdata: + fprintf_unfiltered (gdb_stderr, "constant: %ld", DW_UNSND (&die->attrs[i])); + break; + case DW_FORM_string: + case DW_FORM_strp: + fprintf_unfiltered (gdb_stderr, "string: \"%s\"", + DW_STRING (&die->attrs[i]) + ? DW_STRING (&die->attrs[i]) : ""); + break; + case DW_FORM_flag: + if (DW_UNSND (&die->attrs[i])) + fprintf_unfiltered (gdb_stderr, "flag: TRUE"); + else + fprintf_unfiltered (gdb_stderr, "flag: FALSE"); + break; + case DW_FORM_indirect: + /* the reader will have reduced the indirect form to + the "base form" so this form should not occur */ + fprintf_unfiltered (gdb_stderr, "unexpected attribute form: DW_FORM_indirect"); + break; + default: + fprintf_unfiltered (gdb_stderr, "unsupported attribute form: %d.", + die->attrs[i].form); + } + fprintf_unfiltered (gdb_stderr, "\n"); + } +} + +static void +dump_die_list (struct die_info *die) +{ + while (die) + { + dump_die (die); + die = die->next; + } +} + +static void +store_in_ref_table (unsigned int offset, struct die_info *die) +{ + int h; + struct die_info *old; + + h = (offset % REF_HASH_SIZE); + old = die_ref_table[h]; + die->next_ref = old; + die_ref_table[h] = die; +} + + +static void +dwarf2_empty_hash_tables (void) +{ + memset (die_ref_table, 0, sizeof (die_ref_table)); +} + +static unsigned int +dwarf2_get_ref_die_offset (struct attribute *attr) +{ + unsigned int result = 0; + + switch (attr->form) + { + case DW_FORM_ref_addr: + result = DW_ADDR (attr); + break; + case DW_FORM_ref1: + case DW_FORM_ref2: + case DW_FORM_ref4: + case DW_FORM_ref8: + case DW_FORM_ref_udata: + result = cu_header_offset + DW_UNSND (attr); + break; + default: + complain (&dwarf2_unsupported_die_ref_attr, dwarf_form_name (attr->form)); + } + return result; +} + +static struct die_info * +follow_die_ref (unsigned int offset) +{ + struct die_info *die; + int h; + + h = (offset % REF_HASH_SIZE); + die = die_ref_table[h]; + while (die) + { + if (die->offset == offset) + { + return die; + } + die = die->next_ref; + } + return NULL; +} + +static struct type * +dwarf2_fundamental_type (struct objfile *objfile, int typeid) +{ + if (typeid < 0 || typeid >= FT_NUM_MEMBERS) + { + error ("Dwarf Error: internal error - invalid fundamental type id %d.", + typeid); + } + + /* Look for this particular type in the fundamental type vector. If + one is not found, create and install one appropriate for the + current language and the current target machine. */ + + if (ftypes[typeid] == NULL) + { + ftypes[typeid] = cu_language_defn->la_fund_type (objfile, typeid); + } + + return (ftypes[typeid]); +} + +/* Decode simple location descriptions. + Given a pointer to a dwarf block that defines a location, compute + the location and return the value. + + FIXME: This is a kludge until we figure out a better + way to handle the location descriptions. + Gdb's design does not mesh well with the DWARF2 notion of a location + computing interpreter, which is a shame because the flexibility goes unused. + FIXME: Implement more operations as necessary. + + A location description containing no operations indicates that the + object is optimized out. The global optimized_out flag is set for + those, the return value is meaningless. + + When the result is a register number, the global isreg flag is set, + otherwise it is cleared. + + When the result is a base register offset, the global offreg flag is set + and the register number is returned in basereg, otherwise it is cleared. + + When the DW_OP_fbreg operation is encountered without a corresponding + DW_AT_frame_base attribute, the global islocal flag is set. + Hopefully the machine dependent code knows how to set up a virtual + frame pointer for the local references. + + Note that stack[0] is unused except as a default error return. + Note that stack overflow is not yet handled. */ + +static CORE_ADDR +decode_locdesc (struct dwarf_block *blk, struct objfile *objfile, + const struct comp_unit_head *cu_header) +{ + int i; + int size = blk->size; + char *data = blk->data; + CORE_ADDR stack[64]; + int stacki; + unsigned int bytes_read, unsnd; + unsigned char op; + + i = 0; + stacki = 0; + stack[stacki] = 0; + isreg = 0; + offreg = 0; + isderef = 0; + islocal = 0; + optimized_out = 1; + + while (i < size) + { + optimized_out = 0; + op = data[i++]; + switch (op) + { + case DW_OP_lit0: + case DW_OP_lit1: + case DW_OP_lit2: + case DW_OP_lit3: + case DW_OP_lit4: + case DW_OP_lit5: + case DW_OP_lit6: + case DW_OP_lit7: + case DW_OP_lit8: + case DW_OP_lit9: + case DW_OP_lit10: + case DW_OP_lit11: + case DW_OP_lit12: + case DW_OP_lit13: + case DW_OP_lit14: + case DW_OP_lit15: + case DW_OP_lit16: + case DW_OP_lit17: + case DW_OP_lit18: + case DW_OP_lit19: + case DW_OP_lit20: + case DW_OP_lit21: + case DW_OP_lit22: + case DW_OP_lit23: + case DW_OP_lit24: + case DW_OP_lit25: + case DW_OP_lit26: + case DW_OP_lit27: + case DW_OP_lit28: + case DW_OP_lit29: + case DW_OP_lit30: + case DW_OP_lit31: + stack[++stacki] = op - DW_OP_lit0; + break; + + case DW_OP_reg0: + case DW_OP_reg1: + case DW_OP_reg2: + case DW_OP_reg3: + case DW_OP_reg4: + case DW_OP_reg5: + case DW_OP_reg6: + case DW_OP_reg7: + case DW_OP_reg8: + case DW_OP_reg9: + case DW_OP_reg10: + case DW_OP_reg11: + case DW_OP_reg12: + case DW_OP_reg13: + case DW_OP_reg14: + case DW_OP_reg15: + case DW_OP_reg16: + case DW_OP_reg17: + case DW_OP_reg18: + case DW_OP_reg19: + case DW_OP_reg20: + case DW_OP_reg21: + case DW_OP_reg22: + case DW_OP_reg23: + case DW_OP_reg24: + case DW_OP_reg25: + case DW_OP_reg26: + case DW_OP_reg27: + case DW_OP_reg28: + case DW_OP_reg29: + case DW_OP_reg30: + case DW_OP_reg31: + isreg = 1; + stack[++stacki] = op - DW_OP_reg0; + break; + + case DW_OP_regx: + isreg = 1; + unsnd = read_unsigned_leb128 (NULL, (data + i), &bytes_read); + i += bytes_read; + stack[++stacki] = unsnd; + break; + + case DW_OP_breg0: + case DW_OP_breg1: + case DW_OP_breg2: + case DW_OP_breg3: + case DW_OP_breg4: + case DW_OP_breg5: + case DW_OP_breg6: + case DW_OP_breg7: + case DW_OP_breg8: + case DW_OP_breg9: + case DW_OP_breg10: + case DW_OP_breg11: + case DW_OP_breg12: + case DW_OP_breg13: + case DW_OP_breg14: + case DW_OP_breg15: + case DW_OP_breg16: + case DW_OP_breg17: + case DW_OP_breg18: + case DW_OP_breg19: + case DW_OP_breg20: + case DW_OP_breg21: + case DW_OP_breg22: + case DW_OP_breg23: + case DW_OP_breg24: + case DW_OP_breg25: + case DW_OP_breg26: + case DW_OP_breg27: + case DW_OP_breg28: + case DW_OP_breg29: + case DW_OP_breg30: + case DW_OP_breg31: + offreg = 1; + basereg = op - DW_OP_breg0; + stack[++stacki] = read_signed_leb128 (NULL, (data + i), &bytes_read); + i += bytes_read; + break; + + case DW_OP_bregx: + offreg = 1; + basereg = read_unsigned_leb128 (NULL, (data + i), &bytes_read); + i += bytes_read; + stack[++stacki] = read_signed_leb128 (NULL, (data + i), &bytes_read); + i += bytes_read; + break; + + case DW_OP_fbreg: + stack[++stacki] = read_signed_leb128 (NULL, (data + i), &bytes_read); + i += bytes_read; + if (frame_base_reg >= 0) + { + offreg = 1; + basereg = frame_base_reg; + stack[stacki] += frame_base_offset; + } + else + { + complain (&dwarf2_missing_at_frame_base); + islocal = 1; + } + break; + + case DW_OP_addr: + stack[++stacki] = read_address (objfile->obfd, &data[i], + cu_header, &bytes_read); + i += bytes_read; + break; + + case DW_OP_const1u: + stack[++stacki] = read_1_byte (objfile->obfd, &data[i]); + i += 1; + break; + + case DW_OP_const1s: + stack[++stacki] = read_1_signed_byte (objfile->obfd, &data[i]); + i += 1; + break; + + case DW_OP_const2u: + stack[++stacki] = read_2_bytes (objfile->obfd, &data[i]); + i += 2; + break; + + case DW_OP_const2s: + stack[++stacki] = read_2_signed_bytes (objfile->obfd, &data[i]); + i += 2; + break; + + case DW_OP_const4u: + stack[++stacki] = read_4_bytes (objfile->obfd, &data[i]); + i += 4; + break; + + case DW_OP_const4s: + stack[++stacki] = read_4_signed_bytes (objfile->obfd, &data[i]); + i += 4; + break; + + case DW_OP_constu: + stack[++stacki] = read_unsigned_leb128 (NULL, (data + i), + &bytes_read); + i += bytes_read; + break; + + case DW_OP_consts: + stack[++stacki] = read_signed_leb128 (NULL, (data + i), &bytes_read); + i += bytes_read; + break; + + case DW_OP_dup: + stack[stacki + 1] = stack[stacki]; + stacki++; + break; + + case DW_OP_plus: + stack[stacki - 1] += stack[stacki]; + stacki--; + break; + + case DW_OP_plus_uconst: + stack[stacki] += read_unsigned_leb128 (NULL, (data + i), &bytes_read); + i += bytes_read; + break; + + case DW_OP_minus: + stack[stacki - 1] -= stack[stacki]; + stacki--; + break; + + case DW_OP_deref: + isderef = 1; + /* If we're not the last op, then we definitely can't encode + this using GDB's address_class enum. */ + if (i < size) + complain (&dwarf2_complex_location_expr); + break; + + default: + complain (&dwarf2_unsupported_stack_op, dwarf_stack_op_name (op)); + return (stack[stacki]); + } + } + return (stack[stacki]); +} + +/* memory allocation interface */ + +/* ARGSUSED */ +static void +dwarf2_free_tmp_obstack (PTR ignore) +{ + obstack_free (&dwarf2_tmp_obstack, NULL); +} + +static struct dwarf_block * +dwarf_alloc_block (void) +{ + struct dwarf_block *blk; + + blk = (struct dwarf_block *) + obstack_alloc (&dwarf2_tmp_obstack, sizeof (struct dwarf_block)); + return (blk); +} + +static struct abbrev_info * +dwarf_alloc_abbrev (void) +{ + struct abbrev_info *abbrev; + + abbrev = (struct abbrev_info *) xmalloc (sizeof (struct abbrev_info)); + memset (abbrev, 0, sizeof (struct abbrev_info)); + return (abbrev); +} + +static struct die_info * +dwarf_alloc_die (void) +{ + struct die_info *die; + + die = (struct die_info *) xmalloc (sizeof (struct die_info)); + memset (die, 0, sizeof (struct die_info)); + return (die); +} + + +/* Macro support. */ + + +/* Return the full name of file number I in *LH's file name table. + Use COMP_DIR as the name of the current directory of the + compilation. The result is allocated using xmalloc; the caller is + responsible for freeing it. */ +static char * +file_full_name (int file, struct line_header *lh, const char *comp_dir) +{ + struct file_entry *fe = &lh->file_names[file - 1]; + + if (IS_ABSOLUTE_PATH (fe->name)) + return xstrdup (fe->name); + else + { + const char *dir; + int dir_len; + char *full_name; + + if (fe->dir_index) + dir = lh->include_dirs[fe->dir_index - 1]; + else + dir = comp_dir; + + if (dir) + { + dir_len = strlen (dir); + full_name = xmalloc (dir_len + 1 + strlen (fe->name) + 1); + strcpy (full_name, dir); + full_name[dir_len] = '/'; + strcpy (full_name + dir_len + 1, fe->name); + return full_name; + } + else + return xstrdup (fe->name); + } +} + + +static struct macro_source_file * +macro_start_file (int file, int line, + struct macro_source_file *current_file, + const char *comp_dir, + struct line_header *lh, struct objfile *objfile) +{ + /* The full name of this source file. */ + char *full_name = file_full_name (file, lh, comp_dir); + + /* We don't create a macro table for this compilation unit + at all until we actually get a filename. */ + if (! pending_macros) + pending_macros = new_macro_table (&objfile->symbol_obstack, + objfile->macro_cache); + + if (! current_file) + /* If we have no current file, then this must be the start_file + directive for the compilation unit's main source file. */ + current_file = macro_set_main (pending_macros, full_name); + else + current_file = macro_include (current_file, line, full_name); + + xfree (full_name); + + return current_file; +} + + +/* Copy the LEN characters at BUF to a xmalloc'ed block of memory, + followed by a null byte. */ +static char * +copy_string (const char *buf, int len) +{ + char *s = xmalloc (len + 1); + memcpy (s, buf, len); + s[len] = '\0'; + + return s; +} + + +static const char * +consume_improper_spaces (const char *p, const char *body) +{ + if (*p == ' ') + { + complain (&dwarf2_macro_spaces_in_definition, body); + + while (*p == ' ') + p++; + } + + return p; +} + + +static void +parse_macro_definition (struct macro_source_file *file, int line, + const char *body) +{ + const char *p; + + /* The body string takes one of two forms. For object-like macro + definitions, it should be: + + <macro name> " " <definition> + + For function-like macro definitions, it should be: + + <macro name> "() " <definition> + or + <macro name> "(" <arg name> ( "," <arg name> ) * ") " <definition> + + Spaces may appear only where explicitly indicated, and in the + <definition>. + + The Dwarf 2 spec says that an object-like macro's name is always + followed by a space, but versions of GCC around March 2002 omit + the space when the macro's definition is the empty string. + + The Dwarf 2 spec says that there should be no spaces between the + formal arguments in a function-like macro's formal argument list, + but versions of GCC around March 2002 include spaces after the + commas. */ + + + /* Find the extent of the macro name. The macro name is terminated + by either a space or null character (for an object-like macro) or + an opening paren (for a function-like macro). */ + for (p = body; *p; p++) + if (*p == ' ' || *p == '(') + break; + + if (*p == ' ' || *p == '\0') + { + /* It's an object-like macro. */ + int name_len = p - body; + char *name = copy_string (body, name_len); + const char *replacement; + + if (*p == ' ') + replacement = body + name_len + 1; + else + { + complain (&dwarf2_macro_malformed_definition, body); + replacement = body + name_len; + } + + macro_define_object (file, line, name, replacement); + + xfree (name); + } + else if (*p == '(') + { + /* It's a function-like macro. */ + char *name = copy_string (body, p - body); + int argc = 0; + int argv_size = 1; + char **argv = xmalloc (argv_size * sizeof (*argv)); + + p++; + + p = consume_improper_spaces (p, body); + + /* Parse the formal argument list. */ + while (*p && *p != ')') + { + /* Find the extent of the current argument name. */ + const char *arg_start = p; + + while (*p && *p != ',' && *p != ')' && *p != ' ') + p++; + + if (! *p || p == arg_start) + complain (&dwarf2_macro_malformed_definition, + body); + else + { + /* Make sure argv has room for the new argument. */ + if (argc >= argv_size) + { + argv_size *= 2; + argv = xrealloc (argv, argv_size * sizeof (*argv)); + } + + argv[argc++] = copy_string (arg_start, p - arg_start); + } + + p = consume_improper_spaces (p, body); + + /* Consume the comma, if present. */ + if (*p == ',') + { + p++; + + p = consume_improper_spaces (p, body); + } + } + + if (*p == ')') + { + p++; + + if (*p == ' ') + /* Perfectly formed definition, no complaints. */ + macro_define_function (file, line, name, + argc, (const char **) argv, + p + 1); + else if (*p == '\0') + { + /* Complain, but do define it. */ + complain (&dwarf2_macro_malformed_definition, body); + macro_define_function (file, line, name, + argc, (const char **) argv, + p); + } + else + /* Just complain. */ + complain (&dwarf2_macro_malformed_definition, body); + } + else + /* Just complain. */ + complain (&dwarf2_macro_malformed_definition, body); + + xfree (name); + { + int i; + + for (i = 0; i < argc; i++) + xfree (argv[i]); + } + xfree (argv); + } + else + complain (&dwarf2_macro_malformed_definition, body); +} + + +static void +dwarf_decode_macros (struct line_header *lh, unsigned int offset, + char *comp_dir, bfd *abfd, + const struct comp_unit_head *cu_header, + struct objfile *objfile) +{ + char *mac_ptr, *mac_end; + struct macro_source_file *current_file = 0; + + if (dwarf_macinfo_buffer == NULL) + { + complain (&dwarf2_missing_macinfo_section); + return; + } + + mac_ptr = dwarf_macinfo_buffer + offset; + mac_end = dwarf_macinfo_buffer + dwarf_macinfo_size; + + for (;;) + { + enum dwarf_macinfo_record_type macinfo_type; + + /* Do we at least have room for a macinfo type byte? */ + if (mac_ptr >= mac_end) + { + complain (&dwarf2_macros_too_long); + return; + } + + macinfo_type = read_1_byte (abfd, mac_ptr); + mac_ptr++; + + switch (macinfo_type) + { + /* A zero macinfo type indicates the end of the macro + information. */ + case 0: + return; + + case DW_MACINFO_define: + case DW_MACINFO_undef: + { + int bytes_read; + int line; + char *body; + + line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; + body = read_string (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; + + if (! current_file) + complain (&dwarf2_macro_outside_file, + macinfo_type == DW_MACINFO_define ? "definition" : + macinfo_type == DW_MACINFO_undef ? "undefinition" : + "something-or-other", + body); + else + { + if (macinfo_type == DW_MACINFO_define) + parse_macro_definition (current_file, line, body); + else if (macinfo_type == DW_MACINFO_undef) + macro_undef (current_file, line, body); + } + } + break; + + case DW_MACINFO_start_file: + { + int bytes_read; + int line, file; + + line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; + file = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; + + current_file = macro_start_file (file, line, + current_file, comp_dir, + lh, objfile); + } + break; + + case DW_MACINFO_end_file: + if (! current_file) + complain (&dwarf2_macro_unmatched_end_file); + else + { + current_file = current_file->included_by; + if (! current_file) + { + enum dwarf_macinfo_record_type next_type; + + /* GCC circa March 2002 doesn't produce the zero + type byte marking the end of the compilation + unit. Complain if it's not there, but exit no + matter what. */ + + /* Do we at least have room for a macinfo type byte? */ + if (mac_ptr >= mac_end) + { + complain (&dwarf2_macros_too_long); + return; + } + + /* We don't increment mac_ptr here, so this is just + a look-ahead. */ + next_type = read_1_byte (abfd, mac_ptr); + if (next_type != 0) + complain (&dwarf2_macros_not_terminated); + + return; + } + } + break; + + case DW_MACINFO_vendor_ext: + { + int bytes_read; + int constant; + char *string; + + constant = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; + string = read_string (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; + + /* We don't recognize any vendor extensions. */ + } + break; + } + } +} + +/* Check if the attribute's form is a DW_FORM_block* + if so return true else false. */ +static int +attr_form_is_block (struct attribute *attr) +{ + return (attr == NULL ? 0 : + attr->form == DW_FORM_block1 + || attr->form == DW_FORM_block2 + || attr->form == DW_FORM_block4 + || attr->form == DW_FORM_block); +} diff --git a/gdb/dwarfread.c b/gdb/dwarfread.c new file mode 100644 index 0000000..9c4201d --- /dev/null +++ b/gdb/dwarfread.c @@ -0,0 +1,3788 @@ +/* DWARF debugging format support for GDB. + Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, + 2001, 2002 + Free Software Foundation, Inc. + Written by Fred Fish at Cygnus Support. Portions based on dbxread.c, + mipsread.c, coffread.c, and dwarfread.c from a Data General SVR4 gdb port. + + 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 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* + + FIXME: Do we need to generate dependencies in partial symtabs? + (Perhaps we don't need to). + + FIXME: Resolve minor differences between what information we put in the + partial symbol table and what dbxread puts in. For example, we don't yet + put enum constants there. And dbxread seems to invent a lot of typedefs + we never see. Use the new printpsym command to see the partial symbol table + contents. + + FIXME: Figure out a better way to tell gdb about the name of the function + contain the user's entry point (I.E. main()) + + FIXME: See other FIXME's and "ifdef 0" scattered throughout the code for + other things to work on, if you get bored. :-) + + */ + +#include "defs.h" +#include "symtab.h" +#include "gdbtypes.h" +#include "symfile.h" +#include "objfiles.h" +#include "elf/dwarf.h" +#include "buildsym.h" +#include "demangle.h" +#include "expression.h" /* Needed for enum exp_opcode in language.h, sigh... */ +#include "language.h" +#include "complaints.h" + +#include <fcntl.h> +#include "gdb_string.h" + +/* Some macros to provide DIE info for complaints. */ + +#define DIE_ID (curdie!=NULL ? curdie->die_ref : 0) +#define DIE_NAME (curdie!=NULL && curdie->at_name!=NULL) ? curdie->at_name : "" + +/* Complaints that can be issued during DWARF debug info reading. */ + +struct complaint no_bfd_get_N = +{ + "DIE @ 0x%x \"%s\", no bfd support for %d byte data object", 0, 0 +}; + +struct complaint malformed_die = +{ + "DIE @ 0x%x \"%s\", malformed DIE, bad length (%d bytes)", 0, 0 +}; + +struct complaint bad_die_ref = +{ + "DIE @ 0x%x \"%s\", reference to DIE (0x%x) outside compilation unit", 0, 0 +}; + +struct complaint unknown_attribute_form = +{ + "DIE @ 0x%x \"%s\", unknown attribute form (0x%x)", 0, 0 +}; + +struct complaint unknown_attribute_length = +{ + "DIE @ 0x%x \"%s\", unknown attribute length, skipped remaining attributes", 0, 0 +}; + +struct complaint unexpected_fund_type = +{ + "DIE @ 0x%x \"%s\", unexpected fundamental type 0x%x", 0, 0 +}; + +struct complaint unknown_type_modifier = +{ + "DIE @ 0x%x \"%s\", unknown type modifier %u", 0, 0 +}; + +struct complaint volatile_ignored = +{ + "DIE @ 0x%x \"%s\", type modifier 'volatile' ignored", 0, 0 +}; + +struct complaint const_ignored = +{ + "DIE @ 0x%x \"%s\", type modifier 'const' ignored", 0, 0 +}; + +struct complaint botched_modified_type = +{ + "DIE @ 0x%x \"%s\", botched modified type decoding (mtype 0x%x)", 0, 0 +}; + +struct complaint op_deref2 = +{ + "DIE @ 0x%x \"%s\", OP_DEREF2 address 0x%x not handled", 0, 0 +}; + +struct complaint op_deref4 = +{ + "DIE @ 0x%x \"%s\", OP_DEREF4 address 0x%x not handled", 0, 0 +}; + +struct complaint basereg_not_handled = +{ + "DIE @ 0x%x \"%s\", BASEREG %d not handled", 0, 0 +}; + +struct complaint dup_user_type_allocation = +{ + "DIE @ 0x%x \"%s\", internal error: duplicate user type allocation", 0, 0 +}; + +struct complaint dup_user_type_definition = +{ + "DIE @ 0x%x \"%s\", internal error: duplicate user type definition", 0, 0 +}; + +struct complaint missing_tag = +{ + "DIE @ 0x%x \"%s\", missing class, structure, or union tag", 0, 0 +}; + +struct complaint bad_array_element_type = +{ + "DIE @ 0x%x \"%s\", bad array element type attribute 0x%x", 0, 0 +}; + +struct complaint subscript_data_items = +{ + "DIE @ 0x%x \"%s\", can't decode subscript data items", 0, 0 +}; + +struct complaint unhandled_array_subscript_format = +{ + "DIE @ 0x%x \"%s\", array subscript format 0x%x not handled yet", 0, 0 +}; + +struct complaint unknown_array_subscript_format = +{ + "DIE @ 0x%x \"%s\", unknown array subscript format %x", 0, 0 +}; + +struct complaint not_row_major = +{ + "DIE @ 0x%x \"%s\", array not row major; not handled correctly", 0, 0 +}; + +struct complaint missing_at_name = +{ + "DIE @ 0x%x, AT_name tag missing", 0, 0 +}; + +typedef unsigned int DIE_REF; /* Reference to a DIE */ + +#ifndef GCC_PRODUCER +#define GCC_PRODUCER "GNU C " +#endif + +#ifndef GPLUS_PRODUCER +#define GPLUS_PRODUCER "GNU C++ " +#endif + +#ifndef LCC_PRODUCER +#define LCC_PRODUCER "NCR C/C++" +#endif + +/* OBSOLETE #ifndef CHILL_PRODUCER */ +/* OBSOLETE #define CHILL_PRODUCER "GNU Chill " */ +/* OBSOLETE #endif */ + +/* Flags to target_to_host() that tell whether or not the data object is + expected to be signed. Used, for example, when fetching a signed + integer in the target environment which is used as a signed integer + in the host environment, and the two environments have different sized + ints. In this case, *somebody* has to sign extend the smaller sized + int. */ + +#define GET_UNSIGNED 0 /* No sign extension required */ +#define GET_SIGNED 1 /* Sign extension required */ + +/* Defines for things which are specified in the document "DWARF Debugging + Information Format" published by UNIX International, Programming Languages + SIG. These defines are based on revision 1.0.0, Jan 20, 1992. */ + +#define SIZEOF_DIE_LENGTH 4 +#define SIZEOF_DIE_TAG 2 +#define SIZEOF_ATTRIBUTE 2 +#define SIZEOF_FORMAT_SPECIFIER 1 +#define SIZEOF_FMT_FT 2 +#define SIZEOF_LINETBL_LENGTH 4 +#define SIZEOF_LINETBL_LINENO 4 +#define SIZEOF_LINETBL_STMT 2 +#define SIZEOF_LINETBL_DELTA 4 +#define SIZEOF_LOC_ATOM_CODE 1 + +#define FORM_FROM_ATTR(attr) ((attr) & 0xF) /* Implicitly specified */ + +/* Macros that return the sizes of various types of data in the target + environment. + + FIXME: Currently these are just compile time constants (as they are in + other parts of gdb as well). They need to be able to get the right size + either from the bfd or possibly from the DWARF info. It would be nice if + the DWARF producer inserted DIES that describe the fundamental types in + the target environment into the DWARF info, similar to the way dbx stabs + producers produce information about their fundamental types. */ + +#define TARGET_FT_POINTER_SIZE(objfile) (TARGET_PTR_BIT / TARGET_CHAR_BIT) +#define TARGET_FT_LONG_SIZE(objfile) (TARGET_LONG_BIT / TARGET_CHAR_BIT) + +/* The Amiga SVR4 header file <dwarf.h> defines AT_element_list as a + FORM_BLOCK2, and this is the value emitted by the AT&T compiler. + However, the Issue 2 DWARF specification from AT&T defines it as + a FORM_BLOCK4, as does the latest specification from UI/PLSIG. + For backwards compatibility with the AT&T compiler produced executables + we define AT_short_element_list for this variant. */ + +#define AT_short_element_list (0x00f0|FORM_BLOCK2) + +/* The DWARF debugging information consists of two major pieces, + one is a block of DWARF Information Entries (DIE's) and the other + is a line number table. The "struct dieinfo" structure contains + the information for a single DIE, the one currently being processed. + + In order to make it easier to randomly access the attribute fields + of the current DIE, which are specifically unordered within the DIE, + each DIE is scanned and an instance of the "struct dieinfo" + structure is initialized. + + Initialization is done in two levels. The first, done by basicdieinfo(), + just initializes those fields that are vital to deciding whether or not + to use this DIE, how to skip past it, etc. The second, done by the + function completedieinfo(), fills in the rest of the information. + + Attributes which have block forms are not interpreted at the time + the DIE is scanned, instead we just save pointers to the start + of their value fields. + + Some fields have a flag <name>_p that is set when the value of the + field is valid (I.E. we found a matching attribute in the DIE). Since + we may want to test for the presence of some attributes in the DIE, + such as AT_low_pc, without restricting the values of the field, + we need someway to note that we found such an attribute. + + */ + +typedef char BLOCK; + +struct dieinfo + { + char *die; /* Pointer to the raw DIE data */ + unsigned long die_length; /* Length of the raw DIE data */ + DIE_REF die_ref; /* Offset of this DIE */ + unsigned short die_tag; /* Tag for this DIE */ + unsigned long at_padding; + unsigned long at_sibling; + BLOCK *at_location; + char *at_name; + unsigned short at_fund_type; + BLOCK *at_mod_fund_type; + unsigned long at_user_def_type; + BLOCK *at_mod_u_d_type; + unsigned short at_ordering; + BLOCK *at_subscr_data; + unsigned long at_byte_size; + unsigned short at_bit_offset; + unsigned long at_bit_size; + BLOCK *at_element_list; + unsigned long at_stmt_list; + CORE_ADDR at_low_pc; + CORE_ADDR at_high_pc; + unsigned long at_language; + unsigned long at_member; + unsigned long at_discr; + BLOCK *at_discr_value; + BLOCK *at_string_length; + char *at_comp_dir; + char *at_producer; + unsigned long at_start_scope; + unsigned long at_stride_size; + unsigned long at_src_info; + char *at_prototyped; + unsigned int has_at_low_pc:1; + unsigned int has_at_stmt_list:1; + unsigned int has_at_byte_size:1; + unsigned int short_element_list:1; + + /* Kludge to identify register variables */ + + unsigned int isreg; + + /* Kludge to identify optimized out variables */ + + unsigned int optimized_out; + + /* Kludge to identify basereg references. + Nonzero if we have an offset relative to a basereg. */ + + unsigned int offreg; + + /* Kludge to identify which base register is it relative to. */ + + unsigned int basereg; + }; + +static int diecount; /* Approximate count of dies for compilation unit */ +static struct dieinfo *curdie; /* For warnings and such */ + +static char *dbbase; /* Base pointer to dwarf info */ +static int dbsize; /* Size of dwarf info in bytes */ +static int dbroff; /* Relative offset from start of .debug section */ +static char *lnbase; /* Base pointer to line section */ + +/* This value is added to each symbol value. FIXME: Generalize to + the section_offsets structure used by dbxread (once this is done, + pass the appropriate section number to end_symtab). */ +static CORE_ADDR baseaddr; /* Add to each symbol value */ + +/* The section offsets used in the current psymtab or symtab. FIXME, + only used to pass one value (baseaddr) at the moment. */ +static struct section_offsets *base_section_offsets; + +/* We put a pointer to this structure in the read_symtab_private field + of the psymtab. */ + +struct dwfinfo + { + /* Always the absolute file offset to the start of the ".debug" + section for the file containing the DIE's being accessed. */ + file_ptr dbfoff; + /* Relative offset from the start of the ".debug" section to the + first DIE to be accessed. When building the partial symbol + table, this value will be zero since we are accessing the + entire ".debug" section. When expanding a partial symbol + table entry, this value will be the offset to the first + DIE for the compilation unit containing the symbol that + triggers the expansion. */ + int dbroff; + /* The size of the chunk of DIE's being examined, in bytes. */ + int dblength; + /* The absolute file offset to the line table fragment. Ignored + when building partial symbol tables, but used when expanding + them, and contains the absolute file offset to the fragment + of the ".line" section containing the line numbers for the + current compilation unit. */ + file_ptr lnfoff; + }; + +#define DBFOFF(p) (((struct dwfinfo *)((p)->read_symtab_private))->dbfoff) +#define DBROFF(p) (((struct dwfinfo *)((p)->read_symtab_private))->dbroff) +#define DBLENGTH(p) (((struct dwfinfo *)((p)->read_symtab_private))->dblength) +#define LNFOFF(p) (((struct dwfinfo *)((p)->read_symtab_private))->lnfoff) + +/* The generic symbol table building routines have separate lists for + file scope symbols and all all other scopes (local scopes). So + we need to select the right one to pass to add_symbol_to_list(). + We do it by keeping a pointer to the correct list in list_in_scope. + + FIXME: The original dwarf code just treated the file scope as the first + local scope, and all other local scopes as nested local scopes, and worked + fine. Check to see if we really need to distinguish these in buildsym.c */ + +struct pending **list_in_scope = &file_symbols; + +/* DIES which have user defined types or modified user defined types refer to + other DIES for the type information. Thus we need to associate the offset + of a DIE for a user defined type with a pointer to the type information. + + Originally this was done using a simple but expensive algorithm, with an + array of unsorted structures, each containing an offset/type-pointer pair. + This array was scanned linearly each time a lookup was done. The result + was that gdb was spending over half it's startup time munging through this + array of pointers looking for a structure that had the right offset member. + + The second attempt used the same array of structures, but the array was + sorted using qsort each time a new offset/type was recorded, and a binary + search was used to find the type pointer for a given DIE offset. This was + even slower, due to the overhead of sorting the array each time a new + offset/type pair was entered. + + The third attempt uses a fixed size array of type pointers, indexed by a + value derived from the DIE offset. Since the minimum DIE size is 4 bytes, + we can divide any DIE offset by 4 to obtain a unique index into this fixed + size array. Since each element is a 4 byte pointer, it takes exactly as + much memory to hold this array as to hold the DWARF info for a given + compilation unit. But it gets freed as soon as we are done with it. + This has worked well in practice, as a reasonable tradeoff between memory + consumption and speed, without having to resort to much more complicated + algorithms. */ + +static struct type **utypes; /* Pointer to array of user type pointers */ +static int numutypes; /* Max number of user type pointers */ + +/* Maintain an array of referenced fundamental types for the current + compilation unit being read. For DWARF version 1, we have to construct + the fundamental types on the fly, since no information about the + fundamental types is supplied. Each such fundamental type is created by + calling a language dependent routine to create the type, and then a + pointer to that type is then placed in the array at the index specified + by it's FT_<TYPENAME> value. The array has a fixed size set by the + FT_NUM_MEMBERS compile time constant, which is the number of predefined + fundamental types gdb knows how to construct. */ + +static struct type *ftypes[FT_NUM_MEMBERS]; /* Fundamental types */ + +/* Record the language for the compilation unit which is currently being + processed. We know it once we have seen the TAG_compile_unit DIE, + and we need it while processing the DIE's for that compilation unit. + It is eventually saved in the symtab structure, but we don't finalize + the symtab struct until we have processed all the DIE's for the + compilation unit. We also need to get and save a pointer to the + language struct for this language, so we can call the language + dependent routines for doing things such as creating fundamental + types. */ + +static enum language cu_language; +static const struct language_defn *cu_language_defn; + +/* Forward declarations of static functions so we don't have to worry + about ordering within this file. */ + +static void free_utypes (PTR); + +static int attribute_size (unsigned int); + +static CORE_ADDR target_to_host (char *, int, int, struct objfile *); + +static void add_enum_psymbol (struct dieinfo *, struct objfile *); + +static void handle_producer (char *); + +static void +read_file_scope (struct dieinfo *, char *, char *, struct objfile *); + +static void +read_func_scope (struct dieinfo *, char *, char *, struct objfile *); + +static void +read_lexical_block_scope (struct dieinfo *, char *, char *, struct objfile *); + +static void scan_partial_symbols (char *, char *, struct objfile *); + +static void +scan_compilation_units (char *, char *, file_ptr, file_ptr, struct objfile *); + +static void add_partial_symbol (struct dieinfo *, struct objfile *); + +static void basicdieinfo (struct dieinfo *, char *, struct objfile *); + +static void completedieinfo (struct dieinfo *, struct objfile *); + +static void dwarf_psymtab_to_symtab (struct partial_symtab *); + +static void psymtab_to_symtab_1 (struct partial_symtab *); + +static void read_ofile_symtab (struct partial_symtab *); + +static void process_dies (char *, char *, struct objfile *); + +static void +read_structure_scope (struct dieinfo *, char *, char *, struct objfile *); + +static struct type *decode_array_element_type (char *); + +static struct type *decode_subscript_data_item (char *, char *); + +static void dwarf_read_array_type (struct dieinfo *); + +static void read_tag_pointer_type (struct dieinfo *dip); + +static void read_tag_string_type (struct dieinfo *dip); + +static void read_subroutine_type (struct dieinfo *, char *, char *); + +static void +read_enumeration (struct dieinfo *, char *, char *, struct objfile *); + +static struct type *struct_type (struct dieinfo *, char *, char *, + struct objfile *); + +static struct type *enum_type (struct dieinfo *, struct objfile *); + +static void decode_line_numbers (char *); + +static struct type *decode_die_type (struct dieinfo *); + +static struct type *decode_mod_fund_type (char *); + +static struct type *decode_mod_u_d_type (char *); + +static struct type *decode_modified_type (char *, unsigned int, int); + +static struct type *decode_fund_type (unsigned int); + +static char *create_name (char *, struct obstack *); + +static struct type *lookup_utype (DIE_REF); + +static struct type *alloc_utype (DIE_REF, struct type *); + +static struct symbol *new_symbol (struct dieinfo *, struct objfile *); + +static void +synthesize_typedef (struct dieinfo *, struct objfile *, struct type *); + +static int locval (struct dieinfo *); + +static void set_cu_language (struct dieinfo *); + +static struct type *dwarf_fundamental_type (struct objfile *, int); + + +/* + + LOCAL FUNCTION + + dwarf_fundamental_type -- lookup or create a fundamental type + + SYNOPSIS + + struct type * + dwarf_fundamental_type (struct objfile *objfile, int typeid) + + DESCRIPTION + + DWARF version 1 doesn't supply any fundamental type information, + so gdb has to construct such types. It has a fixed number of + fundamental types that it knows how to construct, which is the + union of all types that it knows how to construct for all languages + that it knows about. These are enumerated in gdbtypes.h. + + As an example, assume we find a DIE that references a DWARF + fundamental type of FT_integer. We first look in the ftypes + array to see if we already have such a type, indexed by the + gdb internal value of FT_INTEGER. If so, we simply return a + pointer to that type. If not, then we ask an appropriate + language dependent routine to create a type FT_INTEGER, using + defaults reasonable for the current target machine, and install + that type in ftypes for future reference. + + RETURNS + + Pointer to a fundamental type. + + */ + +static struct type * +dwarf_fundamental_type (struct objfile *objfile, int typeid) +{ + if (typeid < 0 || typeid >= FT_NUM_MEMBERS) + { + error ("internal error - invalid fundamental type id %d", typeid); + } + + /* Look for this particular type in the fundamental type vector. If one is + not found, create and install one appropriate for the current language + and the current target machine. */ + + if (ftypes[typeid] == NULL) + { + ftypes[typeid] = cu_language_defn->la_fund_type (objfile, typeid); + } + + return (ftypes[typeid]); +} + +/* + + LOCAL FUNCTION + + set_cu_language -- set local copy of language for compilation unit + + SYNOPSIS + + void + set_cu_language (struct dieinfo *dip) + + DESCRIPTION + + Decode the language attribute for a compilation unit DIE and + remember what the language was. We use this at various times + when processing DIE's for a given compilation unit. + + RETURNS + + No return value. + + */ + +static void +set_cu_language (struct dieinfo *dip) +{ + switch (dip->at_language) + { + case LANG_C89: + case LANG_C: + cu_language = language_c; + break; + case LANG_C_PLUS_PLUS: + cu_language = language_cplus; + break; + /* OBSOLETE case LANG_CHILL: */ + /* OBSOLETE cu_language = language_chill; */ + /* OBSOLETE break; */ + case LANG_MODULA2: + cu_language = language_m2; + break; + case LANG_FORTRAN77: + case LANG_FORTRAN90: + cu_language = language_fortran; + break; + case LANG_ADA83: + case LANG_COBOL74: + case LANG_COBOL85: + case LANG_PASCAL83: + /* We don't know anything special about these yet. */ + cu_language = language_unknown; + break; + default: + /* If no at_language, try to deduce one from the filename */ + cu_language = deduce_language_from_filename (dip->at_name); + break; + } + cu_language_defn = language_def (cu_language); +} + +/* + + GLOBAL FUNCTION + + dwarf_build_psymtabs -- build partial symtabs from DWARF debug info + + SYNOPSIS + + void dwarf_build_psymtabs (struct objfile *objfile, + int mainline, file_ptr dbfoff, unsigned int dbfsize, + file_ptr lnoffset, unsigned int lnsize) + + DESCRIPTION + + This function is called upon to build partial symtabs from files + containing DIE's (Dwarf Information Entries) and DWARF line numbers. + + It is passed a bfd* containing the DIES + and line number information, the corresponding filename for that + file, a base address for relocating the symbols, a flag indicating + whether or not this debugging information is from a "main symbol + table" rather than a shared library or dynamically linked file, + and file offset/size pairs for the DIE information and line number + information. + + RETURNS + + No return value. + + */ + +void +dwarf_build_psymtabs (struct objfile *objfile, int mainline, file_ptr dbfoff, + unsigned int dbfsize, file_ptr lnoffset, + unsigned int lnsize) +{ + bfd *abfd = objfile->obfd; + struct cleanup *back_to; + + current_objfile = objfile; + dbsize = dbfsize; + dbbase = xmalloc (dbsize); + dbroff = 0; + if ((bfd_seek (abfd, dbfoff, SEEK_SET) != 0) || + (bfd_bread (dbbase, dbsize, abfd) != dbsize)) + { + xfree (dbbase); + error ("can't read DWARF data from '%s'", bfd_get_filename (abfd)); + } + back_to = make_cleanup (xfree, dbbase); + + /* If we are reinitializing, or if we have never loaded syms yet, init. + Since we have no idea how many DIES we are looking at, we just guess + some arbitrary value. */ + + if (mainline + || (objfile->global_psymbols.size == 0 + && objfile->static_psymbols.size == 0)) + { + init_psymbol_list (objfile, 1024); + } + + /* Save the relocation factor where everybody can see it. */ + + base_section_offsets = objfile->section_offsets; + baseaddr = ANOFFSET (objfile->section_offsets, 0); + + /* Follow the compilation unit sibling chain, building a partial symbol + table entry for each one. Save enough information about each compilation + unit to locate the full DWARF information later. */ + + scan_compilation_units (dbbase, dbbase + dbsize, dbfoff, lnoffset, objfile); + + do_cleanups (back_to); + current_objfile = NULL; +} + +/* + + LOCAL FUNCTION + + read_lexical_block_scope -- process all dies in a lexical block + + SYNOPSIS + + static void read_lexical_block_scope (struct dieinfo *dip, + char *thisdie, char *enddie) + + DESCRIPTION + + Process all the DIES contained within a lexical block scope. + Start a new scope, process the dies, and then close the scope. + + */ + +static void +read_lexical_block_scope (struct dieinfo *dip, char *thisdie, char *enddie, + struct objfile *objfile) +{ + register struct context_stack *new; + + push_context (0, dip->at_low_pc); + process_dies (thisdie + dip->die_length, enddie, objfile); + new = pop_context (); + if (local_symbols != NULL) + { + finish_block (0, &local_symbols, new->old_blocks, new->start_addr, + dip->at_high_pc, objfile); + } + local_symbols = new->locals; +} + +/* + + LOCAL FUNCTION + + lookup_utype -- look up a user defined type from die reference + + SYNOPSIS + + static type *lookup_utype (DIE_REF die_ref) + + DESCRIPTION + + Given a DIE reference, lookup the user defined type associated with + that DIE, if it has been registered already. If not registered, then + return NULL. Alloc_utype() can be called to register an empty + type for this reference, which will be filled in later when the + actual referenced DIE is processed. + */ + +static struct type * +lookup_utype (DIE_REF die_ref) +{ + struct type *type = NULL; + int utypeidx; + + utypeidx = (die_ref - dbroff) / 4; + if ((utypeidx < 0) || (utypeidx >= numutypes)) + { + complain (&bad_die_ref, DIE_ID, DIE_NAME); + } + else + { + type = *(utypes + utypeidx); + } + return (type); +} + + +/* + + LOCAL FUNCTION + + alloc_utype -- add a user defined type for die reference + + SYNOPSIS + + static type *alloc_utype (DIE_REF die_ref, struct type *utypep) + + DESCRIPTION + + Given a die reference DIE_REF, and a possible pointer to a user + defined type UTYPEP, register that this reference has a user + defined type and either use the specified type in UTYPEP or + make a new empty type that will be filled in later. + + We should only be called after calling lookup_utype() to verify that + there is not currently a type registered for DIE_REF. + */ + +static struct type * +alloc_utype (DIE_REF die_ref, struct type *utypep) +{ + struct type **typep; + int utypeidx; + + utypeidx = (die_ref - dbroff) / 4; + typep = utypes + utypeidx; + if ((utypeidx < 0) || (utypeidx >= numutypes)) + { + utypep = dwarf_fundamental_type (current_objfile, FT_INTEGER); + complain (&bad_die_ref, DIE_ID, DIE_NAME); + } + else if (*typep != NULL) + { + utypep = *typep; + complain (&dup_user_type_allocation, DIE_ID, DIE_NAME); + } + else + { + if (utypep == NULL) + { + utypep = alloc_type (current_objfile); + } + *typep = utypep; + } + return (utypep); +} + +/* + + LOCAL FUNCTION + + free_utypes -- free the utypes array and reset pointer & count + + SYNOPSIS + + static void free_utypes (PTR dummy) + + DESCRIPTION + + Called via do_cleanups to free the utypes array, reset the pointer to NULL, + and set numutypes back to zero. This ensures that the utypes does not get + referenced after being freed. + */ + +static void +free_utypes (PTR dummy) +{ + xfree (utypes); + utypes = NULL; + numutypes = 0; +} + + +/* + + LOCAL FUNCTION + + decode_die_type -- return a type for a specified die + + SYNOPSIS + + static struct type *decode_die_type (struct dieinfo *dip) + + DESCRIPTION + + Given a pointer to a die information structure DIP, decode the + type of the die and return a pointer to the decoded type. All + dies without specific types default to type int. + */ + +static struct type * +decode_die_type (struct dieinfo *dip) +{ + struct type *type = NULL; + + if (dip->at_fund_type != 0) + { + type = decode_fund_type (dip->at_fund_type); + } + else if (dip->at_mod_fund_type != NULL) + { + type = decode_mod_fund_type (dip->at_mod_fund_type); + } + else if (dip->at_user_def_type) + { + if ((type = lookup_utype (dip->at_user_def_type)) == NULL) + { + type = alloc_utype (dip->at_user_def_type, NULL); + } + } + else if (dip->at_mod_u_d_type) + { + type = decode_mod_u_d_type (dip->at_mod_u_d_type); + } + else + { + type = dwarf_fundamental_type (current_objfile, FT_VOID); + } + return (type); +} + +/* + + LOCAL FUNCTION + + struct_type -- compute and return the type for a struct or union + + SYNOPSIS + + static struct type *struct_type (struct dieinfo *dip, char *thisdie, + char *enddie, struct objfile *objfile) + + DESCRIPTION + + Given pointer to a die information structure for a die which + defines a union or structure (and MUST define one or the other), + and pointers to the raw die data that define the range of dies which + define the members, compute and return the user defined type for the + structure or union. + */ + +static struct type * +struct_type (struct dieinfo *dip, char *thisdie, char *enddie, + struct objfile *objfile) +{ + struct type *type; + struct nextfield + { + struct nextfield *next; + struct field field; + }; + struct nextfield *list = NULL; + struct nextfield *new; + int nfields = 0; + int n; + struct dieinfo mbr; + char *nextdie; + int anonymous_size; + + if ((type = lookup_utype (dip->die_ref)) == NULL) + { + /* No forward references created an empty type, so install one now */ + type = alloc_utype (dip->die_ref, NULL); + } + INIT_CPLUS_SPECIFIC (type); + switch (dip->die_tag) + { + case TAG_class_type: + TYPE_CODE (type) = TYPE_CODE_CLASS; + break; + case TAG_structure_type: + TYPE_CODE (type) = TYPE_CODE_STRUCT; + break; + case TAG_union_type: + TYPE_CODE (type) = TYPE_CODE_UNION; + break; + default: + /* Should never happen */ + TYPE_CODE (type) = TYPE_CODE_UNDEF; + complain (&missing_tag, DIE_ID, DIE_NAME); + break; + } + /* Some compilers try to be helpful by inventing "fake" names for + anonymous enums, structures, and unions, like "~0fake" or ".0fake". + Thanks, but no thanks... */ + if (dip->at_name != NULL + && *dip->at_name != '~' + && *dip->at_name != '.') + { + TYPE_TAG_NAME (type) = obconcat (&objfile->type_obstack, + "", "", dip->at_name); + } + /* Use whatever size is known. Zero is a valid size. We might however + wish to check has_at_byte_size to make sure that some byte size was + given explicitly, but DWARF doesn't specify that explicit sizes of + zero have to present, so complaining about missing sizes should + probably not be the default. */ + TYPE_LENGTH (type) = dip->at_byte_size; + thisdie += dip->die_length; + while (thisdie < enddie) + { + basicdieinfo (&mbr, thisdie, objfile); + completedieinfo (&mbr, objfile); + if (mbr.die_length <= SIZEOF_DIE_LENGTH) + { + break; + } + else if (mbr.at_sibling != 0) + { + nextdie = dbbase + mbr.at_sibling - dbroff; + } + else + { + nextdie = thisdie + mbr.die_length; + } + switch (mbr.die_tag) + { + case TAG_member: + /* Get space to record the next field's data. */ + new = (struct nextfield *) alloca (sizeof (struct nextfield)); + new->next = list; + list = new; + /* Save the data. */ + list->field.name = + obsavestring (mbr.at_name, strlen (mbr.at_name), + &objfile->type_obstack); + FIELD_TYPE (list->field) = decode_die_type (&mbr); + FIELD_BITPOS (list->field) = 8 * locval (&mbr); + /* Handle bit fields. */ + FIELD_BITSIZE (list->field) = mbr.at_bit_size; + if (BITS_BIG_ENDIAN) + { + /* For big endian bits, the at_bit_offset gives the + additional bit offset from the MSB of the containing + anonymous object to the MSB of the field. We don't + have to do anything special since we don't need to + know the size of the anonymous object. */ + FIELD_BITPOS (list->field) += mbr.at_bit_offset; + } + else + { + /* For little endian bits, we need to have a non-zero + at_bit_size, so that we know we are in fact dealing + with a bitfield. Compute the bit offset to the MSB + of the anonymous object, subtract off the number of + bits from the MSB of the field to the MSB of the + object, and then subtract off the number of bits of + the field itself. The result is the bit offset of + the LSB of the field. */ + if (mbr.at_bit_size > 0) + { + if (mbr.has_at_byte_size) + { + /* The size of the anonymous object containing + the bit field is explicit, so use the + indicated size (in bytes). */ + anonymous_size = mbr.at_byte_size; + } + else + { + /* The size of the anonymous object containing + the bit field matches the size of an object + of the bit field's type. DWARF allows + at_byte_size to be left out in such cases, as + a debug information size optimization. */ + anonymous_size = TYPE_LENGTH (list->field.type); + } + FIELD_BITPOS (list->field) += + anonymous_size * 8 - mbr.at_bit_offset - mbr.at_bit_size; + } + } + nfields++; + break; + default: + process_dies (thisdie, nextdie, objfile); + break; + } + thisdie = nextdie; + } + /* Now create the vector of fields, and record how big it is. We may + not even have any fields, if this DIE was generated due to a reference + to an anonymous structure or union. In this case, TYPE_FLAG_STUB is + set, which clues gdb in to the fact that it needs to search elsewhere + for the full structure definition. */ + if (nfields == 0) + { + TYPE_FLAGS (type) |= TYPE_FLAG_STUB; + } + else + { + TYPE_NFIELDS (type) = nfields; + TYPE_FIELDS (type) = (struct field *) + TYPE_ALLOC (type, sizeof (struct field) * nfields); + /* Copy the saved-up fields into the field vector. */ + for (n = nfields; list; list = list->next) + { + TYPE_FIELD (type, --n) = list->field; + } + } + return (type); +} + +/* + + LOCAL FUNCTION + + read_structure_scope -- process all dies within struct or union + + SYNOPSIS + + static void read_structure_scope (struct dieinfo *dip, + char *thisdie, char *enddie, struct objfile *objfile) + + DESCRIPTION + + Called when we find the DIE that starts a structure or union + scope (definition) to process all dies that define the members + of the structure or union. DIP is a pointer to the die info + struct for the DIE that names the structure or union. + + NOTES + + Note that we need to call struct_type regardless of whether or not + the DIE has an at_name attribute, since it might be an anonymous + structure or union. This gets the type entered into our set of + user defined types. + + However, if the structure is incomplete (an opaque struct/union) + then suppress creating a symbol table entry for it since gdb only + wants to find the one with the complete definition. Note that if + it is complete, we just call new_symbol, which does it's own + checking about whether the struct/union is anonymous or not (and + suppresses creating a symbol table entry itself). + + */ + +static void +read_structure_scope (struct dieinfo *dip, char *thisdie, char *enddie, + struct objfile *objfile) +{ + struct type *type; + struct symbol *sym; + + type = struct_type (dip, thisdie, enddie, objfile); + if (!TYPE_STUB (type)) + { + sym = new_symbol (dip, objfile); + if (sym != NULL) + { + SYMBOL_TYPE (sym) = type; + if (cu_language == language_cplus) + { + synthesize_typedef (dip, objfile, type); + } + } + } +} + +/* + + LOCAL FUNCTION + + decode_array_element_type -- decode type of the array elements + + SYNOPSIS + + static struct type *decode_array_element_type (char *scan, char *end) + + DESCRIPTION + + As the last step in decoding the array subscript information for an + array DIE, we need to decode the type of the array elements. We are + passed a pointer to this last part of the subscript information and + must return the appropriate type. If the type attribute is not + recognized, just warn about the problem and return type int. + */ + +static struct type * +decode_array_element_type (char *scan) +{ + struct type *typep; + DIE_REF die_ref; + unsigned short attribute; + unsigned short fundtype; + int nbytes; + + attribute = target_to_host (scan, SIZEOF_ATTRIBUTE, GET_UNSIGNED, + current_objfile); + scan += SIZEOF_ATTRIBUTE; + if ((nbytes = attribute_size (attribute)) == -1) + { + complain (&bad_array_element_type, DIE_ID, DIE_NAME, attribute); + typep = dwarf_fundamental_type (current_objfile, FT_INTEGER); + } + else + { + switch (attribute) + { + case AT_fund_type: + fundtype = target_to_host (scan, nbytes, GET_UNSIGNED, + current_objfile); + typep = decode_fund_type (fundtype); + break; + case AT_mod_fund_type: + typep = decode_mod_fund_type (scan); + break; + case AT_user_def_type: + die_ref = target_to_host (scan, nbytes, GET_UNSIGNED, + current_objfile); + if ((typep = lookup_utype (die_ref)) == NULL) + { + typep = alloc_utype (die_ref, NULL); + } + break; + case AT_mod_u_d_type: + typep = decode_mod_u_d_type (scan); + break; + default: + complain (&bad_array_element_type, DIE_ID, DIE_NAME, attribute); + typep = dwarf_fundamental_type (current_objfile, FT_INTEGER); + break; + } + } + return (typep); +} + +/* + + LOCAL FUNCTION + + decode_subscript_data_item -- decode array subscript item + + SYNOPSIS + + static struct type * + decode_subscript_data_item (char *scan, char *end) + + DESCRIPTION + + The array subscripts and the data type of the elements of an + array are described by a list of data items, stored as a block + of contiguous bytes. There is a data item describing each array + dimension, and a final data item describing the element type. + The data items are ordered the same as their appearance in the + source (I.E. leftmost dimension first, next to leftmost second, + etc). + + The data items describing each array dimension consist of four + parts: (1) a format specifier, (2) type type of the subscript + index, (3) a description of the low bound of the array dimension, + and (4) a description of the high bound of the array dimension. + + The last data item is the description of the type of each of + the array elements. + + We are passed a pointer to the start of the block of bytes + containing the remaining data items, and a pointer to the first + byte past the data. This function recursively decodes the + remaining data items and returns a type. + + If we somehow fail to decode some data, we complain about it + and return a type "array of int". + + BUGS + FIXME: This code only implements the forms currently used + by the AT&T and GNU C compilers. + + The end pointer is supplied for error checking, maybe we should + use it for that... + */ + +static struct type * +decode_subscript_data_item (char *scan, char *end) +{ + struct type *typep = NULL; /* Array type we are building */ + struct type *nexttype; /* Type of each element (may be array) */ + struct type *indextype; /* Type of this index */ + struct type *rangetype; + unsigned int format; + unsigned short fundtype; + unsigned long lowbound; + unsigned long highbound; + int nbytes; + + format = target_to_host (scan, SIZEOF_FORMAT_SPECIFIER, GET_UNSIGNED, + current_objfile); + scan += SIZEOF_FORMAT_SPECIFIER; + switch (format) + { + case FMT_ET: + typep = decode_array_element_type (scan); + break; + case FMT_FT_C_C: + fundtype = target_to_host (scan, SIZEOF_FMT_FT, GET_UNSIGNED, + current_objfile); + indextype = decode_fund_type (fundtype); + scan += SIZEOF_FMT_FT; + nbytes = TARGET_FT_LONG_SIZE (current_objfile); + lowbound = target_to_host (scan, nbytes, GET_UNSIGNED, current_objfile); + scan += nbytes; + highbound = target_to_host (scan, nbytes, GET_UNSIGNED, current_objfile); + scan += nbytes; + nexttype = decode_subscript_data_item (scan, end); + if (nexttype == NULL) + { + /* Munged subscript data or other problem, fake it. */ + complain (&subscript_data_items, DIE_ID, DIE_NAME); + nexttype = dwarf_fundamental_type (current_objfile, FT_INTEGER); + } + rangetype = create_range_type ((struct type *) NULL, indextype, + lowbound, highbound); + typep = create_array_type ((struct type *) NULL, nexttype, rangetype); + break; + case FMT_FT_C_X: + case FMT_FT_X_C: + case FMT_FT_X_X: + case FMT_UT_C_C: + case FMT_UT_C_X: + case FMT_UT_X_C: + case FMT_UT_X_X: + complain (&unhandled_array_subscript_format, DIE_ID, DIE_NAME, format); + nexttype = dwarf_fundamental_type (current_objfile, FT_INTEGER); + rangetype = create_range_type ((struct type *) NULL, nexttype, 0, 0); + typep = create_array_type ((struct type *) NULL, nexttype, rangetype); + break; + default: + complain (&unknown_array_subscript_format, DIE_ID, DIE_NAME, format); + nexttype = dwarf_fundamental_type (current_objfile, FT_INTEGER); + rangetype = create_range_type ((struct type *) NULL, nexttype, 0, 0); + typep = create_array_type ((struct type *) NULL, nexttype, rangetype); + break; + } + return (typep); +} + +/* + + LOCAL FUNCTION + + dwarf_read_array_type -- read TAG_array_type DIE + + SYNOPSIS + + static void dwarf_read_array_type (struct dieinfo *dip) + + DESCRIPTION + + Extract all information from a TAG_array_type DIE and add to + the user defined type vector. + */ + +static void +dwarf_read_array_type (struct dieinfo *dip) +{ + struct type *type; + struct type *utype; + char *sub; + char *subend; + unsigned short blocksz; + int nbytes; + + if (dip->at_ordering != ORD_row_major) + { + /* FIXME: Can gdb even handle column major arrays? */ + complain (¬_row_major, DIE_ID, DIE_NAME); + } + if ((sub = dip->at_subscr_data) != NULL) + { + nbytes = attribute_size (AT_subscr_data); + blocksz = target_to_host (sub, nbytes, GET_UNSIGNED, current_objfile); + subend = sub + nbytes + blocksz; + sub += nbytes; + type = decode_subscript_data_item (sub, subend); + if ((utype = lookup_utype (dip->die_ref)) == NULL) + { + /* Install user defined type that has not been referenced yet. */ + alloc_utype (dip->die_ref, type); + } + else if (TYPE_CODE (utype) == TYPE_CODE_UNDEF) + { + /* Ick! A forward ref has already generated a blank type in our + slot, and this type probably already has things pointing to it + (which is what caused it to be created in the first place). + If it's just a place holder we can plop our fully defined type + on top of it. We can't recover the space allocated for our + new type since it might be on an obstack, but we could reuse + it if we kept a list of them, but it might not be worth it + (FIXME). */ + *utype = *type; + } + else + { + /* Double ick! Not only is a type already in our slot, but + someone has decorated it. Complain and leave it alone. */ + complain (&dup_user_type_definition, DIE_ID, DIE_NAME); + } + } +} + +/* + + LOCAL FUNCTION + + read_tag_pointer_type -- read TAG_pointer_type DIE + + SYNOPSIS + + static void read_tag_pointer_type (struct dieinfo *dip) + + DESCRIPTION + + Extract all information from a TAG_pointer_type DIE and add to + the user defined type vector. + */ + +static void +read_tag_pointer_type (struct dieinfo *dip) +{ + struct type *type; + struct type *utype; + + type = decode_die_type (dip); + if ((utype = lookup_utype (dip->die_ref)) == NULL) + { + utype = lookup_pointer_type (type); + alloc_utype (dip->die_ref, utype); + } + else + { + TYPE_TARGET_TYPE (utype) = type; + TYPE_POINTER_TYPE (type) = utype; + + /* We assume the machine has only one representation for pointers! */ + /* FIXME: Possably a poor assumption */ + TYPE_LENGTH (utype) = TARGET_PTR_BIT / TARGET_CHAR_BIT; + TYPE_CODE (utype) = TYPE_CODE_PTR; + } +} + +/* + + LOCAL FUNCTION + + read_tag_string_type -- read TAG_string_type DIE + + SYNOPSIS + + static void read_tag_string_type (struct dieinfo *dip) + + DESCRIPTION + + Extract all information from a TAG_string_type DIE and add to + the user defined type vector. It isn't really a user defined + type, but it behaves like one, with other DIE's using an + AT_user_def_type attribute to reference it. + */ + +static void +read_tag_string_type (struct dieinfo *dip) +{ + struct type *utype; + struct type *indextype; + struct type *rangetype; + unsigned long lowbound = 0; + unsigned long highbound; + + if (dip->has_at_byte_size) + { + /* A fixed bounds string */ + highbound = dip->at_byte_size - 1; + } + else + { + /* A varying length string. Stub for now. (FIXME) */ + highbound = 1; + } + indextype = dwarf_fundamental_type (current_objfile, FT_INTEGER); + rangetype = create_range_type ((struct type *) NULL, indextype, lowbound, + highbound); + + utype = lookup_utype (dip->die_ref); + if (utype == NULL) + { + /* No type defined, go ahead and create a blank one to use. */ + utype = alloc_utype (dip->die_ref, (struct type *) NULL); + } + else + { + /* Already a type in our slot due to a forward reference. Make sure it + is a blank one. If not, complain and leave it alone. */ + if (TYPE_CODE (utype) != TYPE_CODE_UNDEF) + { + complain (&dup_user_type_definition, DIE_ID, DIE_NAME); + return; + } + } + + /* Create the string type using the blank type we either found or created. */ + utype = create_string_type (utype, rangetype); +} + +/* + + LOCAL FUNCTION + + read_subroutine_type -- process TAG_subroutine_type dies + + SYNOPSIS + + static void read_subroutine_type (struct dieinfo *dip, char thisdie, + char *enddie) + + DESCRIPTION + + Handle DIES due to C code like: + + struct foo { + int (*funcp)(int a, long l); (Generates TAG_subroutine_type DIE) + int b; + }; + + NOTES + + The parameter DIES are currently ignored. See if gdb has a way to + include this info in it's type system, and decode them if so. Is + this what the type structure's "arg_types" field is for? (FIXME) + */ + +static void +read_subroutine_type (struct dieinfo *dip, char *thisdie, char *enddie) +{ + struct type *type; /* Type that this function returns */ + struct type *ftype; /* Function that returns above type */ + + /* Decode the type that this subroutine returns */ + + type = decode_die_type (dip); + + /* Check to see if we already have a partially constructed user + defined type for this DIE, from a forward reference. */ + + if ((ftype = lookup_utype (dip->die_ref)) == NULL) + { + /* This is the first reference to one of these types. Make + a new one and place it in the user defined types. */ + ftype = lookup_function_type (type); + alloc_utype (dip->die_ref, ftype); + } + else if (TYPE_CODE (ftype) == TYPE_CODE_UNDEF) + { + /* We have an existing partially constructed type, so bash it + into the correct type. */ + TYPE_TARGET_TYPE (ftype) = type; + TYPE_LENGTH (ftype) = 1; + TYPE_CODE (ftype) = TYPE_CODE_FUNC; + } + else + { + complain (&dup_user_type_definition, DIE_ID, DIE_NAME); + } +} + +/* + + LOCAL FUNCTION + + read_enumeration -- process dies which define an enumeration + + SYNOPSIS + + static void read_enumeration (struct dieinfo *dip, char *thisdie, + char *enddie, struct objfile *objfile) + + DESCRIPTION + + Given a pointer to a die which begins an enumeration, process all + the dies that define the members of the enumeration. + + NOTES + + Note that we need to call enum_type regardless of whether or not we + have a symbol, since we might have an enum without a tag name (thus + no symbol for the tagname). + */ + +static void +read_enumeration (struct dieinfo *dip, char *thisdie, char *enddie, + struct objfile *objfile) +{ + struct type *type; + struct symbol *sym; + + type = enum_type (dip, objfile); + sym = new_symbol (dip, objfile); + if (sym != NULL) + { + SYMBOL_TYPE (sym) = type; + if (cu_language == language_cplus) + { + synthesize_typedef (dip, objfile, type); + } + } +} + +/* + + LOCAL FUNCTION + + enum_type -- decode and return a type for an enumeration + + SYNOPSIS + + static type *enum_type (struct dieinfo *dip, struct objfile *objfile) + + DESCRIPTION + + Given a pointer to a die information structure for the die which + starts an enumeration, process all the dies that define the members + of the enumeration and return a type pointer for the enumeration. + + At the same time, for each member of the enumeration, create a + symbol for it with namespace VAR_NAMESPACE and class LOC_CONST, + and give it the type of the enumeration itself. + + NOTES + + Note that the DWARF specification explicitly mandates that enum + constants occur in reverse order from the source program order, + for "consistency" and because this ordering is easier for many + compilers to generate. (Draft 6, sec 3.8.5, Enumeration type + Entries). Because gdb wants to see the enum members in program + source order, we have to ensure that the order gets reversed while + we are processing them. + */ + +static struct type * +enum_type (struct dieinfo *dip, struct objfile *objfile) +{ + struct type *type; + struct nextfield + { + struct nextfield *next; + struct field field; + }; + struct nextfield *list = NULL; + struct nextfield *new; + int nfields = 0; + int n; + char *scan; + char *listend; + unsigned short blocksz; + struct symbol *sym; + int nbytes; + int unsigned_enum = 1; + + if ((type = lookup_utype (dip->die_ref)) == NULL) + { + /* No forward references created an empty type, so install one now */ + type = alloc_utype (dip->die_ref, NULL); + } + TYPE_CODE (type) = TYPE_CODE_ENUM; + /* Some compilers try to be helpful by inventing "fake" names for + anonymous enums, structures, and unions, like "~0fake" or ".0fake". + Thanks, but no thanks... */ + if (dip->at_name != NULL + && *dip->at_name != '~' + && *dip->at_name != '.') + { + TYPE_TAG_NAME (type) = obconcat (&objfile->type_obstack, + "", "", dip->at_name); + } + if (dip->at_byte_size != 0) + { + TYPE_LENGTH (type) = dip->at_byte_size; + } + if ((scan = dip->at_element_list) != NULL) + { + if (dip->short_element_list) + { + nbytes = attribute_size (AT_short_element_list); + } + else + { + nbytes = attribute_size (AT_element_list); + } + blocksz = target_to_host (scan, nbytes, GET_UNSIGNED, objfile); + listend = scan + nbytes + blocksz; + scan += nbytes; + while (scan < listend) + { + new = (struct nextfield *) alloca (sizeof (struct nextfield)); + new->next = list; + list = new; + FIELD_TYPE (list->field) = NULL; + FIELD_BITSIZE (list->field) = 0; + FIELD_BITPOS (list->field) = + target_to_host (scan, TARGET_FT_LONG_SIZE (objfile), GET_SIGNED, + objfile); + scan += TARGET_FT_LONG_SIZE (objfile); + list->field.name = obsavestring (scan, strlen (scan), + &objfile->type_obstack); + scan += strlen (scan) + 1; + nfields++; + /* Handcraft a new symbol for this enum member. */ + sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack, + sizeof (struct symbol)); + memset (sym, 0, sizeof (struct symbol)); + SYMBOL_NAME (sym) = create_name (list->field.name, + &objfile->symbol_obstack); + SYMBOL_INIT_LANGUAGE_SPECIFIC (sym, cu_language); + SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; + SYMBOL_CLASS (sym) = LOC_CONST; + SYMBOL_TYPE (sym) = type; + SYMBOL_VALUE (sym) = FIELD_BITPOS (list->field); + if (SYMBOL_VALUE (sym) < 0) + unsigned_enum = 0; + add_symbol_to_list (sym, list_in_scope); + } + /* Now create the vector of fields, and record how big it is. This is + where we reverse the order, by pulling the members off the list in + reverse order from how they were inserted. If we have no fields + (this is apparently possible in C++) then skip building a field + vector. */ + if (nfields > 0) + { + if (unsigned_enum) + TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED; + TYPE_NFIELDS (type) = nfields; + TYPE_FIELDS (type) = (struct field *) + obstack_alloc (&objfile->symbol_obstack, sizeof (struct field) * nfields); + /* Copy the saved-up fields into the field vector. */ + for (n = 0; (n < nfields) && (list != NULL); list = list->next) + { + TYPE_FIELD (type, n++) = list->field; + } + } + } + return (type); +} + +/* + + LOCAL FUNCTION + + read_func_scope -- process all dies within a function scope + + DESCRIPTION + + Process all dies within a given function scope. We are passed + a die information structure pointer DIP for the die which + starts the function scope, and pointers into the raw die data + that define the dies within the function scope. + + For now, we ignore lexical block scopes within the function. + The problem is that AT&T cc does not define a DWARF lexical + block scope for the function itself, while gcc defines a + lexical block scope for the function. We need to think about + how to handle this difference, or if it is even a problem. + (FIXME) + */ + +static void +read_func_scope (struct dieinfo *dip, char *thisdie, char *enddie, + struct objfile *objfile) +{ + register struct context_stack *new; + + /* AT_name is absent if the function is described with an + AT_abstract_origin tag. + Ignore the function description for now to avoid GDB core dumps. + FIXME: Add code to handle AT_abstract_origin tags properly. */ + if (dip->at_name == NULL) + { + complain (&missing_at_name, DIE_ID); + return; + } + + if (objfile->ei.entry_point >= dip->at_low_pc && + objfile->ei.entry_point < dip->at_high_pc) + { + objfile->ei.entry_func_lowpc = dip->at_low_pc; + objfile->ei.entry_func_highpc = dip->at_high_pc; + } + new = push_context (0, dip->at_low_pc); + new->name = new_symbol (dip, objfile); + list_in_scope = &local_symbols; + process_dies (thisdie + dip->die_length, enddie, objfile); + new = pop_context (); + /* Make a block for the local symbols within. */ + finish_block (new->name, &local_symbols, new->old_blocks, + new->start_addr, dip->at_high_pc, objfile); + list_in_scope = &file_symbols; +} + + +/* + + LOCAL FUNCTION + + handle_producer -- process the AT_producer attribute + + DESCRIPTION + + Perform any operations that depend on finding a particular + AT_producer attribute. + + */ + +static void +handle_producer (char *producer) +{ + + /* If this compilation unit was compiled with g++ or gcc, then set the + processing_gcc_compilation flag. */ + + if (STREQN (producer, GCC_PRODUCER, strlen (GCC_PRODUCER))) + { + char version = producer[strlen (GCC_PRODUCER)]; + processing_gcc_compilation = (version == '2' ? 2 : 1); + } + else + { + processing_gcc_compilation = + STREQN (producer, GPLUS_PRODUCER, strlen (GPLUS_PRODUCER)); + /* OBSOLETE || STREQN (producer, CHILL_PRODUCER, strlen (CHILL_PRODUCER)); */ + } + + /* Select a demangling style if we can identify the producer and if + the current style is auto. We leave the current style alone if it + is not auto. We also leave the demangling style alone if we find a + gcc (cc1) producer, as opposed to a g++ (cc1plus) producer. */ + + if (AUTO_DEMANGLING) + { + if (STREQN (producer, GPLUS_PRODUCER, strlen (GPLUS_PRODUCER))) + { +#if 0 + /* For now, stay with AUTO_DEMANGLING for g++ output, as we don't + know whether it will use the old style or v3 mangling. */ + set_demangling_style (GNU_DEMANGLING_STYLE_STRING); +#endif + } + else if (STREQN (producer, LCC_PRODUCER, strlen (LCC_PRODUCER))) + { + set_demangling_style (LUCID_DEMANGLING_STYLE_STRING); + } + } +} + + +/* + + LOCAL FUNCTION + + read_file_scope -- process all dies within a file scope + + DESCRIPTION + + Process all dies within a given file scope. We are passed a + pointer to the die information structure for the die which + starts the file scope, and pointers into the raw die data which + mark the range of dies within the file scope. + + When the partial symbol table is built, the file offset for the line + number table for each compilation unit is saved in the partial symbol + table entry for that compilation unit. As the symbols for each + compilation unit are read, the line number table is read into memory + and the variable lnbase is set to point to it. Thus all we have to + do is use lnbase to access the line number table for the current + compilation unit. + */ + +static void +read_file_scope (struct dieinfo *dip, char *thisdie, char *enddie, + struct objfile *objfile) +{ + struct cleanup *back_to; + struct symtab *symtab; + + if (objfile->ei.entry_point >= dip->at_low_pc && + objfile->ei.entry_point < dip->at_high_pc) + { + objfile->ei.entry_file_lowpc = dip->at_low_pc; + objfile->ei.entry_file_highpc = dip->at_high_pc; + } + set_cu_language (dip); + if (dip->at_producer != NULL) + { + handle_producer (dip->at_producer); + } + numutypes = (enddie - thisdie) / 4; + utypes = (struct type **) xmalloc (numutypes * sizeof (struct type *)); + back_to = make_cleanup (free_utypes, NULL); + memset (utypes, 0, numutypes * sizeof (struct type *)); + memset (ftypes, 0, FT_NUM_MEMBERS * sizeof (struct type *)); + start_symtab (dip->at_name, dip->at_comp_dir, dip->at_low_pc); + record_debugformat ("DWARF 1"); + decode_line_numbers (lnbase); + process_dies (thisdie + dip->die_length, enddie, objfile); + + symtab = end_symtab (dip->at_high_pc, objfile, 0); + if (symtab != NULL) + { + symtab->language = cu_language; + } + do_cleanups (back_to); +} + +/* + + LOCAL FUNCTION + + process_dies -- process a range of DWARF Information Entries + + SYNOPSIS + + static void process_dies (char *thisdie, char *enddie, + struct objfile *objfile) + + DESCRIPTION + + Process all DIE's in a specified range. May be (and almost + certainly will be) called recursively. + */ + +static void +process_dies (char *thisdie, char *enddie, struct objfile *objfile) +{ + char *nextdie; + struct dieinfo di; + + while (thisdie < enddie) + { + basicdieinfo (&di, thisdie, objfile); + if (di.die_length < SIZEOF_DIE_LENGTH) + { + break; + } + else if (di.die_tag == TAG_padding) + { + nextdie = thisdie + di.die_length; + } + else + { + completedieinfo (&di, objfile); + if (di.at_sibling != 0) + { + nextdie = dbbase + di.at_sibling - dbroff; + } + else + { + nextdie = thisdie + di.die_length; + } + /* I think that these are always text, not data, addresses. */ + di.at_low_pc = SMASH_TEXT_ADDRESS (di.at_low_pc); + di.at_high_pc = SMASH_TEXT_ADDRESS (di.at_high_pc); + switch (di.die_tag) + { + case TAG_compile_unit: + /* Skip Tag_compile_unit if we are already inside a compilation + unit, we are unable to handle nested compilation units + properly (FIXME). */ + if (current_subfile == NULL) + read_file_scope (&di, thisdie, nextdie, objfile); + else + nextdie = thisdie + di.die_length; + break; + case TAG_global_subroutine: + case TAG_subroutine: + if (di.has_at_low_pc) + { + read_func_scope (&di, thisdie, nextdie, objfile); + } + break; + case TAG_lexical_block: + read_lexical_block_scope (&di, thisdie, nextdie, objfile); + break; + case TAG_class_type: + case TAG_structure_type: + case TAG_union_type: + read_structure_scope (&di, thisdie, nextdie, objfile); + break; + case TAG_enumeration_type: + read_enumeration (&di, thisdie, nextdie, objfile); + break; + case TAG_subroutine_type: + read_subroutine_type (&di, thisdie, nextdie); + break; + case TAG_array_type: + dwarf_read_array_type (&di); + break; + case TAG_pointer_type: + read_tag_pointer_type (&di); + break; + case TAG_string_type: + read_tag_string_type (&di); + break; + default: + new_symbol (&di, objfile); + break; + } + } + thisdie = nextdie; + } +} + +/* + + LOCAL FUNCTION + + decode_line_numbers -- decode a line number table fragment + + SYNOPSIS + + static void decode_line_numbers (char *tblscan, char *tblend, + long length, long base, long line, long pc) + + DESCRIPTION + + Translate the DWARF line number information to gdb form. + + The ".line" section contains one or more line number tables, one for + each ".line" section from the objects that were linked. + + The AT_stmt_list attribute for each TAG_source_file entry in the + ".debug" section contains the offset into the ".line" section for the + start of the table for that file. + + The table itself has the following structure: + + <table length><base address><source statement entry> + 4 bytes 4 bytes 10 bytes + + The table length is the total size of the table, including the 4 bytes + for the length information. + + The base address is the address of the first instruction generated + for the source file. + + Each source statement entry has the following structure: + + <line number><statement position><address delta> + 4 bytes 2 bytes 4 bytes + + The line number is relative to the start of the file, starting with + line 1. + + The statement position either -1 (0xFFFF) or the number of characters + from the beginning of the line to the beginning of the statement. + + The address delta is the difference between the base address and + the address of the first instruction for the statement. + + Note that we must copy the bytes from the packed table to our local + variables before attempting to use them, to avoid alignment problems + on some machines, particularly RISC processors. + + BUGS + + Does gdb expect the line numbers to be sorted? They are now by + chance/luck, but are not required to be. (FIXME) + + The line with number 0 is unused, gdb apparently can discover the + span of the last line some other way. How? (FIXME) + */ + +static void +decode_line_numbers (char *linetable) +{ + char *tblscan; + char *tblend; + unsigned long length; + unsigned long base; + unsigned long line; + unsigned long pc; + + if (linetable != NULL) + { + tblscan = tblend = linetable; + length = target_to_host (tblscan, SIZEOF_LINETBL_LENGTH, GET_UNSIGNED, + current_objfile); + tblscan += SIZEOF_LINETBL_LENGTH; + tblend += length; + base = target_to_host (tblscan, TARGET_FT_POINTER_SIZE (objfile), + GET_UNSIGNED, current_objfile); + tblscan += TARGET_FT_POINTER_SIZE (objfile); + base += baseaddr; + while (tblscan < tblend) + { + line = target_to_host (tblscan, SIZEOF_LINETBL_LINENO, GET_UNSIGNED, + current_objfile); + tblscan += SIZEOF_LINETBL_LINENO + SIZEOF_LINETBL_STMT; + pc = target_to_host (tblscan, SIZEOF_LINETBL_DELTA, GET_UNSIGNED, + current_objfile); + tblscan += SIZEOF_LINETBL_DELTA; + pc += base; + if (line != 0) + { + record_line (current_subfile, line, pc); + } + } + } +} + +/* + + LOCAL FUNCTION + + locval -- compute the value of a location attribute + + SYNOPSIS + + static int locval (struct dieinfo *dip) + + DESCRIPTION + + Given pointer to a string of bytes that define a location, compute + the location and return the value. + A location description containing no atoms indicates that the + object is optimized out. The optimized_out flag is set for those, + the return value is meaningless. + + When computing values involving the current value of the frame pointer, + the value zero is used, which results in a value relative to the frame + pointer, rather than the absolute value. This is what GDB wants + anyway. + + When the result is a register number, the isreg flag is set, otherwise + it is cleared. This is a kludge until we figure out a better + way to handle the problem. Gdb's design does not mesh well with the + DWARF notion of a location computing interpreter, which is a shame + because the flexibility goes unused. + + NOTES + + Note that stack[0] is unused except as a default error return. + Note that stack overflow is not yet handled. + */ + +static int +locval (struct dieinfo *dip) +{ + unsigned short nbytes; + unsigned short locsize; + auto long stack[64]; + int stacki; + char *loc; + char *end; + int loc_atom_code; + int loc_value_size; + + loc = dip->at_location; + nbytes = attribute_size (AT_location); + locsize = target_to_host (loc, nbytes, GET_UNSIGNED, current_objfile); + loc += nbytes; + end = loc + locsize; + stacki = 0; + stack[stacki] = 0; + dip->isreg = 0; + dip->offreg = 0; + dip->optimized_out = 1; + loc_value_size = TARGET_FT_LONG_SIZE (current_objfile); + while (loc < end) + { + dip->optimized_out = 0; + loc_atom_code = target_to_host (loc, SIZEOF_LOC_ATOM_CODE, GET_UNSIGNED, + current_objfile); + loc += SIZEOF_LOC_ATOM_CODE; + switch (loc_atom_code) + { + case 0: + /* error */ + loc = end; + break; + case OP_REG: + /* push register (number) */ + stack[++stacki] + = DWARF_REG_TO_REGNUM (target_to_host (loc, loc_value_size, + GET_UNSIGNED, + current_objfile)); + loc += loc_value_size; + dip->isreg = 1; + break; + case OP_BASEREG: + /* push value of register (number) */ + /* Actually, we compute the value as if register has 0, so the + value ends up being the offset from that register. */ + dip->offreg = 1; + dip->basereg = target_to_host (loc, loc_value_size, GET_UNSIGNED, + current_objfile); + loc += loc_value_size; + stack[++stacki] = 0; + break; + case OP_ADDR: + /* push address (relocated address) */ + stack[++stacki] = target_to_host (loc, loc_value_size, + GET_UNSIGNED, current_objfile); + loc += loc_value_size; + break; + case OP_CONST: + /* push constant (number) FIXME: signed or unsigned! */ + stack[++stacki] = target_to_host (loc, loc_value_size, + GET_SIGNED, current_objfile); + loc += loc_value_size; + break; + case OP_DEREF2: + /* pop, deref and push 2 bytes (as a long) */ + complain (&op_deref2, DIE_ID, DIE_NAME, stack[stacki]); + break; + case OP_DEREF4: /* pop, deref and push 4 bytes (as a long) */ + complain (&op_deref4, DIE_ID, DIE_NAME, stack[stacki]); + break; + case OP_ADD: /* pop top 2 items, add, push result */ + stack[stacki - 1] += stack[stacki]; + stacki--; + break; + } + } + return (stack[stacki]); +} + +/* + + LOCAL FUNCTION + + read_ofile_symtab -- build a full symtab entry from chunk of DIE's + + SYNOPSIS + + static void read_ofile_symtab (struct partial_symtab *pst) + + DESCRIPTION + + When expanding a partial symbol table entry to a full symbol table + entry, this is the function that gets called to read in the symbols + for the compilation unit. A pointer to the newly constructed symtab, + which is now the new first one on the objfile's symtab list, is + stashed in the partial symbol table entry. + */ + +static void +read_ofile_symtab (struct partial_symtab *pst) +{ + struct cleanup *back_to; + unsigned long lnsize; + file_ptr foffset; + bfd *abfd; + char lnsizedata[SIZEOF_LINETBL_LENGTH]; + + abfd = pst->objfile->obfd; + current_objfile = pst->objfile; + + /* Allocate a buffer for the entire chunk of DIE's for this compilation + unit, seek to the location in the file, and read in all the DIE's. */ + + diecount = 0; + dbsize = DBLENGTH (pst); + dbbase = xmalloc (dbsize); + dbroff = DBROFF (pst); + foffset = DBFOFF (pst) + dbroff; + base_section_offsets = pst->section_offsets; + baseaddr = ANOFFSET (pst->section_offsets, 0); + if (bfd_seek (abfd, foffset, SEEK_SET) || + (bfd_bread (dbbase, dbsize, abfd) != dbsize)) + { + xfree (dbbase); + error ("can't read DWARF data"); + } + back_to = make_cleanup (xfree, dbbase); + + /* If there is a line number table associated with this compilation unit + then read the size of this fragment in bytes, from the fragment itself. + Allocate a buffer for the fragment and read it in for future + processing. */ + + lnbase = NULL; + if (LNFOFF (pst)) + { + if (bfd_seek (abfd, LNFOFF (pst), SEEK_SET) || + (bfd_bread ((PTR) lnsizedata, sizeof (lnsizedata), abfd) + != sizeof (lnsizedata))) + { + error ("can't read DWARF line number table size"); + } + lnsize = target_to_host (lnsizedata, SIZEOF_LINETBL_LENGTH, + GET_UNSIGNED, pst->objfile); + lnbase = xmalloc (lnsize); + if (bfd_seek (abfd, LNFOFF (pst), SEEK_SET) || + (bfd_bread (lnbase, lnsize, abfd) != lnsize)) + { + xfree (lnbase); + error ("can't read DWARF line numbers"); + } + make_cleanup (xfree, lnbase); + } + + process_dies (dbbase, dbbase + dbsize, pst->objfile); + do_cleanups (back_to); + current_objfile = NULL; + pst->symtab = pst->objfile->symtabs; +} + +/* + + LOCAL FUNCTION + + psymtab_to_symtab_1 -- do grunt work for building a full symtab entry + + SYNOPSIS + + static void psymtab_to_symtab_1 (struct partial_symtab *pst) + + DESCRIPTION + + Called once for each partial symbol table entry that needs to be + expanded into a full symbol table entry. + + */ + +static void +psymtab_to_symtab_1 (struct partial_symtab *pst) +{ + int i; + struct cleanup *old_chain; + + if (pst != NULL) + { + if (pst->readin) + { + warning ("psymtab for %s already read in. Shouldn't happen.", + pst->filename); + } + else + { + /* Read in all partial symtabs on which this one is dependent */ + for (i = 0; i < pst->number_of_dependencies; i++) + { + if (!pst->dependencies[i]->readin) + { + /* Inform about additional files that need to be read in. */ + if (info_verbose) + { + fputs_filtered (" ", gdb_stdout); + wrap_here (""); + fputs_filtered ("and ", gdb_stdout); + wrap_here (""); + printf_filtered ("%s...", + pst->dependencies[i]->filename); + wrap_here (""); + gdb_flush (gdb_stdout); /* Flush output */ + } + psymtab_to_symtab_1 (pst->dependencies[i]); + } + } + if (DBLENGTH (pst)) /* Otherwise it's a dummy */ + { + buildsym_init (); + old_chain = make_cleanup (really_free_pendings, 0); + read_ofile_symtab (pst); + if (info_verbose) + { + printf_filtered ("%d DIE's, sorting...", diecount); + wrap_here (""); + gdb_flush (gdb_stdout); + } + sort_symtab_syms (pst->symtab); + do_cleanups (old_chain); + } + pst->readin = 1; + } + } +} + +/* + + LOCAL FUNCTION + + dwarf_psymtab_to_symtab -- build a full symtab entry from partial one + + SYNOPSIS + + static void dwarf_psymtab_to_symtab (struct partial_symtab *pst) + + DESCRIPTION + + This is the DWARF support entry point for building a full symbol + table entry from a partial symbol table entry. We are passed a + pointer to the partial symbol table entry that needs to be expanded. + + */ + +static void +dwarf_psymtab_to_symtab (struct partial_symtab *pst) +{ + + if (pst != NULL) + { + if (pst->readin) + { + warning ("psymtab for %s already read in. Shouldn't happen.", + pst->filename); + } + else + { + if (DBLENGTH (pst) || pst->number_of_dependencies) + { + /* Print the message now, before starting serious work, to avoid + disconcerting pauses. */ + if (info_verbose) + { + printf_filtered ("Reading in symbols for %s...", + pst->filename); + gdb_flush (gdb_stdout); + } + + psymtab_to_symtab_1 (pst); + +#if 0 /* FIXME: Check to see what dbxread is doing here and see if + we need to do an equivalent or is this something peculiar to + stabs/a.out format. + Match with global symbols. This only needs to be done once, + after all of the symtabs and dependencies have been read in. + */ + scan_file_globals (pst->objfile); +#endif + + /* Finish up the verbose info message. */ + if (info_verbose) + { + printf_filtered ("done.\n"); + gdb_flush (gdb_stdout); + } + } + } + } +} + +/* + + LOCAL FUNCTION + + add_enum_psymbol -- add enumeration members to partial symbol table + + DESCRIPTION + + Given pointer to a DIE that is known to be for an enumeration, + extract the symbolic names of the enumeration members and add + partial symbols for them. + */ + +static void +add_enum_psymbol (struct dieinfo *dip, struct objfile *objfile) +{ + char *scan; + char *listend; + unsigned short blocksz; + int nbytes; + + if ((scan = dip->at_element_list) != NULL) + { + if (dip->short_element_list) + { + nbytes = attribute_size (AT_short_element_list); + } + else + { + nbytes = attribute_size (AT_element_list); + } + blocksz = target_to_host (scan, nbytes, GET_UNSIGNED, objfile); + scan += nbytes; + listend = scan + blocksz; + while (scan < listend) + { + scan += TARGET_FT_LONG_SIZE (objfile); + add_psymbol_to_list (scan, strlen (scan), VAR_NAMESPACE, LOC_CONST, + &objfile->static_psymbols, 0, 0, cu_language, + objfile); + scan += strlen (scan) + 1; + } + } +} + +/* + + LOCAL FUNCTION + + add_partial_symbol -- add symbol to partial symbol table + + DESCRIPTION + + Given a DIE, if it is one of the types that we want to + add to a partial symbol table, finish filling in the die info + and then add a partial symbol table entry for it. + + NOTES + + The caller must ensure that the DIE has a valid name attribute. + */ + +static void +add_partial_symbol (struct dieinfo *dip, struct objfile *objfile) +{ + switch (dip->die_tag) + { + case TAG_global_subroutine: + add_psymbol_to_list (dip->at_name, strlen (dip->at_name), + VAR_NAMESPACE, LOC_BLOCK, + &objfile->global_psymbols, + 0, dip->at_low_pc, cu_language, objfile); + break; + case TAG_global_variable: + add_psymbol_to_list (dip->at_name, strlen (dip->at_name), + VAR_NAMESPACE, LOC_STATIC, + &objfile->global_psymbols, + 0, 0, cu_language, objfile); + break; + case TAG_subroutine: + add_psymbol_to_list (dip->at_name, strlen (dip->at_name), + VAR_NAMESPACE, LOC_BLOCK, + &objfile->static_psymbols, + 0, dip->at_low_pc, cu_language, objfile); + break; + case TAG_local_variable: + add_psymbol_to_list (dip->at_name, strlen (dip->at_name), + VAR_NAMESPACE, LOC_STATIC, + &objfile->static_psymbols, + 0, 0, cu_language, objfile); + break; + case TAG_typedef: + add_psymbol_to_list (dip->at_name, strlen (dip->at_name), + VAR_NAMESPACE, LOC_TYPEDEF, + &objfile->static_psymbols, + 0, 0, cu_language, objfile); + break; + case TAG_class_type: + case TAG_structure_type: + case TAG_union_type: + case TAG_enumeration_type: + /* Do not add opaque aggregate definitions to the psymtab. */ + if (!dip->has_at_byte_size) + break; + add_psymbol_to_list (dip->at_name, strlen (dip->at_name), + STRUCT_NAMESPACE, LOC_TYPEDEF, + &objfile->static_psymbols, + 0, 0, cu_language, objfile); + if (cu_language == language_cplus) + { + /* For C++, these implicitly act as typedefs as well. */ + add_psymbol_to_list (dip->at_name, strlen (dip->at_name), + VAR_NAMESPACE, LOC_TYPEDEF, + &objfile->static_psymbols, + 0, 0, cu_language, objfile); + } + break; + } +} +/* *INDENT-OFF* */ +/* + +LOCAL FUNCTION + + scan_partial_symbols -- scan DIE's within a single compilation unit + +DESCRIPTION + + Process the DIE's within a single compilation unit, looking for + interesting DIE's that contribute to the partial symbol table entry + for this compilation unit. + +NOTES + + There are some DIE's that may appear both at file scope and within + the scope of a function. We are only interested in the ones at file + scope, and the only way to tell them apart is to keep track of the + scope. For example, consider the test case: + + static int i; + main () { int j; } + + for which the relevant DWARF segment has the structure: + + 0x51: + 0x23 global subrtn sibling 0x9b + name main + fund_type FT_integer + low_pc 0x800004cc + high_pc 0x800004d4 + + 0x74: + 0x23 local var sibling 0x97 + name j + fund_type FT_integer + location OP_BASEREG 0xe + OP_CONST 0xfffffffc + OP_ADD + 0x97: + 0x4 + + 0x9b: + 0x1d local var sibling 0xb8 + name i + fund_type FT_integer + location OP_ADDR 0x800025dc + + 0xb8: + 0x4 + + We want to include the symbol 'i' in the partial symbol table, but + not the symbol 'j'. In essence, we want to skip all the dies within + the scope of a TAG_global_subroutine DIE. + + Don't attempt to add anonymous structures or unions since they have + no name. Anonymous enumerations however are processed, because we + want to extract their member names (the check for a tag name is + done later). + + Also, for variables and subroutines, check that this is the place + where the actual definition occurs, rather than just a reference + to an external. + */ +/* *INDENT-ON* */ + + + +static void +scan_partial_symbols (char *thisdie, char *enddie, struct objfile *objfile) +{ + char *nextdie; + char *temp; + struct dieinfo di; + + while (thisdie < enddie) + { + basicdieinfo (&di, thisdie, objfile); + if (di.die_length < SIZEOF_DIE_LENGTH) + { + break; + } + else + { + nextdie = thisdie + di.die_length; + /* To avoid getting complete die information for every die, we + only do it (below) for the cases we are interested in. */ + switch (di.die_tag) + { + case TAG_global_subroutine: + case TAG_subroutine: + completedieinfo (&di, objfile); + if (di.at_name && (di.has_at_low_pc || di.at_location)) + { + add_partial_symbol (&di, objfile); + /* If there is a sibling attribute, adjust the nextdie + pointer to skip the entire scope of the subroutine. + Apply some sanity checking to make sure we don't + overrun or underrun the range of remaining DIE's */ + if (di.at_sibling != 0) + { + temp = dbbase + di.at_sibling - dbroff; + if ((temp < thisdie) || (temp >= enddie)) + { + complain (&bad_die_ref, DIE_ID, DIE_NAME, + di.at_sibling); + } + else + { + nextdie = temp; + } + } + } + break; + case TAG_global_variable: + case TAG_local_variable: + completedieinfo (&di, objfile); + if (di.at_name && (di.has_at_low_pc || di.at_location)) + { + add_partial_symbol (&di, objfile); + } + break; + case TAG_typedef: + case TAG_class_type: + case TAG_structure_type: + case TAG_union_type: + completedieinfo (&di, objfile); + if (di.at_name) + { + add_partial_symbol (&di, objfile); + } + break; + case TAG_enumeration_type: + completedieinfo (&di, objfile); + if (di.at_name) + { + add_partial_symbol (&di, objfile); + } + add_enum_psymbol (&di, objfile); + break; + } + } + thisdie = nextdie; + } +} + +/* + + LOCAL FUNCTION + + scan_compilation_units -- build a psymtab entry for each compilation + + DESCRIPTION + + This is the top level dwarf parsing routine for building partial + symbol tables. + + It scans from the beginning of the DWARF table looking for the first + TAG_compile_unit DIE, and then follows the sibling chain to locate + each additional TAG_compile_unit DIE. + + For each TAG_compile_unit DIE it creates a partial symtab structure, + calls a subordinate routine to collect all the compilation unit's + global DIE's, file scope DIEs, typedef DIEs, etc, and then links the + new partial symtab structure into the partial symbol table. It also + records the appropriate information in the partial symbol table entry + to allow the chunk of DIE's and line number table for this compilation + unit to be located and re-read later, to generate a complete symbol + table entry for the compilation unit. + + Thus it effectively partitions up a chunk of DIE's for multiple + compilation units into smaller DIE chunks and line number tables, + and associates them with a partial symbol table entry. + + NOTES + + If any compilation unit has no line number table associated with + it for some reason (a missing at_stmt_list attribute, rather than + just one with a value of zero, which is valid) then we ensure that + the recorded file offset is zero so that the routine which later + reads line number table fragments knows that there is no fragment + to read. + + RETURNS + + Returns no value. + + */ + +static void +scan_compilation_units (char *thisdie, char *enddie, file_ptr dbfoff, + file_ptr lnoffset, struct objfile *objfile) +{ + char *nextdie; + struct dieinfo di; + struct partial_symtab *pst; + int culength; + int curoff; + file_ptr curlnoffset; + + while (thisdie < enddie) + { + basicdieinfo (&di, thisdie, objfile); + if (di.die_length < SIZEOF_DIE_LENGTH) + { + break; + } + else if (di.die_tag != TAG_compile_unit) + { + nextdie = thisdie + di.die_length; + } + else + { + completedieinfo (&di, objfile); + set_cu_language (&di); + if (di.at_sibling != 0) + { + nextdie = dbbase + di.at_sibling - dbroff; + } + else + { + nextdie = thisdie + di.die_length; + } + curoff = thisdie - dbbase; + culength = nextdie - thisdie; + curlnoffset = di.has_at_stmt_list ? lnoffset + di.at_stmt_list : 0; + + /* First allocate a new partial symbol table structure */ + + pst = start_psymtab_common (objfile, base_section_offsets, + di.at_name, di.at_low_pc, + objfile->global_psymbols.next, + objfile->static_psymbols.next); + + pst->texthigh = di.at_high_pc; + pst->read_symtab_private = (char *) + obstack_alloc (&objfile->psymbol_obstack, + sizeof (struct dwfinfo)); + DBFOFF (pst) = dbfoff; + DBROFF (pst) = curoff; + DBLENGTH (pst) = culength; + LNFOFF (pst) = curlnoffset; + pst->read_symtab = dwarf_psymtab_to_symtab; + + /* Now look for partial symbols */ + + scan_partial_symbols (thisdie + di.die_length, nextdie, objfile); + + pst->n_global_syms = objfile->global_psymbols.next - + (objfile->global_psymbols.list + pst->globals_offset); + pst->n_static_syms = objfile->static_psymbols.next - + (objfile->static_psymbols.list + pst->statics_offset); + sort_pst_symbols (pst); + /* If there is already a psymtab or symtab for a file of this name, + remove it. (If there is a symtab, more drastic things also + happen.) This happens in VxWorks. */ + free_named_symtabs (pst->filename); + } + thisdie = nextdie; + } +} + +/* + + LOCAL FUNCTION + + new_symbol -- make a symbol table entry for a new symbol + + SYNOPSIS + + static struct symbol *new_symbol (struct dieinfo *dip, + struct objfile *objfile) + + DESCRIPTION + + Given a pointer to a DWARF information entry, figure out if we need + to make a symbol table entry for it, and if so, create a new entry + and return a pointer to it. + */ + +static struct symbol * +new_symbol (struct dieinfo *dip, struct objfile *objfile) +{ + struct symbol *sym = NULL; + + if (dip->at_name != NULL) + { + sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack, + sizeof (struct symbol)); + OBJSTAT (objfile, n_syms++); + memset (sym, 0, sizeof (struct symbol)); + SYMBOL_NAME (sym) = create_name (dip->at_name, + &objfile->symbol_obstack); + /* default assumptions */ + SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; + SYMBOL_CLASS (sym) = LOC_STATIC; + SYMBOL_TYPE (sym) = decode_die_type (dip); + + /* If this symbol is from a C++ compilation, then attempt to cache the + demangled form for future reference. This is a typical time versus + space tradeoff, that was decided in favor of time because it sped up + C++ symbol lookups by a factor of about 20. */ + + SYMBOL_LANGUAGE (sym) = cu_language; + SYMBOL_INIT_DEMANGLED_NAME (sym, &objfile->symbol_obstack); + switch (dip->die_tag) + { + case TAG_label: + SYMBOL_VALUE_ADDRESS (sym) = dip->at_low_pc; + SYMBOL_CLASS (sym) = LOC_LABEL; + break; + case TAG_global_subroutine: + case TAG_subroutine: + SYMBOL_VALUE_ADDRESS (sym) = dip->at_low_pc; + SYMBOL_TYPE (sym) = lookup_function_type (SYMBOL_TYPE (sym)); + if (dip->at_prototyped) + TYPE_FLAGS (SYMBOL_TYPE (sym)) |= TYPE_FLAG_PROTOTYPED; + SYMBOL_CLASS (sym) = LOC_BLOCK; + if (dip->die_tag == TAG_global_subroutine) + { + add_symbol_to_list (sym, &global_symbols); + } + else + { + add_symbol_to_list (sym, list_in_scope); + } + break; + case TAG_global_variable: + if (dip->at_location != NULL) + { + SYMBOL_VALUE_ADDRESS (sym) = locval (dip); + add_symbol_to_list (sym, &global_symbols); + SYMBOL_CLASS (sym) = LOC_STATIC; + SYMBOL_VALUE (sym) += baseaddr; + } + break; + case TAG_local_variable: + if (dip->at_location != NULL) + { + int loc = locval (dip); + if (dip->optimized_out) + { + SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT; + } + else if (dip->isreg) + { + SYMBOL_CLASS (sym) = LOC_REGISTER; + } + else if (dip->offreg) + { + SYMBOL_CLASS (sym) = LOC_BASEREG; + SYMBOL_BASEREG (sym) = dip->basereg; + } + else + { + SYMBOL_CLASS (sym) = LOC_STATIC; + SYMBOL_VALUE (sym) += baseaddr; + } + if (SYMBOL_CLASS (sym) == LOC_STATIC) + { + /* LOC_STATIC address class MUST use SYMBOL_VALUE_ADDRESS, + which may store to a bigger location than SYMBOL_VALUE. */ + SYMBOL_VALUE_ADDRESS (sym) = loc; + } + else + { + SYMBOL_VALUE (sym) = loc; + } + add_symbol_to_list (sym, list_in_scope); + } + break; + case TAG_formal_parameter: + if (dip->at_location != NULL) + { + SYMBOL_VALUE (sym) = locval (dip); + } + add_symbol_to_list (sym, list_in_scope); + if (dip->isreg) + { + SYMBOL_CLASS (sym) = LOC_REGPARM; + } + else if (dip->offreg) + { + SYMBOL_CLASS (sym) = LOC_BASEREG_ARG; + SYMBOL_BASEREG (sym) = dip->basereg; + } + else + { + SYMBOL_CLASS (sym) = LOC_ARG; + } + break; + case TAG_unspecified_parameters: + /* From varargs functions; gdb doesn't seem to have any interest in + this information, so just ignore it for now. (FIXME?) */ + break; + case TAG_class_type: + case TAG_structure_type: + case TAG_union_type: + case TAG_enumeration_type: + SYMBOL_CLASS (sym) = LOC_TYPEDEF; + SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE; + add_symbol_to_list (sym, list_in_scope); + break; + case TAG_typedef: + SYMBOL_CLASS (sym) = LOC_TYPEDEF; + SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; + add_symbol_to_list (sym, list_in_scope); + break; + default: + /* Not a tag we recognize. Hopefully we aren't processing trash + data, but since we must specifically ignore things we don't + recognize, there is nothing else we should do at this point. */ + break; + } + } + return (sym); +} + +/* + + LOCAL FUNCTION + + synthesize_typedef -- make a symbol table entry for a "fake" typedef + + SYNOPSIS + + static void synthesize_typedef (struct dieinfo *dip, + struct objfile *objfile, + struct type *type); + + DESCRIPTION + + Given a pointer to a DWARF information entry, synthesize a typedef + for the name in the DIE, using the specified type. + + This is used for C++ class, structs, unions, and enumerations to + set up the tag name as a type. + + */ + +static void +synthesize_typedef (struct dieinfo *dip, struct objfile *objfile, + struct type *type) +{ + struct symbol *sym = NULL; + + if (dip->at_name != NULL) + { + sym = (struct symbol *) + obstack_alloc (&objfile->symbol_obstack, sizeof (struct symbol)); + OBJSTAT (objfile, n_syms++); + memset (sym, 0, sizeof (struct symbol)); + SYMBOL_NAME (sym) = create_name (dip->at_name, + &objfile->symbol_obstack); + SYMBOL_INIT_LANGUAGE_SPECIFIC (sym, cu_language); + SYMBOL_TYPE (sym) = type; + SYMBOL_CLASS (sym) = LOC_TYPEDEF; + SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; + add_symbol_to_list (sym, list_in_scope); + } +} + +/* + + LOCAL FUNCTION + + decode_mod_fund_type -- decode a modified fundamental type + + SYNOPSIS + + static struct type *decode_mod_fund_type (char *typedata) + + DESCRIPTION + + Decode a block of data containing a modified fundamental + type specification. TYPEDATA is a pointer to the block, + which starts with a length containing the size of the rest + of the block. At the end of the block is a fundmental type + code value that gives the fundamental type. Everything + in between are type modifiers. + + We simply compute the number of modifiers and call the general + function decode_modified_type to do the actual work. + */ + +static struct type * +decode_mod_fund_type (char *typedata) +{ + struct type *typep = NULL; + unsigned short modcount; + int nbytes; + + /* Get the total size of the block, exclusive of the size itself */ + + nbytes = attribute_size (AT_mod_fund_type); + modcount = target_to_host (typedata, nbytes, GET_UNSIGNED, current_objfile); + typedata += nbytes; + + /* Deduct the size of the fundamental type bytes at the end of the block. */ + + modcount -= attribute_size (AT_fund_type); + + /* Now do the actual decoding */ + + typep = decode_modified_type (typedata, modcount, AT_mod_fund_type); + return (typep); +} + +/* + + LOCAL FUNCTION + + decode_mod_u_d_type -- decode a modified user defined type + + SYNOPSIS + + static struct type *decode_mod_u_d_type (char *typedata) + + DESCRIPTION + + Decode a block of data containing a modified user defined + type specification. TYPEDATA is a pointer to the block, + which consists of a two byte length, containing the size + of the rest of the block. At the end of the block is a + four byte value that gives a reference to a user defined type. + Everything in between are type modifiers. + + We simply compute the number of modifiers and call the general + function decode_modified_type to do the actual work. + */ + +static struct type * +decode_mod_u_d_type (char *typedata) +{ + struct type *typep = NULL; + unsigned short modcount; + int nbytes; + + /* Get the total size of the block, exclusive of the size itself */ + + nbytes = attribute_size (AT_mod_u_d_type); + modcount = target_to_host (typedata, nbytes, GET_UNSIGNED, current_objfile); + typedata += nbytes; + + /* Deduct the size of the reference type bytes at the end of the block. */ + + modcount -= attribute_size (AT_user_def_type); + + /* Now do the actual decoding */ + + typep = decode_modified_type (typedata, modcount, AT_mod_u_d_type); + return (typep); +} + +/* + + LOCAL FUNCTION + + decode_modified_type -- decode modified user or fundamental type + + SYNOPSIS + + static struct type *decode_modified_type (char *modifiers, + unsigned short modcount, int mtype) + + DESCRIPTION + + Decode a modified type, either a modified fundamental type or + a modified user defined type. MODIFIERS is a pointer to the + block of bytes that define MODCOUNT modifiers. Immediately + following the last modifier is a short containing the fundamental + type or a long containing the reference to the user defined + type. Which one is determined by MTYPE, which is either + AT_mod_fund_type or AT_mod_u_d_type to indicate what modified + type we are generating. + + We call ourself recursively to generate each modified type,` + until MODCOUNT reaches zero, at which point we have consumed + all the modifiers and generate either the fundamental type or + user defined type. When the recursion unwinds, each modifier + is applied in turn to generate the full modified type. + + NOTES + + If we find a modifier that we don't recognize, and it is not one + of those reserved for application specific use, then we issue a + warning and simply ignore the modifier. + + BUGS + + We currently ignore MOD_const and MOD_volatile. (FIXME) + + */ + +static struct type * +decode_modified_type (char *modifiers, unsigned int modcount, int mtype) +{ + struct type *typep = NULL; + unsigned short fundtype; + DIE_REF die_ref; + char modifier; + int nbytes; + + if (modcount == 0) + { + switch (mtype) + { + case AT_mod_fund_type: + nbytes = attribute_size (AT_fund_type); + fundtype = target_to_host (modifiers, nbytes, GET_UNSIGNED, + current_objfile); + typep = decode_fund_type (fundtype); + break; + case AT_mod_u_d_type: + nbytes = attribute_size (AT_user_def_type); + die_ref = target_to_host (modifiers, nbytes, GET_UNSIGNED, + current_objfile); + if ((typep = lookup_utype (die_ref)) == NULL) + { + typep = alloc_utype (die_ref, NULL); + } + break; + default: + complain (&botched_modified_type, DIE_ID, DIE_NAME, mtype); + typep = dwarf_fundamental_type (current_objfile, FT_INTEGER); + break; + } + } + else + { + modifier = *modifiers++; + typep = decode_modified_type (modifiers, --modcount, mtype); + switch (modifier) + { + case MOD_pointer_to: + typep = lookup_pointer_type (typep); + break; + case MOD_reference_to: + typep = lookup_reference_type (typep); + break; + case MOD_const: + complain (&const_ignored, DIE_ID, DIE_NAME); /* FIXME */ + break; + case MOD_volatile: + complain (&volatile_ignored, DIE_ID, DIE_NAME); /* FIXME */ + break; + default: + if (!(MOD_lo_user <= (unsigned char) modifier + && (unsigned char) modifier <= MOD_hi_user)) + { + complain (&unknown_type_modifier, DIE_ID, DIE_NAME, modifier); + } + break; + } + } + return (typep); +} + +/* + + LOCAL FUNCTION + + decode_fund_type -- translate basic DWARF type to gdb base type + + DESCRIPTION + + Given an integer that is one of the fundamental DWARF types, + translate it to one of the basic internal gdb types and return + a pointer to the appropriate gdb type (a "struct type *"). + + NOTES + + For robustness, if we are asked to translate a fundamental + type that we are unprepared to deal with, we return int so + callers can always depend upon a valid type being returned, + and so gdb may at least do something reasonable by default. + If the type is not in the range of those types defined as + application specific types, we also issue a warning. + */ + +static struct type * +decode_fund_type (unsigned int fundtype) +{ + struct type *typep = NULL; + + switch (fundtype) + { + + case FT_void: + typep = dwarf_fundamental_type (current_objfile, FT_VOID); + break; + + case FT_boolean: /* Was FT_set in AT&T version */ + typep = dwarf_fundamental_type (current_objfile, FT_BOOLEAN); + break; + + case FT_pointer: /* (void *) */ + typep = dwarf_fundamental_type (current_objfile, FT_VOID); + typep = lookup_pointer_type (typep); + break; + + case FT_char: + typep = dwarf_fundamental_type (current_objfile, FT_CHAR); + break; + + case FT_signed_char: + typep = dwarf_fundamental_type (current_objfile, FT_SIGNED_CHAR); + break; + + case FT_unsigned_char: + typep = dwarf_fundamental_type (current_objfile, FT_UNSIGNED_CHAR); + break; + + case FT_short: + typep = dwarf_fundamental_type (current_objfile, FT_SHORT); + break; + + case FT_signed_short: + typep = dwarf_fundamental_type (current_objfile, FT_SIGNED_SHORT); + break; + + case FT_unsigned_short: + typep = dwarf_fundamental_type (current_objfile, FT_UNSIGNED_SHORT); + break; + + case FT_integer: + typep = dwarf_fundamental_type (current_objfile, FT_INTEGER); + break; + + case FT_signed_integer: + typep = dwarf_fundamental_type (current_objfile, FT_SIGNED_INTEGER); + break; + + case FT_unsigned_integer: + typep = dwarf_fundamental_type (current_objfile, FT_UNSIGNED_INTEGER); + break; + + case FT_long: + typep = dwarf_fundamental_type (current_objfile, FT_LONG); + break; + + case FT_signed_long: + typep = dwarf_fundamental_type (current_objfile, FT_SIGNED_LONG); + break; + + case FT_unsigned_long: + typep = dwarf_fundamental_type (current_objfile, FT_UNSIGNED_LONG); + break; + + case FT_long_long: + typep = dwarf_fundamental_type (current_objfile, FT_LONG_LONG); + break; + + case FT_signed_long_long: + typep = dwarf_fundamental_type (current_objfile, FT_SIGNED_LONG_LONG); + break; + + case FT_unsigned_long_long: + typep = dwarf_fundamental_type (current_objfile, FT_UNSIGNED_LONG_LONG); + break; + + case FT_float: + typep = dwarf_fundamental_type (current_objfile, FT_FLOAT); + break; + + case FT_dbl_prec_float: + typep = dwarf_fundamental_type (current_objfile, FT_DBL_PREC_FLOAT); + break; + + case FT_ext_prec_float: + typep = dwarf_fundamental_type (current_objfile, FT_EXT_PREC_FLOAT); + break; + + case FT_complex: + typep = dwarf_fundamental_type (current_objfile, FT_COMPLEX); + break; + + case FT_dbl_prec_complex: + typep = dwarf_fundamental_type (current_objfile, FT_DBL_PREC_COMPLEX); + break; + + case FT_ext_prec_complex: + typep = dwarf_fundamental_type (current_objfile, FT_EXT_PREC_COMPLEX); + break; + + } + + if (typep == NULL) + { + typep = dwarf_fundamental_type (current_objfile, FT_INTEGER); + if (!(FT_lo_user <= fundtype && fundtype <= FT_hi_user)) + { + complain (&unexpected_fund_type, DIE_ID, DIE_NAME, fundtype); + } + } + + return (typep); +} + +/* + + LOCAL FUNCTION + + create_name -- allocate a fresh copy of a string on an obstack + + DESCRIPTION + + Given a pointer to a string and a pointer to an obstack, allocates + a fresh copy of the string on the specified obstack. + + */ + +static char * +create_name (char *name, struct obstack *obstackp) +{ + int length; + char *newname; + + length = strlen (name) + 1; + newname = (char *) obstack_alloc (obstackp, length); + strcpy (newname, name); + return (newname); +} + +/* + + LOCAL FUNCTION + + basicdieinfo -- extract the minimal die info from raw die data + + SYNOPSIS + + void basicdieinfo (char *diep, struct dieinfo *dip, + struct objfile *objfile) + + DESCRIPTION + + Given a pointer to raw DIE data, and a pointer to an instance of a + die info structure, this function extracts the basic information + from the DIE data required to continue processing this DIE, along + with some bookkeeping information about the DIE. + + The information we absolutely must have includes the DIE tag, + and the DIE length. If we need the sibling reference, then we + will have to call completedieinfo() to process all the remaining + DIE information. + + Note that since there is no guarantee that the data is properly + aligned in memory for the type of access required (indirection + through anything other than a char pointer), and there is no + guarantee that it is in the same byte order as the gdb host, + we call a function which deals with both alignment and byte + swapping issues. Possibly inefficient, but quite portable. + + We also take care of some other basic things at this point, such + as ensuring that the instance of the die info structure starts + out completely zero'd and that curdie is initialized for use + in error reporting if we have a problem with the current die. + + NOTES + + All DIE's must have at least a valid length, thus the minimum + DIE size is SIZEOF_DIE_LENGTH. In order to have a valid tag, the + DIE size must be at least SIZEOF_DIE_TAG larger, otherwise they + are forced to be TAG_padding DIES. + + Padding DIES must be at least SIZEOF_DIE_LENGTH in length, implying + that if a padding DIE is used for alignment and the amount needed is + less than SIZEOF_DIE_LENGTH, then the padding DIE has to be big + enough to align to the next alignment boundry. + + We do some basic sanity checking here, such as verifying that the + length of the die would not cause it to overrun the recorded end of + the buffer holding the DIE info. If we find a DIE that is either + too small or too large, we force it's length to zero which should + cause the caller to take appropriate action. + */ + +static void +basicdieinfo (struct dieinfo *dip, char *diep, struct objfile *objfile) +{ + curdie = dip; + memset (dip, 0, sizeof (struct dieinfo)); + dip->die = diep; + dip->die_ref = dbroff + (diep - dbbase); + dip->die_length = target_to_host (diep, SIZEOF_DIE_LENGTH, GET_UNSIGNED, + objfile); + if ((dip->die_length < SIZEOF_DIE_LENGTH) || + ((diep + dip->die_length) > (dbbase + dbsize))) + { + complain (&malformed_die, DIE_ID, DIE_NAME, dip->die_length); + dip->die_length = 0; + } + else if (dip->die_length < (SIZEOF_DIE_LENGTH + SIZEOF_DIE_TAG)) + { + dip->die_tag = TAG_padding; + } + else + { + diep += SIZEOF_DIE_LENGTH; + dip->die_tag = target_to_host (diep, SIZEOF_DIE_TAG, GET_UNSIGNED, + objfile); + } +} + +/* + + LOCAL FUNCTION + + completedieinfo -- finish reading the information for a given DIE + + SYNOPSIS + + void completedieinfo (struct dieinfo *dip, struct objfile *objfile) + + DESCRIPTION + + Given a pointer to an already partially initialized die info structure, + scan the raw DIE data and finish filling in the die info structure + from the various attributes found. + + Note that since there is no guarantee that the data is properly + aligned in memory for the type of access required (indirection + through anything other than a char pointer), and there is no + guarantee that it is in the same byte order as the gdb host, + we call a function which deals with both alignment and byte + swapping issues. Possibly inefficient, but quite portable. + + NOTES + + Each time we are called, we increment the diecount variable, which + keeps an approximate count of the number of dies processed for + each compilation unit. This information is presented to the user + if the info_verbose flag is set. + + */ + +static void +completedieinfo (struct dieinfo *dip, struct objfile *objfile) +{ + char *diep; /* Current pointer into raw DIE data */ + char *end; /* Terminate DIE scan here */ + unsigned short attr; /* Current attribute being scanned */ + unsigned short form; /* Form of the attribute */ + int nbytes; /* Size of next field to read */ + + diecount++; + diep = dip->die; + end = diep + dip->die_length; + diep += SIZEOF_DIE_LENGTH + SIZEOF_DIE_TAG; + while (diep < end) + { + attr = target_to_host (diep, SIZEOF_ATTRIBUTE, GET_UNSIGNED, objfile); + diep += SIZEOF_ATTRIBUTE; + if ((nbytes = attribute_size (attr)) == -1) + { + complain (&unknown_attribute_length, DIE_ID, DIE_NAME); + diep = end; + continue; + } + switch (attr) + { + case AT_fund_type: + dip->at_fund_type = target_to_host (diep, nbytes, GET_UNSIGNED, + objfile); + break; + case AT_ordering: + dip->at_ordering = target_to_host (diep, nbytes, GET_UNSIGNED, + objfile); + break; + case AT_bit_offset: + dip->at_bit_offset = target_to_host (diep, nbytes, GET_UNSIGNED, + objfile); + break; + case AT_sibling: + dip->at_sibling = target_to_host (diep, nbytes, GET_UNSIGNED, + objfile); + break; + case AT_stmt_list: + dip->at_stmt_list = target_to_host (diep, nbytes, GET_UNSIGNED, + objfile); + dip->has_at_stmt_list = 1; + break; + case AT_low_pc: + dip->at_low_pc = target_to_host (diep, nbytes, GET_UNSIGNED, + objfile); + dip->at_low_pc += baseaddr; + dip->has_at_low_pc = 1; + break; + case AT_high_pc: + dip->at_high_pc = target_to_host (diep, nbytes, GET_UNSIGNED, + objfile); + dip->at_high_pc += baseaddr; + break; + case AT_language: + dip->at_language = target_to_host (diep, nbytes, GET_UNSIGNED, + objfile); + break; + case AT_user_def_type: + dip->at_user_def_type = target_to_host (diep, nbytes, + GET_UNSIGNED, objfile); + break; + case AT_byte_size: + dip->at_byte_size = target_to_host (diep, nbytes, GET_UNSIGNED, + objfile); + dip->has_at_byte_size = 1; + break; + case AT_bit_size: + dip->at_bit_size = target_to_host (diep, nbytes, GET_UNSIGNED, + objfile); + break; + case AT_member: + dip->at_member = target_to_host (diep, nbytes, GET_UNSIGNED, + objfile); + break; + case AT_discr: + dip->at_discr = target_to_host (diep, nbytes, GET_UNSIGNED, + objfile); + break; + case AT_location: + dip->at_location = diep; + break; + case AT_mod_fund_type: + dip->at_mod_fund_type = diep; + break; + case AT_subscr_data: + dip->at_subscr_data = diep; + break; + case AT_mod_u_d_type: + dip->at_mod_u_d_type = diep; + break; + case AT_element_list: + dip->at_element_list = diep; + dip->short_element_list = 0; + break; + case AT_short_element_list: + dip->at_element_list = diep; + dip->short_element_list = 1; + break; + case AT_discr_value: + dip->at_discr_value = diep; + break; + case AT_string_length: + dip->at_string_length = diep; + break; + case AT_name: + dip->at_name = diep; + break; + case AT_comp_dir: + /* For now, ignore any "hostname:" portion, since gdb doesn't + know how to deal with it. (FIXME). */ + dip->at_comp_dir = strrchr (diep, ':'); + if (dip->at_comp_dir != NULL) + { + dip->at_comp_dir++; + } + else + { + dip->at_comp_dir = diep; + } + break; + case AT_producer: + dip->at_producer = diep; + break; + case AT_start_scope: + dip->at_start_scope = target_to_host (diep, nbytes, GET_UNSIGNED, + objfile); + break; + case AT_stride_size: + dip->at_stride_size = target_to_host (diep, nbytes, GET_UNSIGNED, + objfile); + break; + case AT_src_info: + dip->at_src_info = target_to_host (diep, nbytes, GET_UNSIGNED, + objfile); + break; + case AT_prototyped: + dip->at_prototyped = diep; + break; + default: + /* Found an attribute that we are unprepared to handle. However + it is specifically one of the design goals of DWARF that + consumers should ignore unknown attributes. As long as the + form is one that we recognize (so we know how to skip it), + we can just ignore the unknown attribute. */ + break; + } + form = FORM_FROM_ATTR (attr); + switch (form) + { + case FORM_DATA2: + diep += 2; + break; + case FORM_DATA4: + case FORM_REF: + diep += 4; + break; + case FORM_DATA8: + diep += 8; + break; + case FORM_ADDR: + diep += TARGET_FT_POINTER_SIZE (objfile); + break; + case FORM_BLOCK2: + diep += 2 + target_to_host (diep, nbytes, GET_UNSIGNED, objfile); + break; + case FORM_BLOCK4: + diep += 4 + target_to_host (diep, nbytes, GET_UNSIGNED, objfile); + break; + case FORM_STRING: + diep += strlen (diep) + 1; + break; + default: + complain (&unknown_attribute_form, DIE_ID, DIE_NAME, form); + diep = end; + break; + } + } +} + +/* + + LOCAL FUNCTION + + target_to_host -- swap in target data to host + + SYNOPSIS + + target_to_host (char *from, int nbytes, int signextend, + struct objfile *objfile) + + DESCRIPTION + + Given pointer to data in target format in FROM, a byte count for + the size of the data in NBYTES, a flag indicating whether or not + the data is signed in SIGNEXTEND, and a pointer to the current + objfile in OBJFILE, convert the data to host format and return + the converted value. + + NOTES + + FIXME: If we read data that is known to be signed, and expect to + use it as signed data, then we need to explicitly sign extend the + result until the bfd library is able to do this for us. + + FIXME: Would a 32 bit target ever need an 8 byte result? + + */ + +static CORE_ADDR +target_to_host (char *from, int nbytes, int signextend, /* FIXME: Unused */ + struct objfile *objfile) +{ + CORE_ADDR rtnval; + + switch (nbytes) + { + case 8: + rtnval = bfd_get_64 (objfile->obfd, (bfd_byte *) from); + break; + case 4: + rtnval = bfd_get_32 (objfile->obfd, (bfd_byte *) from); + break; + case 2: + rtnval = bfd_get_16 (objfile->obfd, (bfd_byte *) from); + break; + case 1: + rtnval = bfd_get_8 (objfile->obfd, (bfd_byte *) from); + break; + default: + complain (&no_bfd_get_N, DIE_ID, DIE_NAME, nbytes); + rtnval = 0; + break; + } + return (rtnval); +} + +/* + + LOCAL FUNCTION + + attribute_size -- compute size of data for a DWARF attribute + + SYNOPSIS + + static int attribute_size (unsigned int attr) + + DESCRIPTION + + Given a DWARF attribute in ATTR, compute the size of the first + piece of data associated with this attribute and return that + size. + + Returns -1 for unrecognized attributes. + + */ + +static int +attribute_size (unsigned int attr) +{ + int nbytes; /* Size of next data for this attribute */ + unsigned short form; /* Form of the attribute */ + + form = FORM_FROM_ATTR (attr); + switch (form) + { + case FORM_STRING: /* A variable length field is next */ + nbytes = 0; + break; + case FORM_DATA2: /* Next 2 byte field is the data itself */ + case FORM_BLOCK2: /* Next 2 byte field is a block length */ + nbytes = 2; + break; + case FORM_DATA4: /* Next 4 byte field is the data itself */ + case FORM_BLOCK4: /* Next 4 byte field is a block length */ + case FORM_REF: /* Next 4 byte field is a DIE offset */ + nbytes = 4; + break; + case FORM_DATA8: /* Next 8 byte field is the data itself */ + nbytes = 8; + break; + case FORM_ADDR: /* Next field size is target sizeof(void *) */ + nbytes = TARGET_FT_POINTER_SIZE (objfile); + break; + default: + complain (&unknown_attribute_form, DIE_ID, DIE_NAME, form); + nbytes = -1; + break; + } + return (nbytes); +} diff --git a/gdb/hpread.c b/gdb/hpread.c new file mode 100644 index 0000000..4cc5f18 --- /dev/null +++ b/gdb/hpread.c @@ -0,0 +1,6310 @@ +/* Read hp debug symbols and convert to internal format, for GDB. + Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 + 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 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Written by the Center for Software Science at the University of Utah + and by Cygnus Support. */ + +#include "defs.h" +#include "bfd.h" +#include "gdb_string.h" +#include "hp-symtab.h" +#include "syms.h" +#include "symtab.h" +#include "symfile.h" +#include "objfiles.h" +#include "buildsym.h" +#include "complaints.h" +#include "gdb-stabs.h" +#include "gdbtypes.h" +#include "demangle.h" + +/* Private information attached to an objfile which we use to find + and internalize the HP C debug symbols within that objfile. */ + +struct hpread_symfile_info + { + /* The contents of each of the debug sections (there are 4 of them). */ + char *gntt; + char *lntt; + char *slt; + char *vt; + + /* We keep the size of the $VT$ section for range checking. */ + unsigned int vt_size; + + /* Some routines still need to know the number of symbols in the + main debug sections ($LNTT$ and $GNTT$). */ + unsigned int lntt_symcount; + unsigned int gntt_symcount; + + /* To keep track of all the types we've processed. */ + struct type **dntt_type_vector; + int dntt_type_vector_length; + + /* Keeps track of the beginning of a range of source lines. */ + sltpointer sl_index; + + /* Some state variables we'll need. */ + int within_function; + + /* Keep track of the current function's address. We may need to look + up something based on this address. */ + unsigned int current_function_value; + }; + +/* Accessor macros to get at the fields. */ +#define HPUX_SYMFILE_INFO(o) \ + ((struct hpread_symfile_info *)((o)->sym_private)) +#define GNTT(o) (HPUX_SYMFILE_INFO(o)->gntt) +#define LNTT(o) (HPUX_SYMFILE_INFO(o)->lntt) +#define SLT(o) (HPUX_SYMFILE_INFO(o)->slt) +#define VT(o) (HPUX_SYMFILE_INFO(o)->vt) +#define VT_SIZE(o) (HPUX_SYMFILE_INFO(o)->vt_size) +#define LNTT_SYMCOUNT(o) (HPUX_SYMFILE_INFO(o)->lntt_symcount) +#define GNTT_SYMCOUNT(o) (HPUX_SYMFILE_INFO(o)->gntt_symcount) +#define DNTT_TYPE_VECTOR(o) (HPUX_SYMFILE_INFO(o)->dntt_type_vector) +#define DNTT_TYPE_VECTOR_LENGTH(o) \ + (HPUX_SYMFILE_INFO(o)->dntt_type_vector_length) +#define SL_INDEX(o) (HPUX_SYMFILE_INFO(o)->sl_index) +#define WITHIN_FUNCTION(o) (HPUX_SYMFILE_INFO(o)->within_function) +#define CURRENT_FUNCTION_VALUE(o) (HPUX_SYMFILE_INFO(o)->current_function_value) + +/* Given the native debug symbol SYM, set NAMEP to the name associated + with the debug symbol. Note we may be called with a debug symbol which + has no associated name, in that case we return an empty string. + + Also note we "know" that the name for any symbol is always in the + same place. Hence we don't have to conditionalize on the symbol type. */ +#define SET_NAMESTRING(SYM, NAMEP, OBJFILE) \ + if (! hpread_has_name ((SYM)->dblock.kind)) \ + *NAMEP = ""; \ + else if (((unsigned)(SYM)->dsfile.name) >= VT_SIZE (OBJFILE)) \ + { \ + complain (&string_table_offset_complaint, (char *) symnum); \ + *NAMEP = ""; \ + } \ + else \ + *NAMEP = (SYM)->dsfile.name + VT (OBJFILE) + +/* We put a pointer to this structure in the read_symtab_private field + of the psymtab. */ + +struct symloc + { + /* The offset within the file symbol table of first local symbol for + this file. */ + + int ldsymoff; + + /* Length (in bytes) of the section of the symbol table devoted to + this file's symbols (actually, the section bracketed may contain + more than just this file's symbols). If ldsymlen is 0, the only + reason for this thing's existence is the dependency list. + Nothing else will happen when it is read in. */ + + int ldsymlen; + }; + +#define LDSYMOFF(p) (((struct symloc *)((p)->read_symtab_private))->ldsymoff) +#define LDSYMLEN(p) (((struct symloc *)((p)->read_symtab_private))->ldsymlen) +#define SYMLOC(p) ((struct symloc *)((p)->read_symtab_private)) + +/* FIXME: Shouldn't this stuff be in a .h file somewhere? */ +/* Complaints about the symbols we have encountered. */ +extern struct complaint string_table_offset_complaint; +extern struct complaint lbrac_unmatched_complaint; +extern struct complaint lbrac_mismatch_complaint; + +static struct complaint hpread_unhandled_end_common_complaint = +{ + "unhandled symbol in hp-symtab-read.c: DNTT_TYPE_COMMON/DNTT_TYPE_END.\n", 0, 0 +}; + +static struct complaint hpread_unhandled_type_complaint = +{ + "hpread_type_translate: unhandled type code.", 0, 0 +}; + +static struct complaint hpread_struct_complaint = +{ + "hpread_read_struct_type: expected SVAR type...", 0, 0 +}; + +static struct complaint hpread_array_complaint = +{ + "error in hpread_array_type.", 0, 0 +}; + +static struct complaint hpread_type_lookup_complaint = +{ + "error in hpread_type_lookup().", 0, 0 +}; + + +static struct complaint hpread_unexpected_end_complaint = +{ + "internal error in hp-symtab-read.c: Unexpected DNTT_TYPE_END kind.", 0, 0 +}; + +static struct complaint hpread_tagdef_complaint = +{ + "error processing class tagdef", 0, 0 +}; + +static struct complaint hpread_unhandled_common_complaint = +{ + "unhandled symbol in hp-symtab-read.c: DNTT_TYPE_COMMON.", 0, 0 +}; + +static struct complaint hpread_unhandled_blockdata_complaint = +{ + "unhandled symbol in hp-symtab-read.c: DNTT_TYPE_BLOCKDATA.", 0, 0 +}; + +/* To generate dumping code, uncomment this define. The dumping + itself is controlled by routine-local statics called "dumping". */ +/* #define DUMPING 1 */ + +/* To use the quick look-up tables, uncomment this define. */ +#define QUICK_LOOK_UP 1 + +/* To call PXDB to process un-processed files, uncomment this define. */ +#define USE_PXDB 1 + +/* Forward procedure declarations */ + +void hpread_symfile_init (struct objfile *); + +void do_pxdb (bfd *); + +void hpread_build_psymtabs (struct objfile *, int); + +void hpread_symfile_finish (struct objfile *); + +static union dnttentry *hpread_get_gntt (int, struct objfile *); + +static union dnttentry *hpread_get_lntt (int index, struct objfile *objfile); + + +static unsigned long hpread_get_textlow (int, int, struct objfile *, int); + +static struct partial_symtab *hpread_start_psymtab + (struct objfile *, char *, CORE_ADDR, int, + struct partial_symbol **, struct partial_symbol **); + +static struct partial_symtab *hpread_end_psymtab + (struct partial_symtab *, char **, int, int, CORE_ADDR, + struct partial_symtab **, int); + +static unsigned long hpread_get_scope_start (sltpointer, struct objfile *); + +static unsigned long hpread_get_line (sltpointer, struct objfile *); + +static CORE_ADDR hpread_get_location (sltpointer, struct objfile *); + +static void hpread_psymtab_to_symtab_1 (struct partial_symtab *); + +void hpread_psymtab_to_symtab (struct partial_symtab *); + +static struct symtab *hpread_expand_symtab + (struct objfile *, int, int, CORE_ADDR, int, + struct section_offsets *, char *); + +static int hpread_type_translate (dnttpointer); + +static struct type **hpread_lookup_type (dnttpointer, struct objfile *); + +static struct type *hpread_alloc_type (dnttpointer, struct objfile *); + +static struct type *hpread_read_enum_type + (dnttpointer, union dnttentry *, struct objfile *); + +static struct type *hpread_read_function_type + (dnttpointer, union dnttentry *, struct objfile *, int); + +static struct type *hpread_read_doc_function_type + (dnttpointer, union dnttentry *, struct objfile *, int); + +static struct type *hpread_read_struct_type + (dnttpointer, union dnttentry *, struct objfile *); + +static struct type *hpread_get_nth_template_arg (struct objfile *, int); + +static struct type *hpread_read_templ_arg_type + (dnttpointer, union dnttentry *, struct objfile *, char *); + +static struct type *hpread_read_set_type + (dnttpointer, union dnttentry *, struct objfile *); + +static struct type *hpread_read_array_type + (dnttpointer, union dnttentry *dn_bufp, struct objfile *objfile); + +static struct type *hpread_read_subrange_type + (dnttpointer, union dnttentry *, struct objfile *); + +static struct type *hpread_type_lookup (dnttpointer, struct objfile *); + +static sltpointer hpread_record_lines + (struct subfile *, sltpointer, sltpointer, struct objfile *, CORE_ADDR); + +static void hpread_process_one_debug_symbol + (union dnttentry *, char *, struct section_offsets *, + struct objfile *, CORE_ADDR, int, char *, int, int *); + +static int hpread_get_scope_depth (union dnttentry *, struct objfile *, int); + +static void fix_static_member_physnames + (struct type *, char *, struct objfile *); + +static void fixup_class_method_type + (struct type *, struct type *, struct objfile *); + +static void hpread_adjust_bitoffsets (struct type *, int); + +static dnttpointer hpread_get_next_skip_over_anon_unions + (int, dnttpointer, union dnttentry **, struct objfile *); + + +/* Global to indicate presence of HP-compiled objects, + in particular, SOM executable file with SOM debug info + Defined in symtab.c, used in hppa-tdep.c. */ +extern int hp_som_som_object_present; + +/* Static used to indicate a class type that requires a + fix-up of one of its method types */ +static struct type *fixup_class = NULL; + +/* Static used to indicate the method type that is to be + used to fix-up the type for fixup_class */ +static struct type *fixup_method = NULL; + +#ifdef USE_PXDB + +/* NOTE use of system files! May not be portable. */ + +#define PXDB_SVR4 "/opt/langtools/bin/pxdb" +#define PXDB_BSD "/usr/bin/pxdb" + +#include <stdlib.h> +#include "gdb_string.h" + +/* check for the existence of a file, given its full pathname */ +int +file_exists (char *filename) +{ + if (filename) + return (access (filename, F_OK) == 0); + return 0; +} + + +/* Translate from the "hp_language" enumeration in hp-symtab.h + used in the debug info to gdb's generic enumeration in defs.h. */ +static enum language +trans_lang (enum hp_language in_lang) +{ + if (in_lang == HP_LANGUAGE_C) + return language_c; + + else if (in_lang == HP_LANGUAGE_CPLUSPLUS) + return language_cplus; + + else if (in_lang == HP_LANGUAGE_FORTRAN) + return language_fortran; + + else + return language_unknown; +} + +static char main_string[] = "main"; + +/* Call PXDB to process our file. + + Approach copied from DDE's "dbgk_run_pxdb". Note: we + don't check for BSD location of pxdb, nor for existence + of pxdb itself, etc. + + NOTE: uses system function and string functions directly. + + Return value: 1 if ok, 0 if not */ +int +hpread_call_pxdb (const char *file_name) +{ + char *p; + int status; + int retval; + + if (file_exists (PXDB_SVR4)) + { + p = xmalloc (strlen (PXDB_SVR4) + strlen (file_name) + 2); + strcpy (p, PXDB_SVR4); + strcat (p, " "); + strcat (p, file_name); + + warning ("File not processed by pxdb--about to process now.\n"); + status = system (p); + + retval = (status == 0); + } + else + { + warning ("pxdb not found at standard location: /opt/langtools/bin\ngdb will not be able to debug %s.\nPlease install pxdb at the above location and then restart gdb.\nYou can also run pxdb on %s with the command\n\"pxdb %s\" and then restart gdb.", file_name, file_name, file_name); + + retval = 0; + } + return retval; +} /* hpread_call_pxdb */ + + +/* Return 1 if the file turns out to need pre-processing + by PXDB, and we have thus called PXDB to do this processing + and the file therefore needs to be re-loaded. Otherwise + return 0. */ +int +hpread_pxdb_needed (bfd *sym_bfd) +{ + asection *pinfo_section, *debug_section, *header_section; + unsigned int do_pxdb; + char *buf; + bfd_size_type header_section_size; + + unsigned long tmp; + unsigned int pxdbed; + + header_section = bfd_get_section_by_name (sym_bfd, "$HEADER$"); + if (!header_section) + { + return 0; /* No header at all, can't recover... */ + } + + debug_section = bfd_get_section_by_name (sym_bfd, "$DEBUG$"); + pinfo_section = bfd_get_section_by_name (sym_bfd, "$PINFO$"); + + if (pinfo_section && !debug_section) + { + /* Debug info with DOC, has different header format. + this only happens if the file was pxdbed and compiled optimized + otherwise the PINFO section is not there. */ + header_section_size = bfd_section_size (objfile->obfd, header_section); + + if (header_section_size == (bfd_size_type) sizeof (DOC_info_PXDB_header)) + { + buf = alloca (sizeof (DOC_info_PXDB_header)); + + if (!bfd_get_section_contents (sym_bfd, + header_section, + buf, 0, + header_section_size)) + error ("bfd_get_section_contents\n"); + + tmp = bfd_get_32 (sym_bfd, (bfd_byte *) (buf + sizeof (int) * 4)); + pxdbed = (tmp >> 31) & 0x1; + + if (!pxdbed) + error ("file debug header info invalid\n"); + do_pxdb = 0; + } + + else + error ("invalid $HEADER$ size in executable \n"); + } + + else + { + + /* this can be three different cases: + 1. pxdbed and not doc + - DEBUG and HEADER sections are there + - header is PXDB_header type + - pxdbed flag is set to 1 + + 2. not pxdbed and doc + - DEBUG and HEADER sections are there + - header is DOC_info_header type + - pxdbed flag is set to 0 + + 3. not pxdbed and not doc + - DEBUG and HEADER sections are there + - header is XDB_header type + - pxdbed flag is set to 0 + + NOTE: the pxdbed flag is meaningful also in the not + already pxdb processed version of the header, + because in case on non-already processed by pxdb files + that same bit in the header would be always zero. + Why? Because the bit is the leftmost bit of a word + which contains a 'length' which is always a positive value + so that bit is never set to 1 (otherwise it would be negative) + + Given the above, we have two choices : either we ignore the + size of the header itself and just look at the pxdbed field, + or we check the size and then we (for safety and paranoia related + issues) check the bit. + The first solution is used by DDE, the second by PXDB itself. + I am using the second one here, because I already wrote it, + and it is the end of a long day. + Also, using the first approach would still involve size issues + because we need to read in the contents of the header section, and + give the correct amount of stuff we want to read to the + get_bfd_section_contents function. */ + + /* decide which case depending on the size of the header section. + The size is as defined in hp-symtab.h */ + + header_section_size = bfd_section_size (objfile->obfd, header_section); + + if (header_section_size == (bfd_size_type) sizeof (PXDB_header)) /* pxdb and not doc */ + { + + buf = alloca (sizeof (PXDB_header)); + if (!bfd_get_section_contents (sym_bfd, + header_section, + buf, 0, + header_section_size)) + error ("bfd_get_section_contents\n"); + + tmp = bfd_get_32 (sym_bfd, (bfd_byte *) (buf + sizeof (int) * 3)); + pxdbed = (tmp >> 31) & 0x1; + + if (pxdbed) + do_pxdb = 0; + else + error ("file debug header invalid\n"); + } + else /*not pxdbed and doc OR not pxdbed and non doc */ + do_pxdb = 1; + } + + if (do_pxdb) + { + return 1; + } + else + { + return 0; + } +} /* hpread_pxdb_needed */ + +#endif + +/* Check whether the file needs to be preprocessed by pxdb. + If so, call pxdb. */ + +void +do_pxdb (bfd *sym_bfd) +{ + /* The following code is HP-specific. The "right" way of + doing this is unknown, but we bet would involve a target- + specific pre-file-load check using a generic mechanism. */ + + /* This code will not be executed if the file is not in SOM + format (i.e. if compiled with gcc) */ + if (hpread_pxdb_needed (sym_bfd)) + { + /*This file has not been pre-processed. Preprocess now */ + + if (hpread_call_pxdb (sym_bfd->filename)) + { + /* The call above has changed the on-disk file, + we can close the file anyway, because the + symbols will be reread in when the target is run */ + bfd_close (sym_bfd); + } + } +} + + + +#ifdef QUICK_LOOK_UP + +/* Code to handle quick lookup-tables follows. */ + + +/* Some useful macros */ +#define VALID_FILE(i) ((i) < pxdb_header_p->fd_entries) +#define VALID_MODULE(i) ((i) < pxdb_header_p->md_entries) +#define VALID_PROC(i) ((i) < pxdb_header_p->pd_entries) +#define VALID_CLASS(i) ((i) < pxdb_header_p->cd_entries) + +#define FILE_START(i) (qFD[i].adrStart) +#define MODULE_START(i) (qMD[i].adrStart) +#define PROC_START(i) (qPD[i].adrStart) + +#define FILE_END(i) (qFD[i].adrEnd) +#define MODULE_END(i) (qMD[i].adrEnd) +#define PROC_END(i) (qPD[i].adrEnd) + +#define FILE_ISYM(i) (qFD[i].isym) +#define MODULE_ISYM(i) (qMD[i].isym) +#define PROC_ISYM(i) (qPD[i].isym) + +#define VALID_CURR_FILE (curr_fd < pxdb_header_p->fd_entries) +#define VALID_CURR_MODULE (curr_md < pxdb_header_p->md_entries) +#define VALID_CURR_PROC (curr_pd < pxdb_header_p->pd_entries) +#define VALID_CURR_CLASS (curr_cd < pxdb_header_p->cd_entries) + +#define CURR_FILE_START (qFD[curr_fd].adrStart) +#define CURR_MODULE_START (qMD[curr_md].adrStart) +#define CURR_PROC_START (qPD[curr_pd].adrStart) + +#define CURR_FILE_END (qFD[curr_fd].adrEnd) +#define CURR_MODULE_END (qMD[curr_md].adrEnd) +#define CURR_PROC_END (qPD[curr_pd].adrEnd) + +#define CURR_FILE_ISYM (qFD[curr_fd].isym) +#define CURR_MODULE_ISYM (qMD[curr_md].isym) +#define CURR_PROC_ISYM (qPD[curr_pd].isym) + +#define TELL_OBJFILE \ + do { \ + if( !told_objfile ) { \ + told_objfile = 1; \ + warning ("\nIn object file \"%s\":\n", \ + objfile->name); \ + } \ + } while (0) + + + +/* Keeping track of the start/end symbol table (LNTT) indices of + psymtabs created so far */ + +typedef struct +{ + int start; + int end; +} +pst_syms_struct; + +static pst_syms_struct *pst_syms_array = 0; + +static pst_syms_count = 0; +static pst_syms_size = 0; + +/* used by the TELL_OBJFILE macro */ +static boolean told_objfile = 0; + +/* Set up psymtab symbol index stuff */ +static void +init_pst_syms (void) +{ + pst_syms_count = 0; + pst_syms_size = 20; + pst_syms_array = (pst_syms_struct *) xmalloc (20 * sizeof (pst_syms_struct)); +} + +/* Clean up psymtab symbol index stuff */ +static void +clear_pst_syms (void) +{ + pst_syms_count = 0; + pst_syms_size = 0; + xfree (pst_syms_array); + pst_syms_array = 0; +} + +/* Add information about latest psymtab to symbol index table */ +static void +record_pst_syms (int start_sym, int end_sym) +{ + if (++pst_syms_count > pst_syms_size) + { + pst_syms_array = (pst_syms_struct *) xrealloc (pst_syms_array, + 2 * pst_syms_size * sizeof (pst_syms_struct)); + pst_syms_size *= 2; + } + pst_syms_array[pst_syms_count - 1].start = start_sym; + pst_syms_array[pst_syms_count - 1].end = end_sym; +} + +/* Find a suitable symbol table index which can serve as the upper + bound of a psymtab that starts at INDEX + + This scans backwards in the psymtab symbol index table to find a + "hole" in which the given index can fit. This is a heuristic!! + We don't search the entire table to check for multiple holes, + we don't care about overlaps, etc. + + Return 0 => not found */ +static int +find_next_pst_start (int index) +{ + int i; + + for (i = pst_syms_count - 1; i >= 0; i--) + if (pst_syms_array[i].end <= index) + return (i == pst_syms_count - 1) ? 0 : pst_syms_array[i + 1].start - 1; + + if (pst_syms_array[0].start > index) + return pst_syms_array[0].start - 1; + + return 0; +} + + + +/* Utility functions to find the ending symbol index for a psymtab */ + +/* Find the next file entry that begins beyond INDEX, and return + its starting symbol index - 1. + QFD is the file table, CURR_FD is the file entry from where to start, + PXDB_HEADER_P as in hpread_quick_traverse (to allow macros to work). + + Return 0 => not found */ +static int +find_next_file_isym (int index, quick_file_entry *qFD, int curr_fd, + PXDB_header_ptr pxdb_header_p) +{ + while (VALID_CURR_FILE) + { + if (CURR_FILE_ISYM >= index) + return CURR_FILE_ISYM - 1; + curr_fd++; + } + return 0; +} + +/* Find the next procedure entry that begins beyond INDEX, and return + its starting symbol index - 1. + QPD is the procedure table, CURR_PD is the proc entry from where to start, + PXDB_HEADER_P as in hpread_quick_traverse (to allow macros to work). + + Return 0 => not found */ +static int +find_next_proc_isym (int index, quick_procedure_entry *qPD, int curr_pd, + PXDB_header_ptr pxdb_header_p) +{ + while (VALID_CURR_PROC) + { + if (CURR_PROC_ISYM >= index) + return CURR_PROC_ISYM - 1; + curr_pd++; + } + return 0; +} + +/* Find the next module entry that begins beyond INDEX, and return + its starting symbol index - 1. + QMD is the module table, CURR_MD is the modue entry from where to start, + PXDB_HEADER_P as in hpread_quick_traverse (to allow macros to work). + + Return 0 => not found */ +static int +find_next_module_isym (int index, quick_module_entry *qMD, int curr_md, + PXDB_header_ptr pxdb_header_p) +{ + while (VALID_CURR_MODULE) + { + if (CURR_MODULE_ISYM >= index) + return CURR_MODULE_ISYM - 1; + curr_md++; + } + return 0; +} + +/* Scan and record partial symbols for all functions starting from index + pointed to by CURR_PD_P, and between code addresses START_ADR and END_ADR. + Other parameters are explained in comments below. */ + +/* This used to be inline in hpread_quick_traverse, but now that we do + essentially the same thing for two different cases (modules and + module-less files), it's better organized in a separate routine, + although it does take lots of arguments. pai/1997-10-08 + + CURR_PD_P is the pointer to the current proc index. QPD is the + procedure quick lookup table. MAX_PROCS is the number of entries + in the proc. table. START_ADR is the beginning of the code range + for the current psymtab. end_adr is the end of the code range for + the current psymtab. PST is the current psymtab. VT_bits is + a pointer to the strings table of SOM debug space. OBJFILE is + the current object file. */ + +static int +scan_procs (int *curr_pd_p, quick_procedure_entry *qPD, int max_procs, + CORE_ADDR start_adr, CORE_ADDR end_adr, struct partial_symtab *pst, + char *vt_bits, struct objfile *objfile) +{ + union dnttentry *dn_bufp; + int symbol_count = 0; /* Total number of symbols in this psymtab */ + int curr_pd = *curr_pd_p; /* Convenience variable -- avoid dereferencing pointer all the time */ + +#ifdef DUMPING + /* Turn this on for lots of debugging information in this routine */ + static int dumping = 0; +#endif + +#ifdef DUMPING + if (dumping) + { + printf ("Scan_procs called, addresses %x to %x, proc %x\n", start_adr, end_adr, curr_pd); + } +#endif + + while ((CURR_PROC_START <= end_adr) && (curr_pd < max_procs)) + { + + char *rtn_name; /* mangled name */ + char *rtn_dem_name; /* qualified demangled name */ + char *class_name; + int class; + + if ((trans_lang ((enum hp_language) qPD[curr_pd].language) == language_cplus) && + vt_bits[(long) qPD[curr_pd].sbAlias]) /* not a null string */ + { + /* Get mangled name for the procedure, and demangle it */ + rtn_name = &vt_bits[(long) qPD[curr_pd].sbAlias]; + rtn_dem_name = cplus_demangle (rtn_name, DMGL_ANSI | DMGL_PARAMS); + } + else + { + rtn_name = &vt_bits[(long) qPD[curr_pd].sbProc]; + rtn_dem_name = NULL; + } + + /* Hack to get around HP C/C++ compilers' insistence on providing + "_MAIN_" as an alternate name for "main" */ + if ((strcmp (rtn_name, "_MAIN_") == 0) && + (strcmp (&vt_bits[(long) qPD[curr_pd].sbProc], "main") == 0)) + rtn_dem_name = rtn_name = main_string; + +#ifdef DUMPING + if (dumping) + { + printf ("..add %s (demangled %s), index %x to this psymtab\n", rtn_name, rtn_dem_name, curr_pd); + } +#endif + + /* Check for module-spanning routines. */ + if (CURR_PROC_END > end_adr) + { + TELL_OBJFILE; + warning ("Procedure \"%s\" [0x%x] spans file or module boundaries.", rtn_name, curr_pd); + } + + /* Add this routine symbol to the list in the objfile. + Unfortunately we have to go to the LNTT to determine the + correct list to put it on. An alternative (which the + code used to do) would be to not check and always throw + it on the "static" list. But if we go that route, then + symbol_lookup() needs to be tweaked a bit to account + for the fact that the function might not be found on + the correct list in the psymtab. - RT */ + dn_bufp = hpread_get_lntt (qPD[curr_pd].isym, objfile); + if (dn_bufp->dfunc.global) + add_psymbol_with_dem_name_to_list (rtn_name, + strlen (rtn_name), + rtn_dem_name, + strlen (rtn_dem_name), + VAR_NAMESPACE, + LOC_BLOCK, /* "I am a routine" */ + &objfile->global_psymbols, + (qPD[curr_pd].adrStart + /* Starting address of rtn */ + ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile))), + 0, /* core addr?? */ + trans_lang ((enum hp_language) qPD[curr_pd].language), + objfile); + else + add_psymbol_with_dem_name_to_list (rtn_name, + strlen (rtn_name), + rtn_dem_name, + strlen (rtn_dem_name), + VAR_NAMESPACE, + LOC_BLOCK, /* "I am a routine" */ + &objfile->static_psymbols, + (qPD[curr_pd].adrStart + /* Starting address of rtn */ + ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile))), + 0, /* core addr?? */ + trans_lang ((enum hp_language) qPD[curr_pd].language), + objfile); + + symbol_count++; + *curr_pd_p = ++curr_pd; /* bump up count & reflect in caller */ + } /* loop over procedures */ + +#ifdef DUMPING + if (dumping) + { + if (symbol_count == 0) + printf ("Scan_procs: no symbols found!\n"); + } +#endif + + return symbol_count; +} + + +/* Traverse the quick look-up tables, building a set of psymtabs. + + This constructs a psymtab for modules and files in the quick lookup + tables. + + Mostly, modules correspond to compilation units, so we try to + create psymtabs that correspond to modules; however, in some cases + a file can result in a compiled object which does not have a module + entry for it, so in such cases we create a psymtab for the file. */ + +int +hpread_quick_traverse (struct objfile *objfile, char *gntt_bits, + char *vt_bits, PXDB_header_ptr pxdb_header_p) +{ + struct partial_symtab *pst; + + char *addr; + + quick_procedure_entry *qPD; + quick_file_entry *qFD; + quick_module_entry *qMD; + quick_class_entry *qCD; + + int idx; + int i; + CORE_ADDR start_adr; /* current psymtab's starting code addr */ + CORE_ADDR end_adr; /* current psymtab's ending code addr */ + CORE_ADDR next_mod_adr; /* next module's starting code addr */ + int curr_pd; /* current procedure */ + int curr_fd; /* current file */ + int curr_md; /* current module */ + int start_sym; /* current psymtab's starting symbol index */ + int end_sym; /* current psymtab's ending symbol index */ + int max_LNTT_sym_index; + int syms_in_pst; + B_TYPE *class_entered; + + struct partial_symbol **global_syms; /* We'll be filling in the "global" */ + struct partial_symbol **static_syms; /* and "static" tables in the objfile + as we go, so we need a pair of + current pointers. */ + +#ifdef DUMPING + /* Turn this on for lots of debugging information in this routine. + You get a blow-by-blow account of quick lookup table reading */ + static int dumping = 0; +#endif + + pst = (struct partial_symtab *) 0; + + /* Clear out some globals */ + init_pst_syms (); + told_objfile = 0; + + /* Demangling style -- if EDG style already set, don't change it, + as HP style causes some problems with the KAI EDG compiler */ + if (current_demangling_style != edg_demangling) + { + /* Otherwise, ensure that we are using HP style demangling */ + set_demangling_style (HP_DEMANGLING_STYLE_STRING); + } + + /* First we need to find the starting points of the quick + look-up tables in the GNTT. */ + + addr = gntt_bits; + + qPD = (quick_procedure_entry_ptr) addr; + addr += pxdb_header_p->pd_entries * sizeof (quick_procedure_entry); + +#ifdef DUMPING + if (dumping) + { + printf ("\n Printing routines as we see them\n"); + for (i = 0; VALID_PROC (i); i++) + { + idx = (long) qPD[i].sbProc; + printf ("%s %x..%x\n", &vt_bits[idx], + (int) PROC_START (i), + (int) PROC_END (i)); + } + } +#endif + + qFD = (quick_file_entry_ptr) addr; + addr += pxdb_header_p->fd_entries * sizeof (quick_file_entry); + +#ifdef DUMPING + if (dumping) + { + printf ("\n Printing files as we see them\n"); + for (i = 0; VALID_FILE (i); i++) + { + idx = (long) qFD[i].sbFile; + printf ("%s %x..%x\n", &vt_bits[idx], + (int) FILE_START (i), + (int) FILE_END (i)); + } + } +#endif + + qMD = (quick_module_entry_ptr) addr; + addr += pxdb_header_p->md_entries * sizeof (quick_module_entry); + +#ifdef DUMPING + if (dumping) + { + printf ("\n Printing modules as we see them\n"); + for (i = 0; i < pxdb_header_p->md_entries; i++) + { + idx = (long) qMD[i].sbMod; + printf ("%s\n", &vt_bits[idx]); + } + } +#endif + + qCD = (quick_class_entry_ptr) addr; + addr += pxdb_header_p->cd_entries * sizeof (quick_class_entry); + +#ifdef DUMPING + if (dumping) + { + printf ("\n Printing classes as we see them\n"); + for (i = 0; VALID_CLASS (i); i++) + { + idx = (long) qCD[i].sbClass; + printf ("%s\n", &vt_bits[idx]); + } + + printf ("\n Done with dump, on to build!\n"); + } +#endif + + /* We need this index only while hp-symtab-read.c expects + a byte offset to the end of the LNTT entries for a given + psymtab. Thus the need for it should go away someday. + + When it goes away, then we won't have any need to load the + LNTT from the objfile at psymtab-time, and start-up will be + faster. To make that work, we'll need some way to create + a null pst for the "globals" pseudo-module. */ + max_LNTT_sym_index = LNTT_SYMCOUNT (objfile); + + /* Scan the module descriptors and make a psymtab for each. + + We know the MDs, FDs and the PDs are in order by starting + address. We use that fact to traverse all three arrays in + parallel, knowing when the next PD is in a new file + and we need to create a new psymtab. */ + curr_pd = 0; /* Current procedure entry */ + curr_fd = 0; /* Current file entry */ + curr_md = 0; /* Current module entry */ + + start_adr = 0; /* Current psymtab code range */ + end_adr = 0; + + start_sym = 0; /* Current psymtab symbol range */ + end_sym = 0; + + syms_in_pst = 0; /* Symbol count for psymtab */ + + /* Psts actually just have pointers into the objfile's + symbol table, not their own symbol tables. */ + global_syms = objfile->global_psymbols.list; + static_syms = objfile->static_psymbols.list; + + + /* First skip over pseudo-entries with address 0. These represent inlined + routines and abstract (uninstantiated) template routines. + FIXME: These should be read in and available -- even if we can't set + breakpoints, etc., there's some information that can be presented + to the user. pai/1997-10-08 */ + + while (VALID_CURR_PROC && (CURR_PROC_START == 0)) + curr_pd++; + + /* Loop over files, modules, and procedures in code address order. Each + time we enter an iteration of this loop, curr_pd points to the first + unprocessed procedure, curr_fd points to the first unprocessed file, and + curr_md to the first unprocessed module. Each iteration of this loop + updates these as required -- any or all of them may be bumpd up + each time around. When we exit this loop, we are done with all files + and modules in the tables -- there may still be some procedures, however. + + Note: This code used to loop only over module entries, under the assumption + that files can occur via inclusions and are thus unreliable, while a + compiled object always corresponds to a module. With CTTI in the HP aCC + compiler, it turns out that compiled objects may have only files and no + modules; so we have to loop over files and modules, creating psymtabs for + either as appropriate. Unfortunately there are some problems (notably: + 1. the lack of "SRC_FILE_END" entries in the LNTT, 2. the lack of pointers + to the ending symbol indices of a module or a file) which make it quite hard + to do this correctly. Currently it uses a bunch of heuristics to start and + end psymtabs; they seem to work well with most objects generated by aCC, but + who knows when that will change... */ + + while (VALID_CURR_FILE || VALID_CURR_MODULE) + { + + char *mod_name_string; + char *full_name_string; + + /* First check for modules like "version.c", which have no code + in them but still have qMD entries. They also have no qFD or + qPD entries. Their start address is -1 and their end address + is 0. */ + if (VALID_CURR_MODULE && (CURR_MODULE_START == -1) && (CURR_MODULE_END == 0)) + { + + mod_name_string = &vt_bits[(long) qMD[curr_md].sbMod]; + +#ifdef DUMPING + if (dumping) + printf ("Module with data only %s\n", mod_name_string); +#endif + + /* We'll skip the rest (it makes error-checking easier), and + just make an empty pst. Right now empty psts are not put + in the pst chain, so all this is for naught, but later it + might help. */ + + pst = hpread_start_psymtab (objfile, + mod_name_string, + CURR_MODULE_START, /* Low text address: bogus! */ + (CURR_MODULE_ISYM * sizeof (struct dntt_type_block)), + /* ldsymoff */ + global_syms, + static_syms); + + pst = hpread_end_psymtab (pst, + NULL, /* psymtab_include_list */ + 0, /* includes_used */ + end_sym * sizeof (struct dntt_type_block), + /* byte index in LNTT of end + = capping symbol offset + = LDSYMOFF of nextfile */ + 0, /* text high */ + NULL, /* dependency_list */ + 0); /* dependencies_used */ + + global_syms = objfile->global_psymbols.next; + static_syms = objfile->static_psymbols.next; + + curr_md++; + } + else if (VALID_CURR_MODULE && + ((CURR_MODULE_START == 0) || (CURR_MODULE_START == -1) || + (CURR_MODULE_END == 0) || (CURR_MODULE_END == -1))) + { + TELL_OBJFILE; + warning ("Module \"%s\" [0x%s] has non-standard addresses. It starts at 0x%s, ends at 0x%s, and will be skipped.", + mod_name_string, paddr_nz (curr_md), paddr_nz (start_adr), paddr_nz (end_adr)); + /* On to next module */ + curr_md++; + } + else + { + /* First check if we are looking at a file with code in it + that does not overlap the current module's code range */ + + if (VALID_CURR_FILE ? (VALID_CURR_MODULE ? (CURR_FILE_END < CURR_MODULE_START) : 1) : 0) + { + + /* Looking at file not corresponding to any module, + create a psymtab for it */ + full_name_string = &vt_bits[(long) qFD[curr_fd].sbFile]; + start_adr = CURR_FILE_START; + end_adr = CURR_FILE_END; + start_sym = CURR_FILE_ISYM; + + /* Check if there are any procedures not handled until now, that + begin before the start address of this file, and if so, adjust + this module's start address to include them. This handles routines that + are in between file or module ranges for some reason (probably + indicates a compiler bug */ + + if (CURR_PROC_START < start_adr) + { + TELL_OBJFILE; + warning ("Found procedure \"%s\" [0x%x] that is not in any file or module.", + &vt_bits[(long) qPD[curr_pd].sbProc], curr_pd); + start_adr = CURR_PROC_START; + if (CURR_PROC_ISYM < start_sym) + start_sym = CURR_PROC_ISYM; + } + + /* Sometimes (compiler bug -- COBOL) the module end address is higher + than the start address of the next module, so check for that and + adjust accordingly */ + + if (VALID_FILE (curr_fd + 1) && (FILE_START (curr_fd + 1) <= end_adr)) + { + TELL_OBJFILE; + warning ("File \"%s\" [0x%x] has ending address after starting address of next file; adjusting ending address down.", + full_name_string, curr_fd); + end_adr = FILE_START (curr_fd + 1) - 1; /* Is -4 (or -8 for 64-bit) better? */ + } + if (VALID_MODULE (curr_md) && (CURR_MODULE_START <= end_adr)) + { + TELL_OBJFILE; + warning ("File \"%s\" [0x%x] has ending address after starting address of next module; adjusting ending address down.", + full_name_string, curr_fd); + end_adr = CURR_MODULE_START - 1; /* Is -4 (or -8 for 64-bit) better? */ + } + + +#ifdef DUMPING + if (dumping) + { + printf ("Make new psymtab for file %s (%x to %x).\n", + full_name_string, start_adr, end_adr); + } +#endif + /* Create the basic psymtab, connecting it in the list + for this objfile and pointing its symbol entries + to the current end of the symbol areas in the objfile. + + The "ldsymoff" parameter is the byte offset in the LNTT + of the first symbol in this file. Some day we should + turn this into an index (fix in hp-symtab-read.c as well). + And it's not even the right byte offset, as we're using + the size of a union! FIXME! */ + pst = hpread_start_psymtab (objfile, + full_name_string, + start_adr, /* Low text address */ + (start_sym * sizeof (struct dntt_type_block)), + /* ldsymoff */ + global_syms, + static_syms); + + /* Set up to only enter each class referenced in this module once. */ + class_entered = xmalloc (B_BYTES (pxdb_header_p->cd_entries)); + B_CLRALL (class_entered, pxdb_header_p->cd_entries); + + /* Scan the procedure descriptors for procedures in the current + file, based on the starting addresses. */ + + syms_in_pst = scan_procs (&curr_pd, qPD, pxdb_header_p->pd_entries, + start_adr, end_adr, pst, vt_bits, objfile); + + /* Get ending symbol offset */ + + end_sym = 0; + /* First check for starting index before previous psymtab */ + if (pst_syms_count && start_sym < pst_syms_array[pst_syms_count - 1].end) + { + end_sym = find_next_pst_start (start_sym); + } + /* Look for next start index of a file or module, or procedure */ + if (!end_sym) + { + int next_file_isym = find_next_file_isym (start_sym, qFD, curr_fd + 1, pxdb_header_p); + int next_module_isym = find_next_module_isym (start_sym, qMD, curr_md, pxdb_header_p); + int next_proc_isym = find_next_proc_isym (start_sym, qPD, curr_pd, pxdb_header_p); + + if (next_file_isym && next_module_isym) + { + /* pick lower of next file or module start index */ + end_sym = min (next_file_isym, next_module_isym); + } + else + { + /* one of them is zero, pick the other */ + end_sym = max (next_file_isym, next_module_isym); + } + + /* As a precaution, check next procedure index too */ + if (!end_sym) + end_sym = next_proc_isym; + else + end_sym = min (end_sym, next_proc_isym); + } + + /* Couldn't find procedure, file, or module, use globals as default */ + if (!end_sym) + end_sym = pxdb_header_p->globals; + +#ifdef DUMPING + if (dumping) + { + printf ("File psymtab indices: %x to %x\n", start_sym, end_sym); + } +#endif + + pst = hpread_end_psymtab (pst, + NULL, /* psymtab_include_list */ + 0, /* includes_used */ + end_sym * sizeof (struct dntt_type_block), + /* byte index in LNTT of end + = capping symbol offset + = LDSYMOFF of nextfile */ + end_adr, /* text high */ + NULL, /* dependency_list */ + 0); /* dependencies_used */ + + record_pst_syms (start_sym, end_sym); + + if (NULL == pst) + warning ("No symbols in psymtab for file \"%s\" [0x%x].", full_name_string, curr_fd); + +#ifdef DUMPING + if (dumping) + { + printf ("Made new psymtab for file %s (%x to %x), sym %x to %x.\n", + full_name_string, start_adr, end_adr, CURR_FILE_ISYM, end_sym); + } +#endif + /* Prepare for the next psymtab. */ + global_syms = objfile->global_psymbols.next; + static_syms = objfile->static_psymbols.next; + xfree (class_entered); + + curr_fd++; + } /* Psymtab for file */ + else + { + /* We have a module for which we create a psymtab */ + + mod_name_string = &vt_bits[(long) qMD[curr_md].sbMod]; + + /* We will include the code ranges of any files that happen to + overlap with this module */ + + /* So, first pick the lower of the file's and module's start addresses */ + start_adr = CURR_MODULE_START; + if (VALID_CURR_FILE) + { + if (CURR_FILE_START < CURR_MODULE_START) + { + TELL_OBJFILE; + warning ("File \"%s\" [0x%x] crosses beginning of module \"%s\".", + &vt_bits[(long) qFD[curr_fd].sbFile], + curr_fd, mod_name_string); + + start_adr = CURR_FILE_START; + } + } + + /* Also pick the lower of the file's and the module's start symbol indices */ + start_sym = CURR_MODULE_ISYM; + if (VALID_CURR_FILE && (CURR_FILE_ISYM < CURR_MODULE_ISYM)) + start_sym = CURR_FILE_ISYM; + + /* For the end address, we scan through the files till we find one + that overlaps the current module but ends beyond it; if no such file exists we + simply use the module's start address. + (Note, if file entries themselves overlap + we take the longest overlapping extension beyond the end of the module...) + We assume that modules never overlap. */ + + end_adr = CURR_MODULE_END; + + if (VALID_CURR_FILE) + { + while (VALID_CURR_FILE && (CURR_FILE_START < end_adr)) + { + +#ifdef DUMPING + if (dumping) + printf ("Maybe skipping file %s which overlaps with module %s\n", + &vt_bits[(long) qFD[curr_fd].sbFile], mod_name_string); +#endif + if (CURR_FILE_END > end_adr) + { + TELL_OBJFILE; + warning ("File \"%s\" [0x%x] crosses end of module \"%s\".", + &vt_bits[(long) qFD[curr_fd].sbFile], + curr_fd, mod_name_string); + end_adr = CURR_FILE_END; + } + curr_fd++; + } + curr_fd--; /* back up after going too far */ + } + + /* Sometimes (compiler bug -- COBOL) the module end address is higher + than the start address of the next module, so check for that and + adjust accordingly */ + + if (VALID_MODULE (curr_md + 1) && (MODULE_START (curr_md + 1) <= end_adr)) + { + TELL_OBJFILE; + warning ("Module \"%s\" [0x%x] has ending address after starting address of next module; adjusting ending address down.", + mod_name_string, curr_md); + end_adr = MODULE_START (curr_md + 1) - 1; /* Is -4 (or -8 for 64-bit) better? */ + } + if (VALID_FILE (curr_fd + 1) && (FILE_START (curr_fd + 1) <= end_adr)) + { + TELL_OBJFILE; + warning ("Module \"%s\" [0x%x] has ending address after starting address of next file; adjusting ending address down.", + mod_name_string, curr_md); + end_adr = FILE_START (curr_fd + 1) - 1; /* Is -4 (or -8 for 64-bit) better? */ + } + + /* Use one file to get the full name for the module. This + situation can arise if there is executable code in a #include + file. Each file with code in it gets a qFD. Files which don't + contribute code don't get a qFD, even if they include files + which do, e.g.: + + body.c: rtn.h: + int x; int main() { + #include "rtn.h" return x; + } + + There will a qFD for "rtn.h",and a qMD for "body.c", + but no qMD for "rtn.h" or qFD for "body.c"! + + We pick the name of the last file to overlap with this + module. C convention is to put include files first. In a + perfect world, we could check names and use the file whose full + path name ends with the module name. */ + + if (VALID_CURR_FILE) + full_name_string = &vt_bits[(long) qFD[curr_fd].sbFile]; + else + full_name_string = mod_name_string; + + /* Check if there are any procedures not handled until now, that + begin before the start address we have now, and if so, adjust + this psymtab's start address to include them. This handles routines that + are in between file or module ranges for some reason (probably + indicates a compiler bug */ + + if (CURR_PROC_START < start_adr) + { + TELL_OBJFILE; + warning ("Found procedure \"%s\" [0x%x] that is not in any file or module.", + &vt_bits[(long) qPD[curr_pd].sbProc], curr_pd); + start_adr = CURR_PROC_START; + if (CURR_PROC_ISYM < start_sym) + start_sym = CURR_PROC_ISYM; + } + +#ifdef DUMPING + if (dumping) + { + printf ("Make new psymtab for module %s (%x to %x), using file %s\n", + mod_name_string, start_adr, end_adr, full_name_string); + } +#endif + /* Create the basic psymtab, connecting it in the list + for this objfile and pointing its symbol entries + to the current end of the symbol areas in the objfile. + + The "ldsymoff" parameter is the byte offset in the LNTT + of the first symbol in this file. Some day we should + turn this into an index (fix in hp-symtab-read.c as well). + And it's not even the right byte offset, as we're using + the size of a union! FIXME! */ + pst = hpread_start_psymtab (objfile, + full_name_string, + start_adr, /* Low text address */ + (start_sym * sizeof (struct dntt_type_block)), + /* ldsymoff */ + global_syms, + static_syms); + + /* Set up to only enter each class referenced in this module once. */ + class_entered = xmalloc (B_BYTES (pxdb_header_p->cd_entries)); + B_CLRALL (class_entered, pxdb_header_p->cd_entries); + + /* Scan the procedure descriptors for procedures in the current + module, based on the starting addresses. */ + + syms_in_pst = scan_procs (&curr_pd, qPD, pxdb_header_p->pd_entries, + start_adr, end_adr, pst, vt_bits, objfile); + + /* Get ending symbol offset */ + + end_sym = 0; + /* First check for starting index before previous psymtab */ + if (pst_syms_count && start_sym < pst_syms_array[pst_syms_count - 1].end) + { + end_sym = find_next_pst_start (start_sym); + } + /* Look for next start index of a file or module, or procedure */ + if (!end_sym) + { + int next_file_isym = find_next_file_isym (start_sym, qFD, curr_fd + 1, pxdb_header_p); + int next_module_isym = find_next_module_isym (start_sym, qMD, curr_md + 1, pxdb_header_p); + int next_proc_isym = find_next_proc_isym (start_sym, qPD, curr_pd, pxdb_header_p); + + if (next_file_isym && next_module_isym) + { + /* pick lower of next file or module start index */ + end_sym = min (next_file_isym, next_module_isym); + } + else + { + /* one of them is zero, pick the other */ + end_sym = max (next_file_isym, next_module_isym); + } + + /* As a precaution, check next procedure index too */ + if (!end_sym) + end_sym = next_proc_isym; + else + end_sym = min (end_sym, next_proc_isym); + } + + /* Couldn't find procedure, file, or module, use globals as default */ + if (!end_sym) + end_sym = pxdb_header_p->globals; + +#ifdef DUMPING + if (dumping) + { + printf ("Module psymtab indices: %x to %x\n", start_sym, end_sym); + } +#endif + + pst = hpread_end_psymtab (pst, + NULL, /* psymtab_include_list */ + 0, /* includes_used */ + end_sym * sizeof (struct dntt_type_block), + /* byte index in LNTT of end + = capping symbol offset + = LDSYMOFF of nextfile */ + end_adr, /* text high */ + NULL, /* dependency_list */ + 0); /* dependencies_used */ + + record_pst_syms (start_sym, end_sym); + + if (NULL == pst) + warning ("No symbols in psymtab for module \"%s\" [0x%x].", mod_name_string, curr_md); + +#ifdef DUMPING + if (dumping) + { + printf ("Made new psymtab for module %s (%x to %x), sym %x to %x.\n", + mod_name_string, start_adr, end_adr, CURR_MODULE_ISYM, end_sym); + } +#endif + + /* Prepare for the next psymtab. */ + global_syms = objfile->global_psymbols.next; + static_syms = objfile->static_psymbols.next; + xfree (class_entered); + + curr_md++; + curr_fd++; + } /* psymtab for module */ + } /* psymtab for non-bogus file or module */ + } /* End of while loop over all files & modules */ + + /* There may be some routines after all files and modules -- these will get + inserted in a separate new module of their own */ + if (VALID_CURR_PROC) + { + start_adr = CURR_PROC_START; + end_adr = qPD[pxdb_header_p->pd_entries - 1].adrEnd; + TELL_OBJFILE; + warning ("Found functions beyond end of all files and modules [0x%x].", curr_pd); +#ifdef DUMPING + if (dumping) + { + printf ("Orphan functions at end, PD %d and beyond (%x to %x)\n", + curr_pd, start_adr, end_adr); + } +#endif + pst = hpread_start_psymtab (objfile, + "orphans", + start_adr, /* Low text address */ + (CURR_PROC_ISYM * sizeof (struct dntt_type_block)), + /* ldsymoff */ + global_syms, + static_syms); + + scan_procs (&curr_pd, qPD, pxdb_header_p->pd_entries, + start_adr, end_adr, pst, vt_bits, objfile); + + pst = hpread_end_psymtab (pst, + NULL, /* psymtab_include_list */ + 0, /* includes_used */ + pxdb_header_p->globals * sizeof (struct dntt_type_block), + /* byte index in LNTT of end + = capping symbol offset + = LDSYMOFF of nextfile */ + end_adr, /* text high */ + NULL, /* dependency_list */ + 0); /* dependencies_used */ + } + + +#ifdef NEVER_NEVER + /* Now build psts for non-module things (in the tail of + the LNTT, after the last END MODULE entry). + + If null psts were kept on the chain, this would be + a solution. FIXME */ + pst = hpread_start_psymtab (objfile, + "globals", + 0, + (pxdb_header_p->globals + * sizeof (struct dntt_type_block)), + objfile->global_psymbols.next, + objfile->static_psymbols.next); + hpread_end_psymtab (pst, + NULL, 0, + (max_LNTT_sym_index * sizeof (struct dntt_type_block)), + 0, + NULL, 0); +#endif + + clear_pst_syms (); + + return 1; + +} /* End of hpread_quick_traverse. */ + + +/* Get appropriate header, based on pxdb type. + Return value: 1 if ok, 0 if not */ +int +hpread_get_header (struct objfile *objfile, PXDB_header_ptr pxdb_header_p) +{ + asection *pinfo_section, *debug_section, *header_section; + +#ifdef DUMPING + /* Turn on for debugging information */ + static int dumping = 0; +#endif + + header_section = bfd_get_section_by_name (objfile->obfd, "$HEADER$"); + if (!header_section) + { + /* We don't have either PINFO or DEBUG sections. But + stuff like "libc.sl" has no debug info. There's no + need to warn the user of this, as it may be ok. The + caller will figure it out and issue any needed + messages. */ +#ifdef DUMPING + if (dumping) + printf ("==No debug info at all for %s.\n", objfile->name); +#endif + + return 0; + } + + /* We would like either a $DEBUG$ or $PINFO$ section. + Once we know which, we can understand the header + data (which we have defined to suit the more common + $DEBUG$ case). */ + debug_section = bfd_get_section_by_name (objfile->obfd, "$DEBUG$"); + pinfo_section = bfd_get_section_by_name (objfile->obfd, "$PINFO$"); + if (debug_section) + { + /* The expected case: normal pxdb header. */ + bfd_get_section_contents (objfile->obfd, header_section, + pxdb_header_p, 0, sizeof (PXDB_header)); + + if (!pxdb_header_p->pxdbed) + { + /* This shouldn't happen if we check in "symfile.c". */ + return 0; + } /* DEBUG section */ + } + + else if (pinfo_section) + { + /* The DOC case; we need to translate this into a + regular header. */ + DOC_info_PXDB_header doc_header; + +#ifdef DUMPING + if (dumping) + { + printf ("==OOps, PINFO, let's try to handle this, %s.\n", objfile->name); + } +#endif + + bfd_get_section_contents (objfile->obfd, + header_section, + &doc_header, 0, + sizeof (DOC_info_PXDB_header)); + + if (!doc_header.pxdbed) + { + /* This shouldn't happen if we check in "symfile.c". */ + warning ("File \"%s\" not processed by pxdb!", objfile->name); + return 0; + } + + /* Copy relevent fields to standard header passed in. */ + pxdb_header_p->pd_entries = doc_header.pd_entries; + pxdb_header_p->fd_entries = doc_header.fd_entries; + pxdb_header_p->md_entries = doc_header.md_entries; + pxdb_header_p->pxdbed = doc_header.pxdbed; + pxdb_header_p->bighdr = doc_header.bighdr; + pxdb_header_p->sa_header = doc_header.sa_header; + pxdb_header_p->inlined = doc_header.inlined; + pxdb_header_p->globals = doc_header.globals; + pxdb_header_p->time = doc_header.time; + pxdb_header_p->pg_entries = doc_header.pg_entries; + pxdb_header_p->functions = doc_header.functions; + pxdb_header_p->files = doc_header.files; + pxdb_header_p->cd_entries = doc_header.cd_entries; + pxdb_header_p->aa_entries = doc_header.aa_entries; + pxdb_header_p->oi_entries = doc_header.oi_entries; + pxdb_header_p->version = doc_header.version; + } /* PINFO section */ + + else + { +#ifdef DUMPING + if (dumping) + printf ("==No debug info at all for %s.\n", objfile->name); +#endif + + return 0; + + } + + return 1; +} /* End of hpread_get_header */ +#endif /* QUICK_LOOK_UP */ + + +/* Initialization for reading native HP C debug symbols from OBJFILE. + + Its only purpose in life is to set up the symbol reader's private + per-objfile data structures, and read in the raw contents of the debug + sections (attaching pointers to the debug info into the private data + structures). + + Since BFD doesn't know how to read debug symbols in a format-independent + way (and may never do so...), we have to do it ourselves. Note we may + be called on a file without native HP C debugging symbols. + + FIXME, there should be a cleaner peephole into the BFD environment + here. */ +void +hpread_symfile_init (struct objfile *objfile) +{ + asection *vt_section, *slt_section, *lntt_section, *gntt_section; + + /* Allocate struct to keep track of the symfile */ + objfile->sym_private = (PTR) + xmmalloc (objfile->md, sizeof (struct hpread_symfile_info)); + memset (objfile->sym_private, 0, sizeof (struct hpread_symfile_info)); + + /* We haven't read in any types yet. */ + DNTT_TYPE_VECTOR (objfile) = 0; + + /* Read in data from the $GNTT$ subspace. */ + gntt_section = bfd_get_section_by_name (objfile->obfd, "$GNTT$"); + if (!gntt_section) + return; + + GNTT (objfile) + = obstack_alloc (&objfile->symbol_obstack, + bfd_section_size (objfile->obfd, gntt_section)); + + bfd_get_section_contents (objfile->obfd, gntt_section, GNTT (objfile), + 0, bfd_section_size (objfile->obfd, gntt_section)); + + GNTT_SYMCOUNT (objfile) + = bfd_section_size (objfile->obfd, gntt_section) + / sizeof (struct dntt_type_block); + + /* Read in data from the $LNTT$ subspace. Also keep track of the number + of LNTT symbols. + + FIXME: this could be moved into the psymtab-to-symtab expansion + code, and save startup time. At the moment this data is + still used, though. We'd need a way to tell hp-symtab-read.c + whether or not to load the LNTT. */ + lntt_section = bfd_get_section_by_name (objfile->obfd, "$LNTT$"); + if (!lntt_section) + return; + + LNTT (objfile) + = obstack_alloc (&objfile->symbol_obstack, + bfd_section_size (objfile->obfd, lntt_section)); + + bfd_get_section_contents (objfile->obfd, lntt_section, LNTT (objfile), + 0, bfd_section_size (objfile->obfd, lntt_section)); + + LNTT_SYMCOUNT (objfile) + = bfd_section_size (objfile->obfd, lntt_section) + / sizeof (struct dntt_type_block); + + /* Read in data from the $SLT$ subspace. $SLT$ contains information + on source line numbers. */ + slt_section = bfd_get_section_by_name (objfile->obfd, "$SLT$"); + if (!slt_section) + return; + + SLT (objfile) = + obstack_alloc (&objfile->symbol_obstack, + bfd_section_size (objfile->obfd, slt_section)); + + bfd_get_section_contents (objfile->obfd, slt_section, SLT (objfile), + 0, bfd_section_size (objfile->obfd, slt_section)); + + /* Read in data from the $VT$ subspace. $VT$ contains things like + names and constants. Keep track of the number of symbols in the VT. */ + vt_section = bfd_get_section_by_name (objfile->obfd, "$VT$"); + if (!vt_section) + return; + + VT_SIZE (objfile) = bfd_section_size (objfile->obfd, vt_section); + + VT (objfile) = + (char *) obstack_alloc (&objfile->symbol_obstack, + VT_SIZE (objfile)); + + bfd_get_section_contents (objfile->obfd, vt_section, VT (objfile), + 0, VT_SIZE (objfile)); +} + +/* Scan and build partial symbols for a symbol file. + + The minimal symbol table (either SOM or HP a.out) has already been + read in; all we need to do is setup partial symbols based on the + native debugging information. + + Note that the minimal table is produced by the linker, and has + only global routines in it; the psymtab is based on compiler- + generated debug information and has non-global + routines in it as well as files and class information. + + We assume hpread_symfile_init has been called to initialize the + symbol reader's private data structures. + + MAINLINE is true if we are reading the main symbol table (as + opposed to a shared lib or dynamically loaded file). */ + +void +hpread_build_psymtabs (struct objfile *objfile, int mainline) +{ + +#ifdef DUMPING + /* Turn this on to get debugging output. */ + static int dumping = 0; +#endif + + char *namestring; + int past_first_source_file = 0; + struct cleanup *old_chain; + + int hp_symnum, symcount, i; + int scan_start = 0; + + union dnttentry *dn_bufp; + unsigned long valu; + char *p; + int texthigh = 0; + int have_name = 0; + + /* Current partial symtab */ + struct partial_symtab *pst; + + /* List of current psymtab's include files */ + char **psymtab_include_list; + int includes_allocated; + int includes_used; + + /* Index within current psymtab dependency list */ + struct partial_symtab **dependency_list; + int dependencies_used, dependencies_allocated; + + /* Just in case the stabs reader left turds lying around. */ + free_pending_blocks (); + make_cleanup (really_free_pendings, 0); + + pst = (struct partial_symtab *) 0; + + /* We shouldn't use alloca, instead use malloc/free. Doing so avoids + a number of problems with cross compilation and creating useless holes + in the stack when we have to allocate new entries. FIXME. */ + + includes_allocated = 30; + includes_used = 0; + psymtab_include_list = (char **) alloca (includes_allocated * + sizeof (char *)); + + dependencies_allocated = 30; + dependencies_used = 0; + dependency_list = + (struct partial_symtab **) alloca (dependencies_allocated * + sizeof (struct partial_symtab *)); + + old_chain = make_cleanup_free_objfile (objfile); + + last_source_file = 0; + +#ifdef QUICK_LOOK_UP + { + /* Begin code for new-style loading of quick look-up tables. */ + + /* elz: this checks whether the file has beeen processed by pxdb. + If not we would like to try to read the psymbols in + anyway, but it turns out to be not so easy. So this could + actually be commented out, but I leave it in, just in case + we decide to add support for non-pxdb-ed stuff in the future. */ + PXDB_header pxdb_header; + int found_modules_in_program; + + if (hpread_get_header (objfile, &pxdb_header)) + { + /* Build a minimal table. No types, no global variables, + no include files.... */ +#ifdef DUMPING + if (dumping) + printf ("\nNew method for %s\n", objfile->name); +#endif + + /* elz: quick_traverse returns true if it found + some modules in the main source file, other + than those in end.c + In C and C++, all the files have MODULES entries + in the LNTT, and the quick table traverse is all + based on finding these MODULES entries. Without + those it cannot work. + It happens that F77 programs don't have MODULES + so the quick traverse gets confused. F90 programs + have modules, and the quick method still works. + So, if modules (other than those in end.c) are + not found we give up on the quick table stuff, + and fall back on the slower method */ + found_modules_in_program = hpread_quick_traverse (objfile, + GNTT (objfile), + VT (objfile), + &pxdb_header); + + discard_cleanups (old_chain); + + /* Set up to scan the global section of the LNTT. + + This field is not always correct: if there are + no globals, it will point to the last record in + the regular LNTT, which is usually an END MODULE. + + Since it might happen that there could be a file + with just one global record, there's no way to + tell other than by looking at the record, so that's + done below. */ + if (found_modules_in_program) + scan_start = pxdb_header.globals; + } +#ifdef DUMPING + else + { + if (dumping) + printf ("\nGoing on to old method for %s\n", objfile->name); + } +#endif + } +#endif /* QUICK_LOOK_UP */ + + /* Make two passes, one over the GNTT symbols, the other for the + LNTT symbols. + + JB comment: above isn't true--they only make one pass, over + the LNTT. */ + for (i = 0; i < 1; i++) + { + int within_function = 0; + + if (i) + symcount = GNTT_SYMCOUNT (objfile); + else + symcount = LNTT_SYMCOUNT (objfile); + + + for (hp_symnum = scan_start; hp_symnum < symcount; hp_symnum++) + { + QUIT; + if (i) + dn_bufp = hpread_get_gntt (hp_symnum, objfile); + else + dn_bufp = hpread_get_lntt (hp_symnum, objfile); + + if (dn_bufp->dblock.extension) + continue; + + /* Only handle things which are necessary for minimal symbols. + everything else is ignored. */ + switch (dn_bufp->dblock.kind) + { + case DNTT_TYPE_SRCFILE: + { +#ifdef QUICK_LOOK_UP + if (scan_start == hp_symnum + && symcount == hp_symnum + 1) + { + /* If there are NO globals in an executable, + PXDB's index to the globals will point to + the last record in the file, which + could be this record. (this happened for F77 libraries) + ignore it and be done! */ + continue; + } +#endif /* QUICK_LOOK_UP */ + + /* A source file of some kind. Note this may simply + be an included file. */ + SET_NAMESTRING (dn_bufp, &namestring, objfile); + + /* Check if this is the source file we are already working + with. */ + if (pst && !strcmp (namestring, pst->filename)) + continue; + + /* Check if this is an include file, if so check if we have + already seen it. Add it to the include list */ + p = strrchr (namestring, '.'); + if (!strcmp (p, ".h")) + { + int j, found; + + found = 0; + for (j = 0; j < includes_used; j++) + if (!strcmp (namestring, psymtab_include_list[j])) + { + found = 1; + break; + } + if (found) + continue; + + /* Add it to the list of includes seen so far and + allocate more include space if necessary. */ + psymtab_include_list[includes_used++] = namestring; + if (includes_used >= includes_allocated) + { + char **orig = psymtab_include_list; + + psymtab_include_list = (char **) + alloca ((includes_allocated *= 2) * + sizeof (char *)); + memcpy ((PTR) psymtab_include_list, (PTR) orig, + includes_used * sizeof (char *)); + } + continue; + } + + if (pst) + { + if (!have_name) + { + pst->filename = (char *) + obstack_alloc (&pst->objfile->psymbol_obstack, + strlen (namestring) + 1); + strcpy (pst->filename, namestring); + have_name = 1; + continue; + } + continue; + } + + /* This is a bonafide new source file. + End the current partial symtab and start a new one. */ + + if (pst && past_first_source_file) + { + hpread_end_psymtab (pst, psymtab_include_list, + includes_used, + (hp_symnum + * sizeof (struct dntt_type_block)), + texthigh, + dependency_list, dependencies_used); + pst = (struct partial_symtab *) 0; + includes_used = 0; + dependencies_used = 0; + } + else + past_first_source_file = 1; + + valu = hpread_get_textlow (i, hp_symnum, objfile, symcount); + valu += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + pst = hpread_start_psymtab (objfile, + namestring, valu, + (hp_symnum + * sizeof (struct dntt_type_block)), + objfile->global_psymbols.next, + objfile->static_psymbols.next); + texthigh = valu; + have_name = 1; + continue; + } + + case DNTT_TYPE_MODULE: + /* A source file. It's still unclear to me what the + real difference between a DNTT_TYPE_SRCFILE and DNTT_TYPE_MODULE + is supposed to be. */ + + /* First end the previous psymtab */ + if (pst) + { + hpread_end_psymtab (pst, psymtab_include_list, includes_used, + ((hp_symnum - 1) + * sizeof (struct dntt_type_block)), + texthigh, + dependency_list, dependencies_used); + pst = (struct partial_symtab *) 0; + includes_used = 0; + dependencies_used = 0; + have_name = 0; + } + + /* Now begin a new module and a new psymtab for it */ + SET_NAMESTRING (dn_bufp, &namestring, objfile); + valu = hpread_get_textlow (i, hp_symnum, objfile, symcount); + valu += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + if (!pst) + { + pst = hpread_start_psymtab (objfile, + namestring, valu, + (hp_symnum + * sizeof (struct dntt_type_block)), + objfile->global_psymbols.next, + objfile->static_psymbols.next); + texthigh = valu; + have_name = 0; + } + continue; + + case DNTT_TYPE_FUNCTION: + case DNTT_TYPE_ENTRY: + /* The beginning of a function. DNTT_TYPE_ENTRY may also denote + a secondary entry point. */ + valu = dn_bufp->dfunc.hiaddr + ANOFFSET (objfile->section_offsets, + SECT_OFF_TEXT (objfile)); + if (valu > texthigh) + texthigh = valu; + valu = dn_bufp->dfunc.lowaddr + + ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + SET_NAMESTRING (dn_bufp, &namestring, objfile); + if (dn_bufp->dfunc.global) + add_psymbol_to_list (namestring, strlen (namestring), + VAR_NAMESPACE, LOC_BLOCK, + &objfile->global_psymbols, valu, + 0, language_unknown, objfile); + else + add_psymbol_to_list (namestring, strlen (namestring), + VAR_NAMESPACE, LOC_BLOCK, + &objfile->static_psymbols, valu, + 0, language_unknown, objfile); + within_function = 1; + continue; + + case DNTT_TYPE_DOC_FUNCTION: + valu = dn_bufp->ddocfunc.hiaddr + ANOFFSET (objfile->section_offsets, + SECT_OFF_TEXT (objfile)); + if (valu > texthigh) + texthigh = valu; + valu = dn_bufp->ddocfunc.lowaddr + + ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + SET_NAMESTRING (dn_bufp, &namestring, objfile); + if (dn_bufp->ddocfunc.global) + add_psymbol_to_list (namestring, strlen (namestring), + VAR_NAMESPACE, LOC_BLOCK, + &objfile->global_psymbols, valu, + 0, language_unknown, objfile); + else + add_psymbol_to_list (namestring, strlen (namestring), + VAR_NAMESPACE, LOC_BLOCK, + &objfile->static_psymbols, valu, + 0, language_unknown, objfile); + within_function = 1; + continue; + + case DNTT_TYPE_BEGIN: + case DNTT_TYPE_END: + /* We don't check MODULE end here, because there can be + symbols beyond the module end which properly belong to the + current psymtab -- so we wait till the next MODULE start */ + + +#ifdef QUICK_LOOK_UP + if (scan_start == hp_symnum + && symcount == hp_symnum + 1) + { + /* If there are NO globals in an executable, + PXDB's index to the globals will point to + the last record in the file, which is + probably an END MODULE, i.e. this record. + ignore it and be done! */ + continue; + } +#endif /* QUICK_LOOK_UP */ + + /* Scope block begin/end. We only care about function + and file blocks right now. */ + + if ((dn_bufp->dend.endkind == DNTT_TYPE_FUNCTION) || + (dn_bufp->dend.endkind == DNTT_TYPE_DOC_FUNCTION)) + within_function = 0; + continue; + + case DNTT_TYPE_SVAR: + case DNTT_TYPE_DVAR: + case DNTT_TYPE_TYPEDEF: + case DNTT_TYPE_TAGDEF: + { + /* Variables, typedefs an the like. */ + enum address_class storage; + namespace_enum namespace; + + /* Don't add locals to the partial symbol table. */ + if (within_function + && (dn_bufp->dblock.kind == DNTT_TYPE_SVAR + || dn_bufp->dblock.kind == DNTT_TYPE_DVAR)) + continue; + + /* TAGDEFs go into the structure namespace. */ + if (dn_bufp->dblock.kind == DNTT_TYPE_TAGDEF) + namespace = STRUCT_NAMESPACE; + else + namespace = VAR_NAMESPACE; + + /* What kind of "storage" does this use? */ + if (dn_bufp->dblock.kind == DNTT_TYPE_SVAR) + storage = LOC_STATIC; + else if (dn_bufp->dblock.kind == DNTT_TYPE_DVAR + && dn_bufp->ddvar.regvar) + storage = LOC_REGISTER; + else if (dn_bufp->dblock.kind == DNTT_TYPE_DVAR) + storage = LOC_LOCAL; + else + storage = LOC_UNDEF; + + SET_NAMESTRING (dn_bufp, &namestring, objfile); + if (!pst) + { + pst = hpread_start_psymtab (objfile, + "globals", 0, + (hp_symnum + * sizeof (struct dntt_type_block)), + objfile->global_psymbols.next, + objfile->static_psymbols.next); + } + + /* Compute address of the data symbol */ + valu = dn_bufp->dsvar.location; + /* Relocate in case it's in a shared library */ + if (storage == LOC_STATIC) + valu += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile)); + + /* Luckily, dvar, svar, typedef, and tagdef all + have their "global" bit in the same place, so it works + (though it's bad programming practice) to reference + "dsvar.global" even though we may be looking at + any of the above four types. */ + if (dn_bufp->dsvar.global) + { + add_psymbol_to_list (namestring, strlen (namestring), + namespace, storage, + &objfile->global_psymbols, + valu, + 0, language_unknown, objfile); + } + else + { + add_psymbol_to_list (namestring, strlen (namestring), + namespace, storage, + &objfile->static_psymbols, + valu, + 0, language_unknown, objfile); + } + + /* For TAGDEF's, the above code added the tagname to the + struct namespace. This will cause tag "t" to be found + on a reference of the form "(struct t) x". But for + C++ classes, "t" will also be a typename, which we + want to find on a reference of the form "ptype t". + Therefore, we also add "t" to the var namespace. + Do the same for enum's due to the way aCC generates + debug info for these (see more extended comment + in hp-symtab-read.c). + We do the same for templates, so that "ptype t" + where "t" is a template also works. */ + if (dn_bufp->dblock.kind == DNTT_TYPE_TAGDEF && + dn_bufp->dtype.type.dnttp.index < LNTT_SYMCOUNT (objfile)) + { + int global = dn_bufp->dtag.global; + /* Look ahead to see if it's a C++ class */ + dn_bufp = hpread_get_lntt (dn_bufp->dtype.type.dnttp.index, objfile); + if (dn_bufp->dblock.kind == DNTT_TYPE_CLASS || + dn_bufp->dblock.kind == DNTT_TYPE_ENUM || + dn_bufp->dblock.kind == DNTT_TYPE_TEMPLATE) + { + if (global) + { + add_psymbol_to_list (namestring, strlen (namestring), + VAR_NAMESPACE, storage, + &objfile->global_psymbols, + dn_bufp->dsvar.location, + 0, language_unknown, objfile); + } + else + { + add_psymbol_to_list (namestring, strlen (namestring), + VAR_NAMESPACE, storage, + &objfile->static_psymbols, + dn_bufp->dsvar.location, + 0, language_unknown, objfile); + } + } + } + } + continue; + + case DNTT_TYPE_MEMENUM: + case DNTT_TYPE_CONST: + /* Constants and members of enumerated types. */ + SET_NAMESTRING (dn_bufp, &namestring, objfile); + if (!pst) + { + pst = hpread_start_psymtab (objfile, + "globals", 0, + (hp_symnum + * sizeof (struct dntt_type_block)), + objfile->global_psymbols.next, + objfile->static_psymbols.next); + } + if (dn_bufp->dconst.global) + add_psymbol_to_list (namestring, strlen (namestring), + VAR_NAMESPACE, LOC_CONST, + &objfile->global_psymbols, 0, + 0, language_unknown, objfile); + else + add_psymbol_to_list (namestring, strlen (namestring), + VAR_NAMESPACE, LOC_CONST, + &objfile->static_psymbols, 0, + 0, language_unknown, objfile); + continue; + default: + continue; + } + } + } + + /* End any pending partial symbol table. */ + if (pst) + { + hpread_end_psymtab (pst, psymtab_include_list, includes_used, + hp_symnum * sizeof (struct dntt_type_block), + 0, dependency_list, dependencies_used); + } + + discard_cleanups (old_chain); +} + +/* Perform any local cleanups required when we are done with a particular + objfile. I.E, we are in the process of discarding all symbol information + for an objfile, freeing up all memory held for it, and unlinking the + objfile struct from the global list of known objfiles. */ + +void +hpread_symfile_finish (struct objfile *objfile) +{ + if (objfile->sym_private != NULL) + { + xmfree (objfile->md, objfile->sym_private); + } +} + + +/* The remaining functions are all for internal use only. */ + +/* Various small functions to get entries in the debug symbol sections. */ + +union dnttentry * +hpread_get_lntt (int index, struct objfile *objfile) +{ + return (union dnttentry *) + &(LNTT (objfile)[(index * sizeof (struct dntt_type_block))]); +} + +static union dnttentry * +hpread_get_gntt (int index, struct objfile *objfile) +{ + return (union dnttentry *) + &(GNTT (objfile)[(index * sizeof (struct dntt_type_block))]); +} + +union sltentry * +hpread_get_slt (int index, struct objfile *objfile) +{ + return (union sltentry *) &(SLT (objfile)[index * sizeof (union sltentry)]); +} + +/* Get the low address associated with some symbol (typically the start + of a particular source file or module). Since that information is not + stored as part of the DNTT_TYPE_MODULE or DNTT_TYPE_SRCFILE symbol we + must infer it from the existence of DNTT_TYPE_FUNCTION symbols. */ + +static unsigned long +hpread_get_textlow (int global, int index, struct objfile *objfile, + int symcount) +{ + union dnttentry *dn_bufp; + struct minimal_symbol *msymbol; + + /* Look for a DNTT_TYPE_FUNCTION symbol. */ + if (index < symcount) /* symcount is the number of symbols in */ + { /* the dbinfo, LNTT table */ + do + { + if (global) + dn_bufp = hpread_get_gntt (index++, objfile); + else + dn_bufp = hpread_get_lntt (index++, objfile); + } + while (dn_bufp->dblock.kind != DNTT_TYPE_FUNCTION + && dn_bufp->dblock.kind != DNTT_TYPE_DOC_FUNCTION + && dn_bufp->dblock.kind != DNTT_TYPE_END + && index < symcount); + } + + /* Avoid going past a DNTT_TYPE_END when looking for a DNTT_TYPE_FUNCTION. This + might happen when a sourcefile has no functions. */ + if (dn_bufp->dblock.kind == DNTT_TYPE_END) + return 0; + + /* Avoid going past the end of the LNTT file */ + if (index == symcount) + return 0; + + /* The minimal symbols are typically more accurate for some reason. */ + if (dn_bufp->dblock.kind == DNTT_TYPE_FUNCTION) + msymbol = lookup_minimal_symbol (dn_bufp->dfunc.name + VT (objfile), NULL, + objfile); + else /* must be a DNTT_TYPE_DOC_FUNCTION */ + msymbol = lookup_minimal_symbol (dn_bufp->ddocfunc.name + VT (objfile), NULL, + objfile); + + if (msymbol) + return SYMBOL_VALUE_ADDRESS (msymbol); + else + return dn_bufp->dfunc.lowaddr; +} + +/* Allocate and partially fill a partial symtab. It will be + completely filled at the end of the symbol list. + + SYMFILE_NAME is the name of the symbol-file we are reading from, and ADDR + is the address relative to which its symbols are (incremental) or 0 + (normal). */ + +static struct partial_symtab * +hpread_start_psymtab (struct objfile *objfile, char *filename, + CORE_ADDR textlow, int ldsymoff, + struct partial_symbol **global_syms, + struct partial_symbol **static_syms) +{ + int offset = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + extern void hpread_psymtab_to_symtab (); + struct partial_symtab *result = + start_psymtab_common (objfile, objfile->section_offsets, + filename, textlow, global_syms, static_syms); + + result->textlow += offset; + result->read_symtab_private = (char *) + obstack_alloc (&objfile->psymbol_obstack, sizeof (struct symloc)); + LDSYMOFF (result) = ldsymoff; + result->read_symtab = hpread_psymtab_to_symtab; + + return result; +} + + +/* Close off the current usage of PST. + Returns PST or NULL if the partial symtab was empty and thrown away. + + capping_symbol_offset --Byte index in LNTT or GNTT of the + last symbol processed during the build + of the previous pst. + + FIXME: List variables and peculiarities of same. */ + +static struct partial_symtab * +hpread_end_psymtab (struct partial_symtab *pst, char **include_list, + int num_includes, int capping_symbol_offset, + CORE_ADDR capping_text, + struct partial_symtab **dependency_list, + int number_dependencies) +{ + int i; + struct objfile *objfile = pst->objfile; + int offset = ANOFFSET (pst->section_offsets, SECT_OFF_TEXT (objfile)); + +#ifdef DUMPING + /* Turn on to see what kind of a psymtab we've built. */ + static int dumping = 0; +#endif + + if (capping_symbol_offset != -1) + LDSYMLEN (pst) = capping_symbol_offset - LDSYMOFF (pst); + else + LDSYMLEN (pst) = 0; + pst->texthigh = capping_text + offset; + + pst->n_global_syms = + objfile->global_psymbols.next - (objfile->global_psymbols.list + pst->globals_offset); + pst->n_static_syms = + objfile->static_psymbols.next - (objfile->static_psymbols.list + pst->statics_offset); + +#ifdef DUMPING + if (dumping) + { + printf ("\nPst %s, LDSYMOFF %x (%x), LDSYMLEN %x (%x), globals %d, statics %d\n", + pst->filename, + LDSYMOFF (pst), + LDSYMOFF (pst) / sizeof (struct dntt_type_block), + LDSYMLEN (pst), + LDSYMLEN (pst) / sizeof (struct dntt_type_block), + pst->n_global_syms, pst->n_static_syms); + } +#endif + + pst->number_of_dependencies = number_dependencies; + if (number_dependencies) + { + pst->dependencies = (struct partial_symtab **) + obstack_alloc (&objfile->psymbol_obstack, + number_dependencies * sizeof (struct partial_symtab *)); + memcpy (pst->dependencies, dependency_list, + number_dependencies * sizeof (struct partial_symtab *)); + } + else + pst->dependencies = 0; + + for (i = 0; i < num_includes; i++) + { + struct partial_symtab *subpst = + allocate_psymtab (include_list[i], objfile); + + subpst->section_offsets = pst->section_offsets; + subpst->read_symtab_private = + (char *) obstack_alloc (&objfile->psymbol_obstack, + sizeof (struct symloc)); + LDSYMOFF (subpst) = + LDSYMLEN (subpst) = + subpst->textlow = + subpst->texthigh = 0; + + /* We could save slight bits of space by only making one of these, + shared by the entire set of include files. FIXME-someday. */ + subpst->dependencies = (struct partial_symtab **) + obstack_alloc (&objfile->psymbol_obstack, + sizeof (struct partial_symtab *)); + subpst->dependencies[0] = pst; + subpst->number_of_dependencies = 1; + + subpst->globals_offset = + subpst->n_global_syms = + subpst->statics_offset = + subpst->n_static_syms = 0; + + subpst->readin = 0; + subpst->symtab = 0; + subpst->read_symtab = pst->read_symtab; + } + + sort_pst_symbols (pst); + + /* If there is already a psymtab or symtab for a file of this name, remove it. + (If there is a symtab, more drastic things also happen.) + This happens in VxWorks. */ + free_named_symtabs (pst->filename); + + if (num_includes == 0 + && number_dependencies == 0 + && pst->n_global_syms == 0 + && pst->n_static_syms == 0) + { + /* Throw away this psymtab, it's empty. We can't deallocate it, since + it is on the obstack, but we can forget to chain it on the list. + Empty psymtabs happen as a result of header files which don't have + any symbols in them. There can be a lot of them. But this check + is wrong, in that a psymtab with N_SLINE entries but nothing else + is not empty, but we don't realize that. Fixing that without slowing + things down might be tricky. + It's also wrong if we're using the quick look-up tables, as + we can get empty psymtabs from modules with no routines in + them. */ + + discard_psymtab (pst); + + /* Indicate that psymtab was thrown away. */ + pst = (struct partial_symtab *) NULL; + + } + return pst; +} + + +/* Get the nesting depth for the source line identified by INDEX. */ + +static unsigned long +hpread_get_scope_start (sltpointer index, struct objfile *objfile) +{ + union sltentry *sl_bufp; + + sl_bufp = hpread_get_slt (index, objfile); + return sl_bufp->sspec.backptr.dnttp.index; +} + +/* Get the source line number the the line identified by INDEX. */ + +static unsigned long +hpread_get_line (sltpointer index, struct objfile *objfile) +{ + union sltentry *sl_bufp; + + sl_bufp = hpread_get_slt (index, objfile); + return sl_bufp->snorm.line; +} + +/* Find the code address associated with a given sltpointer */ + +static CORE_ADDR +hpread_get_location (sltpointer index, struct objfile *objfile) +{ + union sltentry *sl_bufp; + int i; + + /* code location of special sltentrys is determined from context */ + sl_bufp = hpread_get_slt (index, objfile); + + if (sl_bufp->snorm.sltdesc == SLT_END) + { + /* find previous normal sltentry and get address */ + for (i = 0; ((sl_bufp->snorm.sltdesc != SLT_NORMAL) && + (sl_bufp->snorm.sltdesc != SLT_NORMAL_OFFSET) && + (sl_bufp->snorm.sltdesc != SLT_EXIT)); i++) + sl_bufp = hpread_get_slt (index - i, objfile); + if (sl_bufp->snorm.sltdesc == SLT_NORMAL_OFFSET) + return sl_bufp->snormoff.address; + else + return sl_bufp->snorm.address; + } + + /* find next normal sltentry and get address */ + for (i = 0; ((sl_bufp->snorm.sltdesc != SLT_NORMAL) && + (sl_bufp->snorm.sltdesc != SLT_NORMAL_OFFSET) && + (sl_bufp->snorm.sltdesc != SLT_EXIT)); i++) + sl_bufp = hpread_get_slt (index + i, objfile); + if (sl_bufp->snorm.sltdesc == SLT_NORMAL_OFFSET) + return sl_bufp->snormoff.address; + else + return sl_bufp->snorm.address; +} + + +/* Return 1 if an HP debug symbol of type KIND has a name associated with + * it, else return 0. (This function is not currently used, but I'll + * leave it here in case it proves useful later on. - RT). + */ + +int +hpread_has_name (enum dntt_entry_type kind) +{ + switch (kind) + { + case DNTT_TYPE_SRCFILE: + case DNTT_TYPE_MODULE: + case DNTT_TYPE_FUNCTION: + case DNTT_TYPE_DOC_FUNCTION: + case DNTT_TYPE_ENTRY: + case DNTT_TYPE_IMPORT: + case DNTT_TYPE_LABEL: + case DNTT_TYPE_FPARAM: + case DNTT_TYPE_SVAR: + case DNTT_TYPE_DVAR: + case DNTT_TYPE_CONST: + case DNTT_TYPE_TYPEDEF: + case DNTT_TYPE_TAGDEF: + case DNTT_TYPE_MEMENUM: + case DNTT_TYPE_FIELD: + case DNTT_TYPE_SA: + case DNTT_TYPE_BLOCKDATA: + case DNTT_TYPE_MEMFUNC: + case DNTT_TYPE_DOC_MEMFUNC: + return 1; + + case DNTT_TYPE_BEGIN: + case DNTT_TYPE_END: + case DNTT_TYPE_POINTER: + case DNTT_TYPE_ENUM: + case DNTT_TYPE_SET: + case DNTT_TYPE_ARRAY: + case DNTT_TYPE_STRUCT: + case DNTT_TYPE_UNION: + case DNTT_TYPE_VARIANT: + case DNTT_TYPE_FILE: + case DNTT_TYPE_FUNCTYPE: + case DNTT_TYPE_SUBRANGE: + case DNTT_TYPE_WITH: + case DNTT_TYPE_COMMON: + case DNTT_TYPE_COBSTRUCT: + case DNTT_TYPE_XREF: + case DNTT_TYPE_MACRO: + case DNTT_TYPE_CLASS_SCOPE: + case DNTT_TYPE_REFERENCE: + case DNTT_TYPE_PTRMEM: + case DNTT_TYPE_PTRMEMFUNC: + case DNTT_TYPE_CLASS: + case DNTT_TYPE_GENFIELD: + case DNTT_TYPE_VFUNC: + case DNTT_TYPE_MEMACCESS: + case DNTT_TYPE_INHERITANCE: + case DNTT_TYPE_FRIEND_CLASS: + case DNTT_TYPE_FRIEND_FUNC: + case DNTT_TYPE_MODIFIER: + case DNTT_TYPE_OBJECT_ID: + case DNTT_TYPE_TEMPLATE: + case DNTT_TYPE_TEMPLATE_ARG: + case DNTT_TYPE_FUNC_TEMPLATE: + case DNTT_TYPE_LINK: + /* DNTT_TYPE_DYN_ARRAY_DESC ? */ + /* DNTT_TYPE_DESC_SUBRANGE ? */ + /* DNTT_TYPE_BEGIN_EXT ? */ + /* DNTT_TYPE_INLN ? */ + /* DNTT_TYPE_INLN_LIST ? */ + /* DNTT_TYPE_ALIAS ? */ + default: + return 0; + } +} + +/* Do the dirty work of reading in the full symbol from a partial symbol + table. */ + +static void +hpread_psymtab_to_symtab_1 (struct partial_symtab *pst) +{ + struct cleanup *old_chain; + int i; + + /* Get out quick if passed junk. */ + if (!pst) + return; + + /* Complain if we've already read in this symbol table. */ + if (pst->readin) + { + fprintf_unfiltered (gdb_stderr, "Psymtab for %s already read in." + " Shouldn't happen.\n", + pst->filename); + return; + } + + /* Read in all partial symtabs on which this one is dependent */ + for (i = 0; i < pst->number_of_dependencies; i++) + if (!pst->dependencies[i]->readin) + { + /* Inform about additional files that need to be read in. */ + if (info_verbose) + { + fputs_filtered (" ", gdb_stdout); + wrap_here (""); + fputs_filtered ("and ", gdb_stdout); + wrap_here (""); + printf_filtered ("%s...", pst->dependencies[i]->filename); + wrap_here (""); /* Flush output */ + gdb_flush (gdb_stdout); + } + hpread_psymtab_to_symtab_1 (pst->dependencies[i]); + } + + /* If it's real... */ + if (LDSYMLEN (pst)) + { + /* Init stuff necessary for reading in symbols */ + buildsym_init (); + old_chain = make_cleanup (really_free_pendings, 0); + + pst->symtab = + hpread_expand_symtab (pst->objfile, LDSYMOFF (pst), LDSYMLEN (pst), + pst->textlow, pst->texthigh - pst->textlow, + pst->section_offsets, pst->filename); + sort_symtab_syms (pst->symtab); + + do_cleanups (old_chain); + } + + pst->readin = 1; +} + +/* Read in all of the symbols for a given psymtab for real. + Be verbose about it if the user wants that. */ + +void +hpread_psymtab_to_symtab (struct partial_symtab *pst) +{ + /* Get out quick if given junk. */ + if (!pst) + return; + + /* Sanity check. */ + if (pst->readin) + { + fprintf_unfiltered (gdb_stderr, "Psymtab for %s already read in." + " Shouldn't happen.\n", + pst->filename); + return; + } + + /* elz: setting the flag to indicate that the code of the target + was compiled using an HP compiler (aCC, cc) + the processing_acc_compilation variable is declared in the + file buildsym.h, the HP_COMPILED_TARGET is defined to be equal + to 3 in the file tm_hppa.h */ + + processing_gcc_compilation = 0; + + if (LDSYMLEN (pst) || pst->number_of_dependencies) + { + /* Print the message now, before reading the string table, + to avoid disconcerting pauses. */ + if (info_verbose) + { + printf_filtered ("Reading in symbols for %s...", pst->filename); + gdb_flush (gdb_stdout); + } + + hpread_psymtab_to_symtab_1 (pst); + + /* Match with global symbols. This only needs to be done once, + after all of the symtabs and dependencies have been read in. */ + scan_file_globals (pst->objfile); + + /* Finish up the debug error message. */ + if (info_verbose) + printf_filtered ("done.\n"); + } +} + +/* Read in a defined section of a specific object file's symbols. + + DESC is the file descriptor for the file, positioned at the + beginning of the symtab + SYM_OFFSET is the offset within the file of + the beginning of the symbols we want to read + SYM_SIZE is the size of the symbol info to read in. + TEXT_OFFSET is the beginning of the text segment we are reading symbols for + TEXT_SIZE is the size of the text segment read in. + SECTION_OFFSETS are the relocation offsets which get added to each symbol. */ + +static struct symtab * +hpread_expand_symtab (struct objfile *objfile, int sym_offset, int sym_size, + CORE_ADDR text_offset, int text_size, + struct section_offsets *section_offsets, char *filename) +{ + char *namestring; + union dnttentry *dn_bufp; + unsigned max_symnum; + int at_module_boundary = 0; + /* 1 => at end, -1 => at beginning */ + + int sym_index = sym_offset / sizeof (struct dntt_type_block); + + current_objfile = objfile; + subfile_stack = 0; + + last_source_file = 0; + + /* Demangling style -- if EDG style already set, don't change it, + as HP style causes some problems with the KAI EDG compiler */ + if (current_demangling_style != edg_demangling) + { + /* Otherwise, ensure that we are using HP style demangling */ + set_demangling_style (HP_DEMANGLING_STYLE_STRING); + } + + dn_bufp = hpread_get_lntt (sym_index, objfile); + if (!((dn_bufp->dblock.kind == (unsigned char) DNTT_TYPE_SRCFILE) || + (dn_bufp->dblock.kind == (unsigned char) DNTT_TYPE_MODULE))) + { + start_symtab ("globals", NULL, 0); + record_debugformat ("HP"); + } + + /* The psymtab builder (hp-psymtab-read.c) is the one that + * determined the "sym_size" argument (i.e. how many DNTT symbols + * are in this symtab), which we use to compute "max_symnum" + * (point in DNTT to which we read). + * + * Perhaps this should be changed so that + * process_one_debug_symbol() "knows" when + * to stop reading (based on reading from the MODULE to the matching + * END), and take out this reliance on a #-syms being passed in... + * (I'm worried about the reliability of this number). But I'll + * leave it as-is, for now. - RT + * + * The change above has been made. I've left the "for" loop control + * in to prepare for backing this out again. -JB + */ + max_symnum = sym_size / sizeof (struct dntt_type_block); + /* No reason to multiply on pst side and divide on sym side... FIXME */ + + /* Read in and process each debug symbol within the specified range. + */ + for (symnum = 0; + symnum < max_symnum; + symnum++) + { + QUIT; /* Allow this to be interruptable */ + dn_bufp = hpread_get_lntt (sym_index + symnum, objfile); + + if (dn_bufp->dblock.extension) + continue; + + /* Yow! We call SET_NAMESTRING on things without names! */ + SET_NAMESTRING (dn_bufp, &namestring, objfile); + + hpread_process_one_debug_symbol (dn_bufp, namestring, section_offsets, + objfile, text_offset, text_size, + filename, symnum + sym_index, + &at_module_boundary + ); + + /* OLD COMMENTS: This routine is only called for psts. All psts + * correspond to MODULES. If we ever do lazy-reading of globals + * from the LNTT, then there will be a pst which ends when the + * LNTT ends, and not at an END MODULE entry. Then we'll have + * to re-visit this break. + + if( at_end_of_module ) + break; + + */ + + /* We no longer break out of the loop when we reach the end of a + module. The reason is that with CTTI, the compiler can generate + function symbols (for template function instantiations) which are not + in any module; typically they show up beyond a module's end, and + before the next module's start. We include them in the current + module. However, we still don't trust the MAX_SYMNUM value from + the psymtab, so we break out if we enter a new module. */ + + if (at_module_boundary == -1) + break; + } + + current_objfile = NULL; + hp_som_som_object_present = 1; /* Indicate we've processed an HP SOM SOM file */ + + return end_symtab (text_offset + text_size, objfile, SECT_OFF_TEXT (objfile)); +} + + + + +/* Convert basic types from HP debug format into GDB internal format. */ + +static int +hpread_type_translate (dnttpointer typep) +{ + if (!typep.dntti.immediate) + { + error ("error in hpread_type_translate\n."); + return FT_VOID; + } + + switch (typep.dntti.type) + { + case HP_TYPE_BOOLEAN: + case HP_TYPE_BOOLEAN_S300_COMPAT: + case HP_TYPE_BOOLEAN_VAX_COMPAT: + return FT_BOOLEAN; + case HP_TYPE_CHAR: /* C signed char, C++ plain char */ + + case HP_TYPE_WIDE_CHAR: + return FT_CHAR; + case HP_TYPE_INT: + if (typep.dntti.bitlength <= 8) + return FT_SIGNED_CHAR; /* C++ signed char */ + if (typep.dntti.bitlength <= 16) + return FT_SHORT; + if (typep.dntti.bitlength <= 32) + return FT_INTEGER; + return FT_LONG_LONG; + case HP_TYPE_LONG: + if (typep.dntti.bitlength <= 8) + return FT_SIGNED_CHAR; /* C++ signed char. */ + return FT_LONG; + case HP_TYPE_UNSIGNED_LONG: + if (typep.dntti.bitlength <= 8) + return FT_UNSIGNED_CHAR; /* C/C++ unsigned char */ + if (typep.dntti.bitlength <= 16) + return FT_UNSIGNED_SHORT; + if (typep.dntti.bitlength <= 32) + return FT_UNSIGNED_LONG; + return FT_UNSIGNED_LONG_LONG; + case HP_TYPE_UNSIGNED_INT: + if (typep.dntti.bitlength <= 8) + return FT_UNSIGNED_CHAR; + if (typep.dntti.bitlength <= 16) + return FT_UNSIGNED_SHORT; + if (typep.dntti.bitlength <= 32) + return FT_UNSIGNED_INTEGER; + return FT_UNSIGNED_LONG_LONG; + case HP_TYPE_REAL: + case HP_TYPE_REAL_3000: + case HP_TYPE_DOUBLE: + if (typep.dntti.bitlength == 64) + return FT_DBL_PREC_FLOAT; + if (typep.dntti.bitlength == 128) + return FT_EXT_PREC_FLOAT; + return FT_FLOAT; + case HP_TYPE_COMPLEX: + case HP_TYPE_COMPLEXS3000: + if (typep.dntti.bitlength == 128) + return FT_DBL_PREC_COMPLEX; + if (typep.dntti.bitlength == 192) + return FT_EXT_PREC_COMPLEX; + return FT_COMPLEX; + case HP_TYPE_VOID: + return FT_VOID; + case HP_TYPE_STRING200: + case HP_TYPE_LONGSTRING200: + case HP_TYPE_FTN_STRING_SPEC: + case HP_TYPE_MOD_STRING_SPEC: + case HP_TYPE_MOD_STRING_3000: + case HP_TYPE_FTN_STRING_S300_COMPAT: + case HP_TYPE_FTN_STRING_VAX_COMPAT: + return FT_STRING; + case HP_TYPE_TEMPLATE_ARG: + return FT_TEMPLATE_ARG; + case HP_TYPE_TEXT: + case HP_TYPE_FLABEL: + case HP_TYPE_PACKED_DECIMAL: + case HP_TYPE_ANYPOINTER: + case HP_TYPE_GLOBAL_ANYPOINTER: + case HP_TYPE_LOCAL_ANYPOINTER: + default: + warning ("hpread_type_translate: unhandled type code.\n"); + return FT_VOID; + } +} + +/* Given a position in the DNTT, return a pointer to the + * already-built "struct type" (if any), for the type defined + * at that position. + */ + +static struct type ** +hpread_lookup_type (dnttpointer hp_type, struct objfile *objfile) +{ + unsigned old_len; + int index = hp_type.dnttp.index; + int size_changed = 0; + + /* The immediate flag indicates this doesn't actually point to + * a type DNTT. + */ + if (hp_type.dntti.immediate) + return NULL; + + /* For each objfile, we maintain a "type vector". + * This an array of "struct type *"'s with one pointer per DNTT index. + * Given a DNTT index, we look in this array to see if we have + * already processed this DNTT and if it is a type definition. + * If so, then we can locate a pointer to the already-built + * "struct type", and not build it again. + * + * The need for this arises because our DNTT-walking code wanders + * around. In particular, it will encounter the same type multiple + * times (once for each object of that type). We don't want to + * built multiple "struct type"'s for the same thing. + * + * Having said this, I should point out that this type-vector is + * an expensive way to keep track of this. If most DNTT entries are + * 3 words, the type-vector will be 1/3 the size of the DNTT itself. + * Alternative solutions: + * - Keep a compressed or hashed table. Less memory, but more expensive + * to search and update. + * - (Suggested by JB): Overwrite the DNTT entry itself + * with the info. Create a new type code "ALREADY_BUILT", and modify + * the DNTT to have that type code and point to the already-built entry. + * -RT + */ + + if (index < LNTT_SYMCOUNT (objfile)) + { + if (index >= DNTT_TYPE_VECTOR_LENGTH (objfile)) + { + old_len = DNTT_TYPE_VECTOR_LENGTH (objfile); + + /* See if we need to allocate a type-vector. */ + if (old_len == 0) + { + DNTT_TYPE_VECTOR_LENGTH (objfile) = LNTT_SYMCOUNT (objfile) + GNTT_SYMCOUNT (objfile); + DNTT_TYPE_VECTOR (objfile) = (struct type **) + xmmalloc (objfile->md, DNTT_TYPE_VECTOR_LENGTH (objfile) * sizeof (struct type *)); + memset (&DNTT_TYPE_VECTOR (objfile)[old_len], 0, + (DNTT_TYPE_VECTOR_LENGTH (objfile) - old_len) * + sizeof (struct type *)); + } + + /* See if we need to resize type-vector. With my change to + * initially allocate a correct-size type-vector, this code + * should no longer trigger. + */ + while (index >= DNTT_TYPE_VECTOR_LENGTH (objfile)) + { + DNTT_TYPE_VECTOR_LENGTH (objfile) *= 2; + size_changed = 1; + } + if (size_changed) + { + DNTT_TYPE_VECTOR (objfile) = (struct type **) + xmrealloc (objfile->md, + (char *) DNTT_TYPE_VECTOR (objfile), + (DNTT_TYPE_VECTOR_LENGTH (objfile) * sizeof (struct type *))); + + memset (&DNTT_TYPE_VECTOR (objfile)[old_len], 0, + (DNTT_TYPE_VECTOR_LENGTH (objfile) - old_len) * + sizeof (struct type *)); + } + + } + return &DNTT_TYPE_VECTOR (objfile)[index]; + } + else + return NULL; +} + +/* Possibly allocate a GDB internal type so we can internalize HP_TYPE. + Note we'll just return the address of a GDB internal type if we already + have it lying around. */ + +static struct type * +hpread_alloc_type (dnttpointer hp_type, struct objfile *objfile) +{ + struct type **type_addr; + + type_addr = hpread_lookup_type (hp_type, objfile); + if (*type_addr == 0) + { + *type_addr = alloc_type (objfile); + + /* A hack - if we really are a C++ class symbol, then this default + * will get overriden later on. + */ + TYPE_CPLUS_SPECIFIC (*type_addr) + = (struct cplus_struct_type *) &cplus_struct_default; + } + + return *type_addr; +} + +/* Read a native enumerated type and return it in GDB internal form. */ + +static struct type * +hpread_read_enum_type (dnttpointer hp_type, union dnttentry *dn_bufp, + struct objfile *objfile) +{ + struct type *type; + struct pending **symlist, *osyms, *syms; + struct pending *local_list = NULL; + int o_nsyms, nsyms = 0; + dnttpointer mem; + union dnttentry *memp; + char *name; + long n; + struct symbol *sym; + + /* Allocate a GDB type. If we've already read in this enum type, + * it'll return the already built GDB type, so stop here. + * (Note: I added this check, to conform with what's done for + * struct, union, class. + * I assume this is OK. - RT) + */ + type = hpread_alloc_type (hp_type, objfile); + if (TYPE_CODE (type) == TYPE_CODE_ENUM) + return type; + + /* HP C supports "sized enums", where a specifier such as "short" or + "char" can be used to get enums of different sizes. So don't assume + an enum is always 4 bytes long. pai/1997-08-21 */ + TYPE_LENGTH (type) = dn_bufp->denum.bitlength / 8; + + symlist = &file_symbols; + osyms = *symlist; + o_nsyms = osyms ? osyms->nsyms : 0; + + /* Get a name for each member and add it to our list of members. + * The list of "mem" SOM records we are walking should all be + * SOM type DNTT_TYPE_MEMENUM (not checked). + */ + mem = dn_bufp->denum.firstmem; + while (mem.word && mem.word != DNTTNIL) + { + memp = hpread_get_lntt (mem.dnttp.index, objfile); + + name = VT (objfile) + memp->dmember.name; + sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack, + sizeof (struct symbol)); + memset (sym, 0, sizeof (struct symbol)); + SYMBOL_NAME (sym) = obsavestring (name, strlen (name), + &objfile->symbol_obstack); + SYMBOL_CLASS (sym) = LOC_CONST; + SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; + SYMBOL_VALUE (sym) = memp->dmember.value; + add_symbol_to_list (sym, symlist); + nsyms++; + mem = memp->dmember.nextmem; + } + + /* Now that we know more about the enum, fill in more info. */ + TYPE_CODE (type) = TYPE_CODE_ENUM; + TYPE_FLAGS (type) &= ~TYPE_FLAG_STUB; + TYPE_NFIELDS (type) = nsyms; + TYPE_FIELDS (type) = (struct field *) + obstack_alloc (&objfile->type_obstack, sizeof (struct field) * nsyms); + + /* Find the symbols for the members and put them into the type. + The symbols can be found in the symlist that we put them on + to cause them to be defined. osyms contains the old value + of that symlist; everything up to there was defined by us. + + Note that we preserve the order of the enum constants, so + that in something like "enum {FOO, LAST_THING=FOO}" we print + FOO, not LAST_THING. */ + for (syms = *symlist, n = 0; syms; syms = syms->next) + { + int j = 0; + if (syms == osyms) + j = o_nsyms; + for (; j < syms->nsyms; j++, n++) + { + struct symbol *xsym = syms->symbol[j]; + SYMBOL_TYPE (xsym) = type; + TYPE_FIELD_NAME (type, n) = SYMBOL_NAME (xsym); + TYPE_FIELD_BITPOS (type, n) = SYMBOL_VALUE (xsym); + TYPE_FIELD_BITSIZE (type, n) = 0; + } + if (syms == osyms) + break; + } + + return type; +} + +/* Read and internalize a native function debug symbol. */ + +static struct type * +hpread_read_function_type (dnttpointer hp_type, union dnttentry *dn_bufp, + struct objfile *objfile, int newblock) +{ + struct type *type, *type1; + struct pending *syms; + struct pending *local_list = NULL; + int nsyms = 0; + dnttpointer param; + union dnttentry *paramp; + char *name; + long n; + struct symbol *sym; + int record_args = 1; + + /* See if we've already read in this type. */ + type = hpread_alloc_type (hp_type, objfile); + if (TYPE_CODE (type) == TYPE_CODE_FUNC) + { + record_args = 0; /* already read in, don't modify type */ + } + else + { + /* Nope, so read it in and store it away. */ + if (dn_bufp->dblock.kind == DNTT_TYPE_FUNCTION || + dn_bufp->dblock.kind == DNTT_TYPE_MEMFUNC) + type1 = lookup_function_type (hpread_type_lookup (dn_bufp->dfunc.retval, + objfile)); + else if (dn_bufp->dblock.kind == DNTT_TYPE_FUNCTYPE) + type1 = lookup_function_type (hpread_type_lookup (dn_bufp->dfunctype.retval, + objfile)); + else /* expect DNTT_TYPE_FUNC_TEMPLATE */ + type1 = lookup_function_type (hpread_type_lookup (dn_bufp->dfunc_template.retval, + objfile)); + replace_type (type, type1); + + /* Mark it -- in the middle of processing */ + TYPE_FLAGS (type) |= TYPE_FLAG_INCOMPLETE; + } + + /* Now examine each parameter noting its type, location, and a + wealth of other information. */ + if (dn_bufp->dblock.kind == DNTT_TYPE_FUNCTION || + dn_bufp->dblock.kind == DNTT_TYPE_MEMFUNC) + param = dn_bufp->dfunc.firstparam; + else if (dn_bufp->dblock.kind == DNTT_TYPE_FUNCTYPE) + param = dn_bufp->dfunctype.firstparam; + else /* expect DNTT_TYPE_FUNC_TEMPLATE */ + param = dn_bufp->dfunc_template.firstparam; + while (param.word && param.word != DNTTNIL) + { + paramp = hpread_get_lntt (param.dnttp.index, objfile); + nsyms++; + param = paramp->dfparam.nextparam; + + /* Get the name. */ + name = VT (objfile) + paramp->dfparam.name; + sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack, + sizeof (struct symbol)); + (void) memset (sym, 0, sizeof (struct symbol)); + SYMBOL_NAME (sym) = obsavestring (name, strlen (name), + &objfile->symbol_obstack); + + /* Figure out where it lives. */ + if (paramp->dfparam.regparam) + SYMBOL_CLASS (sym) = LOC_REGPARM; + else if (paramp->dfparam.indirect) + SYMBOL_CLASS (sym) = LOC_REF_ARG; + else + SYMBOL_CLASS (sym) = LOC_ARG; + SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; + if (paramp->dfparam.copyparam) + { + SYMBOL_VALUE (sym) = paramp->dfparam.location; +#ifdef HPREAD_ADJUST_STACK_ADDRESS + SYMBOL_VALUE (sym) + += HPREAD_ADJUST_STACK_ADDRESS (CURRENT_FUNCTION_VALUE (objfile)); +#endif + /* This is likely a pass-by-invisible reference parameter, + Hack on the symbol class to make GDB happy. */ + /* ??rehrauer: This appears to be broken w/r/t to passing + C values of type float and struct. Perhaps this ought + to be highighted as a special case, but for now, just + allowing these to be LOC_ARGs seems to work fine. + */ +#if 0 + SYMBOL_CLASS (sym) = LOC_REGPARM_ADDR; +#endif + } + else + SYMBOL_VALUE (sym) = paramp->dfparam.location; + + /* Get its type. */ + SYMBOL_TYPE (sym) = hpread_type_lookup (paramp->dfparam.type, objfile); + /* Add it to the symbol list. */ + /* Note 1 (RT) At the moment, add_symbol_to_list() is also being + * called on FPARAM symbols from the process_one_debug_symbol() + * level... so parameters are getting added twice! (this shows + * up in the symbol dump you get from "maint print symbols ..."). + * Note 2 (RT) I took out the processing of FPARAM from the + * process_one_debug_symbol() level, so at the moment parameters are only + * being processed here. This seems to have no ill effect. + */ + /* Note 3 (pai/1997-08-11) I removed the add_symbol_to_list() which put + each fparam on the local_symbols list from here. Now we use the + local_list to which fparams are added below, and set the param_symbols + global to point to that at the end of this routine. */ + /* elz: I added this new list of symbols which is local to the function. + this list is the one which is actually used to build the type for the + function rather than the gloabal list pointed to by symlist. + Using a global list to keep track of the parameters is wrong, because + this function is called recursively if one parameter happend to be + a function itself with more parameters in it. Adding parameters to the + same global symbol list would not work! + Actually it did work in case of cc compiled programs where you do + not check the parameter lists of the arguments. */ + add_symbol_to_list (sym, &local_list); + + } + + /* If type was read in earlier, don't bother with modifying + the type struct */ + if (!record_args) + goto finish; + + /* Note how many parameters we found. */ + TYPE_NFIELDS (type) = nsyms; + TYPE_FIELDS (type) = (struct field *) + obstack_alloc (&objfile->type_obstack, + sizeof (struct field) * nsyms); + + /* Find the symbols for the parameters and + use them to fill parameter-type information into the function-type. + The parameter symbols can be found in the local_list that we just put them on. */ + /* Note that we preserve the order of the parameters, so + that in something like "enum {FOO, LAST_THING=FOO}" we print + FOO, not LAST_THING. */ + + /* get the parameters types from the local list not the global list + so that the type can be correctly constructed for functions which + have function as parameters */ + for (syms = local_list, n = 0; syms; syms = syms->next) + { + int j = 0; + for (j = 0; j < syms->nsyms; j++, n++) + { + struct symbol *xsym = syms->symbol[j]; + TYPE_FIELD_NAME (type, n) = SYMBOL_NAME (xsym); + TYPE_FIELD_TYPE (type, n) = SYMBOL_TYPE (xsym); + TYPE_FIELD_ARTIFICIAL (type, n) = 0; + TYPE_FIELD_BITSIZE (type, n) = 0; + } + } + /* Mark it as having been processed */ + TYPE_FLAGS (type) &= ~(TYPE_FLAG_INCOMPLETE); + + /* Check whether we need to fix-up a class type with this function's type */ + if (fixup_class && (fixup_method == type)) + { + fixup_class_method_type (fixup_class, fixup_method, objfile); + fixup_class = NULL; + fixup_method = NULL; + } + + /* Set the param list of this level of the context stack + to our local list. Do this only if this function was + called for creating a new block, and not if it was called + simply to get the function type. This prevents recursive + invocations from trashing param_symbols. */ +finish: + if (newblock) + param_symbols = local_list; + + return type; +} + + +/* Read and internalize a native DOC function debug symbol. */ +/* This is almost identical to hpread_read_function_type(), except + * for references to dn_bufp->ddocfunc instead of db_bufp->dfunc. + * Since debug information for DOC functions is more likely to be + * volatile, please leave it this way. + */ +static struct type * +hpread_read_doc_function_type (dnttpointer hp_type, union dnttentry *dn_bufp, + struct objfile *objfile, int newblock) +{ + struct type *type, *type1; + struct pending *syms; + struct pending *local_list = NULL; + int nsyms = 0; + dnttpointer param; + union dnttentry *paramp; + char *name; + long n; + struct symbol *sym; + int record_args = 1; + + /* See if we've already read in this type. */ + type = hpread_alloc_type (hp_type, objfile); + if (TYPE_CODE (type) == TYPE_CODE_FUNC) + { + record_args = 0; /* already read in, don't modify type */ + } + else + { + /* Nope, so read it in and store it away. */ + if (dn_bufp->dblock.kind == DNTT_TYPE_DOC_FUNCTION || + dn_bufp->dblock.kind == DNTT_TYPE_DOC_MEMFUNC) + type1 = lookup_function_type (hpread_type_lookup (dn_bufp->ddocfunc.retval, + objfile)); + replace_type (type, type1); + + /* Mark it -- in the middle of processing */ + TYPE_FLAGS (type) |= TYPE_FLAG_INCOMPLETE; + } + + /* Now examine each parameter noting its type, location, and a + wealth of other information. */ + if (dn_bufp->dblock.kind == DNTT_TYPE_DOC_FUNCTION || + dn_bufp->dblock.kind == DNTT_TYPE_DOC_MEMFUNC) + param = dn_bufp->ddocfunc.firstparam; + while (param.word && param.word != DNTTNIL) + { + paramp = hpread_get_lntt (param.dnttp.index, objfile); + nsyms++; + param = paramp->dfparam.nextparam; + + /* Get the name. */ + name = VT (objfile) + paramp->dfparam.name; + sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack, + sizeof (struct symbol)); + (void) memset (sym, 0, sizeof (struct symbol)); + SYMBOL_NAME (sym) = name; + + /* Figure out where it lives. */ + if (paramp->dfparam.regparam) + SYMBOL_CLASS (sym) = LOC_REGPARM; + else if (paramp->dfparam.indirect) + SYMBOL_CLASS (sym) = LOC_REF_ARG; + else + SYMBOL_CLASS (sym) = LOC_ARG; + SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; + if (paramp->dfparam.copyparam) + { + SYMBOL_VALUE (sym) = paramp->dfparam.location; +#ifdef HPREAD_ADJUST_STACK_ADDRESS + SYMBOL_VALUE (sym) + += HPREAD_ADJUST_STACK_ADDRESS (CURRENT_FUNCTION_VALUE (objfile)); +#endif + /* This is likely a pass-by-invisible reference parameter, + Hack on the symbol class to make GDB happy. */ + /* ??rehrauer: This appears to be broken w/r/t to passing + C values of type float and struct. Perhaps this ought + to be highighted as a special case, but for now, just + allowing these to be LOC_ARGs seems to work fine. + */ +#if 0 + SYMBOL_CLASS (sym) = LOC_REGPARM_ADDR; +#endif + } + else + SYMBOL_VALUE (sym) = paramp->dfparam.location; + + /* Get its type. */ + SYMBOL_TYPE (sym) = hpread_type_lookup (paramp->dfparam.type, objfile); + /* Add it to the symbol list. */ + /* Note 1 (RT) At the moment, add_symbol_to_list() is also being + * called on FPARAM symbols from the process_one_debug_symbol() + * level... so parameters are getting added twice! (this shows + * up in the symbol dump you get from "maint print symbols ..."). + * Note 2 (RT) I took out the processing of FPARAM from the + * process_one_debug_symbol() level, so at the moment parameters are only + * being processed here. This seems to have no ill effect. + */ + /* Note 3 (pai/1997-08-11) I removed the add_symbol_to_list() which put + each fparam on the local_symbols list from here. Now we use the + local_list to which fparams are added below, and set the param_symbols + global to point to that at the end of this routine. */ + + /* elz: I added this new list of symbols which is local to the function. + this list is the one which is actually used to build the type for the + function rather than the gloabal list pointed to by symlist. + Using a global list to keep track of the parameters is wrong, because + this function is called recursively if one parameter happend to be + a function itself with more parameters in it. Adding parameters to the + same global symbol list would not work! + Actually it did work in case of cc compiled programs where you do not check the + parameter lists of the arguments. */ + add_symbol_to_list (sym, &local_list); + } + + /* If type was read in earlier, don't bother with modifying + the type struct */ + if (!record_args) + goto finish; + + /* Note how many parameters we found. */ + TYPE_NFIELDS (type) = nsyms; + TYPE_FIELDS (type) = (struct field *) + obstack_alloc (&objfile->type_obstack, + sizeof (struct field) * nsyms); + + /* Find the symbols for the parameters and + use them to fill parameter-type information into the function-type. + The parameter symbols can be found in the local_list that we just put them on. */ + /* Note that we preserve the order of the parameters, so + that in something like "enum {FOO, LAST_THING=FOO}" we print + FOO, not LAST_THING. */ + + /* get the parameters types from the local list not the global list + so that the type can be correctly constructed for functions which + have function as parameters + */ + for (syms = local_list, n = 0; syms; syms = syms->next) + { + int j = 0; + for (j = 0; j < syms->nsyms; j++, n++) + { + struct symbol *xsym = syms->symbol[j]; + TYPE_FIELD_NAME (type, n) = SYMBOL_NAME (xsym); + TYPE_FIELD_TYPE (type, n) = SYMBOL_TYPE (xsym); + TYPE_FIELD_ARTIFICIAL (type, n) = 0; + TYPE_FIELD_BITSIZE (type, n) = 0; + } + } + + /* Mark it as having been processed */ + TYPE_FLAGS (type) &= ~(TYPE_FLAG_INCOMPLETE); + + /* Check whether we need to fix-up a class type with this function's type */ + if (fixup_class && (fixup_method == type)) + { + fixup_class_method_type (fixup_class, fixup_method, objfile); + fixup_class = NULL; + fixup_method = NULL; + } + + /* Set the param list of this level of the context stack + to our local list. Do this only if this function was + called for creating a new block, and not if it was called + simply to get the function type. This prevents recursive + invocations from trashing param_symbols. */ +finish: + if (newblock) + param_symbols = local_list; + + return type; +} + + + +/* A file-level variable which keeps track of the current-template + * being processed. Set in hpread_read_struct_type() while processing + * a template type. Referred to in hpread_get_nth_templ_arg(). + * Yes, this is a kludge, but it arises from the kludge that already + * exists in symtab.h, namely the fact that they encode + * "template argument n" with fundamental type FT_TEMPLATE_ARG and + * bitlength n. This means that deep in processing fundamental types + * I need to ask the question "what template am I in the middle of?". + * The alternative to stuffing a global would be to pass an argument + * down the chain of calls just for this purpose. + * + * There may be problems handling nested templates... tough. + */ +static struct type *current_template = NULL; + +/* Read in and internalize a structure definition. + * This same routine is called for struct, union, and class types. + * Also called for templates, since they build a very similar + * type entry as for class types. + */ + +static struct type * +hpread_read_struct_type (dnttpointer hp_type, union dnttentry *dn_bufp, + struct objfile *objfile) +{ + /* The data members get linked together into a list of struct nextfield's */ + struct nextfield + { + struct nextfield *next; + struct field field; + unsigned char attributes; /* store visibility and virtuality info */ +#define ATTR_VIRTUAL 1 +#define ATTR_PRIVATE 2 +#define ATTR_PROTECT 3 + }; + + + /* The methods get linked together into a list of struct next_fn_field's */ + struct next_fn_field + { + struct next_fn_field *next; + struct fn_fieldlist field; + struct fn_field fn_field; + int num_fn_fields; + }; + + /* The template args get linked together into a list of struct next_template's */ + struct next_template + { + struct next_template *next; + struct template_arg arg; + }; + + /* The template instantiations get linked together into a list of these... */ + struct next_instantiation + { + struct next_instantiation *next; + struct type *t; + }; + + struct type *type; + struct type *baseclass; + struct type *memtype; + struct nextfield *list = 0, *tmp_list = 0; + struct next_fn_field *fn_list = 0; + struct next_fn_field *fn_p; + struct next_template *t_new, *t_list = 0; + struct nextfield *new; + struct next_fn_field *fn_new; + struct next_instantiation *i_new, *i_list = 0; + int n, nfields = 0, n_fn_fields = 0, n_fn_fields_total = 0; + int n_base_classes = 0, n_templ_args = 0; + int ninstantiations = 0; + dnttpointer field, fn_field, parent; + union dnttentry *fieldp, *fn_fieldp, *parentp; + int i; + int static_member = 0; + int const_member = 0; + int volatile_member = 0; + unsigned long vtbl_offset; + int need_bitvectors = 0; + char *method_name = NULL; + char *method_alias = NULL; + + + /* Is it something we've already dealt with? */ + type = hpread_alloc_type (hp_type, objfile); + if ((TYPE_CODE (type) == TYPE_CODE_STRUCT) || + (TYPE_CODE (type) == TYPE_CODE_UNION) || + (TYPE_CODE (type) == TYPE_CODE_CLASS) || + (TYPE_CODE (type) == TYPE_CODE_TEMPLATE)) + return type; + + /* Get the basic type correct. */ + if (dn_bufp->dblock.kind == DNTT_TYPE_STRUCT) + { + TYPE_CODE (type) = TYPE_CODE_STRUCT; + TYPE_LENGTH (type) = dn_bufp->dstruct.bitlength / 8; + } + else if (dn_bufp->dblock.kind == DNTT_TYPE_UNION) + { + TYPE_CODE (type) = TYPE_CODE_UNION; + TYPE_LENGTH (type) = dn_bufp->dunion.bitlength / 8; + } + else if (dn_bufp->dblock.kind == DNTT_TYPE_CLASS) + { + TYPE_CODE (type) = TYPE_CODE_CLASS; + TYPE_LENGTH (type) = dn_bufp->dclass.bitlength / 8; + + /* Overrides the TYPE_CPLUS_SPECIFIC(type) with allocated memory + * rather than &cplus_struct_default. + */ + allocate_cplus_struct_type (type); + + /* Fill in declared-type. + * (The C++ compiler will emit TYPE_CODE_CLASS + * for all 3 of "class", "struct" + * "union", and we have to look at the "class_decl" field if we + * want to know how it was really declared) + */ + /* (0==class, 1==union, 2==struct) */ + TYPE_DECLARED_TYPE (type) = dn_bufp->dclass.class_decl; + } + else if (dn_bufp->dblock.kind == DNTT_TYPE_TEMPLATE) + { + /* Get the basic type correct. */ + TYPE_CODE (type) = TYPE_CODE_TEMPLATE; + allocate_cplus_struct_type (type); + TYPE_DECLARED_TYPE (type) = DECLARED_TYPE_TEMPLATE; + } + else + return type; + + + TYPE_FLAGS (type) &= ~TYPE_FLAG_STUB; + + /* For classes, read the parent list. + * Question (RT): Do we need to do this for templates also? + */ + if (dn_bufp->dblock.kind == DNTT_TYPE_CLASS) + { + + /* First read the parent-list (classes from which we derive fields) */ + parent = dn_bufp->dclass.parentlist; + while (parent.word && parent.word != DNTTNIL) + { + parentp = hpread_get_lntt (parent.dnttp.index, objfile); + + /* "parentp" should point to a DNTT_TYPE_INHERITANCE record */ + + /* Get space to record the next field/data-member. */ + new = (struct nextfield *) alloca (sizeof (struct nextfield)); + new->next = list; + list = new; + + FIELD_BITSIZE (list->field) = 0; + + /* The "classname" field is actually a DNTT pointer to the base class */ + baseclass = hpread_type_lookup (parentp->dinheritance.classname, + objfile); + FIELD_TYPE (list->field) = baseclass; + + list->field.name = type_name_no_tag (FIELD_TYPE (list->field)); + + list->attributes = 0; + + /* Check for virtuality of base, and set the + * offset of the base subobject within the object. + * (Offset set to -1 for virtual bases (for now).) + */ + if (parentp->dinheritance.Virtual) + { + B_SET (&(list->attributes), ATTR_VIRTUAL); + parentp->dinheritance.offset = -1; + } + else + FIELD_BITPOS (list->field) = parentp->dinheritance.offset; + + /* Check visibility */ + switch (parentp->dinheritance.visibility) + { + case 1: + B_SET (&(list->attributes), ATTR_PROTECT); + break; + case 2: + B_SET (&(list->attributes), ATTR_PRIVATE); + break; + } + + n_base_classes++; + nfields++; + + parent = parentp->dinheritance.next; + } + } + + /* For templates, read the template argument list. + * This must be done before processing the member list, because + * the member list may refer back to this. E.g.: + * template <class T1, class T2> class q2 { + * public: + * T1 a; + * T2 b; + * }; + * We need to read the argument list "T1", "T2" first. + */ + if (dn_bufp->dblock.kind == DNTT_TYPE_TEMPLATE) + { + /* Kludge alert: This stuffs a global "current_template" which + * is referred to by hpread_get_nth_templ_arg(). The global + * is cleared at the end of this routine. + */ + current_template = type; + + /* Read in the argument list */ + field = dn_bufp->dtemplate.arglist; + while (field.word && field.word != DNTTNIL) + { + /* Get this template argument */ + fieldp = hpread_get_lntt (field.dnttp.index, objfile); + if (fieldp->dblock.kind != DNTT_TYPE_TEMPLATE_ARG) + { + warning ("Invalid debug info: Template argument entry is of wrong kind"); + break; + } + /* Bump the count */ + n_templ_args++; + /* Allocate and fill in a struct next_template */ + t_new = (struct next_template *) alloca (sizeof (struct next_template)); + t_new->next = t_list; + t_list = t_new; + t_list->arg.name = VT (objfile) + fieldp->dtempl_arg.name; + t_list->arg.type = hpread_read_templ_arg_type (field, fieldp, + objfile, t_list->arg.name); + /* Walk to the next template argument */ + field = fieldp->dtempl_arg.nextarg; + } + } + + TYPE_NTEMPLATE_ARGS (type) = n_templ_args; + + if (n_templ_args > 0) + TYPE_TEMPLATE_ARGS (type) = (struct template_arg *) + obstack_alloc (&objfile->type_obstack, sizeof (struct template_arg) * n_templ_args); + for (n = n_templ_args; t_list; t_list = t_list->next) + { + n -= 1; + TYPE_TEMPLATE_ARG (type, n) = t_list->arg; + } + + /* Next read in and internalize all the fields/members. */ + if (dn_bufp->dblock.kind == DNTT_TYPE_STRUCT) + field = dn_bufp->dstruct.firstfield; + else if (dn_bufp->dblock.kind == DNTT_TYPE_UNION) + field = dn_bufp->dunion.firstfield; + else if (dn_bufp->dblock.kind == DNTT_TYPE_CLASS) + field = dn_bufp->dclass.memberlist; + else if (dn_bufp->dblock.kind == DNTT_TYPE_TEMPLATE) + field = dn_bufp->dtemplate.memberlist; + else + field.word = DNTTNIL; + + while (field.word && field.word != DNTTNIL) + { + fieldp = hpread_get_lntt (field.dnttp.index, objfile); + + /* At this point "fieldp" may point to either a DNTT_TYPE_FIELD + * or a DNTT_TYPE_GENFIELD record. + */ + vtbl_offset = 0; + static_member = 0; + const_member = 0; + volatile_member = 0; + + if (fieldp->dblock.kind == DNTT_TYPE_GENFIELD) + { + + /* The type will be GENFIELD if the field is a method or + * a static member (or some other cases -- see below) + */ + + /* Follow a link to get to the record for the field. */ + fn_field = fieldp->dgenfield.field; + fn_fieldp = hpread_get_lntt (fn_field.dnttp.index, objfile); + + /* Virtual funcs are indicated by a VFUNC which points to the + * real entry + */ + if (fn_fieldp->dblock.kind == DNTT_TYPE_VFUNC) + { + vtbl_offset = fn_fieldp->dvfunc.vtbl_offset; + fn_field = fn_fieldp->dvfunc.funcptr; + fn_fieldp = hpread_get_lntt (fn_field.dnttp.index, objfile); + } + + /* A function's entry may be preceded by a modifier which + * labels it static/constant/volatile. + */ + if (fn_fieldp->dblock.kind == DNTT_TYPE_MODIFIER) + { + static_member = fn_fieldp->dmodifier.m_static; + const_member = fn_fieldp->dmodifier.m_const; + volatile_member = fn_fieldp->dmodifier.m_volatile; + fn_field = fn_fieldp->dmodifier.type; + fn_fieldp = hpread_get_lntt (fn_field.dnttp.index, objfile); + } + + /* Check whether we have a method */ + if ((fn_fieldp->dblock.kind == DNTT_TYPE_MEMFUNC) || + (fn_fieldp->dblock.kind == DNTT_TYPE_FUNCTION) || + (fn_fieldp->dblock.kind == DNTT_TYPE_DOC_MEMFUNC) || + (fn_fieldp->dblock.kind == DNTT_TYPE_DOC_FUNCTION)) + { + /* Method found */ + + short ix = 0; + + /* Look up function type of method */ + memtype = hpread_type_lookup (fn_field, objfile); + + /* Methods can be seen before classes in the SOM records. + If we are processing this class because it's a parameter of a + method, at this point the method's type is actually incomplete; + we'll have to fix it up later; mark the class for this. */ + + if (TYPE_INCOMPLETE (memtype)) + { + TYPE_FLAGS (type) |= TYPE_FLAG_INCOMPLETE; + if (fixup_class) + warning ("Two classes to fix up for method?? Type information may be incorrect for some classes."); + if (fixup_method) + warning ("Two methods to be fixed up at once?? Type information may be incorrect for some classes."); + fixup_class = type; /* remember this class has to be fixed up */ + fixup_method = memtype; /* remember the method type to be used in fixup */ + } + + /* HP aCC generates operator names without the "operator" keyword, and + generates null strings as names for operators that are + user-defined type conversions to basic types (e.g. operator int ()). + So try to reconstruct name as best as possible. */ + + method_name = (char *) (VT (objfile) + fn_fieldp->dfunc.name); + method_alias = (char *) (VT (objfile) + fn_fieldp->dfunc.alias); + + if (!method_name || /* no name */ + !*method_name || /* or null name */ + cplus_mangle_opname (method_name, DMGL_ANSI)) /* or name is an operator like "<" */ + { + char *tmp_name = cplus_demangle (method_alias, DMGL_ANSI); + char *op_string = strstr (tmp_name, "operator"); + method_name = xmalloc (strlen (op_string) + 1); /* don't overwrite VT! */ + strcpy (method_name, op_string); + } + + /* First check if a method of the same name has already been seen. */ + fn_p = fn_list; + while (fn_p) + { + if (STREQ (fn_p->field.name, method_name)) + break; + fn_p = fn_p->next; + } + + /* If no such method was found, allocate a new entry in the list */ + if (!fn_p) + { + /* Get space to record this member function */ + /* Note: alloca used; this will disappear on routine exit */ + fn_new = (struct next_fn_field *) alloca (sizeof (struct next_fn_field)); + fn_new->next = fn_list; + fn_list = fn_new; + + /* Fill in the fields of the struct nextfield */ + + /* Record the (unmangled) method name */ + fn_list->field.name = method_name; + /* Initial space for overloaded methods */ + /* Note: xmalloc is used; this will persist after this routine exits */ + fn_list->field.fn_fields = (struct fn_field *) xmalloc (5 * (sizeof (struct fn_field))); + fn_list->field.length = 1; /* Init # of overloaded instances */ + fn_list->num_fn_fields = 5; /* # of entries for which space allocated */ + fn_p = fn_list; + ix = 0; /* array index for fn_field */ + /* Bump the total count of the distinctly named methods */ + n_fn_fields++; + } + else + /* Another overloaded instance of an already seen method name */ + { + if (++(fn_p->field.length) > fn_p->num_fn_fields) + { + /* Increase space allocated for overloaded instances */ + fn_p->field.fn_fields + = (struct fn_field *) xrealloc (fn_p->field.fn_fields, + (fn_p->num_fn_fields + 5) * sizeof (struct fn_field)); + fn_p->num_fn_fields += 5; + } + ix = fn_p->field.length - 1; /* array index for fn_field */ + } + + /* "physname" is intended to be the name of this overloaded instance. */ + if ((fn_fieldp->dfunc.language == HP_LANGUAGE_CPLUSPLUS) && + method_alias && + *method_alias) /* not a null string */ + fn_p->field.fn_fields[ix].physname = method_alias; + else + fn_p->field.fn_fields[ix].physname = method_name; + /* What's expected here is the function type */ + /* But mark it as NULL if the method was incompletely processed + We'll fix this up later when the method is fully processed */ + if (TYPE_INCOMPLETE (memtype)) + fn_p->field.fn_fields[ix].type = NULL; + else + fn_p->field.fn_fields[ix].type = memtype; + + /* For virtual functions, fill in the voffset field with the + * virtual table offset. (This is just copied over from the + * SOM record; not sure if it is what GDB expects here...). + * But if the function is a static method, set it to 1. + * + * Note that we have to add 1 because 1 indicates a static + * method, and 0 indicates a non-static, non-virtual method */ + + if (static_member) + fn_p->field.fn_fields[ix].voffset = VOFFSET_STATIC; + else + fn_p->field.fn_fields[ix].voffset = vtbl_offset ? vtbl_offset + 1 : 0; + + /* Also fill in the fcontext field with the current + * class. (The latter isn't quite right: should be the baseclass + * that defines the virtual function... Note we do have + * a variable "baseclass" that we could stuff into the fcontext + * field, but "baseclass" isn't necessarily right either, + * since the virtual function could have been defined more + * than one level up). + */ + + if (vtbl_offset != 0) + fn_p->field.fn_fields[ix].fcontext = type; + else + fn_p->field.fn_fields[ix].fcontext = NULL; + + /* Other random fields pertaining to this method */ + fn_p->field.fn_fields[ix].is_const = const_member; + fn_p->field.fn_fields[ix].is_volatile = volatile_member; /* ?? */ + switch (fieldp->dgenfield.visibility) + { + case 1: + fn_p->field.fn_fields[ix].is_protected = 1; + fn_p->field.fn_fields[ix].is_private = 0; + break; + case 2: + fn_p->field.fn_fields[ix].is_protected = 0; + fn_p->field.fn_fields[ix].is_private = 1; + break; + default: /* public */ + fn_p->field.fn_fields[ix].is_protected = 0; + fn_p->field.fn_fields[ix].is_private = 0; + } + fn_p->field.fn_fields[ix].is_stub = 0; + + /* HP aCC emits both MEMFUNC and FUNCTION entries for a method; + if the class points to the FUNCTION, there is usually separate + code for the method; but if we have a MEMFUNC, the method has + been inlined (and there is usually no FUNCTION entry) + FIXME Not sure if this test is accurate. pai/1997-08-22 */ + if ((fn_fieldp->dblock.kind == DNTT_TYPE_MEMFUNC) || + (fn_fieldp->dblock.kind == DNTT_TYPE_DOC_MEMFUNC)) + fn_p->field.fn_fields[ix].is_inlined = 1; + else + fn_p->field.fn_fields[ix].is_inlined = 0; + + fn_p->field.fn_fields[ix].dummy = 0; + + /* Bump the total count of the member functions */ + n_fn_fields_total++; + + } + else if (fn_fieldp->dblock.kind == DNTT_TYPE_SVAR) + { + /* This case is for static data members of classes */ + + /* pai:: FIXME -- check that "staticmem" bit is set */ + + /* Get space to record this static member */ + new = (struct nextfield *) alloca (sizeof (struct nextfield)); + new->next = list; + list = new; + + list->field.name = VT (objfile) + fn_fieldp->dsvar.name; + SET_FIELD_PHYSNAME (list->field, 0); /* initialize to empty */ + memtype = hpread_type_lookup (fn_fieldp->dsvar.type, objfile); + + FIELD_TYPE (list->field) = memtype; + list->attributes = 0; + switch (fieldp->dgenfield.visibility) + { + case 1: + B_SET (&(list->attributes), ATTR_PROTECT); + break; + case 2: + B_SET (&(list->attributes), ATTR_PRIVATE); + break; + } + nfields++; + } + + else if (fn_fieldp->dblock.kind == DNTT_TYPE_FIELD) + { + /* FIELDs follow GENFIELDs for fields of anonymous unions. + Code below is replicated from the case for FIELDs further + below, except that fieldp is replaced by fn_fieldp */ + if (!fn_fieldp->dfield.a_union) + warning ("Debug info inconsistent: FIELD of anonymous union doesn't have a_union bit set"); + /* Get space to record the next field/data-member. */ + new = (struct nextfield *) alloca (sizeof (struct nextfield)); + new->next = list; + list = new; + + list->field.name = VT (objfile) + fn_fieldp->dfield.name; + FIELD_BITPOS (list->field) = fn_fieldp->dfield.bitoffset; + if (fn_fieldp->dfield.bitlength % 8) + list->field.bitsize = fn_fieldp->dfield.bitlength; + else + list->field.bitsize = 0; + + memtype = hpread_type_lookup (fn_fieldp->dfield.type, objfile); + list->field.type = memtype; + list->attributes = 0; + switch (fn_fieldp->dfield.visibility) + { + case 1: + B_SET (&(list->attributes), ATTR_PROTECT); + break; + case 2: + B_SET (&(list->attributes), ATTR_PRIVATE); + break; + } + nfields++; + } + else if (fn_fieldp->dblock.kind == DNTT_TYPE_SVAR) + { + /* Field of anonymous union; union is not inside a class */ + if (!fn_fieldp->dsvar.a_union) + warning ("Debug info inconsistent: SVAR field in anonymous union doesn't have a_union bit set"); + /* Get space to record the next field/data-member. */ + new = (struct nextfield *) alloca (sizeof (struct nextfield)); + new->next = list; + list = new; + + list->field.name = VT (objfile) + fn_fieldp->dsvar.name; + FIELD_BITPOS (list->field) = 0; /* FIXME is this always true? */ + FIELD_BITSIZE (list->field) = 0; /* use length from type */ + memtype = hpread_type_lookup (fn_fieldp->dsvar.type, objfile); + list->field.type = memtype; + list->attributes = 0; + /* No info to set visibility -- always public */ + nfields++; + } + else if (fn_fieldp->dblock.kind == DNTT_TYPE_DVAR) + { + /* Field of anonymous union; union is not inside a class */ + if (!fn_fieldp->ddvar.a_union) + warning ("Debug info inconsistent: DVAR field in anonymous union doesn't have a_union bit set"); + /* Get space to record the next field/data-member. */ + new = (struct nextfield *) alloca (sizeof (struct nextfield)); + new->next = list; + list = new; + + list->field.name = VT (objfile) + fn_fieldp->ddvar.name; + FIELD_BITPOS (list->field) = 0; /* FIXME is this always true? */ + FIELD_BITSIZE (list->field) = 0; /* use length from type */ + memtype = hpread_type_lookup (fn_fieldp->ddvar.type, objfile); + list->field.type = memtype; + list->attributes = 0; + /* No info to set visibility -- always public */ + nfields++; + } + else + { /* Not a method, nor a static data member, nor an anon union field */ + + /* This case is for miscellaneous type entries (local enums, + local function templates, etc.) that can be present + inside a class. */ + + /* Enums -- will be handled by other code that takes care + of DNTT_TYPE_ENUM; here we see only DNTT_TYPE_MEMENUM so + it's not clear we could have handled them here at all. */ + /* FUNC_TEMPLATE: is handled by other code (?). */ + /* MEMACCESS: modified access for inherited member. Not + sure what to do with this, ignoriing it at present. */ + + /* What other entries can appear following a GENFIELD which + we do not handle above? (MODIFIER, VFUNC handled above.) */ + + if ((fn_fieldp->dblock.kind != DNTT_TYPE_MEMACCESS) && + (fn_fieldp->dblock.kind != DNTT_TYPE_MEMENUM) && + (fn_fieldp->dblock.kind != DNTT_TYPE_FUNC_TEMPLATE)) + warning ("Internal error: Unexpected debug record kind %d found following DNTT_GENFIELD", + fn_fieldp->dblock.kind); + } + /* walk to the next FIELD or GENFIELD */ + field = fieldp->dgenfield.nextfield; + + } + else if (fieldp->dblock.kind == DNTT_TYPE_FIELD) + { + + /* Ordinary structure/union/class field */ + struct type *anon_union_type; + + /* Get space to record the next field/data-member. */ + new = (struct nextfield *) alloca (sizeof (struct nextfield)); + new->next = list; + list = new; + + list->field.name = VT (objfile) + fieldp->dfield.name; + + + /* A FIELD by itself (without a GENFIELD) can also be a static member */ + if (fieldp->dfield.staticmem) + { + FIELD_BITPOS (list->field) = -1; + FIELD_BITSIZE (list->field) = 0; + } + else + /* Non-static data member */ + { + FIELD_BITPOS (list->field) = fieldp->dfield.bitoffset; + if (fieldp->dfield.bitlength % 8) + FIELD_BITSIZE (list->field) = fieldp->dfield.bitlength; + else + FIELD_BITSIZE (list->field) = 0; + } + + memtype = hpread_type_lookup (fieldp->dfield.type, objfile); + FIELD_TYPE (list->field) = memtype; + list->attributes = 0; + switch (fieldp->dfield.visibility) + { + case 1: + B_SET (&(list->attributes), ATTR_PROTECT); + break; + case 2: + B_SET (&(list->attributes), ATTR_PRIVATE); + break; + } + nfields++; + + + /* Note 1: First, we have to check if the current field is an anonymous + union. If it is, then *its* fields are threaded along in the + nextfield chain. :-( This was supposed to help debuggers, but is + really just a nuisance since we deal with anonymous unions anyway by + checking that the name is null. So anyway, we skip over the fields + of the anonymous union. pai/1997-08-22 */ + /* Note 2: In addition, the bitoffsets for the fields of the anon union + are relative to the enclosing struct, *NOT* relative to the anon + union! This is an even bigger nuisance -- we have to go in and munge + the anon union's type information appropriately. pai/1997-08-22 */ + + /* Both tasks noted above are done by a separate function. This takes us + to the next FIELD or GENFIELD, skipping anon unions, and recursively + processing intermediate types. */ + field = hpread_get_next_skip_over_anon_unions (1, field, &fieldp, objfile); + + } + else + { + /* neither field nor genfield ?? is this possible?? */ + /* pai:: FIXME walk to the next -- how? */ + warning ("Internal error: unexpected DNTT kind %d encountered as field of struct", + fieldp->dblock.kind); + warning ("Skipping remaining fields of struct"); + break; /* get out of loop of fields */ + } + } + + /* If it's a template, read in the instantiation list */ + if (dn_bufp->dblock.kind == DNTT_TYPE_TEMPLATE) + { + ninstantiations = 0; + field = dn_bufp->dtemplate.expansions; + while (field.word && field.word != DNTTNIL) + { + fieldp = hpread_get_lntt (field.dnttp.index, objfile); + + /* The expansions or nextexp should point to a tagdef */ + if (fieldp->dblock.kind != DNTT_TYPE_TAGDEF) + break; + + i_new = (struct next_instantiation *) alloca (sizeof (struct next_instantiation)); + i_new->next = i_list; + i_list = i_new; + i_list->t = hpread_type_lookup (field, objfile); + ninstantiations++; + + /* And the "type" field of that should point to a class */ + field = fieldp->dtag.type; + fieldp = hpread_get_lntt (field.dnttp.index, objfile); + if (fieldp->dblock.kind != DNTT_TYPE_CLASS) + break; + + /* Get the next expansion */ + field = fieldp->dclass.nextexp; + } + } + TYPE_NINSTANTIATIONS (type) = ninstantiations; + if (ninstantiations > 0) + TYPE_INSTANTIATIONS (type) = (struct type **) + obstack_alloc (&objfile->type_obstack, sizeof (struct type *) * ninstantiations); + for (n = ninstantiations; i_list; i_list = i_list->next) + { + n -= 1; + TYPE_INSTANTIATION (type, n) = i_list->t; + } + + + /* Copy the field-list to GDB's symbol table */ + TYPE_NFIELDS (type) = nfields; + TYPE_N_BASECLASSES (type) = n_base_classes; + TYPE_FIELDS (type) = (struct field *) + obstack_alloc (&objfile->type_obstack, sizeof (struct field) * nfields); + /* Copy the saved-up fields into the field vector. */ + for (n = nfields, tmp_list = list; tmp_list; tmp_list = tmp_list->next) + { + n -= 1; + TYPE_FIELD (type, n) = tmp_list->field; + } + + /* Copy the "function-field-list" (i.e., the list of member + * functions in the class) to GDB's symbol table + */ + TYPE_NFN_FIELDS (type) = n_fn_fields; + TYPE_NFN_FIELDS_TOTAL (type) = n_fn_fields_total; + TYPE_FN_FIELDLISTS (type) = (struct fn_fieldlist *) + obstack_alloc (&objfile->type_obstack, sizeof (struct fn_fieldlist) * n_fn_fields); + for (n = n_fn_fields; fn_list; fn_list = fn_list->next) + { + n -= 1; + TYPE_FN_FIELDLIST (type, n) = fn_list->field; + } + + /* pai:: FIXME -- perhaps each bitvector should be created individually */ + for (n = nfields, tmp_list = list; tmp_list; tmp_list = tmp_list->next) + { + n -= 1; + if (tmp_list->attributes) + { + need_bitvectors = 1; + break; + } + } + + if (need_bitvectors) + { + /* pai:: this step probably redundant */ + ALLOCATE_CPLUS_STRUCT_TYPE (type); + + TYPE_FIELD_VIRTUAL_BITS (type) = + (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields)); + B_CLRALL (TYPE_FIELD_VIRTUAL_BITS (type), nfields); + + TYPE_FIELD_PRIVATE_BITS (type) = + (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields)); + B_CLRALL (TYPE_FIELD_PRIVATE_BITS (type), nfields); + + TYPE_FIELD_PROTECTED_BITS (type) = + (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields)); + B_CLRALL (TYPE_FIELD_PROTECTED_BITS (type), nfields); + + /* this field vector isn't actually used with HP aCC */ + TYPE_FIELD_IGNORE_BITS (type) = + (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields)); + B_CLRALL (TYPE_FIELD_IGNORE_BITS (type), nfields); + + while (nfields-- > 0) + { + if (B_TST (&(list->attributes), ATTR_VIRTUAL)) + SET_TYPE_FIELD_VIRTUAL (type, nfields); + if (B_TST (&(list->attributes), ATTR_PRIVATE)) + SET_TYPE_FIELD_PRIVATE (type, nfields); + if (B_TST (&(list->attributes), ATTR_PROTECT)) + SET_TYPE_FIELD_PROTECTED (type, nfields); + + list = list->next; + } + } + else + { + TYPE_FIELD_VIRTUAL_BITS (type) = NULL; + TYPE_FIELD_PROTECTED_BITS (type) = NULL; + TYPE_FIELD_PRIVATE_BITS (type) = NULL; + } + + if (has_vtable (type)) + { + /* Allocate space for class runtime information */ + TYPE_RUNTIME_PTR (type) = (struct runtime_info *) xmalloc (sizeof (struct runtime_info)); + /* Set flag for vtable */ + TYPE_VTABLE (type) = 1; + /* The first non-virtual base class with a vtable. */ + TYPE_PRIMARY_BASE (type) = primary_base_class (type); + /* The virtual base list. */ + TYPE_VIRTUAL_BASE_LIST (type) = virtual_base_list (type); + } + else + TYPE_RUNTIME_PTR (type) = NULL; + + /* If this is a local type (C++ - declared inside a function), record file name & line # */ + if (hpread_get_scope_depth (dn_bufp, objfile, 1 /* no need for real depth */ )) + { + TYPE_LOCALTYPE_PTR (type) = (struct local_type_info *) xmalloc (sizeof (struct local_type_info)); + TYPE_LOCALTYPE_FILE (type) = (char *) xmalloc (strlen (current_subfile->name) + 1); + strcpy (TYPE_LOCALTYPE_FILE (type), current_subfile->name); + if (current_subfile->line_vector && (current_subfile->line_vector->nitems > 0)) + TYPE_LOCALTYPE_LINE (type) = current_subfile->line_vector->item[current_subfile->line_vector->nitems - 1].line; + else + TYPE_LOCALTYPE_LINE (type) = 0; + } + else + TYPE_LOCALTYPE_PTR (type) = NULL; + + /* Clear the global saying what template we are in the middle of processing */ + current_template = NULL; + + return type; +} + +/* Adjust the physnames for each static member of a struct + or class type to be something like "A::x"; then various + other pieces of code that do a lookup_symbol on the phyname + work correctly. + TYPE is a pointer to the struct/class type + NAME is a char * (string) which is the class/struct name + Void return */ + +static void +fix_static_member_physnames (struct type *type, char *class_name, + struct objfile *objfile) +{ + int i; + + /* We fix the member names only for classes or structs */ + if (TYPE_CODE (type) != TYPE_CODE_STRUCT) + return; + + for (i = 0; i < TYPE_NFIELDS (type); i++) + if (TYPE_FIELD_STATIC (type, i)) + { + if (TYPE_FIELD_STATIC_PHYSNAME (type, i)) + return; /* physnames are already set */ + + SET_FIELD_PHYSNAME (TYPE_FIELDS (type)[i], + obstack_alloc (&objfile->type_obstack, + strlen (class_name) + strlen (TYPE_FIELD_NAME (type, i)) + 3)); + strcpy (TYPE_FIELD_STATIC_PHYSNAME (type, i), class_name); + strcat (TYPE_FIELD_STATIC_PHYSNAME (type, i), "::"); + strcat (TYPE_FIELD_STATIC_PHYSNAME (type, i), TYPE_FIELD_NAME (type, i)); + } +} + +/* Fix-up the type structure for a CLASS so that the type entry + * for a method (previously marked with a null type in hpread_read_struct_type() + * is set correctly to METHOD. + * OBJFILE is as for other such functions. + * Void return. */ + +static void +fixup_class_method_type (struct type *class, struct type *method, + struct objfile *objfile) +{ + int i, j, k; + + if (!class || !method || !objfile) + return; + + /* Only for types that have methods */ + if ((TYPE_CODE (class) != TYPE_CODE_CLASS) && + (TYPE_CODE (class) != TYPE_CODE_UNION)) + return; + + /* Loop over all methods and find the one marked with a NULL type */ + for (i = 0; i < TYPE_NFN_FIELDS (class); i++) + for (j = 0; j < TYPE_FN_FIELDLIST_LENGTH (class, i); j++) + if (TYPE_FN_FIELD_TYPE (TYPE_FN_FIELDLIST1 (class, i), j) == NULL) + { + /* Set the method type */ + TYPE_FN_FIELD_TYPE (TYPE_FN_FIELDLIST1 (class, i), j) = method; + + /* Break out of both loops -- only one method to fix up in a class */ + goto finish; + } + +finish: + TYPE_FLAGS (class) &= ~TYPE_FLAG_INCOMPLETE; +} + + +/* If we're in the middle of processing a template, get a pointer + * to the Nth template argument. + * An example may make this clearer: + * template <class T1, class T2> class q2 { + * public: + * T1 a; + * T2 b; + * }; + * The type for "a" will be "first template arg" and + * the type for "b" will be "second template arg". + * We need to look these up in order to fill in "a" and "b"'s type. + * This is called from hpread_type_lookup(). + */ +static struct type * +hpread_get_nth_template_arg (struct objfile *objfile, int n) +{ + if (current_template != NULL) + return TYPE_TEMPLATE_ARG (current_template, n).type; + else + return lookup_fundamental_type (objfile, FT_TEMPLATE_ARG); +} + +/* Read in and internalize a TEMPL_ARG (template arg) symbol. */ + +static struct type * +hpread_read_templ_arg_type (dnttpointer hp_type, union dnttentry *dn_bufp, + struct objfile *objfile, char *name) +{ + struct type *type; + + /* See if it's something we've already deal with. */ + type = hpread_alloc_type (hp_type, objfile); + if (TYPE_CODE (type) == TYPE_CODE_TEMPLATE_ARG) + return type; + + /* Nope. Fill in the appropriate fields. */ + TYPE_CODE (type) = TYPE_CODE_TEMPLATE_ARG; + TYPE_LENGTH (type) = 0; + TYPE_NFIELDS (type) = 0; + TYPE_NAME (type) = name; + return type; +} + +/* Read in and internalize a set debug symbol. */ + +static struct type * +hpread_read_set_type (dnttpointer hp_type, union dnttentry *dn_bufp, + struct objfile *objfile) +{ + struct type *type; + + /* See if it's something we've already deal with. */ + type = hpread_alloc_type (hp_type, objfile); + if (TYPE_CODE (type) == TYPE_CODE_SET) + return type; + + /* Nope. Fill in the appropriate fields. */ + TYPE_CODE (type) = TYPE_CODE_SET; + TYPE_LENGTH (type) = dn_bufp->dset.bitlength / 8; + TYPE_NFIELDS (type) = 0; + TYPE_TARGET_TYPE (type) = hpread_type_lookup (dn_bufp->dset.subtype, + objfile); + return type; +} + +/* Read in and internalize an array debug symbol. */ + +static struct type * +hpread_read_array_type (dnttpointer hp_type, union dnttentry *dn_bufp, + struct objfile *objfile) +{ + struct type *type; + + /* Allocate an array type symbol. + * Why no check for already-read here, like in the other + * hpread_read_xxx_type routines? Because it kept us + * from properly determining the size of the array! + */ + type = hpread_alloc_type (hp_type, objfile); + + TYPE_CODE (type) = TYPE_CODE_ARRAY; + + /* Although the hp-symtab.h does not *require* this to be the case, + * GDB is assuming that "arrayisbytes" and "elemisbytes" be consistent. + * I.e., express both array-length and element-length in bits, + * or express both array-length and element-length in bytes. + */ + if (!((dn_bufp->darray.arrayisbytes && dn_bufp->darray.elemisbytes) || + (!dn_bufp->darray.arrayisbytes && !dn_bufp->darray.elemisbytes))) + { + warning ("error in hpread_array_type.\n"); + return NULL; + } + else if (dn_bufp->darray.arraylength == 0x7fffffff) + { + /* The HP debug format represents char foo[]; as an array with + * length 0x7fffffff. Internally GDB wants to represent this + * as an array of length zero. + */ + TYPE_LENGTH (type) = 0; + } + else if (dn_bufp->darray.arrayisbytes) + TYPE_LENGTH (type) = dn_bufp->darray.arraylength; + else /* arraylength is in bits */ + TYPE_LENGTH (type) = dn_bufp->darray.arraylength / 8; + + TYPE_TARGET_TYPE (type) = hpread_type_lookup (dn_bufp->darray.elemtype, + objfile); + + /* The one "field" is used to store the subscript type */ + /* Since C and C++ multi-dimensional arrays are simply represented + * as: array of array of ..., we only need one subscript-type + * per array. This subscript type is typically a subrange of integer. + * If this gets extended to support languages like Pascal, then + * we need to fix this to represent multi-dimensional arrays properly. + */ + TYPE_NFIELDS (type) = 1; + TYPE_FIELDS (type) = (struct field *) + obstack_alloc (&objfile->type_obstack, sizeof (struct field)); + TYPE_FIELD_TYPE (type, 0) = hpread_type_lookup (dn_bufp->darray.indextype, + objfile); + return type; +} + +/* Read in and internalize a subrange debug symbol. */ +static struct type * +hpread_read_subrange_type (dnttpointer hp_type, union dnttentry *dn_bufp, + struct objfile *objfile) +{ + struct type *type; + + /* Is it something we've already dealt with. */ + type = hpread_alloc_type (hp_type, objfile); + if (TYPE_CODE (type) == TYPE_CODE_RANGE) + return type; + + /* Nope, internalize it. */ + TYPE_CODE (type) = TYPE_CODE_RANGE; + TYPE_LENGTH (type) = dn_bufp->dsubr.bitlength / 8; + TYPE_NFIELDS (type) = 2; + TYPE_FIELDS (type) + = (struct field *) obstack_alloc (&objfile->type_obstack, + 2 * sizeof (struct field)); + + if (dn_bufp->dsubr.dyn_low) + TYPE_FIELD_BITPOS (type, 0) = 0; + else + TYPE_FIELD_BITPOS (type, 0) = dn_bufp->dsubr.lowbound; + + if (dn_bufp->dsubr.dyn_high) + TYPE_FIELD_BITPOS (type, 1) = -1; + else + TYPE_FIELD_BITPOS (type, 1) = dn_bufp->dsubr.highbound; + TYPE_TARGET_TYPE (type) = hpread_type_lookup (dn_bufp->dsubr.subtype, + objfile); + return type; +} + +/* struct type * hpread_type_lookup(hp_type, objfile) + * Arguments: + * hp_type: A pointer into the DNTT specifying what type we + * are about to "look up"., or else [for fundamental types + * like int, float, ...] an "immediate" structure describing + * the type. + * objfile: ? + * Return value: A pointer to a "struct type" (representation of a + * type in GDB's internal symbol table - see gdbtypes.h) + * Routine description: + * There are a variety of places when scanning the DNTT when we + * need to interpret a "type" field. The simplest and most basic + * example is when we're processing the symbol table record + * for a data symbol (a SVAR or DVAR record). That has + * a "type" field specifying the type of the data symbol. That + * "type" field is either an "immediate" type specification (for the + * fundamental types) or a DNTT pointer (for more complicated types). + * For the more complicated types, we may or may not have already + * processed the pointed-to type. (Multiple data symbols can of course + * share the same type). + * The job of hpread_type_lookup() is to process this "type" field. + * Most of the real work is done in subroutines. Here we interpret + * the immediate flag. If not immediate, chase the DNTT pointer to + * find our way to the SOM record describing the type, switch on + * the SOM kind, and then call an appropriate subroutine depending + * on what kind of type we are constructing. (e.g., an array type, + * a struct/class type, etc). + */ +static struct type * +hpread_type_lookup (dnttpointer hp_type, struct objfile *objfile) +{ + union dnttentry *dn_bufp; + struct type *tmp_type; + + /* First see if it's a simple builtin type. */ + if (hp_type.dntti.immediate) + { + /* If this is a template argument, the argument number is + * encoded in the bitlength. All other cases, just return + * GDB's representation of this fundamental type. + */ + if (hp_type.dntti.type == HP_TYPE_TEMPLATE_ARG) + return hpread_get_nth_template_arg (objfile, hp_type.dntti.bitlength); + else + return lookup_fundamental_type (objfile, + hpread_type_translate (hp_type)); + } + + /* Not a builtin type. We'll have to read it in. */ + if (hp_type.dnttp.index < LNTT_SYMCOUNT (objfile)) + dn_bufp = hpread_get_lntt (hp_type.dnttp.index, objfile); + else + /* This is a fancy way of returning NULL */ + return lookup_fundamental_type (objfile, FT_VOID); + + switch (dn_bufp->dblock.kind) + { + case DNTT_TYPE_SRCFILE: + case DNTT_TYPE_MODULE: + case DNTT_TYPE_ENTRY: + case DNTT_TYPE_BEGIN: + case DNTT_TYPE_END: + case DNTT_TYPE_IMPORT: + case DNTT_TYPE_LABEL: + case DNTT_TYPE_FPARAM: + case DNTT_TYPE_SVAR: + case DNTT_TYPE_DVAR: + case DNTT_TYPE_CONST: + case DNTT_TYPE_MEMENUM: + case DNTT_TYPE_VARIANT: + case DNTT_TYPE_FILE: + case DNTT_TYPE_WITH: + case DNTT_TYPE_COMMON: + case DNTT_TYPE_COBSTRUCT: + case DNTT_TYPE_XREF: + case DNTT_TYPE_SA: + case DNTT_TYPE_MACRO: + case DNTT_TYPE_BLOCKDATA: + case DNTT_TYPE_CLASS_SCOPE: + case DNTT_TYPE_MEMACCESS: + case DNTT_TYPE_INHERITANCE: + case DNTT_TYPE_OBJECT_ID: + case DNTT_TYPE_FRIEND_CLASS: + case DNTT_TYPE_FRIEND_FUNC: + /* These are not types - something went wrong. */ + /* This is a fancy way of returning NULL */ + return lookup_fundamental_type (objfile, FT_VOID); + + case DNTT_TYPE_FUNCTION: + /* We wind up here when dealing with class member functions + * (called from hpread_read_struct_type(), i.e. when processing + * the class definition itself). + */ + return hpread_read_function_type (hp_type, dn_bufp, objfile, 0); + + case DNTT_TYPE_DOC_FUNCTION: + return hpread_read_doc_function_type (hp_type, dn_bufp, objfile, 0); + + case DNTT_TYPE_TYPEDEF: + { + /* A typedef - chase it down by making a recursive call */ + struct type *structtype = hpread_type_lookup (dn_bufp->dtype.type, + objfile); + + /* The following came from the base hpread.c that we inherited. + * It is WRONG so I have commented it out. - RT + *... + + char *suffix; + suffix = VT (objfile) + dn_bufp->dtype.name; + TYPE_NAME (structtype) = suffix; + + * ... further explanation .... + * + * What we have here is a typedef pointing to a typedef. + * E.g., + * typedef int foo; + * typedef foo fum; + * + * What we desire to build is (these are pictures + * of "struct type"'s): + * + * +---------+ +----------+ +------------+ + * | typedef | | typedef | | fund. type | + * | type| -> | type| -> | | + * | "fum" | | "foo" | | "int" | + * +---------+ +----------+ +------------+ + * + * What this commented-out code is doing is smashing the + * name of pointed-to-type to be the same as the pointed-from + * type. So we wind up with something like: + * + * +---------+ +----------+ +------------+ + * | typedef | | typedef | | fund. type | + * | type| -> | type| -> | | + * | "fum" | | "fum" | | "fum" | + * +---------+ +----------+ +------------+ + * + */ + + return structtype; + } + + case DNTT_TYPE_TAGDEF: + { + /* Just a little different from above. We have to tack on + * an identifier of some kind (struct, union, enum, class, etc). + */ + struct type *structtype = hpread_type_lookup (dn_bufp->dtype.type, + objfile); + char *prefix, *suffix; + suffix = VT (objfile) + dn_bufp->dtype.name; + + /* Lookup the next type in the list. It should be a structure, + * union, class, enum, or template type. + * We will need to attach that to our name. + */ + if (dn_bufp->dtype.type.dnttp.index < LNTT_SYMCOUNT (objfile)) + dn_bufp = hpread_get_lntt (dn_bufp->dtype.type.dnttp.index, objfile); + else + { + complain (&hpread_type_lookup_complaint); + return NULL; + } + + if (dn_bufp->dblock.kind == DNTT_TYPE_STRUCT) + { + prefix = "struct "; + } + else if (dn_bufp->dblock.kind == DNTT_TYPE_UNION) + { + prefix = "union "; + } + else if (dn_bufp->dblock.kind == DNTT_TYPE_CLASS) + { + /* Further field for CLASS saying how it was really declared */ + /* 0==class, 1==union, 2==struct */ + if (dn_bufp->dclass.class_decl == 0) + prefix = "class "; + else if (dn_bufp->dclass.class_decl == 1) + prefix = "union "; + else if (dn_bufp->dclass.class_decl == 2) + prefix = "struct "; + else + prefix = ""; + } + else if (dn_bufp->dblock.kind == DNTT_TYPE_ENUM) + { + prefix = "enum "; + } + else if (dn_bufp->dblock.kind == DNTT_TYPE_TEMPLATE) + { + prefix = "template "; + } + else + { + prefix = ""; + } + + /* Build the correct name. */ + TYPE_NAME (structtype) + = (char *) obstack_alloc (&objfile->type_obstack, + strlen (prefix) + strlen (suffix) + 1); + TYPE_NAME (structtype) = strcpy (TYPE_NAME (structtype), prefix); + TYPE_NAME (structtype) = strcat (TYPE_NAME (structtype), suffix); + TYPE_TAG_NAME (structtype) = suffix; + + /* For classes/structs, we have to set the static member "physnames" + to point to strings like "Class::Member" */ + if (TYPE_CODE (structtype) == TYPE_CODE_STRUCT) + fix_static_member_physnames (structtype, suffix, objfile); + + return structtype; + } + + case DNTT_TYPE_POINTER: + /* Pointer type - call a routine in gdbtypes.c that constructs + * the appropriate GDB type. + */ + return make_pointer_type ( + hpread_type_lookup (dn_bufp->dptr.pointsto, + objfile), + NULL); + + case DNTT_TYPE_REFERENCE: + /* C++ reference type - call a routine in gdbtypes.c that constructs + * the appropriate GDB type. + */ + return make_reference_type ( + hpread_type_lookup (dn_bufp->dreference.pointsto, + objfile), + NULL); + + case DNTT_TYPE_ENUM: + return hpread_read_enum_type (hp_type, dn_bufp, objfile); + case DNTT_TYPE_SET: + return hpread_read_set_type (hp_type, dn_bufp, objfile); + case DNTT_TYPE_SUBRANGE: + return hpread_read_subrange_type (hp_type, dn_bufp, objfile); + case DNTT_TYPE_ARRAY: + return hpread_read_array_type (hp_type, dn_bufp, objfile); + case DNTT_TYPE_STRUCT: + case DNTT_TYPE_UNION: + return hpread_read_struct_type (hp_type, dn_bufp, objfile); + case DNTT_TYPE_FIELD: + return hpread_type_lookup (dn_bufp->dfield.type, objfile); + + case DNTT_TYPE_FUNCTYPE: + /* Here we want to read the function SOMs and return a + * type for it. We get here, for instance, when processing + * pointer-to-function type. + */ + return hpread_read_function_type (hp_type, dn_bufp, objfile, 0); + + case DNTT_TYPE_PTRMEM: + /* Declares a C++ pointer-to-data-member type. + * The "pointsto" field defines the class, + * while the "memtype" field defines the pointed-to-type. + */ + { + struct type *ptrmemtype; + struct type *class_type; + struct type *memtype; + memtype = hpread_type_lookup (dn_bufp->dptrmem.memtype, + objfile), + class_type = hpread_type_lookup (dn_bufp->dptrmem.pointsto, + objfile), + ptrmemtype = alloc_type (objfile); + smash_to_member_type (ptrmemtype, class_type, memtype); + return make_pointer_type (ptrmemtype, NULL); + } + break; + + case DNTT_TYPE_PTRMEMFUNC: + /* Defines a C++ pointer-to-function-member type. + * The "pointsto" field defines the class, + * while the "memtype" field defines the pointed-to-type. + */ + { + struct type *ptrmemtype; + struct type *class_type; + struct type *functype; + struct type *retvaltype; + int nargs; + int i; + class_type = hpread_type_lookup (dn_bufp->dptrmem.pointsto, + objfile); + functype = hpread_type_lookup (dn_bufp->dptrmem.memtype, + objfile); + retvaltype = TYPE_TARGET_TYPE (functype); + nargs = TYPE_NFIELDS (functype); + ptrmemtype = alloc_type (objfile); + + smash_to_method_type (ptrmemtype, class_type, retvaltype, + TYPE_FIELDS (functype), + TYPE_NFIELDS (functype), + 0); + return make_pointer_type (ptrmemtype, NULL); + } + break; + + case DNTT_TYPE_CLASS: + return hpread_read_struct_type (hp_type, dn_bufp, objfile); + + case DNTT_TYPE_GENFIELD: + /* Chase pointer from GENFIELD to FIELD, and make recursive + * call on that. + */ + return hpread_type_lookup (dn_bufp->dgenfield.field, objfile); + + case DNTT_TYPE_VFUNC: + /* C++ virtual function. + * We get here in the course of processing a class type which + * contains virtual functions. Just go through another level + * of indirection to get to the pointed-to function SOM. + */ + return hpread_type_lookup (dn_bufp->dvfunc.funcptr, objfile); + + case DNTT_TYPE_MODIFIER: + /* Check the modifiers and then just make a recursive call on + * the "type" pointed to by the modifier DNTT. + * + * pai:: FIXME -- do we ever want to handle "m_duplicate" and + * "m_void" modifiers? Is static_flag really needed here? + * (m_static used for methods of classes, elsewhere). + */ + tmp_type = make_cv_type (dn_bufp->dmodifier.m_const, + dn_bufp->dmodifier.m_volatile, + hpread_type_lookup (dn_bufp->dmodifier.type, objfile), + 0); + return tmp_type; + + + case DNTT_TYPE_MEMFUNC: + /* Member function. Treat like a function. + * I think we get here in the course of processing a + * pointer-to-member-function type... + */ + return hpread_read_function_type (hp_type, dn_bufp, objfile, 0); + + case DNTT_TYPE_DOC_MEMFUNC: + return hpread_read_doc_function_type (hp_type, dn_bufp, objfile, 0); + + case DNTT_TYPE_TEMPLATE: + /* Template - sort of the header for a template definition, + * which like a class, points to a member list and also points + * to a TEMPLATE_ARG list of type-arguments. + */ + return hpread_read_struct_type (hp_type, dn_bufp, objfile); + + case DNTT_TYPE_TEMPLATE_ARG: + { + char *name; + /* The TEMPLATE record points to an argument list of + * TEMPLATE_ARG records, each of which describes one + * of the type-arguments. + */ + name = VT (objfile) + dn_bufp->dtempl_arg.name; + return hpread_read_templ_arg_type (hp_type, dn_bufp, objfile, name); + } + + case DNTT_TYPE_FUNC_TEMPLATE: + /* We wind up here when processing a TEMPLATE type, + * if the template has member function(s). + * Treat it like a FUNCTION. + */ + return hpread_read_function_type (hp_type, dn_bufp, objfile, 0); + + case DNTT_TYPE_LINK: + /* The LINK record is used to link up templates with instantiations. + * There is no type associated with the LINK record per se. + */ + return lookup_fundamental_type (objfile, FT_VOID); + + /* Also not yet handled... */ + /* case DNTT_TYPE_DYN_ARRAY_DESC: */ + /* case DNTT_TYPE_DESC_SUBRANGE: */ + /* case DNTT_TYPE_BEGIN_EXT: */ + /* case DNTT_TYPE_INLN: */ + /* case DNTT_TYPE_INLN_LIST: */ + /* case DNTT_TYPE_ALIAS: */ + default: + /* A fancy way of returning NULL */ + return lookup_fundamental_type (objfile, FT_VOID); + } +} + +static sltpointer +hpread_record_lines (struct subfile *subfile, sltpointer s_idx, + sltpointer e_idx, struct objfile *objfile, + CORE_ADDR offset) +{ + union sltentry *sl_bufp; + + while (s_idx <= e_idx) + { + sl_bufp = hpread_get_slt (s_idx, objfile); + /* Only record "normal" entries in the SLT. */ + if (sl_bufp->snorm.sltdesc == SLT_NORMAL + || sl_bufp->snorm.sltdesc == SLT_EXIT) + record_line (subfile, sl_bufp->snorm.line, + sl_bufp->snorm.address + offset); + else if (sl_bufp->snorm.sltdesc == SLT_NORMAL_OFFSET) + record_line (subfile, sl_bufp->snormoff.line, + sl_bufp->snormoff.address + offset); + s_idx++; + } + return e_idx; +} + +/* Given a function "f" which is a member of a class, find + * the classname that it is a member of. Used to construct + * the name (e.g., "c::f") which GDB will put in the + * "demangled name" field of the function's symbol. + * Called from hpread_process_one_debug_symbol() + * If "f" is not a member function, return NULL. + */ +char * +class_of (struct type *functype) +{ + struct type *first_param_type; + char *first_param_name; + struct type *pointed_to_type; + char *class_name; + + /* Check that the function has a first argument "this", + * and that "this" is a pointer to a class. If not, + * functype is not a member function, so return NULL. + */ + if (TYPE_NFIELDS (functype) == 0) + return NULL; + first_param_name = TYPE_FIELD_NAME (functype, 0); + if (first_param_name == NULL) + return NULL; /* paranoia */ + if (strcmp (first_param_name, "this")) + return NULL; + first_param_type = TYPE_FIELD_TYPE (functype, 0); + if (first_param_type == NULL) + return NULL; /* paranoia */ + if (TYPE_CODE (first_param_type) != TYPE_CODE_PTR) + return NULL; + + /* Get the thing that "this" points to, check that + * it's a class, and get its class name. + */ + pointed_to_type = TYPE_TARGET_TYPE (first_param_type); + if (pointed_to_type == NULL) + return NULL; /* paranoia */ + if (TYPE_CODE (pointed_to_type) != TYPE_CODE_CLASS) + return NULL; + class_name = TYPE_NAME (pointed_to_type); + if (class_name == NULL) + return NULL; /* paranoia */ + + /* The class name may be of the form "class c", in which case + * we want to strip off the leading "class ". + */ + if (strncmp (class_name, "class ", 6) == 0) + class_name += 6; + + return class_name; +} + +/* Internalize one native debug symbol. + * Called in a loop from hpread_expand_symtab(). + * Arguments: + * dn_bufp: + * name: + * section_offsets: + * objfile: + * text_offset: + * text_size: + * filename: + * index: Index of this symbol + * at_module_boundary_p Pointer to boolean flag to control caller's loop. + */ + +static void +hpread_process_one_debug_symbol (union dnttentry *dn_bufp, char *name, + struct section_offsets *section_offsets, + struct objfile *objfile, CORE_ADDR text_offset, + int text_size, char *filename, int index, + int *at_module_boundary_p) +{ + unsigned long desc; + int type; + CORE_ADDR valu; + int offset = ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile)); + int data_offset = ANOFFSET (section_offsets, SECT_OFF_DATA (objfile)); + union dnttentry *dn_temp; + dnttpointer hp_type; + struct symbol *sym; + struct context_stack *new; + char *class_scope_name; + + /* Allocate one GDB debug symbol and fill in some default values. */ + sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack, + sizeof (struct symbol)); + memset (sym, 0, sizeof (struct symbol)); + SYMBOL_NAME (sym) = obsavestring (name, strlen (name), &objfile->symbol_obstack); + SYMBOL_LANGUAGE (sym) = language_auto; + SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; + SYMBOL_LINE (sym) = 0; + SYMBOL_VALUE (sym) = 0; + SYMBOL_CLASS (sym) = LOC_TYPEDEF; + + /* Just a trick in case the SOM debug symbol is a type definition. + * There are routines that are set up to build a GDB type symbol, given + * a SOM dnttpointer. So we set up a dummy SOM dnttpointer "hp_type". + * This allows us to call those same routines. + */ + hp_type.dnttp.extension = 1; + hp_type.dnttp.immediate = 0; + hp_type.dnttp.global = 0; + hp_type.dnttp.index = index; + + /* This "type" is the type of SOM record. + * Switch on SOM type. + */ + type = dn_bufp->dblock.kind; + switch (type) + { + case DNTT_TYPE_SRCFILE: + /* This type of symbol indicates from which source file or + * include file any following data comes. It may indicate: + * + * o The start of an entirely new source file (and thus + * a new module) + * + * o The start of a different source file due to #include + * + * o The end of an include file and the return to the original + * file. Thus if "foo.c" includes "bar.h", we see first + * a SRCFILE for foo.c, then one for bar.h, and then one for + * foo.c again. + * + * If it indicates the start of a new module then we must + * finish the symbol table of the previous module + * (if any) and start accumulating a new symbol table. + */ + + valu = text_offset; + if (!last_source_file) + { + /* + * A note on "last_source_file": this is a char* pointing + * to the actual file name. "start_symtab" sets it, + * "end_symtab" clears it. + * + * So if "last_source_file" is NULL, then either this is + * the first record we are looking at, or a previous call + * to "end_symtab()" was made to close out the previous + * module. Since we're now quitting the scan loop when we + * see a MODULE END record, we should never get here, except + * in the case that we're not using the quick look-up tables + * and have to use the old system as a fall-back. + */ + start_symtab (name, NULL, valu); + record_debugformat ("HP"); + SL_INDEX (objfile) = dn_bufp->dsfile.address; + } + + else + { + /* Either a new include file, or a SRCFILE record + * saying we are back in the main source (or out of + * a nested include file) again. + */ + SL_INDEX (objfile) = hpread_record_lines (current_subfile, + SL_INDEX (objfile), + dn_bufp->dsfile.address, + objfile, offset); + } + + /* A note on "start_subfile". This routine will check + * the name we pass it and look for an existing subfile + * of that name. There's thus only one sub-file for the + * actual source (e.g. for "foo.c" in foo.c), despite the + * fact that we'll see lots of SRCFILE entries for foo.c + * inside foo.c. + */ + start_subfile (name, NULL); + break; + + case DNTT_TYPE_MODULE: + /* + * We no longer ignore DNTT_TYPE_MODULE symbols. The module + * represents the meaningful semantic structure of a compilation + * unit. We expect to start the psymtab-to-symtab expansion + * looking at a MODULE entry, and to end it at the corresponding + * END MODULE entry. + * + *--Begin outdated comments + * + * This record signifies the start of a new source module + * In C/C++ there is no explicit "module" construct in the language, + * but each compilation unit is implicitly a module and they + * do emit the DNTT_TYPE_MODULE records. + * The end of the module is marked by a matching DNTT_TYPE_END record. + * + * The reason GDB gets away with ignoring the DNTT_TYPE_MODULE record + * is it notices the DNTT_TYPE_END record for the previous + * module (see comments under DNTT_TYPE_END case), and then treats + * the next DNTT_TYPE_SRCFILE record as if it were the module-start record. + * (i.e., it makes a start_symtab() call). + * This scheme seems a little convoluted, but I'll leave it + * alone on the principle "if it ain't broke don't fix + * it". (RT). + * + *-- End outdated comments + */ + + valu = text_offset; + if (!last_source_file) + { + /* Start of a new module. We know this because "last_source_file" + * is NULL, which can only happen the first time or if we just + * made a call to end_symtab() to close out the previous module. + */ + start_symtab (name, NULL, valu); + SL_INDEX (objfile) = dn_bufp->dmodule.address; + } + else + { + /* This really shouldn't happen if we're using the quick + * look-up tables, as it would mean we'd scanned past an + * END MODULE entry. But if we're not using the tables, + * we started the module on the SRCFILE entry, so it's ok. + * For now, accept this. + */ + /* warning( "Error expanding psymtab, missed module end, found entry for %s", + * name ); + */ + *at_module_boundary_p = -1; + } + + start_subfile (name, NULL); + break; + + case DNTT_TYPE_FUNCTION: + case DNTT_TYPE_ENTRY: + /* A function or secondary entry point. */ + valu = dn_bufp->dfunc.lowaddr + offset; + + /* Record lines up to this point. */ + SL_INDEX (objfile) = hpread_record_lines (current_subfile, + SL_INDEX (objfile), + dn_bufp->dfunc.address, + objfile, offset); + + WITHIN_FUNCTION (objfile) = 1; + CURRENT_FUNCTION_VALUE (objfile) = valu; + + /* Stack must be empty now. */ + if (context_stack_depth != 0) + complain (&lbrac_unmatched_complaint, (char *) symnum); + new = push_context (0, valu); + + /* Built a type for the function. This includes processing + * the symbol records for the function parameters. + */ + SYMBOL_CLASS (sym) = LOC_BLOCK; + SYMBOL_TYPE (sym) = hpread_read_function_type (hp_type, dn_bufp, objfile, 1); + + /* The "SYMBOL_NAME" field is expected to be the mangled name + * (if any), which we get from the "alias" field of the SOM record + * if that exists. + */ + if ((dn_bufp->dfunc.language == HP_LANGUAGE_CPLUSPLUS) && + dn_bufp->dfunc.alias && /* has an alias */ + *(char *) (VT (objfile) + dn_bufp->dfunc.alias)) /* not a null string */ + SYMBOL_NAME (sym) = VT (objfile) + dn_bufp->dfunc.alias; + else + SYMBOL_NAME (sym) = VT (objfile) + dn_bufp->dfunc.name; + + /* Special hack to get around HP compilers' insistence on + * reporting "main" as "_MAIN_" for C/C++ */ + if ((strcmp (SYMBOL_NAME (sym), "_MAIN_") == 0) && + (strcmp (VT (objfile) + dn_bufp->dfunc.name, "main") == 0)) + SYMBOL_NAME (sym) = VT (objfile) + dn_bufp->dfunc.name; + + /* The SYMBOL_CPLUS_DEMANGLED_NAME field is expected to + * be the demangled name. + */ + if (dn_bufp->dfunc.language == HP_LANGUAGE_CPLUSPLUS) + { + /* SYMBOL_INIT_DEMANGLED_NAME is a macro which winds up + * calling the demangler in libiberty (cplus_demangle()) to + * do the job. This generally does the job, even though + * it's intended for the GNU compiler and not the aCC compiler + * Note that SYMBOL_INIT_DEMANGLED_NAME calls the + * demangler with arguments DMGL_PARAMS | DMGL_ANSI. + * Generally, we don't want params when we display + * a demangled name, but when I took out the DMGL_PARAMS, + * some things broke, so I'm leaving it in here, and + * working around the issue in stack.c. - RT + */ + SYMBOL_INIT_DEMANGLED_NAME (sym, &objfile->symbol_obstack); + if ((SYMBOL_NAME (sym) == VT (objfile) + dn_bufp->dfunc.alias) && + (!SYMBOL_CPLUS_DEMANGLED_NAME (sym))) + { + + /* Well, the symbol name is mangled, but the + * demangler in libiberty failed so the demangled + * field is still NULL. Try to + * do the job ourselves based on the "name" field + * in the SOM record. A complication here is that + * the name field contains only the function name + * (like "f"), whereas we want the class qualification + * (as in "c::f"). Try to reconstruct that. + */ + char *basename; + char *classname; + char *dem_name; + basename = VT (objfile) + dn_bufp->dfunc.name; + classname = class_of (SYMBOL_TYPE (sym)); + if (classname) + { + dem_name = xmalloc (strlen (basename) + strlen (classname) + 3); + strcpy (dem_name, classname); + strcat (dem_name, "::"); + strcat (dem_name, basename); + SYMBOL_CPLUS_DEMANGLED_NAME (sym) = dem_name; + SYMBOL_LANGUAGE (sym) = language_cplus; + } + } + } + + /* Add the function symbol to the list of symbols in this blockvector */ + if (dn_bufp->dfunc.global) + add_symbol_to_list (sym, &global_symbols); + else + add_symbol_to_list (sym, &file_symbols); + new->name = sym; + + /* Search forward to the next BEGIN and also read + * in the line info up to that point. + * Not sure why this is needed. + * In HP FORTRAN this code is harmful since there + * may not be a BEGIN after the FUNCTION. + * So I made it C/C++ specific. - RT + */ + if (dn_bufp->dfunc.language == HP_LANGUAGE_C || + dn_bufp->dfunc.language == HP_LANGUAGE_CPLUSPLUS) + { + while (dn_bufp->dblock.kind != DNTT_TYPE_BEGIN) + { + dn_bufp = hpread_get_lntt (++index, objfile); + if (dn_bufp->dblock.extension) + continue; + } + SL_INDEX (objfile) = hpread_record_lines (current_subfile, + SL_INDEX (objfile), + dn_bufp->dbegin.address, + objfile, offset); + SYMBOL_LINE (sym) = hpread_get_line (dn_bufp->dbegin.address, objfile); + } + record_line (current_subfile, SYMBOL_LINE (sym), valu); + break; + + case DNTT_TYPE_DOC_FUNCTION: + valu = dn_bufp->ddocfunc.lowaddr + offset; + + /* Record lines up to this point. */ + SL_INDEX (objfile) = hpread_record_lines (current_subfile, + SL_INDEX (objfile), + dn_bufp->ddocfunc.address, + objfile, offset); + + WITHIN_FUNCTION (objfile) = 1; + CURRENT_FUNCTION_VALUE (objfile) = valu; + /* Stack must be empty now. */ + if (context_stack_depth != 0) + complain (&lbrac_unmatched_complaint, (char *) symnum); + new = push_context (0, valu); + + /* Built a type for the function. This includes processing + * the symbol records for the function parameters. + */ + SYMBOL_CLASS (sym) = LOC_BLOCK; + SYMBOL_TYPE (sym) = hpread_read_doc_function_type (hp_type, dn_bufp, objfile, 1); + + /* The "SYMBOL_NAME" field is expected to be the mangled name + * (if any), which we get from the "alias" field of the SOM record + * if that exists. + */ + if ((dn_bufp->ddocfunc.language == HP_LANGUAGE_CPLUSPLUS) && + dn_bufp->ddocfunc.alias && /* has an alias */ + *(char *) (VT (objfile) + dn_bufp->ddocfunc.alias)) /* not a null string */ + SYMBOL_NAME (sym) = VT (objfile) + dn_bufp->ddocfunc.alias; + else + SYMBOL_NAME (sym) = VT (objfile) + dn_bufp->ddocfunc.name; + + /* Special hack to get around HP compilers' insistence on + * reporting "main" as "_MAIN_" for C/C++ */ + if ((strcmp (SYMBOL_NAME (sym), "_MAIN_") == 0) && + (strcmp (VT (objfile) + dn_bufp->ddocfunc.name, "main") == 0)) + SYMBOL_NAME (sym) = VT (objfile) + dn_bufp->ddocfunc.name; + + if (dn_bufp->ddocfunc.language == HP_LANGUAGE_CPLUSPLUS) + { + + /* SYMBOL_INIT_DEMANGLED_NAME is a macro which winds up + * calling the demangler in libiberty (cplus_demangle()) to + * do the job. This generally does the job, even though + * it's intended for the GNU compiler and not the aCC compiler + * Note that SYMBOL_INIT_DEMANGLED_NAME calls the + * demangler with arguments DMGL_PARAMS | DMGL_ANSI. + * Generally, we don't want params when we display + * a demangled name, but when I took out the DMGL_PARAMS, + * some things broke, so I'm leaving it in here, and + * working around the issue in stack.c. - RT + */ + SYMBOL_INIT_DEMANGLED_NAME (sym, &objfile->symbol_obstack); + + if ((SYMBOL_NAME (sym) == VT (objfile) + dn_bufp->ddocfunc.alias) && + (!SYMBOL_CPLUS_DEMANGLED_NAME (sym))) + { + + /* Well, the symbol name is mangled, but the + * demangler in libiberty failed so the demangled + * field is still NULL. Try to + * do the job ourselves based on the "name" field + * in the SOM record. A complication here is that + * the name field contains only the function name + * (like "f"), whereas we want the class qualification + * (as in "c::f"). Try to reconstruct that. + */ + char *basename; + char *classname; + char *dem_name; + basename = VT (objfile) + dn_bufp->ddocfunc.name; + classname = class_of (SYMBOL_TYPE (sym)); + if (classname) + { + dem_name = xmalloc (strlen (basename) + strlen (classname) + 3); + strcpy (dem_name, classname); + strcat (dem_name, "::"); + strcat (dem_name, basename); + SYMBOL_CPLUS_DEMANGLED_NAME (sym) = dem_name; + SYMBOL_LANGUAGE (sym) = language_cplus; + } + } + } + + /* Add the function symbol to the list of symbols in this blockvector */ + if (dn_bufp->ddocfunc.global) + add_symbol_to_list (sym, &global_symbols); + else + add_symbol_to_list (sym, &file_symbols); + new->name = sym; + + /* Search forward to the next BEGIN and also read + * in the line info up to that point. + * Not sure why this is needed. + * In HP FORTRAN this code is harmful since there + * may not be a BEGIN after the FUNCTION. + * So I made it C/C++ specific. - RT + */ + if (dn_bufp->ddocfunc.language == HP_LANGUAGE_C || + dn_bufp->ddocfunc.language == HP_LANGUAGE_CPLUSPLUS) + { + while (dn_bufp->dblock.kind != DNTT_TYPE_BEGIN) + { + dn_bufp = hpread_get_lntt (++index, objfile); + if (dn_bufp->dblock.extension) + continue; + } + SL_INDEX (objfile) = hpread_record_lines (current_subfile, + SL_INDEX (objfile), + dn_bufp->dbegin.address, + objfile, offset); + SYMBOL_LINE (sym) = hpread_get_line (dn_bufp->dbegin.address, objfile); + } + record_line (current_subfile, SYMBOL_LINE (sym), valu); + break; + + case DNTT_TYPE_BEGIN: + /* Begin a new scope. */ + if (context_stack_depth == 1 /* this means we're at function level */ && + context_stack[0].name != NULL /* this means it's a function */ && + context_stack[0].depth == 0 /* this means it's the first BEGIN + we've seen after the FUNCTION */ + ) + { + /* This is the first BEGIN after a FUNCTION. + * We ignore this one, since HP compilers always insert + * at least one BEGIN, i.e. it's: + * + * FUNCTION + * argument symbols + * BEGIN + * local symbols + * (possibly nested BEGIN ... END's if there are inner { } blocks) + * END + * END + * + * By ignoring this first BEGIN, the local symbols get treated + * as belonging to the function scope, and "print func::local_sym" + * works (which is what we want). + */ + + /* All we do here is increase the depth count associated with + * the FUNCTION entry in the context stack. This ensures that + * the next BEGIN we see (if any), representing a real nested { } + * block, will get processed. + */ + + context_stack[0].depth++; + + } + else + { + + /* Record lines up to this SLT pointer. */ + SL_INDEX (objfile) = hpread_record_lines (current_subfile, + SL_INDEX (objfile), + dn_bufp->dbegin.address, + objfile, offset); + /* Calculate start address of new scope */ + valu = hpread_get_location (dn_bufp->dbegin.address, objfile); + valu += offset; /* Relocate for dynamic loading */ + /* We use the scope start DNTT index as nesting depth identifier! */ + desc = hpread_get_scope_start (dn_bufp->dbegin.address, objfile); + new = push_context (desc, valu); + } + break; + + case DNTT_TYPE_END: + /* End a scope. */ + + /* Valid end kinds are: + * MODULE + * FUNCTION + * WITH + * COMMON + * BEGIN + * CLASS_SCOPE + */ + + SL_INDEX (objfile) = hpread_record_lines (current_subfile, + SL_INDEX (objfile), + dn_bufp->dend.address, + objfile, offset); + switch (dn_bufp->dend.endkind) + { + case DNTT_TYPE_MODULE: + /* Ending a module ends the symbol table for that module. + * Calling end_symtab() has the side effect of clearing the + * last_source_file pointer, which in turn signals + * process_one_debug_symbol() to treat the next DNTT_TYPE_SRCFILE + * record as a module-begin. + */ + valu = text_offset + text_size + offset; + + /* Tell our caller that we're done with expanding the + * debug information for a module. + */ + *at_module_boundary_p = 1; + + /* Don't do this, as our caller will do it! + + * (void) end_symtab (valu, objfile, 0); + */ + break; + + case DNTT_TYPE_FUNCTION: + /* Ending a function, well, ends the function's scope. */ + dn_temp = hpread_get_lntt (dn_bufp->dend.beginscope.dnttp.index, + objfile); + valu = dn_temp->dfunc.hiaddr + offset; + /* Insert func params into local list */ + merge_symbol_lists (¶m_symbols, &local_symbols); + new = pop_context (); + /* Make a block for the local symbols within. */ + finish_block (new->name, &local_symbols, new->old_blocks, + new->start_addr, valu, objfile); + WITHIN_FUNCTION (objfile) = 0; /* This may have to change for Pascal */ + local_symbols = new->locals; + param_symbols = new->params; + break; + + case DNTT_TYPE_BEGIN: + if (context_stack_depth == 1 && + context_stack[0].name != NULL && + context_stack[0].depth == 1) + { + /* This is the END corresponding to the + * BEGIN which we ignored - see DNTT_TYPE_BEGIN case above. + */ + context_stack[0].depth--; + } + else + { + /* Ending a local scope. */ + valu = hpread_get_location (dn_bufp->dend.address, objfile); + /* Why in the hell is this needed? */ + valu += offset + 9; /* Relocate for dynamic loading */ + new = pop_context (); + desc = dn_bufp->dend.beginscope.dnttp.index; + if (desc != new->depth) + complain (&lbrac_mismatch_complaint, (char *) symnum); + + /* Make a block for the local symbols within. */ + finish_block (new->name, &local_symbols, new->old_blocks, + new->start_addr, valu, objfile); + local_symbols = new->locals; + param_symbols = new->params; + } + break; + + case DNTT_TYPE_WITH: + /* Since we ignore the DNTT_TYPE_WITH that starts the scope, + * we can ignore the DNTT_TYPE_END that ends it. + */ + break; + + case DNTT_TYPE_COMMON: + /* End a FORTRAN common block. We don't currently handle these */ + complain (&hpread_unhandled_end_common_complaint); + break; + + case DNTT_TYPE_CLASS_SCOPE: + + /* pai: FIXME Not handling nested classes for now -- must + * maintain a stack */ + class_scope_name = NULL; + +#if 0 + /* End a class scope */ + valu = hpread_get_location (dn_bufp->dend.address, objfile); + /* Why in the hell is this needed? */ + valu += offset + 9; /* Relocate for dynamic loading */ + new = pop_context (); + desc = dn_bufp->dend.beginscope.dnttp.index; + if (desc != new->depth) + complain (&lbrac_mismatch_complaint, (char *) symnum); + /* Make a block for the local symbols within. */ + finish_block (new->name, &local_symbols, new->old_blocks, + new->start_addr, valu, objfile); + local_symbols = new->locals; + param_symbols = new->params; +#endif + break; + + default: + complain (&hpread_unexpected_end_complaint); + break; + } + break; + + /* DNTT_TYPE_IMPORT is not handled */ + + case DNTT_TYPE_LABEL: + SYMBOL_NAMESPACE (sym) = LABEL_NAMESPACE; + break; + + case DNTT_TYPE_FPARAM: + /* Function parameters. */ + /* Note 1: This code was present in the 4.16 sources, and then + removed, because fparams are handled in + hpread_read_function_type(). However, while fparam symbols + are indeed handled twice, this code here cannot be removed + because then they don't get added to the local symbol list of + the function's code block, which leads to a failure to look + up locals, "this"-relative member names, etc. So I've put + this code back in. pai/1997-07-21 */ + /* Note 2: To fix a defect, we stopped adding FPARAMS to local_symbols + in hpread_read_function_type(), so FPARAMS had to be handled + here. I changed the location to be the appropriate argument + kinds rather than LOC_LOCAL. pai/1997-08-08 */ + /* Note 3: Well, the fix in Note 2 above broke argument printing + in traceback frames, and further it makes assumptions about the + order of the FPARAM entries from HP compilers (cc and aCC in particular + generate them in reverse orders -- fixing one breaks for the other). + So I've added code in hpread_read_function_type() to add fparams + to a param_symbols list for the current context level. These are + then merged into local_symbols when a function end is reached. + pai/1997-08-11 */ + + break; /* do nothing; handled in hpread_read_function_type() */ + +#if 0 /* Old code */ + if (dn_bufp->dfparam.regparam) + SYMBOL_CLASS (sym) = LOC_REGISTER; + else if (dn_bufp->dfparam.indirect) + SYMBOL_CLASS (sym) = LOC_REF_ARG; + else + SYMBOL_CLASS (sym) = LOC_ARG; + SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; + if (dn_bufp->dfparam.copyparam) + { + SYMBOL_VALUE (sym) = dn_bufp->dfparam.location; +#ifdef HPREAD_ADJUST_STACK_ADDRESS + SYMBOL_VALUE (sym) + += HPREAD_ADJUST_STACK_ADDRESS (CURRENT_FUNCTION_VALUE (objfile)); +#endif + } + else + SYMBOL_VALUE (sym) = dn_bufp->dfparam.location; + SYMBOL_TYPE (sym) = hpread_type_lookup (dn_bufp->dfparam.type, objfile); + add_symbol_to_list (sym, &fparam_symbols); + break; +#endif + + case DNTT_TYPE_SVAR: + /* Static variables. */ + SYMBOL_CLASS (sym) = LOC_STATIC; + + /* Note: There is a case that arises with globals in shared + * libraries where we need to set the address to LOC_INDIRECT. + * This case is if you have a global "g" in one library, and + * it is referenced "extern <type> g;" in another library. + * If we're processing the symbols for the referencing library, + * we'll see a global "g", but in this case the address given + * in the symbol table contains a pointer to the real "g". + * We use the storage class LOC_INDIRECT to indicate this. RT + */ + if (is_in_import_list (SYMBOL_NAME (sym), objfile)) + SYMBOL_CLASS (sym) = LOC_INDIRECT; + + SYMBOL_VALUE_ADDRESS (sym) = dn_bufp->dsvar.location + data_offset; + SYMBOL_TYPE (sym) = hpread_type_lookup (dn_bufp->dsvar.type, objfile); + + if (dn_bufp->dsvar.global) + add_symbol_to_list (sym, &global_symbols); + + else if (WITHIN_FUNCTION (objfile)) + add_symbol_to_list (sym, &local_symbols); + + else + add_symbol_to_list (sym, &file_symbols); + + if (dn_bufp->dsvar.thread_specific) + { + /* Thread-local variable. + */ + SYMBOL_CLASS (sym) = LOC_THREAD_LOCAL_STATIC; + SYMBOL_BASEREG (sym) = CR27_REGNUM; + + if (objfile->flags & OBJF_SHARED) + { + /* + * This variable is not only thread local but + * in a shared library. + * + * Alas, the shared lib structures are private + * to "somsolib.c". But C lets us point to one. + */ + struct so_list *so; + + if (objfile->obj_private == NULL) + error ("Internal error in reading shared library information."); + + so = ((obj_private_data_t *) (objfile->obj_private))->so_info; + if (so == NULL) + error ("Internal error in reading shared library information."); + + /* Thread-locals in shared libraries do NOT have the + * standard offset ("data_offset"), so we re-calculate + * where to look for this variable, using a call-back + * to interpret the private shared-library data. + */ + SYMBOL_VALUE_ADDRESS (sym) = dn_bufp->dsvar.location + + so_lib_thread_start_addr (so); + } + } + break; + + case DNTT_TYPE_DVAR: + /* Dynamic variables. */ + if (dn_bufp->ddvar.regvar) + SYMBOL_CLASS (sym) = LOC_REGISTER; + else + SYMBOL_CLASS (sym) = LOC_LOCAL; + + SYMBOL_VALUE (sym) = dn_bufp->ddvar.location; +#ifdef HPREAD_ADJUST_STACK_ADDRESS + SYMBOL_VALUE (sym) + += HPREAD_ADJUST_STACK_ADDRESS (CURRENT_FUNCTION_VALUE (objfile)); +#endif + SYMBOL_TYPE (sym) = hpread_type_lookup (dn_bufp->ddvar.type, objfile); + if (dn_bufp->ddvar.global) + add_symbol_to_list (sym, &global_symbols); + else if (WITHIN_FUNCTION (objfile)) + add_symbol_to_list (sym, &local_symbols); + else + add_symbol_to_list (sym, &file_symbols); + break; + + case DNTT_TYPE_CONST: + /* A constant (pascal?). */ + SYMBOL_CLASS (sym) = LOC_CONST; + SYMBOL_VALUE (sym) = dn_bufp->dconst.location; + SYMBOL_TYPE (sym) = hpread_type_lookup (dn_bufp->dconst.type, objfile); + if (dn_bufp->dconst.global) + add_symbol_to_list (sym, &global_symbols); + else if (WITHIN_FUNCTION (objfile)) + add_symbol_to_list (sym, &local_symbols); + else + add_symbol_to_list (sym, &file_symbols); + break; + + case DNTT_TYPE_TYPEDEF: + /* A typedef. We do want to process these, since a name is + * added to the namespace for the typedef'ed name. + */ + SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; + SYMBOL_TYPE (sym) = hpread_type_lookup (dn_bufp->dtype.type, objfile); + if (dn_bufp->dtype.global) + add_symbol_to_list (sym, &global_symbols); + else if (WITHIN_FUNCTION (objfile)) + add_symbol_to_list (sym, &local_symbols); + else + add_symbol_to_list (sym, &file_symbols); + break; + + case DNTT_TYPE_TAGDEF: + { + int global = dn_bufp->dtag.global; + /* Structure, union, enum, template, or class tag definition */ + /* We do want to process these, since a name is + * added to the namespace for the tag name (and if C++ class, + * for the typename also). + */ + SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE; + + /* The tag contains in its "type" field a pointer to the + * DNTT_TYPE_STRUCT, DNTT_TYPE_UNION, DNTT_TYPE_ENUM, + * DNTT_TYPE_CLASS or DNTT_TYPE_TEMPLATE + * record that actually defines the type. + */ + SYMBOL_TYPE (sym) = hpread_type_lookup (dn_bufp->dtype.type, objfile); + TYPE_NAME (sym->type) = SYMBOL_NAME (sym); + TYPE_TAG_NAME (sym->type) = SYMBOL_NAME (sym); + if (dn_bufp->dtag.global) + add_symbol_to_list (sym, &global_symbols); + else if (WITHIN_FUNCTION (objfile)) + add_symbol_to_list (sym, &local_symbols); + else + add_symbol_to_list (sym, &file_symbols); + + /* If this is a C++ class, then we additionally + * need to define a typedef for the + * class type. E.g., so that the name "c" becomes visible as + * a type name when the user says "class c { ... }". + * In order to figure this out, we need to chase down the "type" + * field to get to the DNTT_TYPE_CLASS record. + * + * We also add the typename for ENUM. Though this isn't + * strictly correct, it is necessary because of the debug info + * generated by the aCC compiler, in which we cannot + * distinguish between: + * enum e { ... }; + * and + * typedef enum { ... } e; + * I.e., the compiler emits the same debug info for the above + * two cases, in both cases "e" appearing as a tagdef. + * Therefore go ahead and generate the typename so that + * "ptype e" will work in the above cases. + * + * We also add the typename for TEMPLATE, so as to allow "ptype t" + * when "t" is a template name. + */ + if (dn_bufp->dtype.type.dnttp.index < LNTT_SYMCOUNT (objfile)) + dn_bufp = hpread_get_lntt (dn_bufp->dtag.type.dnttp.index, objfile); + else + { + complain (&hpread_tagdef_complaint); + return; + } + if (dn_bufp->dblock.kind == DNTT_TYPE_CLASS || + dn_bufp->dblock.kind == DNTT_TYPE_ENUM || + dn_bufp->dblock.kind == DNTT_TYPE_TEMPLATE) + { + struct symbol *newsym; + + newsym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack, + sizeof (struct symbol)); + memset (newsym, 0, sizeof (struct symbol)); + SYMBOL_NAME (newsym) = name; + SYMBOL_LANGUAGE (newsym) = language_auto; + SYMBOL_NAMESPACE (newsym) = VAR_NAMESPACE; + SYMBOL_LINE (newsym) = 0; + SYMBOL_VALUE (newsym) = 0; + SYMBOL_CLASS (newsym) = LOC_TYPEDEF; + SYMBOL_TYPE (newsym) = sym->type; + if (global) + add_symbol_to_list (newsym, &global_symbols); + else if (WITHIN_FUNCTION (objfile)) + add_symbol_to_list (newsym, &local_symbols); + else + add_symbol_to_list (newsym, &file_symbols); + } + } + break; + + case DNTT_TYPE_POINTER: + /* Declares a pointer type. Should not be necessary to do anything + * with the type at this level; these are processed + * at the hpread_type_lookup() level. + */ + break; + + case DNTT_TYPE_ENUM: + /* Declares an enum type. Should not be necessary to do anything + * with the type at this level; these are processed + * at the hpread_type_lookup() level. + */ + break; + + case DNTT_TYPE_MEMENUM: + /* Member of enum */ + /* Ignored at this level, but hpread_read_enum_type() will take + * care of walking the list of enumeration members. + */ + break; + + case DNTT_TYPE_SET: + /* Declares a set type. Should not be necessary to do anything + * with the type at this level; these are processed + * at the hpread_type_lookup() level. + */ + break; + + case DNTT_TYPE_SUBRANGE: + /* Declares a subrange type. Should not be necessary to do anything + * with the type at this level; these are processed + * at the hpread_type_lookup() level. + */ + break; + + case DNTT_TYPE_ARRAY: + /* Declares an array type. Should not be necessary to do anything + * with the type at this level; these are processed + * at the hpread_type_lookup() level. + */ + break; + + case DNTT_TYPE_STRUCT: + case DNTT_TYPE_UNION: + /* Declares an struct/union type. + * Should not be necessary to do anything + * with the type at this level; these are processed + * at the hpread_type_lookup() level. + */ + break; + + case DNTT_TYPE_FIELD: + /* Structure/union/class field */ + /* Ignored at this level, but hpread_read_struct_type() will take + * care of walking the list of structure/union/class members. + */ + break; + + /* DNTT_TYPE_VARIANT is not handled by GDB */ + + /* DNTT_TYPE_FILE is not handled by GDB */ + + case DNTT_TYPE_FUNCTYPE: + /* Function type */ + /* Ignored at this level, handled within hpread_type_lookup() */ + break; + + case DNTT_TYPE_WITH: + /* This is emitted within methods to indicate "with <class>" + * scoping rules (i.e., indicate that the class data members + * are directly visible). + * However, since GDB already infers this by looking at the + * "this" argument, interpreting the DNTT_TYPE_WITH + * symbol record is unnecessary. + */ + break; + + case DNTT_TYPE_COMMON: + /* FORTRAN common. Not yet handled. */ + complain (&hpread_unhandled_common_complaint); + break; + + /* DNTT_TYPE_COBSTRUCT is not handled by GDB. */ + /* DNTT_TYPE_XREF is not handled by GDB. */ + /* DNTT_TYPE_SA is not handled by GDB. */ + /* DNTT_TYPE_MACRO is not handled by GDB */ + + case DNTT_TYPE_BLOCKDATA: + /* Not sure what this is - part of FORTRAN support maybe? + * Anyway, not yet handled. + */ + complain (&hpread_unhandled_blockdata_complaint); + break; + + case DNTT_TYPE_CLASS_SCOPE: + + + + /* The compiler brackets member functions with a CLASS_SCOPE/END + * pair of records, presumably to put them in a different scope + * from the module scope where they are normally defined. + * E.g., in the situation: + * void f() { ... } + * void c::f() { ...} + * The member function "c::f" will be bracketed by a CLASS_SCOPE/END. + * This causes "break f" at the module level to pick the + * the file-level function f(), not the member function + * (which needs to be referenced via "break c::f"). + * + * Here we record the class name to generate the demangled names of + * member functions later. + * + * FIXME Not being used now for anything -- cplus_demangle seems + * enough for getting the class-qualified names of functions. We + * may need this for handling nested classes and types. */ + + /* pai: FIXME Not handling nested classes for now -- need to + * maintain a stack */ + + dn_temp = hpread_get_lntt (dn_bufp->dclass_scope.type.dnttp.index, objfile); + if (dn_temp->dblock.kind == DNTT_TYPE_TAGDEF) + class_scope_name = VT (objfile) + dn_temp->dtag.name; + else + class_scope_name = NULL; + +#if 0 + + /* Begin a new scope. */ + SL_INDEX (objfile) = hpread_record_lines (current_subfile, + SL_INDEX (objfile), + dn_bufp->dclass_scope.address, + objfile, offset); + valu = hpread_get_location (dn_bufp->dclass_scope.address, objfile); + valu += offset; /* Relocate for dynamic loading */ + desc = hpread_get_scope_start (dn_bufp->dclass_scope.address, objfile); + /* We use the scope start DNTT index as the nesting depth identifier! */ + new = push_context (desc, valu); +#endif + break; + + case DNTT_TYPE_REFERENCE: + /* Declares a C++ reference type. Should not be necessary to do anything + * with the type at this level; these are processed + * at the hpread_type_lookup() level. + */ + break; + + case DNTT_TYPE_PTRMEM: + /* Declares a C++ pointer-to-data-member type. This does not + * need to be handled at this level; being a type description it + * is instead handled at the hpread_type_lookup() level. + */ + break; + + case DNTT_TYPE_PTRMEMFUNC: + /* Declares a C++ pointer-to-function-member type. This does not + * need to be handled at this level; being a type description it + * is instead handled at the hpread_type_lookup() level. + */ + break; + + case DNTT_TYPE_CLASS: + /* Declares a class type. + * Should not be necessary to do anything + * with the type at this level; these are processed + * at the hpread_type_lookup() level. + */ + break; + + case DNTT_TYPE_GENFIELD: + /* I believe this is used for class member functions */ + /* Ignored at this level, but hpread_read_struct_type() will take + * care of walking the list of class members. + */ + break; + + case DNTT_TYPE_VFUNC: + /* Virtual function */ + /* This does not have to be handled at this level; handled in + * the course of processing class symbols. + */ + break; + + case DNTT_TYPE_MEMACCESS: + /* DDE ignores this symbol table record. + * It has something to do with "modified access" to class members. + * I'll assume we can safely ignore it too. + */ + break; + + case DNTT_TYPE_INHERITANCE: + /* These don't have to be handled here, since they are handled + * within hpread_read_struct_type() in the process of constructing + * a class type. + */ + break; + + case DNTT_TYPE_FRIEND_CLASS: + case DNTT_TYPE_FRIEND_FUNC: + /* These can safely be ignored, as GDB doesn't need this + * info. DDE only uses it in "describe". We may later want + * to extend GDB's "ptype" to give this info, but for now + * it seems safe enough to ignore it. + */ + break; + + case DNTT_TYPE_MODIFIER: + /* Intended to supply "modified access" to a type */ + /* From the way DDE handles this, it looks like it always + * modifies a type. Therefore it is safe to ignore it at this + * level, and handle it in hpread_type_lookup(). + */ + break; + + case DNTT_TYPE_OBJECT_ID: + /* Just ignore this - that's all DDE does */ + break; + + case DNTT_TYPE_MEMFUNC: + /* Member function */ + /* This does not have to be handled at this level; handled in + * the course of processing class symbols. + */ + break; + + case DNTT_TYPE_DOC_MEMFUNC: + /* Member function */ + /* This does not have to be handled at this level; handled in + * the course of processing class symbols. + */ + break; + + case DNTT_TYPE_TEMPLATE: + /* Template - sort of the header for a template definition, + * which like a class, points to a member list and also points + * to a TEMPLATE_ARG list of type-arguments. + * We do not need to process TEMPLATE records at this level though. + */ + break; + + case DNTT_TYPE_TEMPLATE_ARG: + /* The TEMPLATE record points to an argument list of + * TEMPLATE_ARG records, each of which describes one + * of the type-arguments. + * We do not need to process TEMPLATE_ARG records at this level though. + */ + break; + + case DNTT_TYPE_FUNC_TEMPLATE: + /* This will get emitted for member functions of templates. + * But we don't need to process this record at this level though, + * we will process it in the course of processing a TEMPLATE + * record. + */ + break; + + case DNTT_TYPE_LINK: + /* The LINK record is used to link up templates with instantiations. */ + /* It is not clear why this is needed, and furthermore aCC does + * not appear to generate this, so I think we can safely ignore it. - RT + */ + break; + + /* DNTT_TYPE_DYN_ARRAY_DESC is not handled by GDB */ + /* DNTT_TYPE_DESC_SUBRANGE is not handled by GDB */ + /* DNTT_TYPE_BEGIN_EXT is not handled by GDB */ + /* DNTT_TYPE_INLN is not handled by GDB */ + /* DNTT_TYPE_INLN_LIST is not handled by GDB */ + /* DNTT_TYPE_ALIAS is not handled by GDB */ + + default: + break; + } +} + +/* Get nesting depth for a DNTT entry. + * DN_BUFP points to a DNTT entry. + * OBJFILE is the object file. + * REPORT_NESTED is a flag; if 0, real nesting depth is + * reported, if it is 1, the function simply returns a + * non-zero value if the nesting depth is anything > 0. + * + * Return value is an integer. 0 => not a local type / name + * positive return => type or name is local to some + * block or function. + */ + + +/* elz: ATTENTION: FIXME: NOTE: WARNING!!!! + this function now returns 0 right away. It was taking too much time + at start up. Now, though, the local types are not handled correctly. + */ + + +static int +hpread_get_scope_depth (union dnttentry *dn_bufp, struct objfile *objfile, + int report_nested) +{ + register int index; + register union dnttentry *dn_tmp; + register short depth = 0; +/****************************/ + return 0; +/****************************/ + + index = (((char *) dn_bufp) - LNTT (objfile)) / (sizeof (struct dntt_type_block)); + + while (--index >= 0) + { + dn_tmp = hpread_get_lntt (index, objfile); + switch (dn_tmp->dblock.kind) + { + case DNTT_TYPE_MODULE: + return depth; + case DNTT_TYPE_END: + /* index is signed int; dnttp.index is 29-bit unsigned int! */ + index = (int) dn_tmp->dend.beginscope.dnttp.index; + break; + case DNTT_TYPE_BEGIN: + case DNTT_TYPE_FUNCTION: + case DNTT_TYPE_DOC_FUNCTION: + case DNTT_TYPE_WITH: + case DNTT_TYPE_COMMON: + case DNTT_TYPE_CLASS_SCOPE: + depth++; + if (report_nested) + return 1; + break; + default: + break; + } + } + return depth; +} + +/* Adjust the bitoffsets for all fields of an anonymous union of + type TYPE by negative BITS. This handles HP aCC's hideous habit + of giving members of anonymous unions bit offsets relative to the + enclosing structure instead of relative to the union itself. */ + +static void +hpread_adjust_bitoffsets (struct type *type, int bits) +{ + register int i; + + /* This is done only for unions; caller had better check that + it is an anonymous one. */ + if (TYPE_CODE (type) != TYPE_CODE_UNION) + return; + + /* Adjust each field; since this is a union, there are no base + classes. Also no static membes. Also, no need for recursion as + the members of this union if themeselves structs or unions, have + the correct bitoffsets; if an anonymous union is a member of this + anonymous union, the code in hpread_read_struct_type() will + adjust for that. */ + + for (i = 0; i < TYPE_NFIELDS (type); i++) + TYPE_FIELD_BITPOS (type, i) -= bits; +} + +/* Because of quirks in HP compilers' treatment of anonymous unions inside + classes, we have to chase through a chain of threaded FIELD entries. + If we encounter an anonymous union in the chain, we must recursively skip over + that too. + + This function does a "next" in the chain of FIELD entries, but transparently + skips over anonymous unions' fields (recursively). + + Inputs are the number of times to do "next" at the top level, the dnttpointer + (FIELD) and entry pointer (FIELDP) for the dntt record corresponding to it, + and the ubiquitous objfile parameter. (Note: FIELDP is a **.) Return value + is a dnttpointer for the new field after all the skipped ones */ + +static dnttpointer +hpread_get_next_skip_over_anon_unions (int skip_fields, dnttpointer field, + union dnttentry **fieldp, + struct objfile *objfile) +{ + struct type *anon_type; + register int i; + int bitoffset; + char *name; + + for (i = 0; i < skip_fields; i++) + { + /* Get type of item we're looking at now; recursively processes the types + of these intermediate items we skip over, so they aren't lost. */ + anon_type = hpread_type_lookup ((*fieldp)->dfield.type, objfile); + anon_type = CHECK_TYPEDEF (anon_type); + bitoffset = (*fieldp)->dfield.bitoffset; + name = VT (objfile) + (*fieldp)->dfield.name; + /* First skip over one item to avoid stack death on recursion */ + field = (*fieldp)->dfield.nextfield; + *fieldp = hpread_get_lntt (field.dnttp.index, objfile); + /* Do we have another anonymous union? If so, adjust the bitoffsets + of its members and skip over its members. */ + if ((TYPE_CODE (anon_type) == TYPE_CODE_UNION) && + (!name || STREQ (name, ""))) + { + hpread_adjust_bitoffsets (anon_type, bitoffset); + field = hpread_get_next_skip_over_anon_unions (TYPE_NFIELDS (anon_type), field, fieldp, objfile); + } + } + return field; +} diff --git a/gdb/mdebugread.c b/gdb/mdebugread.c new file mode 100644 index 0000000..1695afd --- /dev/null +++ b/gdb/mdebugread.c @@ -0,0 +1,5021 @@ +/* Read a symbol table in ECOFF format (Third-Eye). + Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, + 1997, 1998, 1999, 2000, 2001, 2002 + Free Software Foundation, Inc. + Original version contributed by Alessandro Forin (af@cs.cmu.edu) at + CMU. Major work by Per Bothner, John Gilmore and Ian Lance Taylor + at Cygnus Support. + + 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 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This module provides the function mdebug_build_psymtabs. It reads + ECOFF debugging information into partial symbol tables. The + debugging information is read from two structures. A struct + ecoff_debug_swap includes the sizes of each ECOFF structure and + swapping routines; these are fixed for a particular target. A + struct ecoff_debug_info points to the debugging information for a + particular object file. + + ECOFF symbol tables are mostly written in the byte order of the + target machine. However, one section of the table (the auxiliary + symbol information) is written in the host byte order. There is a + bit in the other symbol info which describes which host byte order + was used. ECOFF thereby takes the trophy from Intel `b.out' for + the most brain-dead adaptation of a file format to byte order. + + This module can read all four of the known byte-order combinations, + on any type of host. */ + +#include "defs.h" +#include "symtab.h" +#include "gdbtypes.h" +#include "gdbcore.h" +#include "symfile.h" +#include "objfiles.h" +#include "gdb_obstack.h" +#include "buildsym.h" +#include "stabsread.h" +#include "complaints.h" +#include "demangle.h" +#include "gdb_assert.h" + +/* These are needed if the tm.h file does not contain the necessary + mips specific definitions. */ + +#ifndef MIPS_EFI_SYMBOL_NAME +#define MIPS_EFI_SYMBOL_NAME "__GDB_EFI_INFO__" +extern void ecoff_relocate_efi (struct symbol *, CORE_ADDR); +#include "coff/sym.h" +#include "coff/symconst.h" +typedef struct mips_extra_func_info + { + long numargs; + PDR pdr; + } + *mips_extra_func_info_t; +#ifndef RA_REGNUM +#define RA_REGNUM 0 +#endif +#endif + +#ifdef USG +#include <sys/types.h> +#endif + +#include "gdb_stat.h" +#include "gdb_string.h" + +#include "bfd.h" + +#include "coff/ecoff.h" /* COFF-like aspects of ecoff files */ + +#include "libaout.h" /* Private BFD a.out information. */ +#include "aout/aout64.h" +#include "aout/stab_gnu.h" /* STABS information */ + +#include "expression.h" +#include "language.h" /* For local_hex_string() */ + +extern void _initialize_mdebugread (void); + +/* Provide a way to test if we have both ECOFF and ELF symbol tables. + We use this define in order to know whether we should override a + symbol's ECOFF section with its ELF section. This is necessary in + case the symbol's ELF section could not be represented in ECOFF. */ +#define ECOFF_IN_ELF(bfd) (bfd_get_flavour (bfd) == bfd_target_elf_flavour \ + && bfd_get_section_by_name (bfd, ".mdebug") != NULL) + + +/* We put a pointer to this structure in the read_symtab_private field + of the psymtab. */ + +struct symloc + { + /* Index of the FDR that this psymtab represents. */ + int fdr_idx; + /* The BFD that the psymtab was created from. */ + bfd *cur_bfd; + const struct ecoff_debug_swap *debug_swap; + struct ecoff_debug_info *debug_info; + struct mdebug_pending **pending_list; + /* Pointer to external symbols for this file. */ + EXTR *extern_tab; + /* Size of extern_tab. */ + int extern_count; + enum language pst_language; + }; + +#define PST_PRIVATE(p) ((struct symloc *)(p)->read_symtab_private) +#define FDR_IDX(p) (PST_PRIVATE(p)->fdr_idx) +#define CUR_BFD(p) (PST_PRIVATE(p)->cur_bfd) +#define DEBUG_SWAP(p) (PST_PRIVATE(p)->debug_swap) +#define DEBUG_INFO(p) (PST_PRIVATE(p)->debug_info) +#define PENDING_LIST(p) (PST_PRIVATE(p)->pending_list) + +#define SC_IS_TEXT(sc) ((sc) == scText \ + || (sc) == scRConst \ + || (sc) == scInit \ + || (sc) == scFini) +#define SC_IS_DATA(sc) ((sc) == scData \ + || (sc) == scSData \ + || (sc) == scRData \ + || (sc) == scPData \ + || (sc) == scXData) +#define SC_IS_COMMON(sc) ((sc) == scCommon || (sc) == scSCommon) +#define SC_IS_BSS(sc) ((sc) == scBss) +#define SC_IS_SBSS(sc) ((sc) == scSBss) +#define SC_IS_UNDEF(sc) ((sc) == scUndefined || (sc) == scSUndefined) + +/* Various complaints about symbol reading that don't abort the process */ + +static struct complaint bad_file_number_complaint = +{"bad file number %d", 0, 0}; + +static struct complaint index_complaint = +{"bad aux index at symbol %s", 0, 0}; + +static struct complaint aux_index_complaint = +{"bad proc end in aux found from symbol %s", 0, 0}; + +static struct complaint block_index_complaint = +{"bad aux index at block symbol %s", 0, 0}; + +static struct complaint unknown_ext_complaint = +{"unknown external symbol %s", 0, 0}; + +static struct complaint unknown_sym_complaint = +{"unknown local symbol %s", 0, 0}; + +static struct complaint unknown_st_complaint = +{"with type %d", 0, 0}; + +static struct complaint block_overflow_complaint = +{"block containing %s overfilled", 0, 0}; + +static struct complaint basic_type_complaint = +{"cannot map ECOFF basic type 0x%x for %s", 0, 0}; + +static struct complaint unknown_type_qual_complaint = +{"unknown type qualifier 0x%x", 0, 0}; + +static struct complaint array_index_type_complaint = +{"illegal array index type for %s, assuming int", 0, 0}; + +static struct complaint bad_tag_guess_complaint = +{"guessed tag type of %s incorrectly", 0, 0}; + +static struct complaint block_member_complaint = +{"declaration block contains unhandled symbol type %d", 0, 0}; + +static struct complaint stEnd_complaint = +{"stEnd with storage class %d not handled", 0, 0}; + +static struct complaint unknown_mdebug_symtype_complaint = +{"unknown symbol type 0x%x", 0, 0}; + +static struct complaint stab_unknown_complaint = +{"unknown stabs symbol %s", 0, 0}; + +static struct complaint pdr_for_nonsymbol_complaint = +{"PDR for %s, but no symbol", 0, 0}; + +static struct complaint pdr_static_symbol_complaint = +{"can't handle PDR for static proc at 0x%lx", 0, 0}; + +static struct complaint bad_setjmp_pdr_complaint = +{"fixing bad setjmp PDR from libc", 0, 0}; + +static struct complaint bad_fbitfield_complaint = +{"can't handle TIR fBitfield for %s", 0, 0}; + +static struct complaint bad_continued_complaint = +{"illegal TIR continued for %s", 0, 0}; + +static struct complaint bad_rfd_entry_complaint = +{"bad rfd entry for %s: file %d, index %d", 0, 0}; + +static struct complaint unexpected_type_code_complaint = +{"unexpected type code for %s", 0, 0}; + +static struct complaint unable_to_cross_ref_complaint = +{"unable to cross ref btTypedef for %s", 0, 0}; + +static struct complaint bad_indirect_xref_complaint = +{"unable to cross ref btIndirect for %s", 0, 0}; + +static struct complaint illegal_forward_tq0_complaint = +{"illegal tq0 in forward typedef for %s", 0, 0}; + +static struct complaint illegal_forward_bt_complaint = +{"illegal bt %d in forward typedef for %s", 0, 0}; + +static struct complaint bad_linetable_guess_complaint = +{"guessed size of linetable for %s incorrectly", 0, 0}; + +static struct complaint bad_ext_ifd_complaint = +{"bad ifd for external symbol: %d (max %d)", 0, 0}; + +static struct complaint bad_ext_iss_complaint = +{"bad iss for external symbol: %ld (max %ld)", 0, 0}; + +/* Macros and extra defs */ + +/* Puns: hard to find whether -g was used and how */ + +#define MIN_GLEVEL GLEVEL_0 +#define compare_glevel(a,b) \ + (((a) == GLEVEL_3) ? ((b) < GLEVEL_3) : \ + ((b) == GLEVEL_3) ? -1 : (int)((b) - (a))) + +/* Things that really are local to this module */ + +/* Remember what we deduced to be the source language of this psymtab. */ + +static enum language psymtab_language = language_unknown; + +/* Current BFD. */ + +static bfd *cur_bfd; + +/* How to parse debugging information for CUR_BFD. */ + +static const struct ecoff_debug_swap *debug_swap; + +/* Pointers to debugging information for CUR_BFD. */ + +static struct ecoff_debug_info *debug_info; + +/* Pointer to current file decriptor record, and its index */ + +static FDR *cur_fdr; +static int cur_fd; + +/* Index of current symbol */ + +static int cur_sdx; + +/* Note how much "debuggable" this image is. We would like + to see at least one FDR with full symbols */ + +static int max_gdbinfo; +static int max_glevel; + +/* When examining .o files, report on undefined symbols */ + +static int n_undef_symbols, n_undef_labels, n_undef_vars, n_undef_procs; + +/* Pseudo symbol to use when putting stabs into the symbol table. */ + +static char stabs_symbol[] = STABS_SYMBOL; + +/* Types corresponding to mdebug format bt* basic types. */ + +static struct type *mdebug_type_void; +static struct type *mdebug_type_char; +static struct type *mdebug_type_short; +static struct type *mdebug_type_int_32; +#define mdebug_type_int mdebug_type_int_32 +static struct type *mdebug_type_int_64; +static struct type *mdebug_type_long_32; +static struct type *mdebug_type_long_64; +static struct type *mdebug_type_long_long_64; +static struct type *mdebug_type_unsigned_char; +static struct type *mdebug_type_unsigned_short; +static struct type *mdebug_type_unsigned_int_32; +static struct type *mdebug_type_unsigned_int_64; +static struct type *mdebug_type_unsigned_long_32; +static struct type *mdebug_type_unsigned_long_64; +static struct type *mdebug_type_unsigned_long_long_64; +static struct type *mdebug_type_adr_32; +static struct type *mdebug_type_adr_64; +static struct type *mdebug_type_float; +static struct type *mdebug_type_double; +static struct type *mdebug_type_complex; +static struct type *mdebug_type_double_complex; +static struct type *mdebug_type_fixed_dec; +static struct type *mdebug_type_float_dec; +static struct type *mdebug_type_string; + +/* Types for symbols from files compiled without debugging info. */ + +static struct type *nodebug_func_symbol_type; +static struct type *nodebug_var_symbol_type; + +/* Nonzero if we have seen ecoff debugging info for a file. */ + +static int found_ecoff_debugging_info; + +/* Forward declarations */ + +static int upgrade_type (int, struct type **, int, union aux_ext *, + int, char *); + +static void parse_partial_symbols (struct objfile *); + +static int has_opaque_xref (FDR *, SYMR *); + +static int cross_ref (int, union aux_ext *, struct type **, enum type_code, + char **, int, char *); + +static struct symbol *new_symbol (char *); + +static struct type *new_type (char *); + +static struct block *new_block (int); + +static struct symtab *new_symtab (char *, int, int, struct objfile *); + +static struct linetable *new_linetable (int); + +static struct blockvector *new_bvect (int); + +static struct type *parse_type (int, union aux_ext *, unsigned int, int *, + int, char *); + +static struct symbol *mylookup_symbol (char *, struct block *, namespace_enum, + enum address_class); + +static struct block *shrink_block (struct block *, struct symtab *); + +static void sort_blocks (struct symtab *); + +static struct partial_symtab *new_psymtab (char *, struct objfile *); + +static void psymtab_to_symtab_1 (struct partial_symtab *, char *); + +static void add_block (struct block *, struct symtab *); + +static void add_symbol (struct symbol *, struct block *); + +static int add_line (struct linetable *, int, CORE_ADDR, int); + +static struct linetable *shrink_linetable (struct linetable *); + +static void handle_psymbol_enumerators (struct objfile *, FDR *, int, + CORE_ADDR); + +static char *mdebug_next_symbol_text (struct objfile *); + +/* Address bounds for the signal trampoline in inferior, if any */ + +CORE_ADDR sigtramp_address, sigtramp_end; + +/* Allocate zeroed memory */ + +static void * +xzalloc (unsigned int size) +{ + void *p = xmalloc (size); + + memset (p, 0, size); + return p; +} + +/* Exported procedure: Builds a symtab from the PST partial one. + Restores the environment in effect when PST was created, delegates + most of the work to an ancillary procedure, and sorts + and reorders the symtab list at the end */ + +static void +mdebug_psymtab_to_symtab (struct partial_symtab *pst) +{ + + if (!pst) + return; + + if (info_verbose) + { + printf_filtered ("Reading in symbols for %s...", pst->filename); + gdb_flush (gdb_stdout); + } + + next_symbol_text_func = mdebug_next_symbol_text; + + psymtab_to_symtab_1 (pst, pst->filename); + + /* Match with global symbols. This only needs to be done once, + after all of the symtabs and dependencies have been read in. */ + scan_file_globals (pst->objfile); + + if (info_verbose) + printf_filtered ("done.\n"); +} + +/* File-level interface functions */ + +/* Find a file descriptor given its index RF relative to a file CF */ + +static FDR * +get_rfd (int cf, int rf) +{ + FDR *fdrs; + register FDR *f; + RFDT rfd; + + fdrs = debug_info->fdr; + f = fdrs + cf; + /* Object files do not have the RFD table, all refs are absolute */ + if (f->rfdBase == 0) + return fdrs + rf; + (*debug_swap->swap_rfd_in) (cur_bfd, + ((char *) debug_info->external_rfd + + ((f->rfdBase + rf) + * debug_swap->external_rfd_size)), + &rfd); + return fdrs + rfd; +} + +/* Return a safer print NAME for a file descriptor */ + +static char * +fdr_name (FDR *f) +{ + if (f->rss == -1) + return "<stripped file>"; + if (f->rss == 0) + return "<NFY>"; + return debug_info->ss + f->issBase + f->rss; +} + + +/* Read in and parse the symtab of the file OBJFILE. Symbols from + different sections are relocated via the SECTION_OFFSETS. */ + +void +mdebug_build_psymtabs (struct objfile *objfile, + const struct ecoff_debug_swap *swap, + struct ecoff_debug_info *info) +{ + cur_bfd = objfile->obfd; + debug_swap = swap; + debug_info = info; + + stabsread_new_init (); + buildsym_new_init (); + free_header_files (); + init_header_files (); + + /* Make sure all the FDR information is swapped in. */ + if (info->fdr == (FDR *) NULL) + { + char *fdr_src; + char *fdr_end; + FDR *fdr_ptr; + + info->fdr = (FDR *) obstack_alloc (&objfile->psymbol_obstack, + (info->symbolic_header.ifdMax + * sizeof (FDR))); + fdr_src = info->external_fdr; + fdr_end = (fdr_src + + info->symbolic_header.ifdMax * swap->external_fdr_size); + fdr_ptr = info->fdr; + for (; fdr_src < fdr_end; fdr_src += swap->external_fdr_size, fdr_ptr++) + (*swap->swap_fdr_in) (objfile->obfd, fdr_src, fdr_ptr); + } + + parse_partial_symbols (objfile); + +#if 0 + /* Check to make sure file was compiled with -g. If not, warn the + user of this limitation. */ + if (compare_glevel (max_glevel, GLEVEL_2) < 0) + { + if (max_gdbinfo == 0) + printf_unfiltered ("\n%s not compiled with -g, debugging support is limited.\n", + objfile->name); + printf_unfiltered ("You should compile with -g2 or -g3 for best debugging support.\n"); + gdb_flush (gdb_stdout); + } +#endif +} + +/* Local utilities */ + +/* Map of FDR indexes to partial symtabs */ + +struct pst_map +{ + struct partial_symtab *pst; /* the psymtab proper */ + long n_globals; /* exported globals (external symbols) */ + long globals_offset; /* cumulative */ +}; + + +/* Utility stack, used to nest procedures and blocks properly. + It is a doubly linked list, to avoid too many alloc/free. + Since we might need it quite a few times it is NOT deallocated + after use. */ + +static struct parse_stack + { + struct parse_stack *next, *prev; + struct symtab *cur_st; /* Current symtab. */ + struct block *cur_block; /* Block in it. */ + + /* What are we parsing. stFile, or stBlock are for files and + blocks. stProc or stStaticProc means we have seen the start of a + procedure, but not the start of the block within in. When we see + the start of that block, we change it to stNil, without pushing a + new block, i.e. stNil means both a procedure and a block. */ + + int blocktype; + + int maxsyms; /* Max symbols in this block. */ + struct type *cur_type; /* Type we parse fields for. */ + int cur_field; /* Field number in cur_type. */ + CORE_ADDR procadr; /* Start addres of this procedure */ + int numargs; /* Its argument count */ + } + + *top_stack; /* Top stack ptr */ + + +/* Enter a new lexical context */ + +static void +push_parse_stack (void) +{ + struct parse_stack *new; + + /* Reuse frames if possible */ + if (top_stack && top_stack->prev) + new = top_stack->prev; + else + new = (struct parse_stack *) xzalloc (sizeof (struct parse_stack)); + /* Initialize new frame with previous content */ + if (top_stack) + { + register struct parse_stack *prev = new->prev; + + *new = *top_stack; + top_stack->prev = new; + new->prev = prev; + new->next = top_stack; + } + top_stack = new; +} + +/* Exit a lexical context */ + +static void +pop_parse_stack (void) +{ + if (!top_stack) + return; + if (top_stack->next) + top_stack = top_stack->next; +} + + +/* Cross-references might be to things we haven't looked at + yet, e.g. type references. To avoid too many type + duplications we keep a quick fixup table, an array + of lists of references indexed by file descriptor */ + +struct mdebug_pending +{ + struct mdebug_pending *next; /* link */ + char *s; /* the unswapped symbol */ + struct type *t; /* its partial type descriptor */ +}; + + +/* The pending information is kept for an entire object file, and used + to be in the sym_private field. I took it out when I split + mdebugread from mipsread, because this might not be the only type + of symbols read from an object file. Instead, we allocate the + pending information table when we create the partial symbols, and + we store a pointer to the single table in each psymtab. */ + +static struct mdebug_pending **pending_list; + +/* Check whether we already saw symbol SH in file FH */ + +static struct mdebug_pending * +is_pending_symbol (FDR *fh, char *sh) +{ + int f_idx = fh - debug_info->fdr; + register struct mdebug_pending *p; + + /* Linear search is ok, list is typically no more than 10 deep */ + for (p = pending_list[f_idx]; p; p = p->next) + if (p->s == sh) + break; + return p; +} + +/* Add a new symbol SH of type T */ + +static void +add_pending (FDR *fh, char *sh, struct type *t) +{ + int f_idx = fh - debug_info->fdr; + struct mdebug_pending *p = is_pending_symbol (fh, sh); + + /* Make sure we do not make duplicates */ + if (!p) + { + p = ((struct mdebug_pending *) + obstack_alloc (¤t_objfile->psymbol_obstack, + sizeof (struct mdebug_pending))); + p->s = sh; + p->t = t; + p->next = pending_list[f_idx]; + pending_list[f_idx] = p; + } +} + + +/* Parsing Routines proper. */ + +/* Parse a single symbol. Mostly just make up a GDB symbol for it. + For blocks, procedures and types we open a new lexical context. + This is basically just a big switch on the symbol's type. Argument + AX is the base pointer of aux symbols for this file (fh->iauxBase). + EXT_SH points to the unswapped symbol, which is needed for struct, + union, etc., types; it is NULL for an EXTR. BIGEND says whether + aux symbols are big-endian or little-endian. Return count of + SYMR's handled (normally one). */ + +static int +parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend, + struct section_offsets *section_offsets, struct objfile *objfile) +{ + const bfd_size_type external_sym_size = debug_swap->external_sym_size; + void (*const swap_sym_in) (bfd *, void *, SYMR *) = debug_swap->swap_sym_in; + char *name; + struct symbol *s; + struct block *b; + struct mdebug_pending *pend; + struct type *t; + struct field *f; + int count = 1; + enum address_class class; + TIR tir; + long svalue = sh->value; + int bitsize; + + if (ext_sh == (char *) NULL) + name = debug_info->ssext + sh->iss; + else + name = debug_info->ss + cur_fdr->issBase + sh->iss; + + switch (sh->sc) + { + case scText: + case scRConst: + /* Do not relocate relative values. + The value of a stEnd symbol is the displacement from the + corresponding start symbol value. + The value of a stBlock symbol is the displacement from the + procedure address. */ + if (sh->st != stEnd && sh->st != stBlock) + sh->value += ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile)); + break; + case scData: + case scSData: + case scRData: + case scPData: + case scXData: + sh->value += ANOFFSET (section_offsets, SECT_OFF_DATA (objfile)); + break; + case scBss: + case scSBss: + sh->value += ANOFFSET (section_offsets, SECT_OFF_BSS (objfile)); + break; + } + + switch (sh->st) + { + case stNil: + break; + + case stGlobal: /* external symbol, goes into global block */ + class = LOC_STATIC; + b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (top_stack->cur_st), + GLOBAL_BLOCK); + s = new_symbol (name); + SYMBOL_VALUE_ADDRESS (s) = (CORE_ADDR) sh->value; + goto data; + + case stStatic: /* static data, goes into current block. */ + class = LOC_STATIC; + b = top_stack->cur_block; + s = new_symbol (name); + if (SC_IS_COMMON (sh->sc)) + { + /* It is a FORTRAN common block. At least for SGI Fortran the + address is not in the symbol; we need to fix it later in + scan_file_globals. */ + int bucket = hashname (SYMBOL_NAME (s)); + SYMBOL_VALUE_CHAIN (s) = global_sym_chain[bucket]; + global_sym_chain[bucket] = s; + } + else + SYMBOL_VALUE_ADDRESS (s) = (CORE_ADDR) sh->value; + goto data; + + case stLocal: /* local variable, goes into current block */ + if (sh->sc == scRegister) + { + class = LOC_REGISTER; + svalue = ECOFF_REG_TO_REGNUM (svalue); + } + else + class = LOC_LOCAL; + b = top_stack->cur_block; + s = new_symbol (name); + SYMBOL_VALUE (s) = svalue; + + data: /* Common code for symbols describing data */ + SYMBOL_NAMESPACE (s) = VAR_NAMESPACE; + SYMBOL_CLASS (s) = class; + add_symbol (s, b); + + /* Type could be missing if file is compiled without debugging info. */ + if (SC_IS_UNDEF (sh->sc) + || sh->sc == scNil || sh->index == indexNil) + SYMBOL_TYPE (s) = nodebug_var_symbol_type; + else + SYMBOL_TYPE (s) = parse_type (cur_fd, ax, sh->index, 0, bigend, name); + /* Value of a data symbol is its memory address */ + break; + + case stParam: /* arg to procedure, goes into current block */ + max_gdbinfo++; + found_ecoff_debugging_info = 1; + top_stack->numargs++; + + /* Special GNU C++ name. */ + if (is_cplus_marker (name[0]) && name[1] == 't' && name[2] == 0) + name = "this"; /* FIXME, not alloc'd in obstack */ + s = new_symbol (name); + + SYMBOL_NAMESPACE (s) = VAR_NAMESPACE; + switch (sh->sc) + { + case scRegister: + /* Pass by value in register. */ + SYMBOL_CLASS (s) = LOC_REGPARM; + svalue = ECOFF_REG_TO_REGNUM (svalue); + break; + case scVar: + /* Pass by reference on stack. */ + SYMBOL_CLASS (s) = LOC_REF_ARG; + break; + case scVarRegister: + /* Pass by reference in register. */ + SYMBOL_CLASS (s) = LOC_REGPARM_ADDR; + svalue = ECOFF_REG_TO_REGNUM (svalue); + break; + default: + /* Pass by value on stack. */ + SYMBOL_CLASS (s) = LOC_ARG; + break; + } + SYMBOL_VALUE (s) = svalue; + SYMBOL_TYPE (s) = parse_type (cur_fd, ax, sh->index, 0, bigend, name); + add_symbol (s, top_stack->cur_block); + break; + + case stLabel: /* label, goes into current block */ + s = new_symbol (name); + SYMBOL_NAMESPACE (s) = VAR_NAMESPACE; /* so that it can be used */ + SYMBOL_CLASS (s) = LOC_LABEL; /* but not misused */ + SYMBOL_VALUE_ADDRESS (s) = (CORE_ADDR) sh->value; + SYMBOL_TYPE (s) = mdebug_type_int; + add_symbol (s, top_stack->cur_block); + break; + + case stProc: /* Procedure, usually goes into global block */ + case stStaticProc: /* Static procedure, goes into current block */ + s = new_symbol (name); + SYMBOL_NAMESPACE (s) = VAR_NAMESPACE; + SYMBOL_CLASS (s) = LOC_BLOCK; + /* Type of the return value */ + if (SC_IS_UNDEF (sh->sc) || sh->sc == scNil) + t = mdebug_type_int; + else + { + t = parse_type (cur_fd, ax, sh->index + 1, 0, bigend, name); + if (STREQ (name, "malloc") && TYPE_CODE (t) == TYPE_CODE_VOID) + { + /* I don't know why, but, at least under Alpha GNU/Linux, + when linking against a malloc without debugging + symbols, its read as a function returning void---this + is bad because it means we cannot call functions with + string arguments interactively; i.e., "call + printf("howdy\n")" would fail with the error message + "program has no memory available". To avoid this, we + patch up the type and make it void* + instead. (davidm@azstarnet.com) + */ + t = make_pointer_type (t, NULL); + } + } + b = top_stack->cur_block; + if (sh->st == stProc) + { + struct blockvector *bv = BLOCKVECTOR (top_stack->cur_st); + /* The next test should normally be true, but provides a + hook for nested functions (which we don't want to make + global). */ + if (b == BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK)) + b = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK); + /* Irix 5 sometimes has duplicate names for the same + function. We want to add such names up at the global + level, not as a nested function. */ + else if (sh->value == top_stack->procadr) + b = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK); + } + add_symbol (s, b); + + /* Make a type for the procedure itself */ + SYMBOL_TYPE (s) = lookup_function_type (t); + + /* Create and enter a new lexical context */ + b = new_block (top_stack->maxsyms); + SYMBOL_BLOCK_VALUE (s) = b; + BLOCK_FUNCTION (b) = s; + BLOCK_START (b) = BLOCK_END (b) = sh->value; + BLOCK_SUPERBLOCK (b) = top_stack->cur_block; + add_block (b, top_stack->cur_st); + + /* Not if we only have partial info */ + if (SC_IS_UNDEF (sh->sc) || sh->sc == scNil) + break; + + push_parse_stack (); + top_stack->cur_block = b; + top_stack->blocktype = sh->st; + top_stack->cur_type = SYMBOL_TYPE (s); + top_stack->cur_field = -1; + top_stack->procadr = sh->value; + top_stack->numargs = 0; + break; + + /* Beginning of code for structure, union, and enum definitions. + They all share a common set of local variables, defined here. */ + { + enum type_code type_code; + char *ext_tsym; + int nfields; + long max_value; + struct field *f; + + case stStruct: /* Start a block defining a struct type */ + type_code = TYPE_CODE_STRUCT; + goto structured_common; + + case stUnion: /* Start a block defining a union type */ + type_code = TYPE_CODE_UNION; + goto structured_common; + + case stEnum: /* Start a block defining an enum type */ + type_code = TYPE_CODE_ENUM; + goto structured_common; + + case stBlock: /* Either a lexical block, or some type */ + if (sh->sc != scInfo && !SC_IS_COMMON (sh->sc)) + goto case_stBlock_code; /* Lexical block */ + + type_code = TYPE_CODE_UNDEF; /* We have a type. */ + + /* Common code for handling struct, union, enum, and/or as-yet- + unknown-type blocks of info about structured data. `type_code' + has been set to the proper TYPE_CODE, if we know it. */ + structured_common: + found_ecoff_debugging_info = 1; + push_parse_stack (); + top_stack->blocktype = stBlock; + + /* First count the number of fields and the highest value. */ + nfields = 0; + max_value = 0; + for (ext_tsym = ext_sh + external_sym_size; + ; + ext_tsym += external_sym_size) + { + SYMR tsym; + + (*swap_sym_in) (cur_bfd, ext_tsym, &tsym); + + switch (tsym.st) + { + case stEnd: + goto end_of_fields; + + case stMember: + if (nfields == 0 && type_code == TYPE_CODE_UNDEF) + { + /* If the type of the member is Nil (or Void), + without qualifiers, assume the tag is an + enumeration. + Alpha cc -migrate enums are recognized by a zero + index and a zero symbol value. + DU 4.0 cc enums are recognized by a member type of + btEnum without qualifiers and a zero symbol value. */ + if (tsym.index == indexNil + || (tsym.index == 0 && sh->value == 0)) + type_code = TYPE_CODE_ENUM; + else + { + (*debug_swap->swap_tir_in) (bigend, + &ax[tsym.index].a_ti, + &tir); + if ((tir.bt == btNil || tir.bt == btVoid + || (tir.bt == btEnum && sh->value == 0)) + && tir.tq0 == tqNil) + type_code = TYPE_CODE_ENUM; + } + } + nfields++; + if (tsym.value > max_value) + max_value = tsym.value; + break; + + case stBlock: + case stUnion: + case stEnum: + case stStruct: + { +#if 0 + /* This is a no-op; is it trying to tell us something + we should be checking? */ + if (tsym.sc == scVariant); /*UNIMPLEMENTED */ +#endif + if (tsym.index != 0) + { + /* This is something like a struct within a + struct. Skip over the fields of the inner + struct. The -1 is because the for loop will + increment ext_tsym. */ + ext_tsym = ((char *) debug_info->external_sym + + ((cur_fdr->isymBase + tsym.index - 1) + * external_sym_size)); + } + } + break; + + case stTypedef: + /* mips cc puts out a typedef for struct x if it is not yet + defined when it encounters + struct y { struct x *xp; }; + Just ignore it. */ + break; + + case stIndirect: + /* Irix5 cc puts out a stIndirect for struct x if it is not + yet defined when it encounters + struct y { struct x *xp; }; + Just ignore it. */ + break; + + default: + complain (&block_member_complaint, tsym.st); + } + } + end_of_fields:; + + /* In an stBlock, there is no way to distinguish structs, + unions, and enums at this point. This is a bug in the + original design (that has been fixed with the recent + addition of the stStruct, stUnion, and stEnum symbol + types.) The way you can tell is if/when you see a variable + or field of that type. In that case the variable's type + (in the AUX table) says if the type is struct, union, or + enum, and points back to the stBlock here. So you can + patch the tag kind up later - but only if there actually is + a variable or field of that type. + + So until we know for sure, we will guess at this point. + The heuristic is: + If the first member has index==indexNil or a void type, + assume we have an enumeration. + Otherwise, if there is more than one member, and all + the members have offset 0, assume we have a union. + Otherwise, assume we have a struct. + + The heuristic could guess wrong in the case of of an + enumeration with no members or a union with one (or zero) + members, or when all except the last field of a struct have + width zero. These are uncommon and/or illegal situations, + and in any case guessing wrong probably doesn't matter + much. + + But if we later do find out we were wrong, we fixup the tag + kind. Members of an enumeration must be handled + differently from struct/union fields, and that is harder to + patch up, but luckily we shouldn't need to. (If there are + any enumeration members, we can tell for sure it's an enum + here.) */ + + if (type_code == TYPE_CODE_UNDEF) + { + if (nfields > 1 && max_value == 0) + type_code = TYPE_CODE_UNION; + else + type_code = TYPE_CODE_STRUCT; + } + + /* Create a new type or use the pending type. */ + pend = is_pending_symbol (cur_fdr, ext_sh); + if (pend == (struct mdebug_pending *) NULL) + { + t = new_type (NULL); + add_pending (cur_fdr, ext_sh, t); + } + else + t = pend->t; + + /* Do not set the tag name if it is a compiler generated tag name + (.Fxx or .xxfake or empty) for unnamed struct/union/enums. + Alpha cc puts out an sh->iss of zero for those. */ + if (sh->iss == 0 || name[0] == '.' || name[0] == '\0') + TYPE_TAG_NAME (t) = NULL; + else + TYPE_TAG_NAME (t) = obconcat (¤t_objfile->symbol_obstack, + "", "", name); + + TYPE_CODE (t) = type_code; + TYPE_LENGTH (t) = sh->value; + TYPE_NFIELDS (t) = nfields; + TYPE_FIELDS (t) = f = ((struct field *) + TYPE_ALLOC (t, + nfields * sizeof (struct field))); + + if (type_code == TYPE_CODE_ENUM) + { + int unsigned_enum = 1; + + /* This is a non-empty enum. */ + + /* DEC c89 has the number of enumerators in the sh.value field, + not the type length, so we have to compensate for that + incompatibility quirk. + This might do the wrong thing for an enum with one or two + enumerators and gcc -gcoff -fshort-enums, but these cases + are hopefully rare enough. + Alpha cc -migrate has a sh.value field of zero, we adjust + that too. */ + if (TYPE_LENGTH (t) == TYPE_NFIELDS (t) + || TYPE_LENGTH (t) == 0) + TYPE_LENGTH (t) = TARGET_INT_BIT / HOST_CHAR_BIT; + for (ext_tsym = ext_sh + external_sym_size; + ; + ext_tsym += external_sym_size) + { + SYMR tsym; + struct symbol *enum_sym; + + (*swap_sym_in) (cur_bfd, ext_tsym, &tsym); + + if (tsym.st != stMember) + break; + + FIELD_BITPOS (*f) = tsym.value; + FIELD_TYPE (*f) = t; + FIELD_NAME (*f) = debug_info->ss + cur_fdr->issBase + tsym.iss; + FIELD_BITSIZE (*f) = 0; + + enum_sym = ((struct symbol *) + obstack_alloc (¤t_objfile->symbol_obstack, + sizeof (struct symbol))); + memset (enum_sym, 0, sizeof (struct symbol)); + SYMBOL_NAME (enum_sym) = + obsavestring (f->name, strlen (f->name), + ¤t_objfile->symbol_obstack); + SYMBOL_CLASS (enum_sym) = LOC_CONST; + SYMBOL_TYPE (enum_sym) = t; + SYMBOL_NAMESPACE (enum_sym) = VAR_NAMESPACE; + SYMBOL_VALUE (enum_sym) = tsym.value; + if (SYMBOL_VALUE (enum_sym) < 0) + unsigned_enum = 0; + add_symbol (enum_sym, top_stack->cur_block); + + /* Skip the stMembers that we've handled. */ + count++; + f++; + } + if (unsigned_enum) + TYPE_FLAGS (t) |= TYPE_FLAG_UNSIGNED; + } + /* make this the current type */ + top_stack->cur_type = t; + top_stack->cur_field = 0; + + /* Do not create a symbol for alpha cc unnamed structs. */ + if (sh->iss == 0) + break; + + /* gcc puts out an empty struct for an opaque struct definitions, + do not create a symbol for it either. */ + if (TYPE_NFIELDS (t) == 0) + { + TYPE_FLAGS (t) |= TYPE_FLAG_STUB; + break; + } + + s = new_symbol (name); + SYMBOL_NAMESPACE (s) = STRUCT_NAMESPACE; + SYMBOL_CLASS (s) = LOC_TYPEDEF; + SYMBOL_VALUE (s) = 0; + SYMBOL_TYPE (s) = t; + add_symbol (s, top_stack->cur_block); + break; + + /* End of local variables shared by struct, union, enum, and + block (as yet unknown struct/union/enum) processing. */ + } + + case_stBlock_code: + found_ecoff_debugging_info = 1; + /* beginnning of (code) block. Value of symbol + is the displacement from procedure start */ + push_parse_stack (); + + /* Do not start a new block if this is the outermost block of a + procedure. This allows the LOC_BLOCK symbol to point to the + block with the local variables, so funcname::var works. */ + if (top_stack->blocktype == stProc + || top_stack->blocktype == stStaticProc) + { + top_stack->blocktype = stNil; + break; + } + + top_stack->blocktype = stBlock; + b = new_block (top_stack->maxsyms); + BLOCK_START (b) = sh->value + top_stack->procadr; + BLOCK_SUPERBLOCK (b) = top_stack->cur_block; + top_stack->cur_block = b; + add_block (b, top_stack->cur_st); + break; + + case stEnd: /* end (of anything) */ + if (sh->sc == scInfo || SC_IS_COMMON (sh->sc)) + { + /* Finished with type */ + top_stack->cur_type = 0; + } + else if (sh->sc == scText && + (top_stack->blocktype == stProc || + top_stack->blocktype == stStaticProc)) + { + /* Finished with procedure */ + struct blockvector *bv = BLOCKVECTOR (top_stack->cur_st); + struct mips_extra_func_info *e; + struct block *b; + struct type *ftype = top_stack->cur_type; + int i; + + BLOCK_END (top_stack->cur_block) += sh->value; /* size */ + + /* Make up special symbol to contain procedure specific info */ + s = new_symbol (MIPS_EFI_SYMBOL_NAME); + SYMBOL_NAMESPACE (s) = LABEL_NAMESPACE; + SYMBOL_CLASS (s) = LOC_CONST; + SYMBOL_TYPE (s) = mdebug_type_void; + e = ((struct mips_extra_func_info *) + obstack_alloc (¤t_objfile->symbol_obstack, + sizeof (struct mips_extra_func_info))); + memset (e, 0, sizeof (struct mips_extra_func_info)); + SYMBOL_VALUE (s) = (long) e; + e->numargs = top_stack->numargs; + e->pdr.framereg = -1; + add_symbol (s, top_stack->cur_block); + + /* Reallocate symbols, saving memory */ + b = shrink_block (top_stack->cur_block, top_stack->cur_st); + + /* f77 emits proc-level with address bounds==[0,0], + So look for such child blocks, and patch them. */ + for (i = 0; i < BLOCKVECTOR_NBLOCKS (bv); i++) + { + struct block *b_bad = BLOCKVECTOR_BLOCK (bv, i); + if (BLOCK_SUPERBLOCK (b_bad) == b + && BLOCK_START (b_bad) == top_stack->procadr + && BLOCK_END (b_bad) == top_stack->procadr) + { + BLOCK_START (b_bad) = BLOCK_START (b); + BLOCK_END (b_bad) = BLOCK_END (b); + } + } + + if (TYPE_NFIELDS (ftype) <= 0) + { + /* No parameter type information is recorded with the function's + type. Set that from the type of the parameter symbols. */ + int nparams = top_stack->numargs; + int iparams; + struct symbol *sym; + + if (nparams > 0) + { + TYPE_NFIELDS (ftype) = nparams; + TYPE_FIELDS (ftype) = (struct field *) + TYPE_ALLOC (ftype, nparams * sizeof (struct field)); + + for (i = iparams = 0; iparams < nparams; i++) + { + sym = BLOCK_SYM (b, i); + switch (SYMBOL_CLASS (sym)) + { + case LOC_ARG: + case LOC_REF_ARG: + case LOC_REGPARM: + case LOC_REGPARM_ADDR: + TYPE_FIELD_TYPE (ftype, iparams) = SYMBOL_TYPE (sym); + TYPE_FIELD_ARTIFICIAL (ftype, iparams) = 0; + iparams++; + break; + default: + break; + } + } + } + } + } + else if (sh->sc == scText && top_stack->blocktype == stBlock) + { + /* End of (code) block. The value of the symbol is the + displacement from the procedure`s start address of the + end of this block. */ + BLOCK_END (top_stack->cur_block) = sh->value + top_stack->procadr; + shrink_block (top_stack->cur_block, top_stack->cur_st); + } + else if (sh->sc == scText && top_stack->blocktype == stNil) + { + /* End of outermost block. Pop parse stack and ignore. The + following stEnd of stProc will take care of the block. */ + ; + } + else if (sh->sc == scText && top_stack->blocktype == stFile) + { + /* End of file. Pop parse stack and ignore. Higher + level code deals with this. */ + ; + } + else + complain (&stEnd_complaint, sh->sc); + + pop_parse_stack (); /* restore previous lexical context */ + break; + + case stMember: /* member of struct or union */ + f = &TYPE_FIELDS (top_stack->cur_type)[top_stack->cur_field++]; + FIELD_NAME (*f) = name; + FIELD_BITPOS (*f) = sh->value; + bitsize = 0; + FIELD_TYPE (*f) = parse_type (cur_fd, ax, sh->index, &bitsize, bigend, name); + FIELD_BITSIZE (*f) = bitsize; + break; + + case stIndirect: /* forward declaration on Irix5 */ + /* Forward declarations from Irix5 cc are handled by cross_ref, + skip them. */ + break; + + case stTypedef: /* type definition */ + found_ecoff_debugging_info = 1; + + /* Typedefs for forward declarations and opaque structs from alpha cc + are handled by cross_ref, skip them. */ + if (sh->iss == 0) + break; + + /* Parse the type or use the pending type. */ + pend = is_pending_symbol (cur_fdr, ext_sh); + if (pend == (struct mdebug_pending *) NULL) + { + t = parse_type (cur_fd, ax, sh->index, (int *) NULL, bigend, name); + add_pending (cur_fdr, ext_sh, t); + } + else + t = pend->t; + + /* mips cc puts out a typedef with the name of the struct for forward + declarations. These should not go into the symbol table and + TYPE_NAME should not be set for them. + They can't be distinguished from an intentional typedef to + the same name however: + x.h: + struct x { int ix; int jx; }; + struct xx; + x.c: + typedef struct x x; + struct xx {int ixx; int jxx; }; + generates a cross referencing stTypedef for x and xx. + The user visible effect of this is that the type of a pointer + to struct foo sometimes is given as `foo *' instead of `struct foo *'. + The problem is fixed with alpha cc and Irix5 cc. */ + + /* However if the typedef cross references to an opaque aggregate, it + is safe to omit it from the symbol table. */ + + if (has_opaque_xref (cur_fdr, sh)) + break; + s = new_symbol (name); + SYMBOL_NAMESPACE (s) = VAR_NAMESPACE; + SYMBOL_CLASS (s) = LOC_TYPEDEF; + SYMBOL_BLOCK_VALUE (s) = top_stack->cur_block; + SYMBOL_TYPE (s) = t; + add_symbol (s, top_stack->cur_block); + + /* Incomplete definitions of structs should not get a name. */ + if (TYPE_NAME (SYMBOL_TYPE (s)) == NULL + && (TYPE_NFIELDS (SYMBOL_TYPE (s)) != 0 + || (TYPE_CODE (SYMBOL_TYPE (s)) != TYPE_CODE_STRUCT + && TYPE_CODE (SYMBOL_TYPE (s)) != TYPE_CODE_UNION))) + { + if (TYPE_CODE (SYMBOL_TYPE (s)) == TYPE_CODE_PTR + || TYPE_CODE (SYMBOL_TYPE (s)) == TYPE_CODE_FUNC) + { + /* If we are giving a name to a type such as "pointer to + foo" or "function returning foo", we better not set + the TYPE_NAME. If the program contains "typedef char + *caddr_t;", we don't want all variables of type char + * to print as caddr_t. This is not just a + consequence of GDB's type management; CC and GCC (at + least through version 2.4) both output variables of + either type char * or caddr_t with the type + refering to the stTypedef symbol for caddr_t. If a future + compiler cleans this up it GDB is not ready for it + yet, but if it becomes ready we somehow need to + disable this check (without breaking the PCC/GCC2.4 + case). + + Sigh. + + Fortunately, this check seems not to be necessary + for anything except pointers or functions. */ + } + else + TYPE_NAME (SYMBOL_TYPE (s)) = SYMBOL_NAME (s); + } + break; + + case stFile: /* file name */ + push_parse_stack (); + top_stack->blocktype = sh->st; + break; + + /* I`ve never seen these for C */ + case stRegReloc: + break; /* register relocation */ + case stForward: + break; /* forwarding address */ + case stConstant: + break; /* constant */ + default: + complain (&unknown_mdebug_symtype_complaint, sh->st); + break; + } + + return count; +} + +/* Parse the type information provided in the raw AX entries for + the symbol SH. Return the bitfield size in BS, in case. + We must byte-swap the AX entries before we use them; BIGEND says whether + they are big-endian or little-endian (from fh->fBigendian). */ + +static struct type * +parse_type (int fd, union aux_ext *ax, unsigned int aux_index, int *bs, + int bigend, char *sym_name) +{ + /* Null entries in this map are treated specially */ + static struct type **map_bt[] = + { + &mdebug_type_void, /* btNil */ + &mdebug_type_adr_32, /* btAdr */ + &mdebug_type_char, /* btChar */ + &mdebug_type_unsigned_char, /* btUChar */ + &mdebug_type_short, /* btShort */ + &mdebug_type_unsigned_short, /* btUShort */ + &mdebug_type_int_32, /* btInt */ + &mdebug_type_unsigned_int_32, /* btUInt */ + &mdebug_type_long_32, /* btLong */ + &mdebug_type_unsigned_long_32, /* btULong */ + &mdebug_type_float, /* btFloat */ + &mdebug_type_double, /* btDouble */ + 0, /* btStruct */ + 0, /* btUnion */ + 0, /* btEnum */ + 0, /* btTypedef */ + 0, /* btRange */ + 0, /* btSet */ + &mdebug_type_complex, /* btComplex */ + &mdebug_type_double_complex, /* btDComplex */ + 0, /* btIndirect */ + &mdebug_type_fixed_dec, /* btFixedDec */ + &mdebug_type_float_dec, /* btFloatDec */ + &mdebug_type_string, /* btString */ + 0, /* btBit */ + 0, /* btPicture */ + &mdebug_type_void, /* btVoid */ + 0, /* DEC C++: Pointer to member */ + 0, /* DEC C++: Virtual function table */ + 0, /* DEC C++: Class (Record) */ + &mdebug_type_long_64, /* btLong64 */ + &mdebug_type_unsigned_long_64, /* btULong64 */ + &mdebug_type_long_long_64, /* btLongLong64 */ + &mdebug_type_unsigned_long_long_64, /* btULongLong64 */ + &mdebug_type_adr_64, /* btAdr64 */ + &mdebug_type_int_64, /* btInt64 */ + &mdebug_type_unsigned_int_64, /* btUInt64 */ + }; + + TIR t[1]; + struct type *tp = 0; + enum type_code type_code = TYPE_CODE_UNDEF; + + /* Handle undefined types, they have indexNil. */ + if (aux_index == indexNil) + return mdebug_type_int; + + /* Handle corrupt aux indices. */ + if (aux_index >= (debug_info->fdr + fd)->caux) + { + complain (&index_complaint, sym_name); + return mdebug_type_int; + } + ax += aux_index; + + /* Use aux as a type information record, map its basic type. */ + (*debug_swap->swap_tir_in) (bigend, &ax->a_ti, t); + if (t->bt >= (sizeof (map_bt) / sizeof (*map_bt))) + { + complain (&basic_type_complaint, t->bt, sym_name); + return mdebug_type_int; + } + if (map_bt[t->bt]) + { + tp = *map_bt[t->bt]; + } + else + { + tp = NULL; + /* Cannot use builtin types -- build our own */ + switch (t->bt) + { + case btStruct: + type_code = TYPE_CODE_STRUCT; + break; + case btUnion: + type_code = TYPE_CODE_UNION; + break; + case btEnum: + type_code = TYPE_CODE_ENUM; + break; + case btRange: + type_code = TYPE_CODE_RANGE; + break; + case btSet: + type_code = TYPE_CODE_SET; + break; + case btIndirect: + /* alpha cc -migrate uses this for typedefs. The true type will + be obtained by crossreferencing below. */ + type_code = TYPE_CODE_ERROR; + break; + case btTypedef: + /* alpha cc uses this for typedefs. The true type will be + obtained by crossreferencing below. */ + type_code = TYPE_CODE_ERROR; + break; + default: + complain (&basic_type_complaint, t->bt, sym_name); + return mdebug_type_int; + } + } + + /* Move on to next aux */ + ax++; + + if (t->fBitfield) + { + int width = AUX_GET_WIDTH (bigend, ax); + + /* Inhibit core dumps with some cfront generated objects that + corrupt the TIR. */ + if (bs == (int *) NULL) + { + /* Alpha cc -migrate encodes char and unsigned char types + as short and unsigned short types with a field width of 8. + Enum types also have a field width which we ignore for now. */ + if (t->bt == btShort && width == 8) + tp = mdebug_type_char; + else if (t->bt == btUShort && width == 8) + tp = mdebug_type_unsigned_char; + else if (t->bt == btEnum) + ; + else + complain (&bad_fbitfield_complaint, sym_name); + } + else + *bs = width; + ax++; + } + + /* A btIndirect entry cross references to an aux entry containing + the type. */ + if (t->bt == btIndirect) + { + RNDXR rn[1]; + int rf; + FDR *xref_fh; + int xref_fd; + + (*debug_swap->swap_rndx_in) (bigend, &ax->a_rndx, rn); + ax++; + if (rn->rfd == 0xfff) + { + rf = AUX_GET_ISYM (bigend, ax); + ax++; + } + else + rf = rn->rfd; + + if (rf == -1) + { + complain (&bad_indirect_xref_complaint, sym_name); + return mdebug_type_int; + } + xref_fh = get_rfd (fd, rf); + xref_fd = xref_fh - debug_info->fdr; + tp = parse_type (xref_fd, debug_info->external_aux + xref_fh->iauxBase, + rn->index, (int *) NULL, xref_fh->fBigendian, sym_name); + } + + /* All these types really point to some (common) MIPS type + definition, and only the type-qualifiers fully identify + them. We'll make the same effort at sharing. */ + if (t->bt == btStruct || + t->bt == btUnion || + t->bt == btEnum || + + /* btSet (I think) implies that the name is a tag name, not a typedef + name. This apparently is a MIPS extension for C sets. */ + t->bt == btSet) + { + char *name; + + /* Try to cross reference this type, build new type on failure. */ + ax += cross_ref (fd, ax, &tp, type_code, &name, bigend, sym_name); + if (tp == (struct type *) NULL) + tp = init_type (type_code, 0, 0, (char *) NULL, current_objfile); + + /* DEC c89 produces cross references to qualified aggregate types, + dereference them. */ + while (TYPE_CODE (tp) == TYPE_CODE_PTR + || TYPE_CODE (tp) == TYPE_CODE_ARRAY) + tp = TYPE_TARGET_TYPE (tp); + + /* Make sure that TYPE_CODE(tp) has an expected type code. + Any type may be returned from cross_ref if file indirect entries + are corrupted. */ + if (TYPE_CODE (tp) != TYPE_CODE_STRUCT + && TYPE_CODE (tp) != TYPE_CODE_UNION + && TYPE_CODE (tp) != TYPE_CODE_ENUM) + { + complain (&unexpected_type_code_complaint, sym_name); + } + else + { + + /* Usually, TYPE_CODE(tp) is already type_code. The main + exception is if we guessed wrong re struct/union/enum. + But for struct vs. union a wrong guess is harmless, so + don't complain(). */ + if ((TYPE_CODE (tp) == TYPE_CODE_ENUM + && type_code != TYPE_CODE_ENUM) + || (TYPE_CODE (tp) != TYPE_CODE_ENUM + && type_code == TYPE_CODE_ENUM)) + { + complain (&bad_tag_guess_complaint, sym_name); + } + + if (TYPE_CODE (tp) != type_code) + { + TYPE_CODE (tp) = type_code; + } + + /* Do not set the tag name if it is a compiler generated tag name + (.Fxx or .xxfake or empty) for unnamed struct/union/enums. */ + if (name[0] == '.' || name[0] == '\0') + TYPE_TAG_NAME (tp) = NULL; + else if (TYPE_TAG_NAME (tp) == NULL + || !STREQ (TYPE_TAG_NAME (tp), name)) + TYPE_TAG_NAME (tp) = obsavestring (name, strlen (name), + ¤t_objfile->type_obstack); + } + } + + /* All these types really point to some (common) MIPS type + definition, and only the type-qualifiers fully identify + them. We'll make the same effort at sharing. + FIXME: We are not doing any guessing on range types. */ + if (t->bt == btRange) + { + char *name; + + /* Try to cross reference this type, build new type on failure. */ + ax += cross_ref (fd, ax, &tp, type_code, &name, bigend, sym_name); + if (tp == (struct type *) NULL) + tp = init_type (type_code, 0, 0, (char *) NULL, current_objfile); + + /* Make sure that TYPE_CODE(tp) has an expected type code. + Any type may be returned from cross_ref if file indirect entries + are corrupted. */ + if (TYPE_CODE (tp) != TYPE_CODE_RANGE) + { + complain (&unexpected_type_code_complaint, sym_name); + } + else + { + /* Usually, TYPE_CODE(tp) is already type_code. The main + exception is if we guessed wrong re struct/union/enum. */ + if (TYPE_CODE (tp) != type_code) + { + complain (&bad_tag_guess_complaint, sym_name); + TYPE_CODE (tp) = type_code; + } + if (TYPE_NAME (tp) == NULL || !STREQ (TYPE_NAME (tp), name)) + TYPE_NAME (tp) = obsavestring (name, strlen (name), + ¤t_objfile->type_obstack); + } + } + if (t->bt == btTypedef) + { + char *name; + + /* Try to cross reference this type, it should succeed. */ + ax += cross_ref (fd, ax, &tp, type_code, &name, bigend, sym_name); + if (tp == (struct type *) NULL) + { + complain (&unable_to_cross_ref_complaint, sym_name); + tp = mdebug_type_int; + } + } + + /* Deal with range types */ + if (t->bt == btRange) + { + TYPE_NFIELDS (tp) = 2; + TYPE_FIELDS (tp) = ((struct field *) + TYPE_ALLOC (tp, 2 * sizeof (struct field))); + TYPE_FIELD_NAME (tp, 0) = obsavestring ("Low", strlen ("Low"), + ¤t_objfile->type_obstack); + TYPE_FIELD_BITPOS (tp, 0) = AUX_GET_DNLOW (bigend, ax); + ax++; + TYPE_FIELD_NAME (tp, 1) = obsavestring ("High", strlen ("High"), + ¤t_objfile->type_obstack); + TYPE_FIELD_BITPOS (tp, 1) = AUX_GET_DNHIGH (bigend, ax); + ax++; + } + + /* Parse all the type qualifiers now. If there are more + than 6 the game will continue in the next aux */ + + while (1) + { +#define PARSE_TQ(tq) \ + if (t->tq != tqNil) \ + ax += upgrade_type(fd, &tp, t->tq, ax, bigend, sym_name); \ + else \ + break; + + PARSE_TQ (tq0); + PARSE_TQ (tq1); + PARSE_TQ (tq2); + PARSE_TQ (tq3); + PARSE_TQ (tq4); + PARSE_TQ (tq5); +#undef PARSE_TQ + + /* mips cc 2.x and gcc never put out continued aux entries. */ + if (!t->continued) + break; + + (*debug_swap->swap_tir_in) (bigend, &ax->a_ti, t); + ax++; + } + + /* Complain for illegal continuations due to corrupt aux entries. */ + if (t->continued) + complain (&bad_continued_complaint, sym_name); + + return tp; +} + +/* Make up a complex type from a basic one. Type is passed by + reference in TPP and side-effected as necessary. The type + qualifier TQ says how to handle the aux symbols at AX for + the symbol SX we are currently analyzing. BIGEND says whether + aux symbols are big-endian or little-endian. + Returns the number of aux symbols we parsed. */ + +static int +upgrade_type (int fd, struct type **tpp, int tq, union aux_ext *ax, int bigend, + char *sym_name) +{ + int off; + struct type *t; + + /* Used in array processing */ + int rf, id; + FDR *fh; + struct type *range; + struct type *indx; + int lower, upper; + RNDXR rndx; + + switch (tq) + { + case tqPtr: + t = lookup_pointer_type (*tpp); + *tpp = t; + return 0; + + case tqProc: + t = lookup_function_type (*tpp); + *tpp = t; + return 0; + + case tqArray: + off = 0; + + /* Determine and record the domain type (type of index) */ + (*debug_swap->swap_rndx_in) (bigend, &ax->a_rndx, &rndx); + id = rndx.index; + rf = rndx.rfd; + if (rf == 0xfff) + { + ax++; + rf = AUX_GET_ISYM (bigend, ax); + off++; + } + fh = get_rfd (fd, rf); + + indx = parse_type (fh - debug_info->fdr, + debug_info->external_aux + fh->iauxBase, + id, (int *) NULL, bigend, sym_name); + + /* The bounds type should be an integer type, but might be anything + else due to corrupt aux entries. */ + if (TYPE_CODE (indx) != TYPE_CODE_INT) + { + complain (&array_index_type_complaint, sym_name); + indx = mdebug_type_int; + } + + /* Get the bounds, and create the array type. */ + ax++; + lower = AUX_GET_DNLOW (bigend, ax); + ax++; + upper = AUX_GET_DNHIGH (bigend, ax); + ax++; + rf = AUX_GET_WIDTH (bigend, ax); /* bit size of array element */ + + range = create_range_type ((struct type *) NULL, indx, + lower, upper); + + t = create_array_type ((struct type *) NULL, *tpp, range); + + /* We used to fill in the supplied array element bitsize + here if the TYPE_LENGTH of the target type was zero. + This happens for a `pointer to an array of anonymous structs', + but in this case the array element bitsize is also zero, + so nothing is gained. + And we used to check the TYPE_LENGTH of the target type against + the supplied array element bitsize. + gcc causes a mismatch for `pointer to array of object', + since the sdb directives it uses do not have a way of + specifying the bitsize, but it does no harm (the + TYPE_LENGTH should be correct) and we should be able to + ignore the erroneous bitsize from the auxiliary entry safely. + dbx seems to ignore it too. */ + + /* TYPE_FLAG_TARGET_STUB now takes care of the zero TYPE_LENGTH + problem. */ + if (TYPE_LENGTH (*tpp) == 0) + { + TYPE_FLAGS (t) |= TYPE_FLAG_TARGET_STUB; + } + + *tpp = t; + return 4 + off; + + case tqVol: + /* Volatile -- currently ignored */ + return 0; + + case tqConst: + /* Const -- currently ignored */ + return 0; + + default: + complain (&unknown_type_qual_complaint, tq); + return 0; + } +} + + +/* Parse a procedure descriptor record PR. Note that the procedure is + parsed _after_ the local symbols, now we just insert the extra + information we need into a MIPS_EFI_SYMBOL_NAME symbol that has + already been placed in the procedure's main block. Note also that + images that have been partially stripped (ld -x) have been deprived + of local symbols, and we have to cope with them here. FIRST_OFF is + the offset of the first procedure for this FDR; we adjust the + address by this amount, but I don't know why. SEARCH_SYMTAB is the symtab + to look for the function which contains the MIPS_EFI_SYMBOL_NAME symbol + in question, or NULL to use top_stack->cur_block. */ + +static void parse_procedure (PDR *, struct symtab *, struct partial_symtab *); + +static void +parse_procedure (PDR *pr, struct symtab *search_symtab, + struct partial_symtab *pst) +{ + struct symbol *s, *i; + struct block *b; + struct mips_extra_func_info *e; + char *sh_name; + + /* Simple rule to find files linked "-x" */ + if (cur_fdr->rss == -1) + { + if (pr->isym == -1) + { + /* Static procedure at address pr->adr. Sigh. */ + /* FIXME-32x64. assuming pr->adr fits in long. */ + complain (&pdr_static_symbol_complaint, (unsigned long) pr->adr); + return; + } + else + { + /* external */ + EXTR she; + + (*debug_swap->swap_ext_in) (cur_bfd, + ((char *) debug_info->external_ext + + (pr->isym + * debug_swap->external_ext_size)), + &she); + sh_name = debug_info->ssext + she.asym.iss; + } + } + else + { + /* Full symbols */ + SYMR sh; + + (*debug_swap->swap_sym_in) (cur_bfd, + ((char *) debug_info->external_sym + + ((cur_fdr->isymBase + pr->isym) + * debug_swap->external_sym_size)), + &sh); + sh_name = debug_info->ss + cur_fdr->issBase + sh.iss; + } + + if (search_symtab != NULL) + { +#if 0 + /* This loses both in the case mentioned (want a static, find a global), + but also if we are looking up a non-mangled name which happens to + match the name of a mangled function. */ + /* We have to save the cur_fdr across the call to lookup_symbol. + If the pdr is for a static function and if a global function with + the same name exists, lookup_symbol will eventually read in the symtab + for the global function and clobber cur_fdr. */ + FDR *save_cur_fdr = cur_fdr; + s = lookup_symbol (sh_name, NULL, VAR_NAMESPACE, 0, NULL); + cur_fdr = save_cur_fdr; +#else + s = mylookup_symbol + (sh_name, + BLOCKVECTOR_BLOCK (BLOCKVECTOR (search_symtab), STATIC_BLOCK), + VAR_NAMESPACE, + LOC_BLOCK); +#endif + } + else + s = mylookup_symbol (sh_name, top_stack->cur_block, + VAR_NAMESPACE, LOC_BLOCK); + + if (s != 0) + { + b = SYMBOL_BLOCK_VALUE (s); + } + else + { + complain (&pdr_for_nonsymbol_complaint, sh_name); +#if 1 + return; +#else +/* FIXME -- delete. We can't do symbol allocation now; it's all done. */ + s = new_symbol (sh_name); + SYMBOL_NAMESPACE (s) = VAR_NAMESPACE; + SYMBOL_CLASS (s) = LOC_BLOCK; + /* Donno its type, hope int is ok */ + SYMBOL_TYPE (s) = lookup_function_type (mdebug_type_int); + add_symbol (s, top_stack->cur_block); + /* Wont have symbols for this one */ + b = new_block (2); + SYMBOL_BLOCK_VALUE (s) = b; + BLOCK_FUNCTION (b) = s; + BLOCK_START (b) = pr->adr; + /* BOUND used to be the end of procedure's text, but the + argument is no longer passed in. */ + BLOCK_END (b) = bound; + BLOCK_SUPERBLOCK (b) = top_stack->cur_block; + add_block (b, top_stack->cur_st); +#endif + } + + i = mylookup_symbol (MIPS_EFI_SYMBOL_NAME, b, LABEL_NAMESPACE, LOC_CONST); + + if (i) + { + e = (struct mips_extra_func_info *) SYMBOL_VALUE (i); + e->pdr = *pr; + e->pdr.isym = (long) s; + + /* GDB expects the absolute function start address for the + procedure descriptor in e->pdr.adr. + As the address in the procedure descriptor is usually relative, + we would have to relocate e->pdr.adr with cur_fdr->adr and + ANOFFSET (pst->section_offsets, SECT_OFF_TEXT (pst->objfile)). + Unfortunately cur_fdr->adr and e->pdr.adr are both absolute + in shared libraries on some systems, and on other systems + e->pdr.adr is sometimes offset by a bogus value. + To work around these problems, we replace e->pdr.adr with + the start address of the function. */ + e->pdr.adr = BLOCK_START (b); + + /* Correct incorrect setjmp procedure descriptor from the library + to make backtrace through setjmp work. */ + if (e->pdr.pcreg == 0 && STREQ (sh_name, "setjmp")) + { + complain (&bad_setjmp_pdr_complaint, 0); + e->pdr.pcreg = RA_REGNUM; + e->pdr.regmask = 0x80000000; + e->pdr.regoffset = -4; + } + } + + /* It would be reasonable that functions that have been compiled + without debugging info have a btNil type for their return value, + and functions that are void and are compiled with debugging info + have btVoid. + gcc and DEC f77 put out btNil types for both cases, so btNil is mapped + to TYPE_CODE_VOID in parse_type to get the `compiled with debugging info' + case right. + The glevel field in cur_fdr could be used to determine the presence + of debugging info, but GCC doesn't always pass the -g switch settings + to the assembler and GAS doesn't set the glevel field from the -g switch + settings. + To work around these problems, the return value type of a TYPE_CODE_VOID + function is adjusted accordingly if no debugging info was found in the + compilation unit. */ + + if (processing_gcc_compilation == 0 + && found_ecoff_debugging_info == 0 + && TYPE_CODE (TYPE_TARGET_TYPE (SYMBOL_TYPE (s))) == TYPE_CODE_VOID) + SYMBOL_TYPE (s) = nodebug_func_symbol_type; +} + +/* Relocate the extra function info pointed to by the symbol table. */ + +void +ecoff_relocate_efi (struct symbol *sym, CORE_ADDR delta) +{ + struct mips_extra_func_info *e; + + e = (struct mips_extra_func_info *) SYMBOL_VALUE (sym); + + e->pdr.adr += delta; +} + +/* Parse the external symbol ES. Just call parse_symbol() after + making sure we know where the aux are for it. + BIGEND says whether aux entries are big-endian or little-endian. + + This routine clobbers top_stack->cur_block and ->cur_st. */ + +static void parse_external (EXTR *, int, struct section_offsets *, + struct objfile *); + +static void +parse_external (EXTR *es, int bigend, struct section_offsets *section_offsets, + struct objfile *objfile) +{ + union aux_ext *ax; + + if (es->ifd != ifdNil) + { + cur_fd = es->ifd; + cur_fdr = debug_info->fdr + cur_fd; + ax = debug_info->external_aux + cur_fdr->iauxBase; + } + else + { + cur_fdr = debug_info->fdr; + ax = 0; + } + + /* Reading .o files */ + if (SC_IS_UNDEF (es->asym.sc) || es->asym.sc == scNil) + { + char *what; + switch (es->asym.st) + { + case stNil: + /* These are generated for static symbols in .o files, + ignore them. */ + return; + case stStaticProc: + case stProc: + what = "procedure"; + n_undef_procs++; + break; + case stGlobal: + what = "variable"; + n_undef_vars++; + break; + case stLabel: + what = "label"; + n_undef_labels++; + break; + default: + what = "symbol"; + break; + } + n_undef_symbols++; + /* FIXME: Turn this into a complaint? */ + if (info_verbose) + printf_filtered ("Warning: %s `%s' is undefined (in %s)\n", + what, debug_info->ssext + es->asym.iss, + fdr_name (cur_fdr)); + return; + } + + switch (es->asym.st) + { + case stProc: + case stStaticProc: + /* There is no need to parse the external procedure symbols. + If they are from objects compiled without -g, their index will + be indexNil, and the symbol definition from the minimal symbol + is preferrable (yielding a function returning int instead of int). + If the index points to a local procedure symbol, the local + symbol already provides the correct type. + Note that the index of the external procedure symbol points + to the local procedure symbol in the local symbol table, and + _not_ to the auxiliary symbol info. */ + break; + case stGlobal: + case stLabel: + /* Global common symbols are resolved by the runtime loader, + ignore them. */ + if (SC_IS_COMMON (es->asym.sc)) + break; + + /* Note that the case of a symbol with indexNil must be handled + anyways by parse_symbol(). */ + parse_symbol (&es->asym, ax, (char *) NULL, bigend, section_offsets, objfile); + break; + default: + break; + } +} + +/* Parse the line number info for file descriptor FH into + GDB's linetable LT. MIPS' encoding requires a little bit + of magic to get things out. Note also that MIPS' line + numbers can go back and forth, apparently we can live + with that and do not need to reorder our linetables */ + +static void parse_lines (FDR *, PDR *, struct linetable *, int, + struct partial_symtab *, CORE_ADDR); + +static void +parse_lines (FDR *fh, PDR *pr, struct linetable *lt, int maxlines, + struct partial_symtab *pst, CORE_ADDR lowest_pdr_addr) +{ + unsigned char *base; + int j, k; + int delta, count, lineno = 0; + + if (fh->cbLine == 0) + return; + + /* Scan by procedure descriptors */ + k = 0; + for (j = 0; j < fh->cpd; j++, pr++) + { + CORE_ADDR l; + CORE_ADDR adr; + unsigned char *halt; + + /* No code for this one */ + if (pr->iline == ilineNil || + pr->lnLow == -1 || pr->lnHigh == -1) + continue; + + /* Determine start and end address of compressed line bytes for + this procedure. */ + base = debug_info->line + fh->cbLineOffset; + if (j != (fh->cpd - 1)) + halt = base + pr[1].cbLineOffset; + else + halt = base + fh->cbLine; + base += pr->cbLineOffset; + + adr = pst->textlow + pr->adr - lowest_pdr_addr; + + l = adr >> 2; /* in words */ + for (lineno = pr->lnLow; base < halt;) + { + count = *base & 0x0f; + delta = *base++ >> 4; + if (delta >= 8) + delta -= 16; + if (delta == -8) + { + delta = (base[0] << 8) | base[1]; + if (delta >= 0x8000) + delta -= 0x10000; + base += 2; + } + lineno += delta; /* first delta is 0 */ + + /* Complain if the line table overflows. Could happen + with corrupt binaries. */ + if (lt->nitems >= maxlines) + { + complain (&bad_linetable_guess_complaint, fdr_name (fh)); + break; + } + k = add_line (lt, lineno, l, k); + l += count + 1; + } + } +} + +/* Master parsing procedure for first-pass reading of file symbols + into a partial_symtab. */ + +static void +parse_partial_symbols (struct objfile *objfile) +{ + const bfd_size_type external_sym_size = debug_swap->external_sym_size; + const bfd_size_type external_rfd_size = debug_swap->external_rfd_size; + const bfd_size_type external_ext_size = debug_swap->external_ext_size; + void (*const swap_ext_in) (bfd *, void *, EXTR *) = debug_swap->swap_ext_in; + void (*const swap_sym_in) (bfd *, void *, SYMR *) = debug_swap->swap_sym_in; + void (*const swap_rfd_in) (bfd *, void *, RFDT *) = debug_swap->swap_rfd_in; + int f_idx, s_idx; + HDRR *hdr = &debug_info->symbolic_header; + /* Running pointers */ + FDR *fh; + char *ext_out; + char *ext_out_end; + EXTR *ext_block; + register EXTR *ext_in; + EXTR *ext_in_end; + SYMR sh; + struct partial_symtab *pst; + int textlow_not_set = 1; + int past_first_source_file = 0; + + /* List of current psymtab's include files */ + char **psymtab_include_list; + int includes_allocated; + int includes_used; + EXTR *extern_tab; + struct pst_map *fdr_to_pst; + /* Index within current psymtab dependency list */ + struct partial_symtab **dependency_list; + int dependencies_used, dependencies_allocated; + struct cleanup *old_chain; + char *name; + enum language prev_language; + asection *text_sect; + int relocatable = 0; + + /* Irix 5.2 shared libraries have a fh->adr field of zero, but + the shared libraries are prelinked at a high memory address. + We have to adjust the start address of the object file for this case, + by setting it to the start address of the first procedure in the file. + But we should do no adjustments if we are debugging a .o file, where + the text section (and fh->adr) really starts at zero. */ + text_sect = bfd_get_section_by_name (cur_bfd, ".text"); + if (text_sect != NULL + && (bfd_get_section_flags (cur_bfd, text_sect) & SEC_RELOC)) + relocatable = 1; + + extern_tab = (EXTR *) obstack_alloc (&objfile->psymbol_obstack, + sizeof (EXTR) * hdr->iextMax); + + includes_allocated = 30; + includes_used = 0; + psymtab_include_list = (char **) alloca (includes_allocated * + sizeof (char *)); + next_symbol_text_func = mdebug_next_symbol_text; + + dependencies_allocated = 30; + dependencies_used = 0; + dependency_list = + (struct partial_symtab **) alloca (dependencies_allocated * + sizeof (struct partial_symtab *)); + + last_source_file = NULL; + + /* + * Big plan: + * + * Only parse the Local and External symbols, and the Relative FDR. + * Fixup enough of the loader symtab to be able to use it. + * Allocate space only for the file's portions we need to + * look at. (XXX) + */ + + max_gdbinfo = 0; + max_glevel = MIN_GLEVEL; + + /* Allocate the map FDR -> PST. + Minor hack: -O3 images might claim some global data belongs + to FDR -1. We`ll go along with that */ + fdr_to_pst = (struct pst_map *) xzalloc ((hdr->ifdMax + 1) * sizeof *fdr_to_pst); + old_chain = make_cleanup (xfree, fdr_to_pst); + fdr_to_pst++; + { + struct partial_symtab *pst = new_psymtab ("", objfile); + fdr_to_pst[-1].pst = pst; + FDR_IDX (pst) = -1; + } + + /* Allocate the global pending list. */ + pending_list = + ((struct mdebug_pending **) + obstack_alloc (&objfile->psymbol_obstack, + hdr->ifdMax * sizeof (struct mdebug_pending *))); + memset (pending_list, 0, + hdr->ifdMax * sizeof (struct mdebug_pending *)); + + /* Pass 0 over external syms: swap them in. */ + ext_block = (EXTR *) xmalloc (hdr->iextMax * sizeof (EXTR)); + make_cleanup (xfree, ext_block); + + ext_out = (char *) debug_info->external_ext; + ext_out_end = ext_out + hdr->iextMax * external_ext_size; + ext_in = ext_block; + for (; ext_out < ext_out_end; ext_out += external_ext_size, ext_in++) + (*swap_ext_in) (cur_bfd, ext_out, ext_in); + + /* Pass 1 over external syms: Presize and partition the list */ + ext_in = ext_block; + ext_in_end = ext_in + hdr->iextMax; + for (; ext_in < ext_in_end; ext_in++) + { + /* See calls to complain below. */ + if (ext_in->ifd >= -1 + && ext_in->ifd < hdr->ifdMax + && ext_in->asym.iss >= 0 + && ext_in->asym.iss < hdr->issExtMax) + fdr_to_pst[ext_in->ifd].n_globals++; + } + + /* Pass 1.5 over files: partition out global symbol space */ + s_idx = 0; + for (f_idx = -1; f_idx < hdr->ifdMax; f_idx++) + { + fdr_to_pst[f_idx].globals_offset = s_idx; + s_idx += fdr_to_pst[f_idx].n_globals; + fdr_to_pst[f_idx].n_globals = 0; + } + + /* ECOFF in ELF: + + For ECOFF in ELF, we skip the creation of the minimal symbols. + The ECOFF symbols should be a subset of the Elf symbols, and the + section information of the elf symbols will be more accurate. + FIXME! What about Irix 5's native linker? + + By default, Elf sections which don't exist in ECOFF + get put in ECOFF's absolute section by the gnu linker. + Since absolute sections don't get relocated, we + end up calculating an address different from that of + the symbol's minimal symbol (created earlier from the + Elf symtab). + + To fix this, either : + 1) don't create the duplicate symbol + (assumes ECOFF symtab is a subset of the ELF symtab; + assumes no side-effects result from ignoring ECOFF symbol) + 2) create it, only if lookup for existing symbol in ELF's minimal + symbols fails + (inefficient; + assumes no side-effects result from ignoring ECOFF symbol) + 3) create it, but lookup ELF's minimal symbol and use it's section + during relocation, then modify "uniqify" phase to merge and + eliminate the duplicate symbol + (highly inefficient) + + I've implemented #1 here... + Skip the creation of the minimal symbols based on the ECOFF + symbol table. */ + + /* Pass 2 over external syms: fill in external symbols */ + ext_in = ext_block; + ext_in_end = ext_in + hdr->iextMax; + for (; ext_in < ext_in_end; ext_in++) + { + enum minimal_symbol_type ms_type = mst_text; + CORE_ADDR svalue = ext_in->asym.value; + + /* The Irix 5 native tools seem to sometimes generate bogus + external symbols. */ + if (ext_in->ifd < -1 || ext_in->ifd >= hdr->ifdMax) + { + complain (&bad_ext_ifd_complaint, ext_in->ifd, hdr->ifdMax); + continue; + } + if (ext_in->asym.iss < 0 || ext_in->asym.iss >= hdr->issExtMax) + { + complain (&bad_ext_iss_complaint, ext_in->asym.iss, + hdr->issExtMax); + continue; + } + + extern_tab[fdr_to_pst[ext_in->ifd].globals_offset + + fdr_to_pst[ext_in->ifd].n_globals++] = *ext_in; + + + if (SC_IS_UNDEF (ext_in->asym.sc) || ext_in->asym.sc == scNil) + continue; + + + /* Pass 3 over files, over local syms: fill in static symbols */ + name = debug_info->ssext + ext_in->asym.iss; + + /* Process ECOFF Symbol Types and Storage Classes */ + switch (ext_in->asym.st) + { + case stProc: + /* Beginnning of Procedure */ + svalue += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + break; + case stStaticProc: + /* Load time only static procs */ + ms_type = mst_file_text; + svalue += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + break; + case stGlobal: + /* External symbol */ + if (SC_IS_COMMON (ext_in->asym.sc)) + { + /* The value of a common symbol is its size, not its address. + Ignore it. */ + continue; + } + else if (SC_IS_DATA (ext_in->asym.sc)) + { + ms_type = mst_data; + svalue += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile)); + } + else if (SC_IS_BSS (ext_in->asym.sc)) + { + ms_type = mst_bss; + svalue += ANOFFSET (objfile->section_offsets, SECT_OFF_BSS (objfile)); + } + else if (SC_IS_SBSS (ext_in->asym.sc)) + { + ms_type = mst_bss; + svalue += ANOFFSET (objfile->section_offsets, + get_section_index (objfile, ".sbss")); + } + else + ms_type = mst_abs; + break; + case stLabel: + /* Label */ + + /* On certain platforms, some extra label symbols can be + generated by the linker. One possible usage for this kind + of symbols is to represent the address of the begining of a + given section. For instance, on Tru64 5.1, the address of + the _ftext label is the start address of the .text section. + + The storage class of these symbols is usually directly + related to the section to which the symbol refers. For + instance, on Tru64 5.1, the storage class for the _fdata + label is scData, refering to the .data section. + + It is actually possible that the section associated to the + storage class of the label does not exist. On True64 5.1 + for instance, the libm.so shared library does not contain + any .data section, although it contains a _fpdata label + which storage class is scData... Since these symbols are + usually useless for the debugger user anyway, we just + discard these symbols. + */ + + if (SC_IS_TEXT (ext_in->asym.sc)) + { + if (objfile->sect_index_text == -1) + continue; + + ms_type = mst_file_text; + svalue += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + } + else if (SC_IS_DATA (ext_in->asym.sc)) + { + if (objfile->sect_index_data == -1) + continue; + + ms_type = mst_file_data; + svalue += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile)); + } + else if (SC_IS_BSS (ext_in->asym.sc)) + { + if (objfile->sect_index_bss == -1) + continue; + + ms_type = mst_file_bss; + svalue += ANOFFSET (objfile->section_offsets, SECT_OFF_BSS (objfile)); + } + else if (SC_IS_SBSS (ext_in->asym.sc)) + { + const int sbss_sect_index = get_section_index (objfile, ".sbss"); + + if (sbss_sect_index == -1) + continue; + + ms_type = mst_file_bss; + svalue += ANOFFSET (objfile->section_offsets, sbss_sect_index); + } + else + ms_type = mst_abs; + break; + case stLocal: + case stNil: + /* The alpha has the section start addresses in stLocal symbols + whose name starts with a `.'. Skip those but complain for all + other stLocal symbols. + Irix6 puts the section start addresses in stNil symbols, skip + those too. */ + if (name[0] == '.') + continue; + /* Fall through. */ + default: + ms_type = mst_unknown; + complain (&unknown_ext_complaint, name); + } + if (!ECOFF_IN_ELF (cur_bfd)) + prim_record_minimal_symbol (name, svalue, ms_type, objfile); + } + + /* Pass 3 over files, over local syms: fill in static symbols */ + for (f_idx = 0; f_idx < hdr->ifdMax; f_idx++) + { + struct partial_symtab *save_pst; + EXTR *ext_ptr; + CORE_ADDR textlow; + + cur_fdr = fh = debug_info->fdr + f_idx; + + if (fh->csym == 0) + { + fdr_to_pst[f_idx].pst = NULL; + continue; + } + + /* Determine the start address for this object file from the + file header and relocate it, except for Irix 5.2 zero fh->adr. */ + if (fh->cpd) + { + textlow = fh->adr; + if (relocatable || textlow != 0) + textlow += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + } + else + textlow = 0; + pst = start_psymtab_common (objfile, objfile->section_offsets, + fdr_name (fh), + textlow, + objfile->global_psymbols.next, + objfile->static_psymbols.next); + pst->read_symtab_private = ((char *) + obstack_alloc (&objfile->psymbol_obstack, + sizeof (struct symloc))); + memset (pst->read_symtab_private, 0, sizeof (struct symloc)); + + save_pst = pst; + FDR_IDX (pst) = f_idx; + CUR_BFD (pst) = cur_bfd; + DEBUG_SWAP (pst) = debug_swap; + DEBUG_INFO (pst) = debug_info; + PENDING_LIST (pst) = pending_list; + + /* The way to turn this into a symtab is to call... */ + pst->read_symtab = mdebug_psymtab_to_symtab; + + /* Set up language for the pst. + The language from the FDR is used if it is unambigious (e.g. cfront + with native cc and g++ will set the language to C). + Otherwise we have to deduce the language from the filename. + Native ecoff has every header file in a separate FDR, so + deduce_language_from_filename will return language_unknown for + a header file, which is not what we want. + But the FDRs for the header files are after the FDR for the source + file, so we can assign the language of the source file to the + following header files. Then we save the language in the private + pst data so that we can reuse it when building symtabs. */ + prev_language = psymtab_language; + + switch (fh->lang) + { + case langCplusplusV2: + psymtab_language = language_cplus; + break; + default: + psymtab_language = deduce_language_from_filename (fdr_name (fh)); + break; + } + if (psymtab_language == language_unknown) + psymtab_language = prev_language; + PST_PRIVATE (pst)->pst_language = psymtab_language; + + pst->texthigh = pst->textlow; + + /* For stabs-in-ecoff files, the second symbol must be @stab. + This symbol is emitted by mips-tfile to signal that the + current object file uses encapsulated stabs instead of mips + ecoff for local symbols. (It is the second symbol because + the first symbol is the stFile used to signal the start of a + file). */ + processing_gcc_compilation = 0; + if (fh->csym >= 2) + { + (*swap_sym_in) (cur_bfd, + ((char *) debug_info->external_sym + + (fh->isymBase + 1) * external_sym_size), + &sh); + if (STREQ (debug_info->ss + fh->issBase + sh.iss, stabs_symbol)) + processing_gcc_compilation = 2; + } + + if (processing_gcc_compilation != 0) + { + for (cur_sdx = 2; cur_sdx < fh->csym; cur_sdx++) + { + int type_code; + char *namestring; + + (*swap_sym_in) (cur_bfd, + (((char *) debug_info->external_sym) + + (fh->isymBase + cur_sdx) * external_sym_size), + &sh); + type_code = ECOFF_UNMARK_STAB (sh.index); + if (!ECOFF_IS_STAB (&sh)) + { + if (sh.st == stProc || sh.st == stStaticProc) + { + CORE_ADDR procaddr; + long isym; + + sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + if (sh.st == stStaticProc) + { + namestring = debug_info->ss + fh->issBase + sh.iss; + prim_record_minimal_symbol_and_info (namestring, + sh.value, + mst_file_text, + NULL, + SECT_OFF_TEXT (objfile), + NULL, + objfile); + } + procaddr = sh.value; + + isym = AUX_GET_ISYM (fh->fBigendian, + (debug_info->external_aux + + fh->iauxBase + + sh.index)); + (*swap_sym_in) (cur_bfd, + ((char *) debug_info->external_sym + + ((fh->isymBase + isym - 1) + * external_sym_size)), + &sh); + if (sh.st == stEnd) + { + CORE_ADDR high = procaddr + sh.value; + + /* Kludge for Irix 5.2 zero fh->adr. */ + if (!relocatable + && (pst->textlow == 0 || procaddr < pst->textlow)) + pst->textlow = procaddr; + if (high > pst->texthigh) + pst->texthigh = high; + } + } + else if (sh.st == stStatic) + { + switch (sh.sc) + { + case scUndefined: + case scSUndefined: + case scNil: + case scAbs: + break; + + case scData: + case scSData: + case scRData: + case scPData: + case scXData: + namestring = debug_info->ss + fh->issBase + sh.iss; + sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile)); + prim_record_minimal_symbol_and_info (namestring, + sh.value, + mst_file_data, + NULL, + SECT_OFF_DATA (objfile), + NULL, + objfile); + break; + + default: + /* FIXME! Shouldn't this use cases for bss, + then have the default be abs? */ + namestring = debug_info->ss + fh->issBase + sh.iss; + sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_BSS (objfile)); + prim_record_minimal_symbol_and_info (namestring, + sh.value, + mst_file_bss, + NULL, + SECT_OFF_BSS (objfile), + NULL, + objfile); + break; + } + } + continue; + } + /* Handle stabs continuation */ + { + char *stabstring = debug_info->ss + fh->issBase + sh.iss; + int len = strlen (stabstring); + while (stabstring[len - 1] == '\\') + { + SYMR sh2; + char *stabstring1 = stabstring; + char *stabstring2; + int len2; + + /* Ignore continuation char from 1st string */ + len--; + + /* Read next stabstring */ + cur_sdx++; + (*swap_sym_in) (cur_bfd, + (((char *) debug_info->external_sym) + + (fh->isymBase + cur_sdx) + * external_sym_size), + &sh2); + stabstring2 = debug_info->ss + fh->issBase + sh2.iss; + len2 = strlen (stabstring2); + + /* Concatinate stabstring2 with stabstring1 */ + if (stabstring + && stabstring != debug_info->ss + fh->issBase + sh.iss) + stabstring = xrealloc (stabstring, len + len2 + 1); + else + { + stabstring = xmalloc (len + len2 + 1); + strcpy (stabstring, stabstring1); + } + strcpy (stabstring + len, stabstring2); + len += len2; + } + + switch (type_code) + { + static struct complaint function_outside_compilation_unit = { + "function `%s' appears to be defined outside of all compilation units", 0, 0 + }; + char *p; + /* + * Standard, external, non-debugger, symbols + */ + + case N_TEXT | N_EXT: + case N_NBTEXT | N_EXT: + sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + goto record_it; + + case N_DATA | N_EXT: + case N_NBDATA | N_EXT: + sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile)); + goto record_it; + + case N_BSS: + case N_BSS | N_EXT: + case N_NBBSS | N_EXT: + case N_SETV | N_EXT: /* FIXME, is this in BSS? */ + sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_BSS (objfile)); + goto record_it; + + case N_ABS | N_EXT: + record_it: + continue; + + /* Standard, local, non-debugger, symbols */ + + case N_NBTEXT: + + /* We need to be able to deal with both N_FN or N_TEXT, + because we have no way of knowing whether the sys-supplied ld + or GNU ld was used to make the executable. Sequents throw + in another wrinkle -- they renumbered N_FN. */ + + case N_FN: + case N_FN_SEQ: + case N_TEXT: + continue; + + case N_DATA: + sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile)); + goto record_it; + + case N_UNDF | N_EXT: + continue; /* Just undefined, not COMMON */ + + case N_UNDF: + continue; + + /* Lots of symbol types we can just ignore. */ + + case N_ABS: + case N_NBDATA: + case N_NBBSS: + continue; + + /* Keep going . . . */ + + /* + * Special symbol types for GNU + */ + case N_INDR: + case N_INDR | N_EXT: + case N_SETA: + case N_SETA | N_EXT: + case N_SETT: + case N_SETT | N_EXT: + case N_SETD: + case N_SETD | N_EXT: + case N_SETB: + case N_SETB | N_EXT: + case N_SETV: + continue; + + /* + * Debugger symbols + */ + + case N_SO: + { + CORE_ADDR valu; + static int prev_so_symnum = -10; + static int first_so_symnum; + char *p; + int prev_textlow_not_set; + + valu = sh.value + ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + + prev_textlow_not_set = textlow_not_set; + +#ifdef SOFUN_ADDRESS_MAYBE_MISSING + /* A zero value is probably an indication for the SunPRO 3.0 + compiler. end_psymtab explicitly tests for zero, so + don't relocate it. */ + + if (sh.value == 0) + { + textlow_not_set = 1; + valu = 0; + } + else + textlow_not_set = 0; +#else + textlow_not_set = 0; +#endif + past_first_source_file = 1; + + if (prev_so_symnum != symnum - 1) + { /* Here if prev stab wasn't N_SO */ + first_so_symnum = symnum; + + if (pst) + { + pst = (struct partial_symtab *) 0; + includes_used = 0; + dependencies_used = 0; + } + } + + prev_so_symnum = symnum; + + /* End the current partial symtab and start a new one */ + + /* SET_NAMESTRING ();*/ + namestring = stabstring; + + /* Null name means end of .o file. Don't start a new one. */ + if (*namestring == '\000') + continue; + + /* Some compilers (including gcc) emit a pair of initial N_SOs. + The first one is a directory name; the second the file name. + If pst exists, is empty, and has a filename ending in '/', + we assume the previous N_SO was a directory name. */ + + p = strrchr (namestring, '/'); + if (p && *(p + 1) == '\000') + continue; /* Simply ignore directory name SOs */ + + /* Some other compilers (C++ ones in particular) emit useless + SOs for non-existant .c files. We ignore all subsequent SOs that + immediately follow the first. */ + + if (!pst) + pst = save_pst; + continue; + } + + case N_BINCL: + continue; + + case N_SOL: + { + enum language tmp_language; + /* Mark down an include file in the current psymtab */ + + /* SET_NAMESTRING ();*/ + namestring = stabstring; + + tmp_language = deduce_language_from_filename (namestring); + + /* Only change the psymtab's language if we've learned + something useful (eg. tmp_language is not language_unknown). + In addition, to match what start_subfile does, never change + from C++ to C. */ + if (tmp_language != language_unknown + && (tmp_language != language_c + || psymtab_language != language_cplus)) + psymtab_language = tmp_language; + + /* In C++, one may expect the same filename to come round many + times, when code is coming alternately from the main file + and from inline functions in other files. So I check to see + if this is a file we've seen before -- either the main + source file, or a previously included file. + + This seems to be a lot of time to be spending on N_SOL, but + things like "break c-exp.y:435" need to work (I + suppose the psymtab_include_list could be hashed or put + in a binary tree, if profiling shows this is a major hog). */ + if (pst && STREQ (namestring, pst->filename)) + continue; + { + register int i; + for (i = 0; i < includes_used; i++) + if (STREQ (namestring, psymtab_include_list[i])) + { + i = -1; + break; + } + if (i == -1) + continue; + } + + psymtab_include_list[includes_used++] = namestring; + if (includes_used >= includes_allocated) + { + char **orig = psymtab_include_list; + + psymtab_include_list = (char **) + alloca ((includes_allocated *= 2) * + sizeof (char *)); + memcpy ((PTR) psymtab_include_list, (PTR) orig, + includes_used * sizeof (char *)); + } + continue; + } + case N_LSYM: /* Typedef or automatic variable. */ + case N_STSYM: /* Data seg var -- static */ + case N_LCSYM: /* BSS " */ + case N_ROSYM: /* Read-only data seg var -- static. */ + case N_NBSTS: /* Gould nobase. */ + case N_NBLCS: /* symbols. */ + case N_FUN: + case N_GSYM: /* Global (extern) variable; can be + data or bss (sigh FIXME). */ + + /* Following may probably be ignored; I'll leave them here + for now (until I do Pascal and Modula 2 extensions). */ + + case N_PC: /* I may or may not need this; I + suspect not. */ + case N_M2C: /* I suspect that I can ignore this here. */ + case N_SCOPE: /* Same. */ + + /* SET_NAMESTRING ();*/ + namestring = stabstring; + p = (char *) strchr (namestring, ':'); + if (!p) + continue; /* Not a debugging symbol. */ + + + + /* Main processing section for debugging symbols which + the initial read through the symbol tables needs to worry + about. If we reach this point, the symbol which we are + considering is definitely one we are interested in. + p must also contain the (valid) index into the namestring + which indicates the debugging type symbol. */ + + switch (p[1]) + { + case 'S': + sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile)); +#ifdef STATIC_TRANSFORM_NAME + namestring = STATIC_TRANSFORM_NAME (namestring); +#endif + add_psymbol_to_list (namestring, p - namestring, + VAR_NAMESPACE, LOC_STATIC, + &objfile->static_psymbols, + 0, sh.value, + psymtab_language, objfile); + continue; + case 'G': + sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile)); + /* The addresses in these entries are reported to be + wrong. See the code that reads 'G's for symtabs. */ + add_psymbol_to_list (namestring, p - namestring, + VAR_NAMESPACE, LOC_STATIC, + &objfile->global_psymbols, + 0, sh.value, + psymtab_language, objfile); + continue; + + case 'T': + /* When a 'T' entry is defining an anonymous enum, it + may have a name which is the empty string, or a + single space. Since they're not really defining a + symbol, those shouldn't go in the partial symbol + table. We do pick up the elements of such enums at + 'check_enum:', below. */ + if (p >= namestring + 2 + || (p == namestring + 1 + && namestring[0] != ' ')) + { + add_psymbol_to_list (namestring, p - namestring, + STRUCT_NAMESPACE, LOC_TYPEDEF, + &objfile->static_psymbols, + sh.value, 0, + psymtab_language, objfile); + if (p[2] == 't') + { + /* Also a typedef with the same name. */ + add_psymbol_to_list (namestring, p - namestring, + VAR_NAMESPACE, LOC_TYPEDEF, + &objfile->static_psymbols, + sh.value, 0, + psymtab_language, objfile); + p += 1; + } + /* The semantics of C++ state that "struct foo { ... }" + also defines a typedef for "foo". Unfortuantely, cfront + never makes the typedef when translating from C++ to C. + We make the typedef here so that "ptype foo" works as + expected for cfront translated code. */ + else if (psymtab_language == language_cplus) + { + /* Also a typedef with the same name. */ + add_psymbol_to_list (namestring, p - namestring, + VAR_NAMESPACE, LOC_TYPEDEF, + &objfile->static_psymbols, + sh.value, 0, + psymtab_language, objfile); + } + } + goto check_enum; + case 't': + if (p != namestring) /* a name is there, not just :T... */ + { + add_psymbol_to_list (namestring, p - namestring, + VAR_NAMESPACE, LOC_TYPEDEF, + &objfile->static_psymbols, + sh.value, 0, + psymtab_language, objfile); + } + check_enum: + /* If this is an enumerated type, we need to + add all the enum constants to the partial symbol + table. This does not cover enums without names, e.g. + "enum {a, b} c;" in C, but fortunately those are + rare. There is no way for GDB to find those from the + enum type without spending too much time on it. Thus + to solve this problem, the compiler needs to put out the + enum in a nameless type. GCC2 does this. */ + + /* We are looking for something of the form + <name> ":" ("t" | "T") [<number> "="] "e" + {<constant> ":" <value> ","} ";". */ + + /* Skip over the colon and the 't' or 'T'. */ + p += 2; + /* This type may be given a number. Also, numbers can come + in pairs like (0,26). Skip over it. */ + while ((*p >= '0' && *p <= '9') + || *p == '(' || *p == ',' || *p == ')' + || *p == '=') + p++; + + if (*p++ == 'e') + { + /* The aix4 compiler emits extra crud before the members. */ + if (*p == '-') + { + /* Skip over the type (?). */ + while (*p != ':') + p++; + + /* Skip over the colon. */ + p++; + } + + /* We have found an enumerated type. */ + /* According to comments in read_enum_type + a comma could end it instead of a semicolon. + I don't know where that happens. + Accept either. */ + while (*p && *p != ';' && *p != ',') + { + char *q; + + /* Check for and handle cretinous dbx symbol name + continuation! */ + if (*p == '\\' || (*p == '?' && p[1] == '\0')) + p = next_symbol_text (objfile); + + /* Point to the character after the name + of the enum constant. */ + for (q = p; *q && *q != ':'; q++) + ; + /* Note that the value doesn't matter for + enum constants in psymtabs, just in symtabs. */ + add_psymbol_to_list (p, q - p, + VAR_NAMESPACE, LOC_CONST, + &objfile->static_psymbols, 0, + 0, psymtab_language, objfile); + /* Point past the name. */ + p = q; + /* Skip over the value. */ + while (*p && *p != ',') + p++; + /* Advance past the comma. */ + if (*p) + p++; + } + } + continue; + case 'c': + /* Constant, e.g. from "const" in Pascal. */ + add_psymbol_to_list (namestring, p - namestring, + VAR_NAMESPACE, LOC_CONST, + &objfile->static_psymbols, sh.value, + 0, psymtab_language, objfile); + continue; + + case 'f': + if (! pst) + { + int name_len = p - namestring; + char *name = xmalloc (name_len + 1); + memcpy (name, namestring, name_len); + name[name_len] = '\0'; + complain (&function_outside_compilation_unit, name); + xfree (name); + } + sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + add_psymbol_to_list (namestring, p - namestring, + VAR_NAMESPACE, LOC_BLOCK, + &objfile->static_psymbols, + 0, sh.value, + psymtab_language, objfile); + continue; + + /* Global functions were ignored here, but now they + are put into the global psymtab like one would expect. + They're also in the minimal symbol table. */ + case 'F': + if (! pst) + { + int name_len = p - namestring; + char *name = xmalloc (name_len + 1); + memcpy (name, namestring, name_len); + name[name_len] = '\0'; + complain (&function_outside_compilation_unit, name); + xfree (name); + } + sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + add_psymbol_to_list (namestring, p - namestring, + VAR_NAMESPACE, LOC_BLOCK, + &objfile->global_psymbols, + 0, sh.value, + psymtab_language, objfile); + continue; + + /* Two things show up here (hopefully); static symbols of + local scope (static used inside braces) or extensions + of structure symbols. We can ignore both. */ + case 'V': + case '(': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + case '#': /* for symbol identification (used in live ranges) */ + /* added to support cfront stabs strings */ + case 'Z': /* for definition continuations */ + case 'P': /* for prototypes */ + continue; + + case ':': + /* It is a C++ nested symbol. We don't need to record it + (I don't think); if we try to look up foo::bar::baz, + then symbols for the symtab containing foo should get + read in, I think. */ + /* Someone says sun cc puts out symbols like + /foo/baz/maclib::/usr/local/bin/maclib, + which would get here with a symbol type of ':'. */ + continue; + + default: + /* Unexpected symbol descriptor. The second and subsequent stabs + of a continued stab can show up here. The question is + whether they ever can mimic a normal stab--it would be + nice if not, since we certainly don't want to spend the + time searching to the end of every string looking for + a backslash. */ + + complain (&unknown_symchar_complaint, p[1]); + + /* Ignore it; perhaps it is an extension that we don't + know about. */ + continue; + } + + case N_EXCL: + continue; + + case N_ENDM: +#ifdef SOFUN_ADDRESS_MAYBE_MISSING + /* Solaris 2 end of module, finish current partial + symbol table. END_PSYMTAB will set + pst->texthigh to the proper value, which is + necessary if a module compiled without + debugging info follows this module. */ + if (pst) + { + pst = (struct partial_symtab *) 0; + includes_used = 0; + dependencies_used = 0; + } +#endif + continue; + + case N_RBRAC: + if (sh.value > save_pst->texthigh) + save_pst->texthigh = sh.value; + continue; + case N_EINCL: + case N_DSLINE: + case N_BSLINE: + case N_SSYM: /* Claim: Structure or union element. + Hopefully, I can ignore this. */ + case N_ENTRY: /* Alternate entry point; can ignore. */ + case N_MAIN: /* Can definitely ignore this. */ + case N_CATCH: /* These are GNU C++ extensions */ + case N_EHDECL: /* that can safely be ignored here. */ + case N_LENG: + case N_BCOMM: + case N_ECOMM: + case N_ECOML: + case N_FNAME: + case N_SLINE: + case N_RSYM: + case N_PSYM: + case N_LBRAC: + case N_NSYMS: /* Ultrix 4.0: symbol count */ + case N_DEFD: /* GNU Modula-2 */ + case N_ALIAS: /* SunPro F77: alias name, ignore for now. */ + + case N_OBJ: /* useless types from Solaris */ + case N_OPT: + /* These symbols aren't interesting; don't worry about them */ + + continue; + + default: + /* If we haven't found it yet, ignore it. It's probably some + new type we don't know about yet. */ + complain (&unknown_symtype_complaint, + local_hex_string (type_code)); /*CUR_SYMBOL_TYPE*/ + continue; + } + if (stabstring + && stabstring != debug_info->ss + fh->issBase + sh.iss) + xfree (stabstring); + } + /* end - Handle continuation */ + } + } + else + { + for (cur_sdx = 0; cur_sdx < fh->csym;) + { + char *name; + enum address_class class; + + (*swap_sym_in) (cur_bfd, + ((char *) debug_info->external_sym + + ((fh->isymBase + cur_sdx) + * external_sym_size)), + &sh); + + if (ECOFF_IS_STAB (&sh)) + { + cur_sdx++; + continue; + } + + /* Non absolute static symbols go into the minimal table. */ + if (SC_IS_UNDEF (sh.sc) || sh.sc == scNil + || (sh.index == indexNil + && (sh.st != stStatic || sh.sc == scAbs))) + { + /* FIXME, premature? */ + cur_sdx++; + continue; + } + + name = debug_info->ss + fh->issBase + sh.iss; + + switch (sh.sc) + { + case scText: + case scRConst: + /* The value of a stEnd symbol is the displacement from the + corresponding start symbol value, do not relocate it. */ + if (sh.st != stEnd) + sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + break; + case scData: + case scSData: + case scRData: + case scPData: + case scXData: + sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile)); + break; + case scBss: + case scSBss: + sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_BSS (objfile)); + break; + } + + switch (sh.st) + { + CORE_ADDR high; + CORE_ADDR procaddr; + int new_sdx; + + case stStaticProc: + prim_record_minimal_symbol_and_info (name, sh.value, + mst_file_text, NULL, + SECT_OFF_TEXT (objfile), NULL, + objfile); + + /* FALLTHROUGH */ + + case stProc: + /* Usually there is a local and a global stProc symbol + for a function. This means that the function name + has already been entered into the mimimal symbol table + while processing the global symbols in pass 2 above. + One notable exception is the PROGRAM name from + f77 compiled executables, it is only put out as + local stProc symbol, and a global MAIN__ stProc symbol + points to it. It doesn't matter though, as gdb is + still able to find the PROGRAM name via the partial + symbol table, and the MAIN__ symbol via the minimal + symbol table. */ + if (sh.st == stProc) + add_psymbol_to_list (name, strlen (name), + VAR_NAMESPACE, LOC_BLOCK, + &objfile->global_psymbols, + 0, sh.value, psymtab_language, objfile); + else + add_psymbol_to_list (name, strlen (name), + VAR_NAMESPACE, LOC_BLOCK, + &objfile->static_psymbols, + 0, sh.value, psymtab_language, objfile); + + /* Skip over procedure to next one. */ + if (sh.index >= hdr->iauxMax) + { + /* Should not happen, but does when cross-compiling + with the MIPS compiler. FIXME -- pull later. */ + complain (&index_complaint, name); + new_sdx = cur_sdx + 1; /* Don't skip at all */ + } + else + new_sdx = AUX_GET_ISYM (fh->fBigendian, + (debug_info->external_aux + + fh->iauxBase + + sh.index)); + procaddr = sh.value; + + if (new_sdx <= cur_sdx) + { + /* This should not happen either... FIXME. */ + complain (&aux_index_complaint, name); + new_sdx = cur_sdx + 1; /* Don't skip backward */ + } + + cur_sdx = new_sdx; + (*swap_sym_in) (cur_bfd, + ((char *) debug_info->external_sym + + ((fh->isymBase + cur_sdx - 1) + * external_sym_size)), + &sh); + if (sh.st != stEnd) + continue; + + /* Kludge for Irix 5.2 zero fh->adr. */ + if (!relocatable + && (pst->textlow == 0 || procaddr < pst->textlow)) + pst->textlow = procaddr; + + high = procaddr + sh.value; + if (high > pst->texthigh) + pst->texthigh = high; + continue; + + case stStatic: /* Variable */ + if (SC_IS_DATA (sh.sc)) + prim_record_minimal_symbol_and_info (name, sh.value, + mst_file_data, NULL, + SECT_OFF_DATA (objfile), + NULL, + objfile); + else + prim_record_minimal_symbol_and_info (name, sh.value, + mst_file_bss, NULL, + SECT_OFF_BSS (objfile), + NULL, + objfile); + class = LOC_STATIC; + break; + + case stIndirect: /* Irix5 forward declaration */ + /* Skip forward declarations from Irix5 cc */ + goto skip; + + case stTypedef: /* Typedef */ + /* Skip typedefs for forward declarations and opaque + structs from alpha and mips cc. */ + if (sh.iss == 0 || has_opaque_xref (fh, &sh)) + goto skip; + class = LOC_TYPEDEF; + break; + + case stConstant: /* Constant decl */ + class = LOC_CONST; + break; + + case stUnion: + case stStruct: + case stEnum: + case stBlock: /* { }, str, un, enum */ + /* Do not create a partial symbol for cc unnamed aggregates + and gcc empty aggregates. */ + if ((sh.sc == scInfo + || SC_IS_COMMON (sh.sc)) + && sh.iss != 0 + && sh.index != cur_sdx + 2) + { + add_psymbol_to_list (name, strlen (name), + STRUCT_NAMESPACE, LOC_TYPEDEF, + &objfile->static_psymbols, + 0, (CORE_ADDR) 0, + psymtab_language, objfile); + } + handle_psymbol_enumerators (objfile, fh, sh.st, sh.value); + + /* Skip over the block */ + new_sdx = sh.index; + if (new_sdx <= cur_sdx) + { + /* This happens with the Ultrix kernel. */ + complain (&block_index_complaint, name); + new_sdx = cur_sdx + 1; /* Don't skip backward */ + } + cur_sdx = new_sdx; + continue; + + case stFile: /* File headers */ + case stLabel: /* Labels */ + case stEnd: /* Ends of files */ + goto skip; + + case stLocal: /* Local variables */ + /* Normally these are skipped because we skip over + all blocks we see. However, these can occur + as visible symbols in a .h file that contains code. */ + goto skip; + + default: + /* Both complaints are valid: one gives symbol name, + the other the offending symbol type. */ + complain (&unknown_sym_complaint, name); + complain (&unknown_st_complaint, sh.st); + cur_sdx++; + continue; + } + /* Use this gdb symbol */ + add_psymbol_to_list (name, strlen (name), + VAR_NAMESPACE, class, + &objfile->static_psymbols, + 0, sh.value, psymtab_language, objfile); + skip: + cur_sdx++; /* Go to next file symbol */ + } + + /* Now do enter the external symbols. */ + ext_ptr = &extern_tab[fdr_to_pst[f_idx].globals_offset]; + cur_sdx = fdr_to_pst[f_idx].n_globals; + PST_PRIVATE (save_pst)->extern_count = cur_sdx; + PST_PRIVATE (save_pst)->extern_tab = ext_ptr; + for (; --cur_sdx >= 0; ext_ptr++) + { + enum address_class class; + SYMR *psh; + char *name; + CORE_ADDR svalue; + + if (ext_ptr->ifd != f_idx) + internal_error (__FILE__, __LINE__, "failed internal consistency check"); + psh = &ext_ptr->asym; + + /* Do not add undefined symbols to the partial symbol table. */ + if (SC_IS_UNDEF (psh->sc) || psh->sc == scNil) + continue; + + svalue = psh->value; + switch (psh->sc) + { + case scText: + case scRConst: + svalue += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + break; + case scData: + case scSData: + case scRData: + case scPData: + case scXData: + svalue += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile)); + break; + case scBss: + case scSBss: + svalue += ANOFFSET (objfile->section_offsets, SECT_OFF_BSS (objfile)); + break; + } + + switch (psh->st) + { + case stNil: + /* These are generated for static symbols in .o files, + ignore them. */ + continue; + case stProc: + case stStaticProc: + /* External procedure symbols have been entered + into the minimal symbol table in pass 2 above. + Ignore them, as parse_external will ignore them too. */ + continue; + case stLabel: + class = LOC_LABEL; + break; + default: + complain (&unknown_ext_complaint, + debug_info->ssext + psh->iss); + /* Fall through, pretend it's global. */ + case stGlobal: + /* Global common symbols are resolved by the runtime loader, + ignore them. */ + if (SC_IS_COMMON (psh->sc)) + continue; + + class = LOC_STATIC; + break; + } + name = debug_info->ssext + psh->iss; + add_psymbol_to_list (name, strlen (name), + VAR_NAMESPACE, class, + &objfile->global_psymbols, + 0, svalue, + psymtab_language, objfile); + } + } + + /* Link pst to FDR. end_psymtab returns NULL if the psymtab was + empty and put on the free list. */ + fdr_to_pst[f_idx].pst = end_psymtab (save_pst, + psymtab_include_list, includes_used, + -1, save_pst->texthigh, + dependency_list, dependencies_used, textlow_not_set); + includes_used = 0; + dependencies_used = 0; + + if (objfile->ei.entry_point >= save_pst->textlow && + objfile->ei.entry_point < save_pst->texthigh) + { + objfile->ei.entry_file_lowpc = save_pst->textlow; + objfile->ei.entry_file_highpc = save_pst->texthigh; + } + + /* The objfile has its functions reordered if this partial symbol + table overlaps any other partial symbol table. + We cannot assume a reordered objfile if a partial symbol table + is contained within another partial symbol table, as partial symbol + tables for include files with executable code are contained + within the partial symbol table for the including source file, + and we do not want to flag the objfile reordered for these cases. + + This strategy works well for Irix-5.2 shared libraries, but we + might have to use a more elaborate (and slower) algorithm for + other cases. */ + save_pst = fdr_to_pst[f_idx].pst; + if (save_pst != NULL + && save_pst->textlow != 0 + && !(objfile->flags & OBJF_REORDERED)) + { + ALL_OBJFILE_PSYMTABS (objfile, pst) + { + if (save_pst != pst + && save_pst->textlow >= pst->textlow + && save_pst->textlow < pst->texthigh + && save_pst->texthigh > pst->texthigh) + { + objfile->flags |= OBJF_REORDERED; + break; + } + } + } + } + + /* Now scan the FDRs for dependencies */ + for (f_idx = 0; f_idx < hdr->ifdMax; f_idx++) + { + fh = f_idx + debug_info->fdr; + pst = fdr_to_pst[f_idx].pst; + + if (pst == (struct partial_symtab *) NULL) + continue; + + /* This should catch stabs-in-ecoff. */ + if (fh->crfd <= 1) + continue; + + /* Skip the first file indirect entry as it is a self dependency + for source files or a reverse .h -> .c dependency for header files. */ + pst->number_of_dependencies = 0; + pst->dependencies = + ((struct partial_symtab **) + obstack_alloc (&objfile->psymbol_obstack, + ((fh->crfd - 1) + * sizeof (struct partial_symtab *)))); + for (s_idx = 1; s_idx < fh->crfd; s_idx++) + { + RFDT rh; + + (*swap_rfd_in) (cur_bfd, + ((char *) debug_info->external_rfd + + (fh->rfdBase + s_idx) * external_rfd_size), + &rh); + if (rh < 0 || rh >= hdr->ifdMax) + { + complain (&bad_file_number_complaint, rh); + continue; + } + + /* Skip self dependencies of header files. */ + if (rh == f_idx) + continue; + + /* Do not add to dependeny list if psymtab was empty. */ + if (fdr_to_pst[rh].pst == (struct partial_symtab *) NULL) + continue; + pst->dependencies[pst->number_of_dependencies++] = fdr_to_pst[rh].pst; + } + } + + /* Remove the dummy psymtab created for -O3 images above, if it is + still empty, to enable the detection of stripped executables. */ + if (objfile->psymtabs->next == NULL + && objfile->psymtabs->number_of_dependencies == 0 + && objfile->psymtabs->n_global_syms == 0 + && objfile->psymtabs->n_static_syms == 0) + objfile->psymtabs = NULL; + do_cleanups (old_chain); +} + +/* If the current psymbol has an enumerated type, we need to add + all the the enum constants to the partial symbol table. */ + +static void +handle_psymbol_enumerators (struct objfile *objfile, FDR *fh, int stype, + CORE_ADDR svalue) +{ + const bfd_size_type external_sym_size = debug_swap->external_sym_size; + void (*const swap_sym_in) (bfd *, void *, SYMR *) = debug_swap->swap_sym_in; + char *ext_sym = ((char *) debug_info->external_sym + + ((fh->isymBase + cur_sdx + 1) * external_sym_size)); + SYMR sh; + TIR tir; + + switch (stype) + { + case stEnum: + break; + + case stBlock: + /* It is an enumerated type if the next symbol entry is a stMember + and its auxiliary index is indexNil or its auxiliary entry + is a plain btNil or btVoid. + Alpha cc -migrate enums are recognized by a zero index and + a zero symbol value. + DU 4.0 cc enums are recognized by a member type of btEnum without + qualifiers and a zero symbol value. */ + (*swap_sym_in) (cur_bfd, ext_sym, &sh); + if (sh.st != stMember) + return; + + if (sh.index == indexNil + || (sh.index == 0 && svalue == 0)) + break; + (*debug_swap->swap_tir_in) (fh->fBigendian, + &(debug_info->external_aux + + fh->iauxBase + sh.index)->a_ti, + &tir); + if ((tir.bt != btNil + && tir.bt != btVoid + && (tir.bt != btEnum || svalue != 0)) + || tir.tq0 != tqNil) + return; + break; + + default: + return; + } + + for (;;) + { + char *name; + + (*swap_sym_in) (cur_bfd, ext_sym, &sh); + if (sh.st != stMember) + break; + name = debug_info->ss + cur_fdr->issBase + sh.iss; + + /* Note that the value doesn't matter for enum constants + in psymtabs, just in symtabs. */ + add_psymbol_to_list (name, strlen (name), + VAR_NAMESPACE, LOC_CONST, + &objfile->static_psymbols, 0, + (CORE_ADDR) 0, psymtab_language, objfile); + ext_sym += external_sym_size; + } +} + +/* Get the next symbol. OBJFILE is unused. */ + +static char * +mdebug_next_symbol_text (struct objfile *objfile) +{ + SYMR sh; + + cur_sdx++; + (*debug_swap->swap_sym_in) (cur_bfd, + ((char *) debug_info->external_sym + + ((cur_fdr->isymBase + cur_sdx) + * debug_swap->external_sym_size)), + &sh); + return debug_info->ss + cur_fdr->issBase + sh.iss; +} + +/* Ancillary function to psymtab_to_symtab(). Does all the work + for turning the partial symtab PST into a symtab, recurring + first on all dependent psymtabs. The argument FILENAME is + only passed so we can see in debug stack traces what file + is being read. + + This function has a split personality, based on whether the + symbol table contains ordinary ecoff symbols, or stabs-in-ecoff. + The flow of control and even the memory allocation differs. FIXME. */ + +static void +psymtab_to_symtab_1 (struct partial_symtab *pst, char *filename) +{ + bfd_size_type external_sym_size; + bfd_size_type external_pdr_size; + void (*swap_sym_in) (bfd *, void *, SYMR *); + void (*swap_pdr_in) (bfd *, void *, PDR *); + int i; + struct symtab *st = NULL; + FDR *fh; + struct linetable *lines; + CORE_ADDR lowest_pdr_addr = 0; + int last_symtab_ended = 0; + + if (pst->readin) + return; + pst->readin = 1; + + /* Read in all partial symbtabs on which this one is dependent. + NOTE that we do have circular dependencies, sigh. We solved + that by setting pst->readin before this point. */ + + for (i = 0; i < pst->number_of_dependencies; i++) + if (!pst->dependencies[i]->readin) + { + /* Inform about additional files to be read in. */ + if (info_verbose) + { + fputs_filtered (" ", gdb_stdout); + wrap_here (""); + fputs_filtered ("and ", gdb_stdout); + wrap_here (""); + printf_filtered ("%s...", + pst->dependencies[i]->filename); + wrap_here (""); /* Flush output */ + gdb_flush (gdb_stdout); + } + /* We only pass the filename for debug purposes */ + psymtab_to_symtab_1 (pst->dependencies[i], + pst->dependencies[i]->filename); + } + + /* Do nothing if this is a dummy psymtab. */ + + if (pst->n_global_syms == 0 && pst->n_static_syms == 0 + && pst->textlow == 0 && pst->texthigh == 0) + return; + + /* Now read the symbols for this symtab */ + + cur_bfd = CUR_BFD (pst); + debug_swap = DEBUG_SWAP (pst); + debug_info = DEBUG_INFO (pst); + pending_list = PENDING_LIST (pst); + external_sym_size = debug_swap->external_sym_size; + external_pdr_size = debug_swap->external_pdr_size; + swap_sym_in = debug_swap->swap_sym_in; + swap_pdr_in = debug_swap->swap_pdr_in; + current_objfile = pst->objfile; + cur_fd = FDR_IDX (pst); + fh = ((cur_fd == -1) + ? (FDR *) NULL + : debug_info->fdr + cur_fd); + cur_fdr = fh; + + /* See comment in parse_partial_symbols about the @stabs sentinel. */ + processing_gcc_compilation = 0; + if (fh != (FDR *) NULL && fh->csym >= 2) + { + SYMR sh; + + (*swap_sym_in) (cur_bfd, + ((char *) debug_info->external_sym + + (fh->isymBase + 1) * external_sym_size), + &sh); + if (STREQ (debug_info->ss + fh->issBase + sh.iss, + stabs_symbol)) + { + /* We indicate that this is a GCC compilation so that certain + features will be enabled in stabsread/dbxread. */ + processing_gcc_compilation = 2; + } + } + + if (processing_gcc_compilation != 0) + { + + /* This symbol table contains stabs-in-ecoff entries. */ + + /* Parse local symbols first */ + + if (fh->csym <= 2) /* FIXME, this blows psymtab->symtab ptr */ + { + current_objfile = NULL; + return; + } + for (cur_sdx = 2; cur_sdx < fh->csym; cur_sdx++) + { + SYMR sh; + char *name; + CORE_ADDR valu; + + (*swap_sym_in) (cur_bfd, + (((char *) debug_info->external_sym) + + (fh->isymBase + cur_sdx) * external_sym_size), + &sh); + name = debug_info->ss + fh->issBase + sh.iss; + valu = sh.value; + /* XXX This is a hack. It will go away! */ + if (ECOFF_IS_STAB (&sh) || (name[0] == '#')) + { + int type_code = ECOFF_UNMARK_STAB (sh.index); + + /* We should never get non N_STAB symbols here, but they + should be harmless, so keep process_one_symbol from + complaining about them. */ + if (type_code & N_STAB) + { + /* If we found a trailing N_SO with no name, process + it here instead of in process_one_symbol, so we + can keep a handle to its symtab. The symtab + would otherwise be ended twice, once in + process_one_symbol, and once after this loop. */ + if (type_code == N_SO + && last_source_file + && previous_stab_code != (unsigned char) N_SO + && *name == '\000') + { + valu += ANOFFSET (pst->section_offsets, + SECT_OFF_TEXT (pst->objfile)); + previous_stab_code = N_SO; + st = end_symtab (valu, pst->objfile, + SECT_OFF_TEXT (pst->objfile)); + end_stabs (); + last_symtab_ended = 1; + } + else + { + last_symtab_ended = 0; + process_one_symbol (type_code, 0, valu, name, + pst->section_offsets, pst->objfile); + } + } + /* Similarly a hack. */ + else if (name[0] == '#') + { + process_one_symbol (N_SLINE, 0, valu, name, + pst->section_offsets, pst->objfile); + } + if (type_code == N_FUN) + { + /* Make up special symbol to contain + procedure specific info */ + struct mips_extra_func_info *e = + ((struct mips_extra_func_info *) + obstack_alloc (¤t_objfile->symbol_obstack, + sizeof (struct mips_extra_func_info))); + struct symbol *s = new_symbol (MIPS_EFI_SYMBOL_NAME); + + memset (e, 0, sizeof (struct mips_extra_func_info)); + SYMBOL_NAMESPACE (s) = LABEL_NAMESPACE; + SYMBOL_CLASS (s) = LOC_CONST; + SYMBOL_TYPE (s) = mdebug_type_void; + SYMBOL_VALUE (s) = (long) e; + e->pdr.framereg = -1; + add_symbol_to_list (s, &local_symbols); + } + } + else if (sh.st == stLabel) + { + if (sh.index == indexNil) + { + /* This is what the gcc2_compiled and __gnu_compiled_* + show up as. So don't complain. */ + ; + } + else + { + /* Handle encoded stab line number. */ + valu += ANOFFSET (pst->section_offsets, SECT_OFF_TEXT (pst->objfile)); + record_line (current_subfile, sh.index, valu); + } + } + else if (sh.st == stProc || sh.st == stStaticProc + || sh.st == stStatic || sh.st == stEnd) + /* These are generated by gcc-2.x, do not complain */ + ; + else + complain (&stab_unknown_complaint, name); + } + + if (! last_symtab_ended) + { + st = end_symtab (pst->texthigh, pst->objfile, SECT_OFF_TEXT (pst->objfile)); + end_stabs (); + } + + /* Sort the symbol table now, we are done adding symbols to it. + We must do this before parse_procedure calls lookup_symbol. */ + sort_symtab_syms (st); + + /* There used to be a call to sort_blocks here, but this should not + be necessary for stabs symtabs. And as sort_blocks modifies the + start address of the GLOBAL_BLOCK to the FIRST_LOCAL_BLOCK, + it did the wrong thing if the first procedure in a file was + generated via asm statements. */ + + /* Fill in procedure info next. */ + if (fh->cpd > 0) + { + PDR *pr_block; + struct cleanup *old_chain; + char *pdr_ptr; + char *pdr_end; + PDR *pdr_in; + PDR *pdr_in_end; + + pr_block = (PDR *) xmalloc (fh->cpd * sizeof (PDR)); + old_chain = make_cleanup (xfree, pr_block); + + pdr_ptr = ((char *) debug_info->external_pdr + + fh->ipdFirst * external_pdr_size); + pdr_end = pdr_ptr + fh->cpd * external_pdr_size; + pdr_in = pr_block; + for (; + pdr_ptr < pdr_end; + pdr_ptr += external_pdr_size, pdr_in++) + { + (*swap_pdr_in) (cur_bfd, pdr_ptr, pdr_in); + + /* Determine lowest PDR address, the PDRs are not always + sorted. */ + if (pdr_in == pr_block) + lowest_pdr_addr = pdr_in->adr; + else if (pdr_in->adr < lowest_pdr_addr) + lowest_pdr_addr = pdr_in->adr; + } + + pdr_in = pr_block; + pdr_in_end = pdr_in + fh->cpd; + for (; pdr_in < pdr_in_end; pdr_in++) + parse_procedure (pdr_in, st, pst); + + do_cleanups (old_chain); + } + } + else + { + /* This symbol table contains ordinary ecoff entries. */ + + int f_max; + int maxlines; + EXTR *ext_ptr; + + /* How many symbols will we need */ + /* FIXME, this does not count enum values. */ + f_max = pst->n_global_syms + pst->n_static_syms; + if (fh == 0) + { + maxlines = 0; + st = new_symtab ("unknown", f_max, 0, pst->objfile); + } + else + { + f_max += fh->csym + fh->cpd; + maxlines = 2 * fh->cline; + st = new_symtab (pst->filename, 2 * f_max, maxlines, pst->objfile); + + /* The proper language was already determined when building + the psymtab, use it. */ + st->language = PST_PRIVATE (pst)->pst_language; + } + + psymtab_language = st->language; + + lines = LINETABLE (st); + + /* Get a new lexical context */ + + push_parse_stack (); + top_stack->cur_st = st; + top_stack->cur_block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (st), + STATIC_BLOCK); + BLOCK_START (top_stack->cur_block) = pst->textlow; + BLOCK_END (top_stack->cur_block) = 0; + top_stack->blocktype = stFile; + top_stack->maxsyms = 2 * f_max; + top_stack->cur_type = 0; + top_stack->procadr = 0; + top_stack->numargs = 0; + found_ecoff_debugging_info = 0; + + if (fh) + { + char *sym_ptr; + char *sym_end; + + /* Parse local symbols first */ + sym_ptr = ((char *) debug_info->external_sym + + fh->isymBase * external_sym_size); + sym_end = sym_ptr + fh->csym * external_sym_size; + while (sym_ptr < sym_end) + { + SYMR sh; + int c; + + (*swap_sym_in) (cur_bfd, sym_ptr, &sh); + c = parse_symbol (&sh, + debug_info->external_aux + fh->iauxBase, + sym_ptr, fh->fBigendian, pst->section_offsets, pst->objfile); + sym_ptr += c * external_sym_size; + } + + /* Linenumbers. At the end, check if we can save memory. + parse_lines has to look ahead an arbitrary number of PDR + structures, so we swap them all first. */ + if (fh->cpd > 0) + { + PDR *pr_block; + struct cleanup *old_chain; + char *pdr_ptr; + char *pdr_end; + PDR *pdr_in; + PDR *pdr_in_end; + + pr_block = (PDR *) xmalloc (fh->cpd * sizeof (PDR)); + + old_chain = make_cleanup (xfree, pr_block); + + pdr_ptr = ((char *) debug_info->external_pdr + + fh->ipdFirst * external_pdr_size); + pdr_end = pdr_ptr + fh->cpd * external_pdr_size; + pdr_in = pr_block; + for (; + pdr_ptr < pdr_end; + pdr_ptr += external_pdr_size, pdr_in++) + { + (*swap_pdr_in) (cur_bfd, pdr_ptr, pdr_in); + + /* Determine lowest PDR address, the PDRs are not always + sorted. */ + if (pdr_in == pr_block) + lowest_pdr_addr = pdr_in->adr; + else if (pdr_in->adr < lowest_pdr_addr) + lowest_pdr_addr = pdr_in->adr; + } + + parse_lines (fh, pr_block, lines, maxlines, pst, lowest_pdr_addr); + if (lines->nitems < fh->cline) + lines = shrink_linetable (lines); + + /* Fill in procedure info next. */ + pdr_in = pr_block; + pdr_in_end = pdr_in + fh->cpd; + for (; pdr_in < pdr_in_end; pdr_in++) + parse_procedure (pdr_in, 0, pst); + + do_cleanups (old_chain); + } + } + + LINETABLE (st) = lines; + + /* .. and our share of externals. + XXX use the global list to speed up things here. how? + FIXME, Maybe quit once we have found the right number of ext's? */ + top_stack->cur_st = st; + top_stack->cur_block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (top_stack->cur_st), + GLOBAL_BLOCK); + top_stack->blocktype = stFile; + top_stack->maxsyms + = (debug_info->symbolic_header.isymMax + + debug_info->symbolic_header.ipdMax + + debug_info->symbolic_header.iextMax); + + ext_ptr = PST_PRIVATE (pst)->extern_tab; + for (i = PST_PRIVATE (pst)->extern_count; --i >= 0; ext_ptr++) + parse_external (ext_ptr, fh->fBigendian, pst->section_offsets, pst->objfile); + + /* If there are undefined symbols, tell the user. + The alpha has an undefined symbol for every symbol that is + from a shared library, so tell the user only if verbose is on. */ + if (info_verbose && n_undef_symbols) + { + printf_filtered ("File %s contains %d unresolved references:", + st->filename, n_undef_symbols); + printf_filtered ("\n\t%4d variables\n\t%4d procedures\n\t%4d labels\n", + n_undef_vars, n_undef_procs, n_undef_labels); + n_undef_symbols = n_undef_labels = n_undef_vars = n_undef_procs = 0; + + } + pop_parse_stack (); + + st->primary = 1; + + /* Sort the symbol table now, we are done adding symbols to it. */ + sort_symtab_syms (st); + + sort_blocks (st); + } + + /* Now link the psymtab and the symtab. */ + pst->symtab = st; + + current_objfile = NULL; +} + +/* Ancillary parsing procedures. */ + +/* Return 1 if the symbol pointed to by SH has a cross reference + to an opaque aggregate type, else 0. */ + +static int +has_opaque_xref (FDR *fh, SYMR *sh) +{ + TIR tir; + union aux_ext *ax; + RNDXR rn[1]; + unsigned int rf; + + if (sh->index == indexNil) + return 0; + + ax = debug_info->external_aux + fh->iauxBase + sh->index; + (*debug_swap->swap_tir_in) (fh->fBigendian, &ax->a_ti, &tir); + if (tir.bt != btStruct && tir.bt != btUnion && tir.bt != btEnum) + return 0; + + ax++; + (*debug_swap->swap_rndx_in) (fh->fBigendian, &ax->a_rndx, rn); + if (rn->rfd == 0xfff) + rf = AUX_GET_ISYM (fh->fBigendian, ax + 1); + else + rf = rn->rfd; + if (rf != -1) + return 0; + return 1; +} + +/* Lookup the type at relative index RN. Return it in TPP + if found and in any event come up with its name PNAME. + BIGEND says whether aux symbols are big-endian or not (from fh->fBigendian). + Return value says how many aux symbols we ate. */ + +static int +cross_ref (int fd, union aux_ext *ax, struct type **tpp, enum type_code type_code, /* Use to alloc new type if none is found. */ + char **pname, int bigend, char *sym_name) +{ + RNDXR rn[1]; + unsigned int rf; + int result = 1; + FDR *fh; + char *esh; + SYMR sh; + int xref_fd; + struct mdebug_pending *pend; + + *tpp = (struct type *) NULL; + + (*debug_swap->swap_rndx_in) (bigend, &ax->a_rndx, rn); + + /* Escape index means 'the next one' */ + if (rn->rfd == 0xfff) + { + result++; + rf = AUX_GET_ISYM (bigend, ax + 1); + } + else + { + rf = rn->rfd; + } + + /* mips cc uses a rf of -1 for opaque struct definitions. + Set TYPE_FLAG_STUB for these types so that check_typedef will + resolve them if the struct gets defined in another compilation unit. */ + if (rf == -1) + { + *pname = "<undefined>"; + *tpp = init_type (type_code, 0, TYPE_FLAG_STUB, (char *) NULL, current_objfile); + return result; + } + + /* mips cc uses an escaped rn->index of 0 for struct return types + of procedures that were compiled without -g. These will always remain + undefined. */ + if (rn->rfd == 0xfff && rn->index == 0) + { + *pname = "<undefined>"; + return result; + } + + /* Find the relative file descriptor and the symbol in it. */ + fh = get_rfd (fd, rf); + xref_fd = fh - debug_info->fdr; + + if (rn->index >= fh->csym) + { + /* File indirect entry is corrupt. */ + *pname = "<illegal>"; + complain (&bad_rfd_entry_complaint, + sym_name, xref_fd, rn->index); + return result; + } + + /* If we have processed this symbol then we left a forwarding + pointer to the type in the pending list. If not, we`ll put + it in a list of pending types, to be processed later when + the file will be. In any event, we collect the name for the + type here. */ + + esh = ((char *) debug_info->external_sym + + ((fh->isymBase + rn->index) + * debug_swap->external_sym_size)); + (*debug_swap->swap_sym_in) (cur_bfd, esh, &sh); + + /* Make sure that this type of cross reference can be handled. */ + if ((sh.sc != scInfo + || (sh.st != stBlock && sh.st != stTypedef && sh.st != stIndirect + && sh.st != stStruct && sh.st != stUnion + && sh.st != stEnum)) + && (sh.st != stBlock || !SC_IS_COMMON (sh.sc))) + { + /* File indirect entry is corrupt. */ + *pname = "<illegal>"; + complain (&bad_rfd_entry_complaint, + sym_name, xref_fd, rn->index); + return result; + } + + *pname = debug_info->ss + fh->issBase + sh.iss; + + pend = is_pending_symbol (fh, esh); + if (pend) + *tpp = pend->t; + else + { + /* We have not yet seen this type. */ + + if ((sh.iss == 0 && sh.st == stTypedef) || sh.st == stIndirect) + { + TIR tir; + + /* alpha cc puts out a stTypedef with a sh.iss of zero for + two cases: + a) forward declarations of structs/unions/enums which are not + defined in this compilation unit. + For these the type will be void. This is a bad design decision + as cross referencing across compilation units is impossible + due to the missing name. + b) forward declarations of structs/unions/enums/typedefs which + are defined later in this file or in another file in the same + compilation unit. Irix5 cc uses a stIndirect symbol for this. + Simply cross reference those again to get the true type. + The forward references are not entered in the pending list and + in the symbol table. */ + + (*debug_swap->swap_tir_in) (bigend, + &(debug_info->external_aux + + fh->iauxBase + sh.index)->a_ti, + &tir); + if (tir.tq0 != tqNil) + complain (&illegal_forward_tq0_complaint, sym_name); + switch (tir.bt) + { + case btVoid: + *tpp = init_type (type_code, 0, 0, (char *) NULL, + current_objfile); + *pname = "<undefined>"; + break; + + case btStruct: + case btUnion: + case btEnum: + cross_ref (xref_fd, + (debug_info->external_aux + + fh->iauxBase + sh.index + 1), + tpp, type_code, pname, + fh->fBigendian, sym_name); + break; + + case btTypedef: + /* Follow a forward typedef. This might recursively + call cross_ref till we get a non typedef'ed type. + FIXME: This is not correct behaviour, but gdb currently + cannot handle typedefs without type copying. Type + copying is impossible as we might have mutual forward + references between two files and the copied type would not + get filled in when we later parse its definition. */ + *tpp = parse_type (xref_fd, + debug_info->external_aux + fh->iauxBase, + sh.index, + (int *) NULL, + fh->fBigendian, + debug_info->ss + fh->issBase + sh.iss); + add_pending (fh, esh, *tpp); + break; + + default: + complain (&illegal_forward_bt_complaint, tir.bt, sym_name); + *tpp = init_type (type_code, 0, 0, (char *) NULL, + current_objfile); + break; + } + return result; + } + else if (sh.st == stTypedef) + { + /* Parse the type for a normal typedef. This might recursively call + cross_ref till we get a non typedef'ed type. + FIXME: This is not correct behaviour, but gdb currently + cannot handle typedefs without type copying. But type copying is + impossible as we might have mutual forward references between + two files and the copied type would not get filled in when + we later parse its definition. */ + *tpp = parse_type (xref_fd, + debug_info->external_aux + fh->iauxBase, + sh.index, + (int *) NULL, + fh->fBigendian, + debug_info->ss + fh->issBase + sh.iss); + } + else + { + /* Cross reference to a struct/union/enum which is defined + in another file in the same compilation unit but that file + has not been parsed yet. + Initialize the type only, it will be filled in when + it's definition is parsed. */ + *tpp = init_type (type_code, 0, 0, (char *) NULL, current_objfile); + } + add_pending (fh, esh, *tpp); + } + + /* We used one auxent normally, two if we got a "next one" rf. */ + return result; +} + + +/* Quick&dirty lookup procedure, to avoid the MI ones that require + keeping the symtab sorted */ + +static struct symbol * +mylookup_symbol (char *name, register struct block *block, + namespace_enum namespace, enum address_class class) +{ + int i, inc; + struct symbol *sym; + + inc = name[0]; + ALL_BLOCK_SYMBOLS (block, i, sym) + { + if (SYMBOL_NAME (sym)[0] == inc + && SYMBOL_NAMESPACE (sym) == namespace + && SYMBOL_CLASS (sym) == class + && strcmp (SYMBOL_NAME (sym), name) == 0) + return sym; + } + + block = BLOCK_SUPERBLOCK (block); + if (block) + return mylookup_symbol (name, block, namespace, class); + return 0; +} + + +/* Add a new symbol S to a block B. + Infrequently, we will need to reallocate the block to make it bigger. + We only detect this case when adding to top_stack->cur_block, since + that's the only time we know how big the block is. FIXME. */ + +static void +add_symbol (struct symbol *s, struct block *b) +{ + int nsyms = BLOCK_NSYMS (b)++; + struct block *origb; + struct parse_stack *stackp; + + if (b == top_stack->cur_block && + nsyms >= top_stack->maxsyms) + { + complain (&block_overflow_complaint, SYMBOL_NAME (s)); + /* In this case shrink_block is actually grow_block, since + BLOCK_NSYMS(b) is larger than its current size. */ + origb = b; + b = shrink_block (top_stack->cur_block, top_stack->cur_st); + + /* Now run through the stack replacing pointers to the + original block. shrink_block has already done this + for the blockvector and BLOCK_FUNCTION. */ + for (stackp = top_stack; stackp; stackp = stackp->next) + { + if (stackp->cur_block == origb) + { + stackp->cur_block = b; + stackp->maxsyms = BLOCK_NSYMS (b); + } + } + } + BLOCK_SYM (b, nsyms) = s; +} + +/* Add a new block B to a symtab S */ + +static void +add_block (struct block *b, struct symtab *s) +{ + struct blockvector *bv = BLOCKVECTOR (s); + + bv = (struct blockvector *) xrealloc ((void *) bv, + (sizeof (struct blockvector) + + BLOCKVECTOR_NBLOCKS (bv) + * sizeof (bv->block))); + if (bv != BLOCKVECTOR (s)) + BLOCKVECTOR (s) = bv; + + BLOCKVECTOR_BLOCK (bv, BLOCKVECTOR_NBLOCKS (bv)++) = b; +} + +/* Add a new linenumber entry (LINENO,ADR) to a linevector LT. + MIPS' linenumber encoding might need more than one byte + to describe it, LAST is used to detect these continuation lines. + + Combining lines with the same line number seems like a bad idea. + E.g: There could be a line number entry with the same line number after the + prologue and GDB should not ignore it (this is a better way to find + a prologue than mips_skip_prologue). + But due to the compressed line table format there are line number entries + for the same line which are needed to bridge the gap to the next + line number entry. These entries have a bogus address info with them + and we are unable to tell them from intended duplicate line number + entries. + This is another reason why -ggdb debugging format is preferable. */ + +static int +add_line (struct linetable *lt, int lineno, CORE_ADDR adr, int last) +{ + /* DEC c89 sometimes produces zero linenos which confuse gdb. + Change them to something sensible. */ + if (lineno == 0) + lineno = 1; + if (last == 0) + last = -2; /* make sure we record first line */ + + if (last == lineno) /* skip continuation lines */ + return lineno; + + lt->item[lt->nitems].line = lineno; + lt->item[lt->nitems++].pc = adr << 2; + return lineno; +} + +/* Sorting and reordering procedures */ + +/* Blocks with a smaller low bound should come first */ + +static int +compare_blocks (const void *arg1, const void *arg2) +{ + register int addr_diff; + struct block **b1 = (struct block **) arg1; + struct block **b2 = (struct block **) arg2; + + addr_diff = (BLOCK_START ((*b1))) - (BLOCK_START ((*b2))); + if (addr_diff == 0) + return (BLOCK_END ((*b2))) - (BLOCK_END ((*b1))); + return addr_diff; +} + +/* Sort the blocks of a symtab S. + Reorder the blocks in the blockvector by code-address, + as required by some MI search routines */ + +static void +sort_blocks (struct symtab *s) +{ + struct blockvector *bv = BLOCKVECTOR (s); + + if (BLOCKVECTOR_NBLOCKS (bv) <= 2) + { + /* Cosmetic */ + if (BLOCK_END (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK)) == 0) + BLOCK_START (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK)) = 0; + if (BLOCK_END (BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK)) == 0) + BLOCK_START (BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK)) = 0; + return; + } + /* + * This is very unfortunate: normally all functions are compiled in + * the order they are found, but if the file is compiled -O3 things + * are very different. It would be nice to find a reliable test + * to detect -O3 images in advance. + */ + if (BLOCKVECTOR_NBLOCKS (bv) > 3) + qsort (&BLOCKVECTOR_BLOCK (bv, FIRST_LOCAL_BLOCK), + BLOCKVECTOR_NBLOCKS (bv) - FIRST_LOCAL_BLOCK, + sizeof (struct block *), + compare_blocks); + + { + register CORE_ADDR high = 0; + register int i, j = BLOCKVECTOR_NBLOCKS (bv); + + for (i = FIRST_LOCAL_BLOCK; i < j; i++) + if (high < BLOCK_END (BLOCKVECTOR_BLOCK (bv, i))) + high = BLOCK_END (BLOCKVECTOR_BLOCK (bv, i)); + BLOCK_END (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK)) = high; + } + + BLOCK_START (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK)) = + BLOCK_START (BLOCKVECTOR_BLOCK (bv, FIRST_LOCAL_BLOCK)); + + BLOCK_START (BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK)) = + BLOCK_START (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK)); + BLOCK_END (BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK)) = + BLOCK_END (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK)); +} + + +/* Constructor/restructor/destructor procedures */ + +/* Allocate a new symtab for NAME. Needs an estimate of how many symbols + MAXSYMS and linenumbers MAXLINES we'll put in it */ + +static struct symtab * +new_symtab (char *name, int maxsyms, int maxlines, struct objfile *objfile) +{ + struct symtab *s = allocate_symtab (name, objfile); + + LINETABLE (s) = new_linetable (maxlines); + + /* All symtabs must have at least two blocks */ + BLOCKVECTOR (s) = new_bvect (2); + BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK) = new_block (maxsyms); + BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK) = new_block (maxsyms); + BLOCK_SUPERBLOCK (BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK)) = + BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK); + + s->free_code = free_linetable; + s->debugformat = obsavestring ("ECOFF", 5, + &objfile->symbol_obstack); + return (s); +} + +/* Allocate a new partial_symtab NAME */ + +static struct partial_symtab * +new_psymtab (char *name, struct objfile *objfile) +{ + struct partial_symtab *psymtab; + + psymtab = allocate_psymtab (name, objfile); + psymtab->section_offsets = objfile->section_offsets; + + /* Keep a backpointer to the file's symbols */ + + psymtab->read_symtab_private = ((char *) + obstack_alloc (&objfile->psymbol_obstack, + sizeof (struct symloc))); + memset (psymtab->read_symtab_private, 0, sizeof (struct symloc)); + CUR_BFD (psymtab) = cur_bfd; + DEBUG_SWAP (psymtab) = debug_swap; + DEBUG_INFO (psymtab) = debug_info; + PENDING_LIST (psymtab) = pending_list; + + /* The way to turn this into a symtab is to call... */ + psymtab->read_symtab = mdebug_psymtab_to_symtab; + return (psymtab); +} + + +/* Allocate a linetable array of the given SIZE. Since the struct + already includes one item, we subtract one when calculating the + proper size to allocate. */ + +static struct linetable * +new_linetable (int size) +{ + struct linetable *l; + + size = (size - 1) * sizeof (l->item) + sizeof (struct linetable); + l = (struct linetable *) xmalloc (size); + l->nitems = 0; + return l; +} + +/* Oops, too big. Shrink it. This was important with the 2.4 linetables, + I am not so sure about the 3.4 ones. + + Since the struct linetable already includes one item, we subtract one when + calculating the proper size to allocate. */ + +static struct linetable * +shrink_linetable (struct linetable *lt) +{ + + return (struct linetable *) xrealloc ((void *) lt, + (sizeof (struct linetable) + + ((lt->nitems - 1) + * sizeof (lt->item)))); +} + +/* Allocate and zero a new blockvector of NBLOCKS blocks. */ + +static struct blockvector * +new_bvect (int nblocks) +{ + struct blockvector *bv; + int size; + + size = sizeof (struct blockvector) + nblocks * sizeof (struct block *); + bv = (struct blockvector *) xzalloc (size); + + BLOCKVECTOR_NBLOCKS (bv) = nblocks; + + return bv; +} + +/* Allocate and zero a new block of MAXSYMS symbols */ + +static struct block * +new_block (int maxsyms) +{ + int size = sizeof (struct block) + (maxsyms - 1) * sizeof (struct symbol *); + + return (struct block *) xzalloc (size); +} + +/* Ooops, too big. Shrink block B in symtab S to its minimal size. + Shrink_block can also be used by add_symbol to grow a block. */ + +static struct block * +shrink_block (struct block *b, struct symtab *s) +{ + struct block *new; + struct blockvector *bv = BLOCKVECTOR (s); + int i; + + /* Just reallocate it and fix references to the old one */ + + new = (struct block *) xrealloc ((void *) b, + (sizeof (struct block) + + ((BLOCK_NSYMS (b) - 1) + * sizeof (struct symbol *)))); + + /* FIXME: Not worth hashing this block as it's built. */ + /* All callers should have created the block with new_block (), which + would mean it was not previously hashed. Make sure. */ + gdb_assert (BLOCK_HASHTABLE (new) == 0); + + /* Should chase pointers to old one. Fortunately, that`s just + the block`s function and inferior blocks */ + if (BLOCK_FUNCTION (new) && SYMBOL_BLOCK_VALUE (BLOCK_FUNCTION (new)) == b) + SYMBOL_BLOCK_VALUE (BLOCK_FUNCTION (new)) = new; + for (i = 0; i < BLOCKVECTOR_NBLOCKS (bv); i++) + if (BLOCKVECTOR_BLOCK (bv, i) == b) + BLOCKVECTOR_BLOCK (bv, i) = new; + else if (BLOCK_SUPERBLOCK (BLOCKVECTOR_BLOCK (bv, i)) == b) + BLOCK_SUPERBLOCK (BLOCKVECTOR_BLOCK (bv, i)) = new; + return new; +} + +/* Create a new symbol with printname NAME */ + +static struct symbol * +new_symbol (char *name) +{ + struct symbol *s = ((struct symbol *) + obstack_alloc (¤t_objfile->symbol_obstack, + sizeof (struct symbol))); + + memset (s, 0, sizeof (*s)); + SYMBOL_NAME (s) = obsavestring (name, strlen (name), + ¤t_objfile->symbol_obstack); + SYMBOL_LANGUAGE (s) = psymtab_language; + SYMBOL_INIT_DEMANGLED_NAME (s, ¤t_objfile->symbol_obstack); + return s; +} + +/* Create a new type with printname NAME */ + +static struct type * +new_type (char *name) +{ + struct type *t; + + t = alloc_type (current_objfile); + TYPE_NAME (t) = name; + TYPE_CPLUS_SPECIFIC (t) = (struct cplus_struct_type *) &cplus_struct_default; + return t; +} + +/* Read ECOFF debugging information from a BFD section. This is + called from elfread.c. It parses the section into a + ecoff_debug_info struct, and then lets the rest of the file handle + it as normal. */ + +void +elfmdebug_build_psymtabs (struct objfile *objfile, + const struct ecoff_debug_swap *swap, asection *sec) +{ + bfd *abfd = objfile->obfd; + struct ecoff_debug_info *info; + + info = ((struct ecoff_debug_info *) + obstack_alloc (&objfile->psymbol_obstack, + sizeof (struct ecoff_debug_info))); + + if (!(*swap->read_debug_info) (abfd, sec, info)) + error ("Error reading ECOFF debugging information: %s", + bfd_errmsg (bfd_get_error ())); + + mdebug_build_psymtabs (objfile, swap, info); +} + + +/* Things used for calling functions in the inferior. + These functions are exported to our companion + mips-tdep.c file and are here because they play + with the symbol-table explicitly. */ + +/* Sigtramp: make sure we have all the necessary information + about the signal trampoline code. Since the official code + from MIPS does not do so, we make up that information ourselves. + If they fix the library (unlikely) this code will neutralize itself. */ + +/* FIXME: This function is called only by mips-tdep.c. It needs to be + here because it calls functions defined in this file, but perhaps + this could be handled in a better way. Only compile it in when + tm-mips.h is included. */ + +#ifdef TM_MIPS_H + +void +fixup_sigtramp (void) +{ + struct symbol *s; + struct symtab *st; + struct block *b, *b0 = NULL; + + sigtramp_address = -1; + + /* We have to handle the following cases here: + a) The Mips library has a sigtramp label within sigvec. + b) Irix has a _sigtramp which we want to use, but it also has sigvec. */ + s = lookup_symbol ("sigvec", 0, VAR_NAMESPACE, 0, NULL); + if (s != 0) + { + b0 = SYMBOL_BLOCK_VALUE (s); + s = lookup_symbol ("sigtramp", b0, VAR_NAMESPACE, 0, NULL); + } + if (s == 0) + { + /* No sigvec or no sigtramp inside sigvec, try _sigtramp. */ + s = lookup_symbol ("_sigtramp", 0, VAR_NAMESPACE, 0, NULL); + } + + /* But maybe this program uses its own version of sigvec */ + if (s == 0) + return; + + /* Did we or MIPSco fix the library ? */ + if (SYMBOL_CLASS (s) == LOC_BLOCK) + { + sigtramp_address = BLOCK_START (SYMBOL_BLOCK_VALUE (s)); + sigtramp_end = BLOCK_END (SYMBOL_BLOCK_VALUE (s)); + return; + } + + sigtramp_address = SYMBOL_VALUE (s); + sigtramp_end = sigtramp_address + 0x88; /* black magic */ + + /* But what symtab does it live in ? */ + st = find_pc_symtab (SYMBOL_VALUE (s)); + + /* + * Ok, there goes the fix: turn it into a procedure, with all the + * needed info. Note we make it a nested procedure of sigvec, + * which is the way the (assembly) code is actually written. + */ + SYMBOL_NAMESPACE (s) = VAR_NAMESPACE; + SYMBOL_CLASS (s) = LOC_BLOCK; + SYMBOL_TYPE (s) = init_type (TYPE_CODE_FUNC, 4, 0, (char *) NULL, + st->objfile); + TYPE_TARGET_TYPE (SYMBOL_TYPE (s)) = mdebug_type_void; + + /* Need a block to allocate MIPS_EFI_SYMBOL_NAME in */ + b = new_block (1); + SYMBOL_BLOCK_VALUE (s) = b; + BLOCK_START (b) = sigtramp_address; + BLOCK_END (b) = sigtramp_end; + BLOCK_FUNCTION (b) = s; + BLOCK_SUPERBLOCK (b) = BLOCK_SUPERBLOCK (b0); + add_block (b, st); + sort_blocks (st); + + /* Make a MIPS_EFI_SYMBOL_NAME entry for it */ + { + struct mips_extra_func_info *e = + ((struct mips_extra_func_info *) + xzalloc (sizeof (struct mips_extra_func_info))); + + e->numargs = 0; /* the kernel thinks otherwise */ + e->pdr.frameoffset = 32; + e->pdr.framereg = SP_REGNUM; + /* Note that setting pcreg is no longer strictly necessary as + mips_frame_saved_pc is now aware of signal handler frames. */ + e->pdr.pcreg = PC_REGNUM; + e->pdr.regmask = -2; + /* Offset to saved r31, in the sigtramp case the saved registers + are above the frame in the sigcontext. + We have 4 alignment bytes, 12 bytes for onstack, mask and pc, + 32 * 4 bytes for the general registers, 12 bytes for mdhi, mdlo, ownedfp + and 32 * 4 bytes for the floating point registers. */ + e->pdr.regoffset = 4 + 12 + 31 * 4; + e->pdr.fregmask = -1; + /* Offset to saved f30 (first saved *double* register). */ + e->pdr.fregoffset = 4 + 12 + 32 * 4 + 12 + 30 * 4; + e->pdr.isym = (long) s; + e->pdr.adr = sigtramp_address; + + current_objfile = st->objfile; /* Keep new_symbol happy */ + s = new_symbol (MIPS_EFI_SYMBOL_NAME); + SYMBOL_VALUE (s) = (long) e; + SYMBOL_NAMESPACE (s) = LABEL_NAMESPACE; + SYMBOL_CLASS (s) = LOC_CONST; + SYMBOL_TYPE (s) = mdebug_type_void; + current_objfile = NULL; + } + + BLOCK_SYM (b, BLOCK_NSYMS (b)++) = s; +} + +#endif /* TM_MIPS_H */ + +void +_initialize_mdebugread (void) +{ + mdebug_type_void = + init_type (TYPE_CODE_VOID, 1, + 0, + "void", (struct objfile *) NULL); + mdebug_type_char = + init_type (TYPE_CODE_INT, 1, + 0, + "char", (struct objfile *) NULL); + mdebug_type_unsigned_char = + init_type (TYPE_CODE_INT, 1, + TYPE_FLAG_UNSIGNED, + "unsigned char", (struct objfile *) NULL); + mdebug_type_short = + init_type (TYPE_CODE_INT, 2, + 0, + "short", (struct objfile *) NULL); + mdebug_type_unsigned_short = + init_type (TYPE_CODE_INT, 2, + TYPE_FLAG_UNSIGNED, + "unsigned short", (struct objfile *) NULL); + mdebug_type_int_32 = + init_type (TYPE_CODE_INT, 4, + 0, + "int", (struct objfile *) NULL); + mdebug_type_unsigned_int_32 = + init_type (TYPE_CODE_INT, 4, + TYPE_FLAG_UNSIGNED, + "unsigned int", (struct objfile *) NULL); + mdebug_type_int_64 = + init_type (TYPE_CODE_INT, 8, + 0, + "int", (struct objfile *) NULL); + mdebug_type_unsigned_int_64 = + init_type (TYPE_CODE_INT, 8, + TYPE_FLAG_UNSIGNED, + "unsigned int", (struct objfile *) NULL); + mdebug_type_long_32 = + init_type (TYPE_CODE_INT, 4, + 0, + "long", (struct objfile *) NULL); + mdebug_type_unsigned_long_32 = + init_type (TYPE_CODE_INT, 4, + TYPE_FLAG_UNSIGNED, + "unsigned long", (struct objfile *) NULL); + mdebug_type_long_64 = + init_type (TYPE_CODE_INT, 8, + 0, + "long", (struct objfile *) NULL); + mdebug_type_unsigned_long_64 = + init_type (TYPE_CODE_INT, 8, + TYPE_FLAG_UNSIGNED, + "unsigned long", (struct objfile *) NULL); + mdebug_type_long_long_64 = + init_type (TYPE_CODE_INT, 8, + 0, + "long long", (struct objfile *) NULL); + mdebug_type_unsigned_long_long_64 = + init_type (TYPE_CODE_INT, 8, + TYPE_FLAG_UNSIGNED, + "unsigned long long", (struct objfile *) NULL); + mdebug_type_adr_32 = + init_type (TYPE_CODE_PTR, 4, + TYPE_FLAG_UNSIGNED, + "adr_32", (struct objfile *) NULL); + TYPE_TARGET_TYPE (mdebug_type_adr_32) = mdebug_type_void; + mdebug_type_adr_64 = + init_type (TYPE_CODE_PTR, 8, + TYPE_FLAG_UNSIGNED, + "adr_64", (struct objfile *) NULL); + TYPE_TARGET_TYPE (mdebug_type_adr_64) = mdebug_type_void; + mdebug_type_float = + init_type (TYPE_CODE_FLT, TARGET_FLOAT_BIT / TARGET_CHAR_BIT, + 0, + "float", (struct objfile *) NULL); + mdebug_type_double = + init_type (TYPE_CODE_FLT, TARGET_DOUBLE_BIT / TARGET_CHAR_BIT, + 0, + "double", (struct objfile *) NULL); + mdebug_type_complex = + init_type (TYPE_CODE_COMPLEX, 2 * TARGET_FLOAT_BIT / TARGET_CHAR_BIT, + 0, + "complex", (struct objfile *) NULL); + TYPE_TARGET_TYPE (mdebug_type_complex) = mdebug_type_float; + mdebug_type_double_complex = + init_type (TYPE_CODE_COMPLEX, 2 * TARGET_DOUBLE_BIT / TARGET_CHAR_BIT, + 0, + "double complex", (struct objfile *) NULL); + TYPE_TARGET_TYPE (mdebug_type_double_complex) = mdebug_type_double; + + /* Is a "string" the way btString means it the same as TYPE_CODE_STRING? + FIXME. */ + mdebug_type_string = + init_type (TYPE_CODE_STRING, + TARGET_CHAR_BIT / TARGET_CHAR_BIT, + 0, "string", + (struct objfile *) NULL); + + /* We use TYPE_CODE_INT to print these as integers. Does this do any + good? Would we be better off with TYPE_CODE_ERROR? Should + TYPE_CODE_ERROR print things in hex if it knows the size? */ + mdebug_type_fixed_dec = + init_type (TYPE_CODE_INT, + TARGET_INT_BIT / TARGET_CHAR_BIT, + 0, "fixed decimal", + (struct objfile *) NULL); + + mdebug_type_float_dec = + init_type (TYPE_CODE_ERROR, + TARGET_DOUBLE_BIT / TARGET_CHAR_BIT, + 0, "floating decimal", + (struct objfile *) NULL); + + nodebug_func_symbol_type = init_type (TYPE_CODE_FUNC, 1, 0, + "<function, no debug info>", NULL); + TYPE_TARGET_TYPE (nodebug_func_symbol_type) = mdebug_type_int; + nodebug_var_symbol_type = + init_type (TYPE_CODE_INT, TARGET_INT_BIT / HOST_CHAR_BIT, 0, + "<variable, no debug info>", NULL); +} diff --git a/gdb/symfile.c b/gdb/symfile.c new file mode 100644 index 0000000..66bbf71 --- /dev/null +++ b/gdb/symfile.c @@ -0,0 +1,3340 @@ +/* Generic symbol file reading for the GNU debugger, GDB. + + Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, + 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + + Contributed by Cygnus Support, using pieces from other GDB modules. + + 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 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "symtab.h" +#include "gdbtypes.h" +#include "gdbcore.h" +#include "frame.h" +#include "target.h" +#include "value.h" +#include "symfile.h" +#include "objfiles.h" +#include "source.h" +#include "gdbcmd.h" +#include "breakpoint.h" +#include "language.h" +#include "complaints.h" +#include "demangle.h" +#include "inferior.h" /* for write_pc */ +#include "gdb-stabs.h" +#include "gdb_obstack.h" +#include "completer.h" +#include "bcache.h" + +#include <sys/types.h> +#include <fcntl.h> +#include "gdb_string.h" +#include "gdb_stat.h" +#include <ctype.h> +#include <time.h> + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +#ifdef HPUXHPPA + +/* Some HP-UX related globals to clear when a new "main" + symbol file is loaded. HP-specific. */ + +extern int hp_som_som_object_present; +extern int hp_cxx_exception_support_initialized; +#define RESET_HP_UX_GLOBALS() do {\ + hp_som_som_object_present = 0; /* indicates HP-compiled code */ \ + hp_cxx_exception_support_initialized = 0; /* must reinitialize exception stuff */ \ + } while (0) +#endif + +int (*ui_load_progress_hook) (const char *section, unsigned long num); +void (*show_load_progress) (const char *section, + unsigned long section_sent, + unsigned long section_size, + unsigned long total_sent, + unsigned long total_size); +void (*pre_add_symbol_hook) (char *); +void (*post_add_symbol_hook) (void); +void (*target_new_objfile_hook) (struct objfile *); + +static void clear_symtab_users_cleanup (void *ignore); + +/* Global variables owned by this file */ +int readnow_symbol_files; /* Read full symbols immediately */ + +/* External variables and functions referenced. */ + +extern void report_transfer_performance (unsigned long, time_t, time_t); + +/* Functions this file defines */ + +#if 0 +static int simple_read_overlay_region_table (void); +static void simple_free_overlay_region_table (void); +#endif + +static void set_initial_language (void); + +static void load_command (char *, int); + +static void symbol_file_add_main_1 (char *args, int from_tty, int flags); + +static void add_symbol_file_command (char *, int); + +static void add_shared_symbol_files_command (char *, int); + +static void cashier_psymtab (struct partial_symtab *); + +bfd *symfile_bfd_open (char *); + +int get_section_index (struct objfile *, char *); + +static void find_sym_fns (struct objfile *); + +static void decrement_reading_symtab (void *); + +static void overlay_invalidate_all (void); + +static int overlay_is_mapped (struct obj_section *); + +void list_overlays_command (char *, int); + +void map_overlay_command (char *, int); + +void unmap_overlay_command (char *, int); + +static void overlay_auto_command (char *, int); + +static void overlay_manual_command (char *, int); + +static void overlay_off_command (char *, int); + +static void overlay_load_command (char *, int); + +static void overlay_command (char *, int); + +static void simple_free_overlay_table (void); + +static void read_target_long_array (CORE_ADDR, unsigned int *, int); + +static int simple_read_overlay_table (void); + +static int simple_overlay_update_1 (struct obj_section *); + +static void add_filename_language (char *ext, enum language lang); + +static void set_ext_lang_command (char *args, int from_tty); + +static void info_ext_lang_command (char *args, int from_tty); + +static void init_filename_language_table (void); + +void _initialize_symfile (void); + +/* List of all available sym_fns. On gdb startup, each object file reader + calls add_symtab_fns() to register information on each format it is + prepared to read. */ + +static struct sym_fns *symtab_fns = NULL; + +/* Flag for whether user will be reloading symbols multiple times. + Defaults to ON for VxWorks, otherwise OFF. */ + +#ifdef SYMBOL_RELOADING_DEFAULT +int symbol_reloading = SYMBOL_RELOADING_DEFAULT; +#else +int symbol_reloading = 0; +#endif + +/* If non-zero, shared library symbols will be added automatically + when the inferior is created, new libraries are loaded, or when + attaching to the inferior. This is almost always what users will + want to have happen; but for very large programs, the startup time + will be excessive, and so if this is a problem, the user can clear + this flag and then add the shared library symbols as needed. Note + that there is a potential for confusion, since if the shared + library symbols are not loaded, commands like "info fun" will *not* + report all the functions that are actually present. */ + +int auto_solib_add = 1; + +/* For systems that support it, a threshold size in megabytes. If + automatically adding a new library's symbol table to those already + known to the debugger would cause the total shared library symbol + size to exceed this threshhold, then the shlib's symbols are not + added. The threshold is ignored if the user explicitly asks for a + shlib to be added, such as when using the "sharedlibrary" + command. */ + +int auto_solib_limit; + + +/* Since this function is called from within qsort, in an ANSI environment + it must conform to the prototype for qsort, which specifies that the + comparison function takes two "void *" pointers. */ + +static int +compare_symbols (const void *s1p, const void *s2p) +{ + register struct symbol **s1, **s2; + + s1 = (struct symbol **) s1p; + s2 = (struct symbol **) s2p; + return (strcmp (SYMBOL_SOURCE_NAME (*s1), SYMBOL_SOURCE_NAME (*s2))); +} + +/* + + LOCAL FUNCTION + + compare_psymbols -- compare two partial symbols by name + + DESCRIPTION + + Given pointers to pointers to two partial symbol table entries, + compare them by name and return -N, 0, or +N (ala strcmp). + Typically used by sorting routines like qsort(). + + NOTES + + Does direct compare of first two characters before punting + and passing to strcmp for longer compares. Note that the + original version had a bug whereby two null strings or two + identically named one character strings would return the + comparison of memory following the null byte. + + */ + +static int +compare_psymbols (const void *s1p, const void *s2p) +{ + register struct partial_symbol **s1, **s2; + register char *st1, *st2; + + s1 = (struct partial_symbol **) s1p; + s2 = (struct partial_symbol **) s2p; + st1 = SYMBOL_SOURCE_NAME (*s1); + st2 = SYMBOL_SOURCE_NAME (*s2); + + + if ((st1[0] - st2[0]) || !st1[0]) + { + return (st1[0] - st2[0]); + } + else if ((st1[1] - st2[1]) || !st1[1]) + { + return (st1[1] - st2[1]); + } + else + { + return (strcmp (st1, st2)); + } +} + +void +sort_pst_symbols (struct partial_symtab *pst) +{ + /* Sort the global list; don't sort the static list */ + + qsort (pst->objfile->global_psymbols.list + pst->globals_offset, + pst->n_global_syms, sizeof (struct partial_symbol *), + compare_psymbols); +} + +/* Call sort_block_syms to sort alphabetically the symbols of one block. */ + +void +sort_block_syms (register struct block *b) +{ + qsort (&BLOCK_SYM (b, 0), BLOCK_NSYMS (b), + sizeof (struct symbol *), compare_symbols); +} + +/* Call sort_symtab_syms to sort alphabetically + the symbols of each block of one symtab. */ + +void +sort_symtab_syms (register struct symtab *s) +{ + register struct blockvector *bv; + int nbl; + int i; + register struct block *b; + + if (s == 0) + return; + bv = BLOCKVECTOR (s); + nbl = BLOCKVECTOR_NBLOCKS (bv); + for (i = 0; i < nbl; i++) + { + b = BLOCKVECTOR_BLOCK (bv, i); + if (BLOCK_SHOULD_SORT (b)) + sort_block_syms (b); + } +} + +/* Make a null terminated copy of the string at PTR with SIZE characters in + the obstack pointed to by OBSTACKP . Returns the address of the copy. + Note that the string at PTR does not have to be null terminated, I.E. it + may be part of a larger string and we are only saving a substring. */ + +char * +obsavestring (char *ptr, int size, struct obstack *obstackp) +{ + register char *p = (char *) obstack_alloc (obstackp, size + 1); + /* Open-coded memcpy--saves function call time. These strings are usually + short. FIXME: Is this really still true with a compiler that can + inline memcpy? */ + { + register char *p1 = ptr; + register char *p2 = p; + char *end = ptr + size; + while (p1 != end) + *p2++ = *p1++; + } + p[size] = 0; + return p; +} + +/* Concatenate strings S1, S2 and S3; return the new string. Space is found + in the obstack pointed to by OBSTACKP. */ + +char * +obconcat (struct obstack *obstackp, const char *s1, const char *s2, + const char *s3) +{ + register int len = strlen (s1) + strlen (s2) + strlen (s3) + 1; + register char *val = (char *) obstack_alloc (obstackp, len); + strcpy (val, s1); + strcat (val, s2); + strcat (val, s3); + return val; +} + +/* True if we are nested inside psymtab_to_symtab. */ + +int currently_reading_symtab = 0; + +static void +decrement_reading_symtab (void *dummy) +{ + currently_reading_symtab--; +} + +/* Get the symbol table that corresponds to a partial_symtab. + This is fast after the first time you do it. In fact, there + is an even faster macro PSYMTAB_TO_SYMTAB that does the fast + case inline. */ + +struct symtab * +psymtab_to_symtab (register struct partial_symtab *pst) +{ + /* If it's been looked up before, return it. */ + if (pst->symtab) + return pst->symtab; + + /* If it has not yet been read in, read it. */ + if (!pst->readin) + { + struct cleanup *back_to = make_cleanup (decrement_reading_symtab, NULL); + currently_reading_symtab++; + (*pst->read_symtab) (pst); + do_cleanups (back_to); + } + + return pst->symtab; +} + +/* Initialize entry point information for this objfile. */ + +void +init_entry_point_info (struct objfile *objfile) +{ + /* Save startup file's range of PC addresses to help blockframe.c + decide where the bottom of the stack is. */ + + if (bfd_get_file_flags (objfile->obfd) & EXEC_P) + { + /* Executable file -- record its entry point so we'll recognize + the startup file because it contains the entry point. */ + objfile->ei.entry_point = bfd_get_start_address (objfile->obfd); + } + else + { + /* Examination of non-executable.o files. Short-circuit this stuff. */ + objfile->ei.entry_point = INVALID_ENTRY_POINT; + } + objfile->ei.entry_file_lowpc = INVALID_ENTRY_LOWPC; + objfile->ei.entry_file_highpc = INVALID_ENTRY_HIGHPC; + objfile->ei.entry_func_lowpc = INVALID_ENTRY_LOWPC; + objfile->ei.entry_func_highpc = INVALID_ENTRY_HIGHPC; + objfile->ei.main_func_lowpc = INVALID_ENTRY_LOWPC; + objfile->ei.main_func_highpc = INVALID_ENTRY_HIGHPC; +} + +/* Get current entry point address. */ + +CORE_ADDR +entry_point_address (void) +{ + return symfile_objfile ? symfile_objfile->ei.entry_point : 0; +} + +/* Remember the lowest-addressed loadable section we've seen. + This function is called via bfd_map_over_sections. + + In case of equal vmas, the section with the largest size becomes the + lowest-addressed loadable section. + + If the vmas and sizes are equal, the last section is considered the + lowest-addressed loadable section. */ + +void +find_lowest_section (bfd *abfd, asection *sect, PTR obj) +{ + asection **lowest = (asection **) obj; + + if (0 == (bfd_get_section_flags (abfd, sect) & SEC_LOAD)) + return; + if (!*lowest) + *lowest = sect; /* First loadable section */ + else if (bfd_section_vma (abfd, *lowest) > bfd_section_vma (abfd, sect)) + *lowest = sect; /* A lower loadable section */ + else if (bfd_section_vma (abfd, *lowest) == bfd_section_vma (abfd, sect) + && (bfd_section_size (abfd, (*lowest)) + <= bfd_section_size (abfd, sect))) + *lowest = sect; +} + + +/* Build (allocate and populate) a section_addr_info struct from + an existing section table. */ + +extern struct section_addr_info * +build_section_addr_info_from_section_table (const struct section_table *start, + const struct section_table *end) +{ + struct section_addr_info *sap; + const struct section_table *stp; + int oidx; + + sap = xmalloc (sizeof (struct section_addr_info)); + memset (sap, 0, sizeof (struct section_addr_info)); + + for (stp = start, oidx = 0; stp != end; stp++) + { + if (bfd_get_section_flags (stp->bfd, + stp->the_bfd_section) & (SEC_ALLOC | SEC_LOAD) + && oidx < MAX_SECTIONS) + { + sap->other[oidx].addr = stp->addr; + sap->other[oidx].name + = xstrdup (bfd_section_name (stp->bfd, stp->the_bfd_section)); + sap->other[oidx].sectindex = stp->the_bfd_section->index; + oidx++; + } + } + + return sap; +} + + +/* Free all memory allocated by build_section_addr_info_from_section_table. */ + +extern void +free_section_addr_info (struct section_addr_info *sap) +{ + int idx; + + for (idx = 0; idx < MAX_SECTIONS; idx++) + if (sap->other[idx].name) + xfree (sap->other[idx].name); + xfree (sap); +} + + +/* Parse the user's idea of an offset for dynamic linking, into our idea + of how to represent it for fast symbol reading. This is the default + version of the sym_fns.sym_offsets function for symbol readers that + don't need to do anything special. It allocates a section_offsets table + for the objectfile OBJFILE and stuffs ADDR into all of the offsets. */ + +void +default_symfile_offsets (struct objfile *objfile, + struct section_addr_info *addrs) +{ + int i; + asection *sect = NULL; + + objfile->num_sections = SECT_OFF_MAX; + objfile->section_offsets = (struct section_offsets *) + obstack_alloc (&objfile->psymbol_obstack, SIZEOF_SECTION_OFFSETS); + memset (objfile->section_offsets, 0, SIZEOF_SECTION_OFFSETS); + + /* Now calculate offsets for section that were specified by the + caller. */ + for (i = 0; i < MAX_SECTIONS && addrs->other[i].name; i++) + { + struct other_sections *osp ; + + osp = &addrs->other[i] ; + if (osp->addr == 0) + continue; + + /* Record all sections in offsets */ + /* The section_offsets in the objfile are here filled in using + the BFD index. */ + (objfile->section_offsets)->offsets[osp->sectindex] = osp->addr; + } + + /* Remember the bfd indexes for the .text, .data, .bss and + .rodata sections. */ + + sect = bfd_get_section_by_name (objfile->obfd, ".text"); + if (sect) + objfile->sect_index_text = sect->index; + + sect = bfd_get_section_by_name (objfile->obfd, ".data"); + if (sect) + objfile->sect_index_data = sect->index; + + sect = bfd_get_section_by_name (objfile->obfd, ".bss"); + if (sect) + objfile->sect_index_bss = sect->index; + + sect = bfd_get_section_by_name (objfile->obfd, ".rodata"); + if (sect) + objfile->sect_index_rodata = sect->index; + + /* This is where things get really weird... We MUST have valid + indices for the various sect_index_* members or gdb will abort. + So if for example, there is no ".text" section, we have to + accomodate that. Except when explicitly adding symbol files at + some address, section_offsets contains nothing but zeros, so it + doesn't matter which slot in section_offsets the individual + sect_index_* members index into. So if they are all zero, it is + safe to just point all the currently uninitialized indices to the + first slot. */ + + for (i = 0; i < objfile->num_sections; i++) + { + if (ANOFFSET (objfile->section_offsets, i) != 0) + { + break; + } + } + if (i == objfile->num_sections) + { + if (objfile->sect_index_text == -1) + objfile->sect_index_text = 0; + if (objfile->sect_index_data == -1) + objfile->sect_index_data = 0; + if (objfile->sect_index_bss == -1) + objfile->sect_index_bss = 0; + if (objfile->sect_index_rodata == -1) + objfile->sect_index_rodata = 0; + } +} + +/* Process a symbol file, as either the main file or as a dynamically + loaded file. + + OBJFILE is where the symbols are to be read from. + + ADDR is the address where the text segment was loaded, unless the + objfile is the main symbol file, in which case it is zero. + + MAINLINE is nonzero if this is the main symbol file, or zero if + it's an extra symbol file such as dynamically loaded code. + + VERBO is nonzero if the caller has printed a verbose message about + the symbol reading (and complaints can be more terse about it). */ + +void +syms_from_objfile (struct objfile *objfile, struct section_addr_info *addrs, + int mainline, int verbo) +{ + asection *lower_sect; + asection *sect; + CORE_ADDR lower_offset; + struct section_addr_info local_addr; + struct cleanup *old_chain; + int i; + + /* If ADDRS is NULL, initialize the local section_addr_info struct and + point ADDRS to it. We now establish the convention that an addr of + zero means no load address was specified. */ + + if (addrs == NULL) + { + memset (&local_addr, 0, sizeof (local_addr)); + addrs = &local_addr; + } + + init_entry_point_info (objfile); + find_sym_fns (objfile); + + if (objfile->sf == NULL) + return; /* No symbols. */ + + /* Make sure that partially constructed symbol tables will be cleaned up + if an error occurs during symbol reading. */ + old_chain = make_cleanup_free_objfile (objfile); + + if (mainline) + { + /* We will modify the main symbol table, make sure that all its users + will be cleaned up if an error occurs during symbol reading. */ + make_cleanup (clear_symtab_users_cleanup, 0 /*ignore*/); + + /* Since no error yet, throw away the old symbol table. */ + + if (symfile_objfile != NULL) + { + free_objfile (symfile_objfile); + symfile_objfile = NULL; + } + + /* Currently we keep symbols from the add-symbol-file command. + If the user wants to get rid of them, they should do "symbol-file" + without arguments first. Not sure this is the best behavior + (PR 2207). */ + + (*objfile->sf->sym_new_init) (objfile); + } + + /* Convert addr into an offset rather than an absolute address. + We find the lowest address of a loaded segment in the objfile, + and assume that <addr> is where that got loaded. + + We no longer warn if the lowest section is not a text segment (as + happens for the PA64 port. */ + if (!mainline) + { + /* Find lowest loadable section to be used as starting point for + continguous sections. FIXME!! won't work without call to find + .text first, but this assumes text is lowest section. */ + lower_sect = bfd_get_section_by_name (objfile->obfd, ".text"); + if (lower_sect == NULL) + bfd_map_over_sections (objfile->obfd, find_lowest_section, + (PTR) &lower_sect); + if (lower_sect == NULL) + warning ("no loadable sections found in added symbol-file %s", + objfile->name); + else + if ((bfd_get_section_flags (objfile->obfd, lower_sect) & SEC_CODE) == 0) + warning ("Lowest section in %s is %s at %s", + objfile->name, + bfd_section_name (objfile->obfd, lower_sect), + paddr (bfd_section_vma (objfile->obfd, lower_sect))); + if (lower_sect != NULL) + lower_offset = bfd_section_vma (objfile->obfd, lower_sect); + else + lower_offset = 0; + + /* Calculate offsets for the loadable sections. + FIXME! Sections must be in order of increasing loadable section + so that contiguous sections can use the lower-offset!!! + + Adjust offsets if the segments are not contiguous. + If the section is contiguous, its offset should be set to + the offset of the highest loadable section lower than it + (the loadable section directly below it in memory). + this_offset = lower_offset = lower_addr - lower_orig_addr */ + + /* Calculate offsets for sections. */ + for (i=0 ; i < MAX_SECTIONS && addrs->other[i].name; i++) + { + if (addrs->other[i].addr != 0) + { + sect = bfd_get_section_by_name (objfile->obfd, addrs->other[i].name); + if (sect) + { + addrs->other[i].addr -= bfd_section_vma (objfile->obfd, sect); + lower_offset = addrs->other[i].addr; + /* This is the index used by BFD. */ + addrs->other[i].sectindex = sect->index ; + } + else + { + warning ("section %s not found in %s", addrs->other[i].name, + objfile->name); + addrs->other[i].addr = 0; + } + } + else + addrs->other[i].addr = lower_offset; + } + } + + /* Initialize symbol reading routines for this objfile, allow complaints to + appear for this new file, and record how verbose to be, then do the + initial symbol reading for this file. */ + + (*objfile->sf->sym_init) (objfile); + clear_complaints (&symfile_complaints, 1, verbo); + + (*objfile->sf->sym_offsets) (objfile, addrs); + +#ifndef IBM6000_TARGET + /* This is a SVR4/SunOS specific hack, I think. In any event, it + screws RS/6000. sym_offsets should be doing this sort of thing, + because it knows the mapping between bfd sections and + section_offsets. */ + /* This is a hack. As far as I can tell, section offsets are not + target dependent. They are all set to addr with a couple of + exceptions. The exceptions are sysvr4 shared libraries, whose + offsets are kept in solib structures anyway and rs6000 xcoff + which handles shared libraries in a completely unique way. + + Section offsets are built similarly, except that they are built + by adding addr in all cases because there is no clear mapping + from section_offsets into actual sections. Note that solib.c + has a different algorithm for finding section offsets. + + These should probably all be collapsed into some target + independent form of shared library support. FIXME. */ + + if (addrs) + { + struct obj_section *s; + + /* Map section offsets in "addr" back to the object's + sections by comparing the section names with bfd's + section names. Then adjust the section address by + the offset. */ /* for gdb/13815 */ + + ALL_OBJFILE_OSECTIONS (objfile, s) + { + CORE_ADDR s_addr = 0; + int i; + + for (i = 0; + !s_addr && i < MAX_SECTIONS && addrs->other[i].name; + i++) + if (strcmp (bfd_section_name (s->objfile->obfd, + s->the_bfd_section), + addrs->other[i].name) == 0) + s_addr = addrs->other[i].addr; /* end added for gdb/13815 */ + + s->addr -= s->offset; + s->addr += s_addr; + s->endaddr -= s->offset; + s->endaddr += s_addr; + s->offset += s_addr; + } + } +#endif /* not IBM6000_TARGET */ + + (*objfile->sf->sym_read) (objfile, mainline); + + if (!have_partial_symbols () && !have_full_symbols ()) + { + wrap_here (""); + printf_filtered ("(no debugging symbols found)..."); + wrap_here (""); + } + + /* Don't allow char * to have a typename (else would get caddr_t). + Ditto void *. FIXME: Check whether this is now done by all the + symbol readers themselves (many of them now do), and if so remove + it from here. */ + + TYPE_NAME (lookup_pointer_type (builtin_type_char)) = 0; + TYPE_NAME (lookup_pointer_type (builtin_type_void)) = 0; + + /* Mark the objfile has having had initial symbol read attempted. Note + that this does not mean we found any symbols... */ + + objfile->flags |= OBJF_SYMS; + + /* Discard cleanups as symbol reading was successful. */ + + discard_cleanups (old_chain); + + /* Call this after reading in a new symbol table to give target + dependent code a crack at the new symbols. For instance, this + could be used to update the values of target-specific symbols GDB + needs to keep track of (such as _sigtramp, or whatever). */ + + TARGET_SYMFILE_POSTREAD (objfile); +} + +/* Perform required actions after either reading in the initial + symbols for a new objfile, or mapping in the symbols from a reusable + objfile. */ + +void +new_symfile_objfile (struct objfile *objfile, int mainline, int verbo) +{ + + /* If this is the main symbol file we have to clean up all users of the + old main symbol file. Otherwise it is sufficient to fixup all the + breakpoints that may have been redefined by this symbol file. */ + if (mainline) + { + /* OK, make it the "real" symbol file. */ + symfile_objfile = objfile; + + clear_symtab_users (); + } + else + { + breakpoint_re_set (); + } + + /* We're done reading the symbol file; finish off complaints. */ + clear_complaints (&symfile_complaints, 0, verbo); +} + +/* Process a symbol file, as either the main file or as a dynamically + loaded file. + + NAME is the file name (which will be tilde-expanded and made + absolute herein) (but we don't free or modify NAME itself). + FROM_TTY says how verbose to be. MAINLINE specifies whether this + is the main symbol file, or whether it's an extra symbol file such + as dynamically loaded code. If !mainline, ADDR is the address + where the text segment was loaded. + + Upon success, returns a pointer to the objfile that was added. + Upon failure, jumps back to command level (never returns). */ + +struct objfile * +symbol_file_add (char *name, int from_tty, struct section_addr_info *addrs, + int mainline, int flags) +{ + struct objfile *objfile; + struct partial_symtab *psymtab; + bfd *abfd; + + /* Open a bfd for the file, and give user a chance to burp if we'd be + interactively wiping out any existing symbols. */ + + abfd = symfile_bfd_open (name); + + if ((have_full_symbols () || have_partial_symbols ()) + && mainline + && from_tty + && !query ("Load new symbol table from \"%s\"? ", name)) + error ("Not confirmed."); + + objfile = allocate_objfile (abfd, flags); + + /* If the objfile uses a mapped symbol file, and we have a psymtab for + it, then skip reading any symbols at this time. */ + + if ((objfile->flags & OBJF_MAPPED) && (objfile->flags & OBJF_SYMS)) + { + /* We mapped in an existing symbol table file that already has had + initial symbol reading performed, so we can skip that part. Notify + the user that instead of reading the symbols, they have been mapped. + */ + if (from_tty || info_verbose) + { + printf_filtered ("Mapped symbols for %s...", name); + wrap_here (""); + gdb_flush (gdb_stdout); + } + init_entry_point_info (objfile); + find_sym_fns (objfile); + } + else + { + /* We either created a new mapped symbol table, mapped an existing + symbol table file which has not had initial symbol reading + performed, or need to read an unmapped symbol table. */ + if (from_tty || info_verbose) + { + if (pre_add_symbol_hook) + pre_add_symbol_hook (name); + else + { + printf_filtered ("Reading symbols from %s...", name); + wrap_here (""); + gdb_flush (gdb_stdout); + } + } + syms_from_objfile (objfile, addrs, mainline, from_tty); + } + + /* We now have at least a partial symbol table. Check to see if the + user requested that all symbols be read on initial access via either + 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 (from_tty || info_verbose) + { + printf_filtered ("expanding to full symbols..."); + wrap_here (""); + gdb_flush (gdb_stdout); + } + + for (psymtab = objfile->psymtabs; + psymtab != NULL; + psymtab = psymtab->next) + { + psymtab_to_symtab (psymtab); + } + } + + if (from_tty || info_verbose) + { + if (post_add_symbol_hook) + post_add_symbol_hook (); + else + { + printf_filtered ("done.\n"); + gdb_flush (gdb_stdout); + } + } + + if (objfile->sf == NULL) + return objfile; /* No symbols. */ + + new_symfile_objfile (objfile, mainline, from_tty); + + if (target_new_objfile_hook) + target_new_objfile_hook (objfile); + + return (objfile); +} + +/* Call symbol_file_add() with default values and update whatever is + affected by the loading of a new main(). + Used when the file is supplied in the gdb command line + and by some targets with special loading requirements. + The auxiliary function, symbol_file_add_main_1(), has the flags + argument for the switches that can only be specified in the symbol_file + command itself. */ + +void +symbol_file_add_main (char *args, int from_tty) +{ + symbol_file_add_main_1 (args, from_tty, 0); +} + +static void +symbol_file_add_main_1 (char *args, int from_tty, int flags) +{ + symbol_file_add (args, from_tty, NULL, 1, flags); + +#ifdef HPUXHPPA + RESET_HP_UX_GLOBALS (); +#endif + + /* Getting new symbols may change our opinion about + what is frameless. */ + reinit_frame_cache (); + + set_initial_language (); +} + +void +symbol_file_clear (int from_tty) +{ + if ((have_full_symbols () || have_partial_symbols ()) + && from_tty + && !query ("Discard symbol table from `%s'? ", + symfile_objfile->name)) + error ("Not confirmed."); + free_all_objfiles (); + + /* solib descriptors may have handles to objfiles. Since their + storage has just been released, we'd better wipe the solib + descriptors as well. + */ +#if defined(SOLIB_RESTART) + SOLIB_RESTART (); +#endif + + symfile_objfile = NULL; + if (from_tty) + printf_unfiltered ("No symbol file now.\n"); +#ifdef HPUXHPPA + RESET_HP_UX_GLOBALS (); +#endif +} + +/* This is the symbol-file command. Read the file, analyze its + symbols, and add a struct symtab to a symtab list. The syntax of + the command is rather bizarre--(1) buildargv implements various + quoting conventions which are undocumented and have little or + nothing in common with the way things are quoted (or not quoted) + elsewhere in GDB, (2) options are used, which are not generally + used in GDB (perhaps "set mapped on", "set readnow on" would be + better), (3) the order of options matters, which is contrary to GNU + conventions (because it is confusing and inconvenient). */ +/* Note: ezannoni 2000-04-17. This function used to have support for + rombug (see remote-os9k.c). It consisted of a call to target_link() + (target.c) to get the address of the text segment from the target, + and pass that to symbol_file_add(). This is no longer supported. */ + +void +symbol_file_command (char *args, int from_tty) +{ + char **argv; + char *name = NULL; + struct cleanup *cleanups; + int flags = OBJF_USERLOADED; + + dont_repeat (); + + if (args == NULL) + { + symbol_file_clear (from_tty); + } + else + { + if ((argv = buildargv (args)) == NULL) + { + nomem (0); + } + cleanups = make_cleanup_freeargv (argv); + while (*argv != NULL) + { + if (STREQ (*argv, "-mapped")) + flags |= OBJF_MAPPED; + else + if (STREQ (*argv, "-readnow")) + flags |= OBJF_READNOW; + else + if (**argv == '-') + error ("unknown option `%s'", *argv); + else + { + name = *argv; + + symbol_file_add_main_1 (name, from_tty, flags); + } + argv++; + } + + if (name == NULL) + { + error ("no symbol file name was specified"); + } + do_cleanups (cleanups); + } +} + +/* Set the initial language. + + A better solution would be to record the language in the psymtab when reading + partial symbols, and then use it (if known) to set the language. This would + be a win for formats that encode the language in an easily discoverable place, + such as DWARF. For stabs, we can jump through hoops looking for specially + named symbols or try to intuit the language from the specific type of stabs + we find, but we can't do that until later when we read in full symbols. + FIXME. */ + +static void +set_initial_language (void) +{ + struct partial_symtab *pst; + enum language lang = language_unknown; + + pst = find_main_psymtab (); + if (pst != NULL) + { + if (pst->filename != NULL) + { + lang = deduce_language_from_filename (pst->filename); + } + if (lang == language_unknown) + { + /* Make C the default language */ + lang = language_c; + } + set_language (lang); + expected_language = current_language; /* Don't warn the user */ + } +} + +/* Open file specified by NAME and hand it off to BFD for preliminary + analysis. Result is a newly initialized bfd *, which includes a newly + malloc'd` copy of NAME (tilde-expanded and made absolute). + In case of trouble, error() is called. */ + +bfd * +symfile_bfd_open (char *name) +{ + bfd *sym_bfd; + int desc; + char *absolute_name; + + + + name = tilde_expand (name); /* Returns 1st new malloc'd copy */ + + /* Look down path for it, allocate 2nd new malloc'd copy. */ + desc = openp (getenv ("PATH"), 1, name, O_RDONLY | O_BINARY, 0, &absolute_name); +#if defined(__GO32__) || defined(_WIN32) || defined (__CYGWIN__) + if (desc < 0) + { + char *exename = alloca (strlen (name) + 5); + strcat (strcpy (exename, name), ".exe"); + desc = openp (getenv ("PATH"), 1, exename, O_RDONLY | O_BINARY, + 0, &absolute_name); + } +#endif + if (desc < 0) + { + make_cleanup (xfree, name); + perror_with_name (name); + } + xfree (name); /* Free 1st new malloc'd copy */ + name = absolute_name; /* Keep 2nd malloc'd copy in bfd */ + /* It'll be freed in free_objfile(). */ + + sym_bfd = bfd_fdopenr (name, gnutarget, desc); + if (!sym_bfd) + { + close (desc); + make_cleanup (xfree, name); + error ("\"%s\": can't open to read symbols: %s.", name, + bfd_errmsg (bfd_get_error ())); + } + sym_bfd->cacheable = 1; + + if (!bfd_check_format (sym_bfd, bfd_object)) + { + /* FIXME: should be checking for errors from bfd_close (for one thing, + on error it does not free all the storage associated with the + bfd). */ + bfd_close (sym_bfd); /* This also closes desc */ + make_cleanup (xfree, name); + error ("\"%s\": can't read symbols: %s.", name, + bfd_errmsg (bfd_get_error ())); + } + return (sym_bfd); +} + +/* Return the section index for the given section name. Return -1 if + the section was not found. */ +int +get_section_index (struct objfile *objfile, char *section_name) +{ + asection *sect = bfd_get_section_by_name (objfile->obfd, section_name); + if (sect) + return sect->index; + else + return -1; +} + +/* Link a new symtab_fns into the global symtab_fns list. Called on gdb + startup by the _initialize routine in each object file format reader, + to register information about each format the the reader is prepared + to handle. */ + +void +add_symtab_fns (struct sym_fns *sf) +{ + sf->next = symtab_fns; + symtab_fns = sf; +} + + +/* Initialize to read symbols from the symbol file sym_bfd. It either + returns or calls error(). The result is an initialized struct sym_fns + in the objfile structure, that contains cached information about the + symbol file. */ + +static void +find_sym_fns (struct objfile *objfile) +{ + struct sym_fns *sf; + enum bfd_flavour our_flavour = bfd_get_flavour (objfile->obfd); + char *our_target = bfd_get_target (objfile->obfd); + + if (our_flavour == bfd_target_srec_flavour + || our_flavour == bfd_target_ihex_flavour + || our_flavour == bfd_target_tekhex_flavour) + return; /* No symbols. */ + + /* Special kludge for apollo. See dstread.c. */ + if (STREQN (our_target, "apollo", 6)) + our_flavour = (enum bfd_flavour) -2; + + for (sf = symtab_fns; sf != NULL; sf = sf->next) + { + if (our_flavour == sf->sym_flavour) + { + objfile->sf = sf; + return; + } + } + error ("I'm sorry, Dave, I can't do that. Symbol format `%s' unknown.", + bfd_get_target (objfile->obfd)); +} + +/* This function runs the load command of our current target. */ + +static void +load_command (char *arg, int from_tty) +{ + if (arg == NULL) + arg = get_exec_file (1); + target_load (arg, from_tty); + + /* After re-loading the executable, we don't really know which + overlays are mapped any more. */ + overlay_cache_invalid = 1; +} + +/* This version of "load" should be usable for any target. Currently + it is just used for remote targets, not inftarg.c or core files, + on the theory that only in that case is it useful. + + Avoiding xmodem and the like seems like a win (a) because we don't have + to worry about finding it, and (b) On VMS, fork() is very slow and so + we don't want to run a subprocess. On the other hand, I'm not sure how + performance compares. */ + +static int download_write_size = 512; +static int validate_download = 0; + +/* Callback service function for generic_load (bfd_map_over_sections). */ + +static void +add_section_size_callback (bfd *abfd, asection *asec, void *data) +{ + bfd_size_type *sum = data; + + *sum += bfd_get_section_size_before_reloc (asec); +} + +/* Opaque data for load_section_callback. */ +struct load_section_data { + unsigned long load_offset; + unsigned long write_count; + unsigned long data_count; + bfd_size_type total_size; +}; + +/* Callback service function for generic_load (bfd_map_over_sections). */ + +static void +load_section_callback (bfd *abfd, asection *asec, void *data) +{ + struct load_section_data *args = data; + + if (bfd_get_section_flags (abfd, asec) & SEC_LOAD) + { + bfd_size_type size = bfd_get_section_size_before_reloc (asec); + if (size > 0) + { + char *buffer; + struct cleanup *old_chain; + CORE_ADDR lma = bfd_section_lma (abfd, asec) + args->load_offset; + bfd_size_type block_size; + int err; + const char *sect_name = bfd_get_section_name (abfd, asec); + bfd_size_type sent; + + if (download_write_size > 0 && size > download_write_size) + block_size = download_write_size; + else + block_size = size; + + buffer = xmalloc (size); + old_chain = make_cleanup (xfree, buffer); + + /* Is this really necessary? I guess it gives the user something + to look at during a long download. */ + ui_out_message (uiout, 0, "Loading section %s, size 0x%s lma 0x%s\n", + sect_name, paddr_nz (size), paddr_nz (lma)); + + bfd_get_section_contents (abfd, asec, buffer, 0, size); + + sent = 0; + do + { + int len; + bfd_size_type this_transfer = size - sent; + + if (this_transfer >= block_size) + this_transfer = block_size; + len = target_write_memory_partial (lma, buffer, + this_transfer, &err); + if (err) + break; + if (validate_download) + { + /* Broken memories and broken monitors manifest + themselves here when bring new computers to + life. This doubles already slow downloads. */ + /* NOTE: cagney/1999-10-18: A more efficient + implementation might add a verify_memory() + method to the target vector and then use + that. remote.c could implement that method + using the ``qCRC'' packet. */ + char *check = xmalloc (len); + struct cleanup *verify_cleanups = + make_cleanup (xfree, check); + + if (target_read_memory (lma, check, len) != 0) + error ("Download verify read failed at 0x%s", + paddr (lma)); + if (memcmp (buffer, check, len) != 0) + error ("Download verify compare failed at 0x%s", + paddr (lma)); + do_cleanups (verify_cleanups); + } + args->data_count += len; + lma += len; + buffer += len; + args->write_count += 1; + sent += len; + if (quit_flag + || (ui_load_progress_hook != NULL + && ui_load_progress_hook (sect_name, sent))) + error ("Canceled the download"); + + if (show_load_progress != NULL) + show_load_progress (sect_name, sent, size, + args->data_count, args->total_size); + } + while (sent < size); + + if (err != 0) + error ("Memory access error while loading section %s.", sect_name); + + do_cleanups (old_chain); + } + } +} + +void +generic_load (char *args, int from_tty) +{ + asection *s; + bfd *loadfile_bfd; + time_t start_time, end_time; /* Start and end times of download */ + char *filename; + struct cleanup *old_cleanups; + char *offptr; + struct load_section_data cbdata; + CORE_ADDR entry; + + cbdata.load_offset = 0; /* Offset to add to vma for each section. */ + cbdata.write_count = 0; /* Number of writes needed. */ + cbdata.data_count = 0; /* Number of bytes written to target memory. */ + cbdata.total_size = 0; /* Total size of all bfd sectors. */ + + /* Parse the input argument - the user can specify a load offset as + a second argument. */ + filename = xmalloc (strlen (args) + 1); + old_cleanups = make_cleanup (xfree, filename); + strcpy (filename, args); + offptr = strchr (filename, ' '); + if (offptr != NULL) + { + char *endptr; + + cbdata.load_offset = strtoul (offptr, &endptr, 0); + if (offptr == endptr) + error ("Invalid download offset:%s\n", offptr); + *offptr = '\0'; + } + else + cbdata.load_offset = 0; + + /* Open the file for loading. */ + loadfile_bfd = bfd_openr (filename, gnutarget); + if (loadfile_bfd == NULL) + { + perror_with_name (filename); + return; + } + + /* FIXME: should be checking for errors from bfd_close (for one thing, + on error it does not free all the storage associated with the + bfd). */ + make_cleanup_bfd_close (loadfile_bfd); + + if (!bfd_check_format (loadfile_bfd, bfd_object)) + { + error ("\"%s\" is not an object file: %s", filename, + bfd_errmsg (bfd_get_error ())); + } + + bfd_map_over_sections (loadfile_bfd, add_section_size_callback, + (void *) &cbdata.total_size); + + start_time = time (NULL); + + bfd_map_over_sections (loadfile_bfd, load_section_callback, &cbdata); + + end_time = time (NULL); + + entry = bfd_get_start_address (loadfile_bfd); + ui_out_text (uiout, "Start address "); + ui_out_field_fmt (uiout, "address", "0x%s", paddr_nz (entry)); + ui_out_text (uiout, ", load size "); + ui_out_field_fmt (uiout, "load-size", "%lu", cbdata.data_count); + ui_out_text (uiout, "\n"); + /* We were doing this in remote-mips.c, I suspect it is right + for other targets too. */ + write_pc (entry); + + /* FIXME: are we supposed to call symbol_file_add or not? According to + a comment from remote-mips.c (where a call to symbol_file_add was + commented out), making the call confuses GDB if more than one file is + loaded in. remote-nindy.c had no call to symbol_file_add, but remote-vx.c + does. */ + + print_transfer_performance (gdb_stdout, cbdata.data_count, + cbdata.write_count, end_time - start_time); + + do_cleanups (old_cleanups); +} + +/* Report how fast the transfer went. */ + +/* DEPRECATED: cagney/1999-10-18: report_transfer_performance is being + replaced by print_transfer_performance (with a very different + function signature). */ + +void +report_transfer_performance (unsigned long data_count, time_t start_time, + time_t end_time) +{ + print_transfer_performance (gdb_stdout, data_count, + end_time - start_time, 0); +} + +void +print_transfer_performance (struct ui_file *stream, + unsigned long data_count, + unsigned long write_count, + unsigned long time_count) +{ + ui_out_text (uiout, "Transfer rate: "); + if (time_count > 0) + { + ui_out_field_fmt (uiout, "transfer-rate", "%lu", + (data_count * 8) / time_count); + ui_out_text (uiout, " bits/sec"); + } + else + { + ui_out_field_fmt (uiout, "transferred-bits", "%lu", (data_count * 8)); + ui_out_text (uiout, " bits in <1 sec"); + } + if (write_count > 0) + { + ui_out_text (uiout, ", "); + ui_out_field_fmt (uiout, "write-rate", "%lu", data_count / write_count); + ui_out_text (uiout, " bytes/write"); + } + ui_out_text (uiout, ".\n"); +} + +/* This function allows the addition of incrementally linked object files. + It does not modify any state in the target, only in the debugger. */ +/* Note: ezannoni 2000-04-13 This function/command used to have a + special case syntax for the rombug target (Rombug is the boot + monitor for Microware's OS-9 / OS-9000, see remote-os9k.c). In the + rombug case, the user doesn't need to supply a text address, + instead a call to target_link() (in target.c) would supply the + value to use. We are now discontinuing this type of ad hoc syntax. */ + +/* ARGSUSED */ +static void +add_symbol_file_command (char *args, int from_tty) +{ + char *filename = NULL; + int flags = OBJF_USERLOADED; + char *arg; + int expecting_option = 0; + int section_index = 0; + int argcnt = 0; + int sec_num = 0; + int i; + int expecting_sec_name = 0; + int expecting_sec_addr = 0; + + struct + { + char *name; + char *value; + } sect_opts[SECT_OFF_MAX]; + + struct section_addr_info section_addrs; + struct cleanup *my_cleanups = make_cleanup (null_cleanup, NULL); + + dont_repeat (); + + if (args == NULL) + error ("add-symbol-file takes a file name and an address"); + + /* Make a copy of the string that we can safely write into. */ + args = xstrdup (args); + + /* Ensure section_addrs is initialized */ + memset (§ion_addrs, 0, sizeof (section_addrs)); + + while (*args != '\000') + { + /* Any leading spaces? */ + while (isspace (*args)) + args++; + + /* Point arg to the beginning of the argument. */ + arg = args; + + /* Move args pointer over the argument. */ + while ((*args != '\000') && !isspace (*args)) + args++; + + /* If there are more arguments, terminate arg and + proceed past it. */ + if (*args != '\000') + *args++ = '\000'; + + /* Now process the argument. */ + if (argcnt == 0) + { + /* The first argument is the file name. */ + filename = tilde_expand (arg); + make_cleanup (xfree, filename); + } + else + if (argcnt == 1) + { + /* The second argument is always the text address at which + to load the program. */ + sect_opts[section_index].name = ".text"; + sect_opts[section_index].value = arg; + section_index++; + } + else + { + /* It's an option (starting with '-') or it's an argument + to an option */ + + if (*arg == '-') + { + if (strcmp (arg, "-mapped") == 0) + flags |= OBJF_MAPPED; + else + if (strcmp (arg, "-readnow") == 0) + flags |= OBJF_READNOW; + else + if (strcmp (arg, "-s") == 0) + { + if (section_index >= SECT_OFF_MAX) + error ("Too many sections specified."); + expecting_sec_name = 1; + expecting_sec_addr = 1; + } + } + else + { + if (expecting_sec_name) + { + sect_opts[section_index].name = arg; + expecting_sec_name = 0; + } + else + if (expecting_sec_addr) + { + sect_opts[section_index].value = arg; + expecting_sec_addr = 0; + section_index++; + } + else + error ("USAGE: add-symbol-file <filename> <textaddress> [-mapped] [-readnow] [-s <secname> <addr>]*"); + } + } + argcnt++; + } + + /* Print the prompt for the query below. And save the arguments into + a sect_addr_info structure to be passed around to other + functions. We have to split this up into separate print + statements because local_hex_string returns a local static + string. */ + + printf_filtered ("add symbol table from file \"%s\" at\n", filename); + for (i = 0; i < section_index; i++) + { + CORE_ADDR addr; + char *val = sect_opts[i].value; + char *sec = sect_opts[i].name; + + val = sect_opts[i].value; + if (val[0] == '0' && val[1] == 'x') + addr = strtoul (val+2, NULL, 16); + else + addr = strtoul (val, NULL, 10); + + /* Here we store the section offsets in the order they were + entered on the command line. */ + section_addrs.other[sec_num].name = sec; + section_addrs.other[sec_num].addr = addr; + printf_filtered ("\t%s_addr = %s\n", + sec, + local_hex_string ((unsigned long)addr)); + sec_num++; + + /* The object's sections are initialized when a + call is made to build_objfile_section_table (objfile). + This happens in reread_symbols. + At this point, we don't know what file type this is, + so we can't determine what section names are valid. */ + } + + if (from_tty && (!query ("%s", ""))) + error ("Not confirmed."); + + symbol_file_add (filename, from_tty, §ion_addrs, 0, flags); + + /* Getting new symbols may change our opinion about what is + frameless. */ + reinit_frame_cache (); + do_cleanups (my_cleanups); +} + +static void +add_shared_symbol_files_command (char *args, int from_tty) +{ +#ifdef ADD_SHARED_SYMBOL_FILES + ADD_SHARED_SYMBOL_FILES (args, from_tty); +#else + error ("This command is not available in this configuration of GDB."); +#endif +} + +/* Re-read symbols if a symbol-file has changed. */ +void +reread_symbols (void) +{ + struct objfile *objfile; + long new_modtime; + int reread_one = 0; + struct stat new_statbuf; + int res; + + /* With the addition of shared libraries, this should be modified, + the load time should be saved in the partial symbol tables, since + different tables may come from different source files. FIXME. + This routine should then walk down each partial symbol table + and see if the symbol table that it originates from has been changed */ + + for (objfile = object_files; objfile; objfile = objfile->next) + { + if (objfile->obfd) + { +#ifdef IBM6000_TARGET + /* If this object is from a shared library, then you should + stat on the library name, not member name. */ + + if (objfile->obfd->my_archive) + res = stat (objfile->obfd->my_archive->filename, &new_statbuf); + else +#endif + res = stat (objfile->name, &new_statbuf); + if (res != 0) + { + /* FIXME, should use print_sys_errmsg but it's not filtered. */ + printf_filtered ("`%s' has disappeared; keeping its symbols.\n", + objfile->name); + continue; + } + new_modtime = new_statbuf.st_mtime; + if (new_modtime != objfile->mtime) + { + struct cleanup *old_cleanups; + struct section_offsets *offsets; + int num_offsets; + char *obfd_filename; + + printf_filtered ("`%s' has changed; re-reading symbols.\n", + objfile->name); + + /* There are various functions like symbol_file_add, + symfile_bfd_open, syms_from_objfile, etc., which might + appear to do what we want. But they have various other + effects which we *don't* want. So we just do stuff + ourselves. We don't worry about mapped files (for one thing, + any mapped file will be out of date). */ + + /* If we get an error, blow away this objfile (not sure if + that is the correct response for things like shared + libraries). */ + old_cleanups = make_cleanup_free_objfile (objfile); + /* We need to do this whenever any symbols go away. */ + make_cleanup (clear_symtab_users_cleanup, 0 /*ignore*/); + + /* Clean up any state BFD has sitting around. We don't need + to close the descriptor but BFD lacks a way of closing the + BFD without closing the descriptor. */ + obfd_filename = bfd_get_filename (objfile->obfd); + if (!bfd_close (objfile->obfd)) + error ("Can't close BFD for %s: %s", objfile->name, + bfd_errmsg (bfd_get_error ())); + objfile->obfd = bfd_openr (obfd_filename, gnutarget); + if (objfile->obfd == NULL) + error ("Can't open %s to read symbols.", objfile->name); + /* bfd_openr sets cacheable to true, which is what we want. */ + if (!bfd_check_format (objfile->obfd, bfd_object)) + error ("Can't read symbols from %s: %s.", objfile->name, + bfd_errmsg (bfd_get_error ())); + + /* Save the offsets, we will nuke them with the rest of the + psymbol_obstack. */ + num_offsets = objfile->num_sections; + offsets = (struct section_offsets *) alloca (SIZEOF_SECTION_OFFSETS); + memcpy (offsets, objfile->section_offsets, SIZEOF_SECTION_OFFSETS); + + /* Nuke all the state that we will re-read. Much of the following + code which sets things to NULL really is necessary to tell + other parts of GDB that there is nothing currently there. */ + + /* FIXME: Do we have to free a whole linked list, or is this + enough? */ + if (objfile->global_psymbols.list) + xmfree (objfile->md, objfile->global_psymbols.list); + memset (&objfile->global_psymbols, 0, + sizeof (objfile->global_psymbols)); + if (objfile->static_psymbols.list) + xmfree (objfile->md, objfile->static_psymbols.list); + memset (&objfile->static_psymbols, 0, + sizeof (objfile->static_psymbols)); + + /* Free the obstacks for non-reusable objfiles */ + bcache_xfree (objfile->psymbol_cache); + objfile->psymbol_cache = bcache_xmalloc (); + bcache_xfree (objfile->macro_cache); + objfile->macro_cache = bcache_xmalloc (); + obstack_free (&objfile->psymbol_obstack, 0); + obstack_free (&objfile->symbol_obstack, 0); + obstack_free (&objfile->type_obstack, 0); + objfile->sections = NULL; + objfile->symtabs = NULL; + objfile->psymtabs = NULL; + objfile->free_psymtabs = NULL; + objfile->msymbols = NULL; + objfile->minimal_symbol_count = 0; + memset (&objfile->msymbol_hash, 0, + sizeof (objfile->msymbol_hash)); + memset (&objfile->msymbol_demangled_hash, 0, + sizeof (objfile->msymbol_demangled_hash)); + objfile->fundamental_types = NULL; + if (objfile->sf != NULL) + { + (*objfile->sf->sym_finish) (objfile); + } + + /* We never make this a mapped file. */ + objfile->md = NULL; + /* obstack_specify_allocation also initializes the obstack so + it is empty. */ + objfile->psymbol_cache = bcache_xmalloc (); + objfile->macro_cache = bcache_xmalloc (); + obstack_specify_allocation (&objfile->psymbol_obstack, 0, 0, + xmalloc, xfree); + obstack_specify_allocation (&objfile->symbol_obstack, 0, 0, + xmalloc, xfree); + obstack_specify_allocation (&objfile->type_obstack, 0, 0, + xmalloc, xfree); + if (build_objfile_section_table (objfile)) + { + error ("Can't find the file sections in `%s': %s", + objfile->name, bfd_errmsg (bfd_get_error ())); + } + + /* We use the same section offsets as from last time. I'm not + sure whether that is always correct for shared libraries. */ + objfile->section_offsets = (struct section_offsets *) + obstack_alloc (&objfile->psymbol_obstack, SIZEOF_SECTION_OFFSETS); + memcpy (objfile->section_offsets, offsets, SIZEOF_SECTION_OFFSETS); + objfile->num_sections = num_offsets; + + /* What the hell is sym_new_init for, anyway? The concept of + distinguishing between the main file and additional files + in this way seems rather dubious. */ + if (objfile == symfile_objfile) + { + (*objfile->sf->sym_new_init) (objfile); +#ifdef HPUXHPPA + RESET_HP_UX_GLOBALS (); +#endif + } + + (*objfile->sf->sym_init) (objfile); + clear_complaints (&symfile_complaints, 1, 1); + /* The "mainline" parameter is a hideous hack; I think leaving it + zero is OK since dbxread.c also does what it needs to do if + objfile->global_psymbols.size is 0. */ + (*objfile->sf->sym_read) (objfile, 0); + if (!have_partial_symbols () && !have_full_symbols ()) + { + wrap_here (""); + printf_filtered ("(no debugging symbols found)\n"); + wrap_here (""); + } + objfile->flags |= OBJF_SYMS; + + /* We're done reading the symbol file; finish off complaints. */ + clear_complaints (&symfile_complaints, 0, 1); + + /* Getting new symbols may change our opinion about what is + frameless. */ + + reinit_frame_cache (); + + /* Discard cleanups as symbol reading was successful. */ + discard_cleanups (old_cleanups); + + /* If the mtime has changed between the time we set new_modtime + and now, we *want* this to be out of date, so don't call stat + again now. */ + objfile->mtime = new_modtime; + reread_one = 1; + + /* Call this after reading in a new symbol table to give target + dependent code a crack at the new symbols. For instance, this + could be used to update the values of target-specific symbols GDB + needs to keep track of (such as _sigtramp, or whatever). */ + + TARGET_SYMFILE_POSTREAD (objfile); + } + } + } + + if (reread_one) + clear_symtab_users (); +} + + + +typedef struct +{ + char *ext; + enum language lang; +} +filename_language; + +static filename_language *filename_language_table; +static int fl_table_size, fl_table_next; + +static void +add_filename_language (char *ext, enum language lang) +{ + if (fl_table_next >= fl_table_size) + { + fl_table_size += 10; + filename_language_table = + xrealloc (filename_language_table, + fl_table_size * sizeof (*filename_language_table)); + } + + filename_language_table[fl_table_next].ext = xstrdup (ext); + filename_language_table[fl_table_next].lang = lang; + fl_table_next++; +} + +static char *ext_args; + +static void +set_ext_lang_command (char *args, int from_tty) +{ + int i; + char *cp = ext_args; + enum language lang; + + /* First arg is filename extension, starting with '.' */ + if (*cp != '.') + error ("'%s': Filename extension must begin with '.'", ext_args); + + /* Find end of first arg. */ + while (*cp && !isspace (*cp)) + cp++; + + if (*cp == '\0') + error ("'%s': two arguments required -- filename extension and language", + ext_args); + + /* Null-terminate first arg */ + *cp++ = '\0'; + + /* Find beginning of second arg, which should be a source language. */ + while (*cp && isspace (*cp)) + cp++; + + if (*cp == '\0') + error ("'%s': two arguments required -- filename extension and language", + ext_args); + + /* Lookup the language from among those we know. */ + lang = language_enum (cp); + + /* Now lookup the filename extension: do we already know it? */ + for (i = 0; i < fl_table_next; i++) + if (0 == strcmp (ext_args, filename_language_table[i].ext)) + break; + + if (i >= fl_table_next) + { + /* new file extension */ + add_filename_language (ext_args, lang); + } + else + { + /* redefining a previously known filename extension */ + + /* if (from_tty) */ + /* query ("Really make files of type %s '%s'?", */ + /* ext_args, language_str (lang)); */ + + xfree (filename_language_table[i].ext); + filename_language_table[i].ext = xstrdup (ext_args); + filename_language_table[i].lang = lang; + } +} + +static void +info_ext_lang_command (char *args, int from_tty) +{ + int i; + + printf_filtered ("Filename extensions and the languages they represent:"); + printf_filtered ("\n\n"); + for (i = 0; i < fl_table_next; i++) + printf_filtered ("\t%s\t- %s\n", + filename_language_table[i].ext, + language_str (filename_language_table[i].lang)); +} + +static void +init_filename_language_table (void) +{ + if (fl_table_size == 0) /* protect against repetition */ + { + fl_table_size = 20; + fl_table_next = 0; + filename_language_table = + xmalloc (fl_table_size * sizeof (*filename_language_table)); + add_filename_language (".c", language_c); + add_filename_language (".C", language_cplus); + add_filename_language (".cc", language_cplus); + add_filename_language (".cp", language_cplus); + add_filename_language (".cpp", language_cplus); + add_filename_language (".cxx", language_cplus); + add_filename_language (".c++", language_cplus); + add_filename_language (".java", language_java); + add_filename_language (".class", language_java); + /* OBSOLETE add_filename_language (".ch", language_chill); */ + /* OBSOLETE add_filename_language (".c186", language_chill); */ + /* OBSOLETE add_filename_language (".c286", language_chill); */ + add_filename_language (".f", language_fortran); + add_filename_language (".F", language_fortran); + add_filename_language (".s", language_asm); + add_filename_language (".S", language_asm); + add_filename_language (".pas", language_pascal); + add_filename_language (".p", language_pascal); + add_filename_language (".pp", language_pascal); + } +} + +enum language +deduce_language_from_filename (char *filename) +{ + int i; + char *cp; + + if (filename != NULL) + if ((cp = strrchr (filename, '.')) != NULL) + for (i = 0; i < fl_table_next; i++) + if (strcmp (cp, filename_language_table[i].ext) == 0) + return filename_language_table[i].lang; + + return language_unknown; +} + +/* allocate_symtab: + + Allocate and partly initialize a new symbol table. Return a pointer + to it. error() if no space. + + Caller must set these fields: + LINETABLE(symtab) + symtab->blockvector + symtab->dirname + symtab->free_code + symtab->free_ptr + possibly free_named_symtabs (symtab->filename); + */ + +struct symtab * +allocate_symtab (char *filename, struct objfile *objfile) +{ + register struct symtab *symtab; + + symtab = (struct symtab *) + obstack_alloc (&objfile->symbol_obstack, sizeof (struct symtab)); + memset (symtab, 0, sizeof (*symtab)); + symtab->filename = obsavestring (filename, strlen (filename), + &objfile->symbol_obstack); + symtab->fullname = NULL; + symtab->language = deduce_language_from_filename (filename); + symtab->debugformat = obsavestring ("unknown", 7, + &objfile->symbol_obstack); + + /* Hook it to the objfile it comes from */ + + symtab->objfile = objfile; + symtab->next = objfile->symtabs; + objfile->symtabs = symtab; + + /* FIXME: This should go away. It is only defined for the Z8000, + and the Z8000 definition of this macro doesn't have anything to + do with the now-nonexistent EXTRA_SYMTAB_INFO macro, it's just + here for convenience. */ +#ifdef INIT_EXTRA_SYMTAB_INFO + INIT_EXTRA_SYMTAB_INFO (symtab); +#endif + + return (symtab); +} + +struct partial_symtab * +allocate_psymtab (char *filename, struct objfile *objfile) +{ + struct partial_symtab *psymtab; + + if (objfile->free_psymtabs) + { + psymtab = objfile->free_psymtabs; + objfile->free_psymtabs = psymtab->next; + } + else + psymtab = (struct partial_symtab *) + obstack_alloc (&objfile->psymbol_obstack, + sizeof (struct partial_symtab)); + + memset (psymtab, 0, sizeof (struct partial_symtab)); + psymtab->filename = obsavestring (filename, strlen (filename), + &objfile->psymbol_obstack); + psymtab->symtab = NULL; + + /* Prepend it to the psymtab list for the objfile it belongs to. + Psymtabs are searched in most recent inserted -> least recent + inserted order. */ + + psymtab->objfile = objfile; + psymtab->next = objfile->psymtabs; + objfile->psymtabs = psymtab; +#if 0 + { + struct partial_symtab **prev_pst; + psymtab->objfile = objfile; + psymtab->next = NULL; + prev_pst = &(objfile->psymtabs); + while ((*prev_pst) != NULL) + prev_pst = &((*prev_pst)->next); + (*prev_pst) = psymtab; + } +#endif + + return (psymtab); +} + +void +discard_psymtab (struct partial_symtab *pst) +{ + struct partial_symtab **prev_pst; + + /* From dbxread.c: + Empty psymtabs happen as a result of header files which don't + have any symbols in them. There can be a lot of them. But this + check is wrong, in that a psymtab with N_SLINE entries but + nothing else is not empty, but we don't realize that. Fixing + that without slowing things down might be tricky. */ + + /* First, snip it out of the psymtab chain */ + + prev_pst = &(pst->objfile->psymtabs); + while ((*prev_pst) != pst) + prev_pst = &((*prev_pst)->next); + (*prev_pst) = pst->next; + + /* Next, put it on a free list for recycling */ + + pst->next = pst->objfile->free_psymtabs; + pst->objfile->free_psymtabs = pst; +} + + +/* Reset all data structures in gdb which may contain references to symbol + table data. */ + +void +clear_symtab_users (void) +{ + /* Someday, we should do better than this, by only blowing away + the things that really need to be blown. */ + clear_value_history (); + clear_displays (); + clear_internalvars (); + breakpoint_re_set (); + set_default_breakpoint (0, 0, 0, 0); + clear_current_source_symtab_and_line (); + clear_pc_function_cache (); + if (target_new_objfile_hook) + target_new_objfile_hook (NULL); +} + +static void +clear_symtab_users_cleanup (void *ignore) +{ + clear_symtab_users (); +} + +/* clear_symtab_users_once: + + This function is run after symbol reading, or from a cleanup. + If an old symbol table was obsoleted, the old symbol table + has been blown away, but the other GDB data structures that may + reference it have not yet been cleared or re-directed. (The old + symtab was zapped, and the cleanup queued, in free_named_symtab() + below.) + + This function can be queued N times as a cleanup, or called + directly; it will do all the work the first time, and then will be a + no-op until the next time it is queued. This works by bumping a + counter at queueing time. Much later when the cleanup is run, or at + the end of symbol processing (in case the cleanup is discarded), if + the queued count is greater than the "done-count", we do the work + and set the done-count to the queued count. If the queued count is + less than or equal to the done-count, we just ignore the call. This + is needed because reading a single .o file will often replace many + symtabs (one per .h file, for example), and we don't want to reset + the breakpoints N times in the user's face. + + The reason we both queue a cleanup, and call it directly after symbol + reading, is because the cleanup protects us in case of errors, but is + discarded if symbol reading is successful. */ + +#if 0 +/* FIXME: As free_named_symtabs is currently a big noop this function + is no longer needed. */ +static void clear_symtab_users_once (void); + +static int clear_symtab_users_queued; +static int clear_symtab_users_done; + +static void +clear_symtab_users_once (void) +{ + /* Enforce once-per-`do_cleanups'-semantics */ + if (clear_symtab_users_queued <= clear_symtab_users_done) + return; + clear_symtab_users_done = clear_symtab_users_queued; + + clear_symtab_users (); +} +#endif + +/* Delete the specified psymtab, and any others that reference it. */ + +static void +cashier_psymtab (struct partial_symtab *pst) +{ + struct partial_symtab *ps, *pprev = NULL; + int i; + + /* Find its previous psymtab in the chain */ + for (ps = pst->objfile->psymtabs; ps; ps = ps->next) + { + if (ps == pst) + break; + pprev = ps; + } + + if (ps) + { + /* Unhook it from the chain. */ + if (ps == pst->objfile->psymtabs) + pst->objfile->psymtabs = ps->next; + else + pprev->next = ps->next; + + /* FIXME, we can't conveniently deallocate the entries in the + partial_symbol lists (global_psymbols/static_psymbols) that + this psymtab points to. These just take up space until all + the psymtabs are reclaimed. Ditto the dependencies list and + filename, which are all in the psymbol_obstack. */ + + /* We need to cashier any psymtab that has this one as a dependency... */ + again: + for (ps = pst->objfile->psymtabs; ps; ps = ps->next) + { + for (i = 0; i < ps->number_of_dependencies; i++) + { + if (ps->dependencies[i] == pst) + { + cashier_psymtab (ps); + goto again; /* Must restart, chain has been munged. */ + } + } + } + } +} + +/* If a symtab or psymtab for filename NAME is found, free it along + with any dependent breakpoints, displays, etc. + Used when loading new versions of object modules with the "add-file" + command. This is only called on the top-level symtab or psymtab's name; + it is not called for subsidiary files such as .h files. + + Return value is 1 if we blew away the environment, 0 if not. + FIXME. The return value appears to never be used. + + FIXME. I think this is not the best way to do this. We should + work on being gentler to the environment while still cleaning up + all stray pointers into the freed symtab. */ + +int +free_named_symtabs (char *name) +{ +#if 0 + /* FIXME: With the new method of each objfile having it's own + psymtab list, this function needs serious rethinking. In particular, + why was it ever necessary to toss psymtabs with specific compilation + unit filenames, as opposed to all psymtabs from a particular symbol + file? -- fnf + Well, the answer is that some systems permit reloading of particular + compilation units. We want to blow away any old info about these + compilation units, regardless of which objfiles they arrived in. --gnu. */ + + register struct symtab *s; + register struct symtab *prev; + register struct partial_symtab *ps; + struct blockvector *bv; + int blewit = 0; + + /* We only wack things if the symbol-reload switch is set. */ + if (!symbol_reloading) + return 0; + + /* Some symbol formats have trouble providing file names... */ + if (name == 0 || *name == '\0') + return 0; + + /* Look for a psymtab with the specified name. */ + +again2: + for (ps = partial_symtab_list; ps; ps = ps->next) + { + if (STREQ (name, ps->filename)) + { + cashier_psymtab (ps); /* Blow it away...and its little dog, too. */ + goto again2; /* Must restart, chain has been munged */ + } + } + + /* Look for a symtab with the specified name. */ + + for (s = symtab_list; s; s = s->next) + { + if (STREQ (name, s->filename)) + break; + prev = s; + } + + if (s) + { + if (s == symtab_list) + symtab_list = s->next; + else + prev->next = s->next; + + /* For now, queue a delete for all breakpoints, displays, etc., whether + or not they depend on the symtab being freed. This should be + changed so that only those data structures affected are deleted. */ + + /* But don't delete anything if the symtab is empty. + This test is necessary due to a bug in "dbxread.c" that + causes empty symtabs to be created for N_SO symbols that + contain the pathname of the object file. (This problem + has been fixed in GDB 3.9x). */ + + bv = BLOCKVECTOR (s); + if (BLOCKVECTOR_NBLOCKS (bv) > 2 + || BLOCK_NSYMS (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK)) + || BLOCK_NSYMS (BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK))) + { + complaint (&symfile_complaints, "Replacing old symbols for `%s'", + name); + clear_symtab_users_queued++; + make_cleanup (clear_symtab_users_once, 0); + blewit = 1; + } + else + { + complaint (&symfile_complaints, "Empty symbol table found for `%s'", + name); + } + + free_symtab (s); + } + else + { + /* It is still possible that some breakpoints will be affected + even though no symtab was found, since the file might have + been compiled without debugging, and hence not be associated + with a symtab. In order to handle this correctly, we would need + to keep a list of text address ranges for undebuggable files. + For now, we do nothing, since this is a fairly obscure case. */ + ; + } + + /* FIXME, what about the minimal symbol table? */ + return blewit; +#else + return (0); +#endif +} + +/* Allocate and partially fill a partial symtab. It will be + completely filled at the end of the symbol list. + + FILENAME is the name of the symbol-file we are reading from. */ + +struct partial_symtab * +start_psymtab_common (struct objfile *objfile, + struct section_offsets *section_offsets, char *filename, + CORE_ADDR textlow, struct partial_symbol **global_syms, + struct partial_symbol **static_syms) +{ + struct partial_symtab *psymtab; + + psymtab = allocate_psymtab (filename, objfile); + psymtab->section_offsets = section_offsets; + psymtab->textlow = textlow; + psymtab->texthigh = psymtab->textlow; /* default */ + psymtab->globals_offset = global_syms - objfile->global_psymbols.list; + psymtab->statics_offset = static_syms - objfile->static_psymbols.list; + return (psymtab); +} + +/* Add a symbol with a long value to a psymtab. + Since one arg is a struct, we pass in a ptr and deref it (sigh). */ + +void +add_psymbol_to_list (char *name, int namelength, namespace_enum namespace, + enum address_class class, + struct psymbol_allocation_list *list, long val, /* Value as a long */ + CORE_ADDR coreaddr, /* Value as a CORE_ADDR */ + enum language language, struct objfile *objfile) +{ + register struct partial_symbol *psym; + char *buf = alloca (namelength + 1); + /* psymbol is static so that there will be no uninitialized gaps in the + structure which might contain random data, causing cache misses in + bcache. */ + static struct partial_symbol psymbol; + + /* Create local copy of the partial symbol */ + memcpy (buf, name, namelength); + buf[namelength] = '\0'; + SYMBOL_NAME (&psymbol) = bcache (buf, namelength + 1, objfile->psymbol_cache); + /* val and coreaddr are mutually exclusive, one of them *will* be zero */ + if (val != 0) + { + SYMBOL_VALUE (&psymbol) = val; + } + else + { + SYMBOL_VALUE_ADDRESS (&psymbol) = coreaddr; + } + SYMBOL_SECTION (&psymbol) = 0; + SYMBOL_LANGUAGE (&psymbol) = language; + PSYMBOL_NAMESPACE (&psymbol) = namespace; + PSYMBOL_CLASS (&psymbol) = class; + SYMBOL_INIT_LANGUAGE_SPECIFIC (&psymbol, language); + + /* Stash the partial symbol away in the cache */ + psym = bcache (&psymbol, sizeof (struct partial_symbol), objfile->psymbol_cache); + + /* Save pointer to partial symbol in psymtab, growing symtab if needed. */ + if (list->next >= list->list + list->size) + { + extend_psymbol_list (list, objfile); + } + *list->next++ = psym; + OBJSTAT (objfile, n_psyms++); +} + +/* Add a symbol with a long value to a psymtab. This differs from + * add_psymbol_to_list above in taking both a mangled and a demangled + * name. */ + +void +add_psymbol_with_dem_name_to_list (char *name, int namelength, char *dem_name, + int dem_namelength, namespace_enum namespace, + enum address_class class, + struct psymbol_allocation_list *list, long val, /* Value as a long */ + CORE_ADDR coreaddr, /* Value as a CORE_ADDR */ + enum language language, + struct objfile *objfile) +{ + register struct partial_symbol *psym; + char *buf = alloca (namelength + 1); + /* psymbol is static so that there will be no uninitialized gaps in the + structure which might contain random data, causing cache misses in + bcache. */ + static struct partial_symbol psymbol; + + /* Create local copy of the partial symbol */ + + memcpy (buf, name, namelength); + buf[namelength] = '\0'; + SYMBOL_NAME (&psymbol) = bcache (buf, namelength + 1, objfile->psymbol_cache); + + buf = alloca (dem_namelength + 1); + memcpy (buf, dem_name, dem_namelength); + buf[dem_namelength] = '\0'; + + switch (language) + { + case language_c: + case language_cplus: + SYMBOL_CPLUS_DEMANGLED_NAME (&psymbol) = + bcache (buf, dem_namelength + 1, objfile->psymbol_cache); + break; + /* OBSOLETE case language_chill: */ + /* OBSOLETE SYMBOL_CHILL_DEMANGLED_NAME (&psymbol) = */ + /* OBSOLETE bcache (buf, dem_namelength + 1, objfile->psymbol_cache); */ + + /* FIXME What should be done for the default case? Ignoring for now. */ + } + + /* val and coreaddr are mutually exclusive, one of them *will* be zero */ + if (val != 0) + { + SYMBOL_VALUE (&psymbol) = val; + } + else + { + SYMBOL_VALUE_ADDRESS (&psymbol) = coreaddr; + } + SYMBOL_SECTION (&psymbol) = 0; + SYMBOL_LANGUAGE (&psymbol) = language; + PSYMBOL_NAMESPACE (&psymbol) = namespace; + PSYMBOL_CLASS (&psymbol) = class; + SYMBOL_INIT_LANGUAGE_SPECIFIC (&psymbol, language); + + /* Stash the partial symbol away in the cache */ + psym = bcache (&psymbol, sizeof (struct partial_symbol), objfile->psymbol_cache); + + /* Save pointer to partial symbol in psymtab, growing symtab if needed. */ + if (list->next >= list->list + list->size) + { + extend_psymbol_list (list, objfile); + } + *list->next++ = psym; + OBJSTAT (objfile, n_psyms++); +} + +/* Initialize storage for partial symbols. */ + +void +init_psymbol_list (struct objfile *objfile, int total_symbols) +{ + /* Free any previously allocated psymbol lists. */ + + if (objfile->global_psymbols.list) + { + xmfree (objfile->md, (PTR) objfile->global_psymbols.list); + } + if (objfile->static_psymbols.list) + { + xmfree (objfile->md, (PTR) objfile->static_psymbols.list); + } + + /* Current best guess is that approximately a twentieth + of the total symbols (in a debugging file) are global or static + oriented symbols */ + + objfile->global_psymbols.size = total_symbols / 10; + objfile->static_psymbols.size = total_symbols / 10; + + if (objfile->global_psymbols.size > 0) + { + objfile->global_psymbols.next = + objfile->global_psymbols.list = (struct partial_symbol **) + xmmalloc (objfile->md, (objfile->global_psymbols.size + * sizeof (struct partial_symbol *))); + } + if (objfile->static_psymbols.size > 0) + { + objfile->static_psymbols.next = + objfile->static_psymbols.list = (struct partial_symbol **) + xmmalloc (objfile->md, (objfile->static_psymbols.size + * sizeof (struct partial_symbol *))); + } +} + +/* OVERLAYS: + The following code implements an abstraction for debugging overlay sections. + + The target model is as follows: + 1) The gnu linker will permit multiple sections to be mapped into the + same VMA, each with its own unique LMA (or load address). + 2) It is assumed that some runtime mechanism exists for mapping the + sections, one by one, from the load address into the VMA address. + 3) This code provides a mechanism for gdb to keep track of which + sections should be considered to be mapped from the VMA to the LMA. + This information is used for symbol lookup, and memory read/write. + For instance, if a section has been mapped then its contents + should be read from the VMA, otherwise from the LMA. + + Two levels of debugger support for overlays are available. One is + "manual", in which the debugger relies on the user to tell it which + overlays are currently mapped. This level of support is + implemented entirely in the core debugger, and the information about + whether a section is mapped is kept in the objfile->obj_section table. + + The second level of support is "automatic", and is only available if + the target-specific code provides functionality to read the target's + overlay mapping table, and translate its contents for the debugger + (by updating the mapped state information in the obj_section tables). + + The interface is as follows: + User commands: + overlay map <name> -- tell gdb to consider this section mapped + overlay unmap <name> -- tell gdb to consider this section unmapped + overlay list -- list the sections that GDB thinks are mapped + overlay read-target -- get the target's state of what's mapped + overlay off/manual/auto -- set overlay debugging state + Functional interface: + find_pc_mapped_section(pc): if the pc is in the range of a mapped + section, return that section. + find_pc_overlay(pc): find any overlay section that contains + the pc, either in its VMA or its LMA + overlay_is_mapped(sect): true if overlay is marked as mapped + section_is_overlay(sect): true if section's VMA != LMA + pc_in_mapped_range(pc,sec): true if pc belongs to section's VMA + pc_in_unmapped_range(...): true if pc belongs to section's LMA + sections_overlap(sec1, sec2): true if mapped sec1 and sec2 ranges overlap + overlay_mapped_address(...): map an address from section's LMA to VMA + overlay_unmapped_address(...): map an address from section's VMA to LMA + symbol_overlayed_address(...): Return a "current" address for symbol: + either in VMA or LMA depending on whether + the symbol's section is currently mapped + */ + +/* Overlay debugging state: */ + +enum overlay_debugging_state overlay_debugging = ovly_off; +int overlay_cache_invalid = 0; /* True if need to refresh mapped state */ + +/* Target vector for refreshing overlay mapped state */ +static void simple_overlay_update (struct obj_section *); +void (*target_overlay_update) (struct obj_section *) = simple_overlay_update; + +/* Function: section_is_overlay (SECTION) + Returns true if SECTION has VMA not equal to LMA, ie. + SECTION is loaded at an address different from where it will "run". */ + +int +section_is_overlay (asection *section) +{ + /* FIXME: need bfd *, so we can use bfd_section_lma methods. */ + + if (overlay_debugging) + if (section && section->lma != 0 && + section->vma != section->lma) + return 1; + + return 0; +} + +/* Function: overlay_invalidate_all (void) + Invalidate the mapped state of all overlay sections (mark it as stale). */ + +static void +overlay_invalidate_all (void) +{ + struct objfile *objfile; + struct obj_section *sect; + + ALL_OBJSECTIONS (objfile, sect) + if (section_is_overlay (sect->the_bfd_section)) + sect->ovly_mapped = -1; +} + +/* Function: overlay_is_mapped (SECTION) + Returns true if section is an overlay, and is currently mapped. + Private: public access is thru function section_is_mapped. + + Access to the ovly_mapped flag is restricted to this function, so + that we can do automatic update. If the global flag + OVERLAY_CACHE_INVALID is set (by wait_for_inferior), then call + overlay_invalidate_all. If the mapped state of the particular + section is stale, then call TARGET_OVERLAY_UPDATE to refresh it. */ + +static int +overlay_is_mapped (struct obj_section *osect) +{ + if (osect == 0 || !section_is_overlay (osect->the_bfd_section)) + return 0; + + switch (overlay_debugging) + { + default: + case ovly_off: + return 0; /* overlay debugging off */ + case ovly_auto: /* overlay debugging automatic */ + /* Unles there is a target_overlay_update function, + there's really nothing useful to do here (can't really go auto) */ + if (target_overlay_update) + { + if (overlay_cache_invalid) + { + overlay_invalidate_all (); + overlay_cache_invalid = 0; + } + if (osect->ovly_mapped == -1) + (*target_overlay_update) (osect); + } + /* fall thru to manual case */ + case ovly_on: /* overlay debugging manual */ + return osect->ovly_mapped == 1; + } +} + +/* Function: section_is_mapped + Returns true if section is an overlay, and is currently mapped. */ + +int +section_is_mapped (asection *section) +{ + struct objfile *objfile; + struct obj_section *osect; + + if (overlay_debugging) + if (section && section_is_overlay (section)) + ALL_OBJSECTIONS (objfile, osect) + if (osect->the_bfd_section == section) + return overlay_is_mapped (osect); + + return 0; +} + +/* Function: pc_in_unmapped_range + If PC falls into the lma range of SECTION, return true, else false. */ + +CORE_ADDR +pc_in_unmapped_range (CORE_ADDR pc, asection *section) +{ + /* FIXME: need bfd *, so we can use bfd_section_lma methods. */ + + int size; + + if (overlay_debugging) + if (section && section_is_overlay (section)) + { + size = bfd_get_section_size_before_reloc (section); + if (section->lma <= pc && pc < section->lma + size) + return 1; + } + return 0; +} + +/* Function: pc_in_mapped_range + If PC falls into the vma range of SECTION, return true, else false. */ + +CORE_ADDR +pc_in_mapped_range (CORE_ADDR pc, asection *section) +{ + /* FIXME: need bfd *, so we can use bfd_section_vma methods. */ + + int size; + + if (overlay_debugging) + if (section && section_is_overlay (section)) + { + size = bfd_get_section_size_before_reloc (section); + if (section->vma <= pc && pc < section->vma + size) + return 1; + } + return 0; +} + + +/* Return true if the mapped ranges of sections A and B overlap, false + otherwise. */ +int +sections_overlap (asection *a, asection *b) +{ + /* FIXME: need bfd *, so we can use bfd_section_vma methods. */ + + CORE_ADDR a_start = a->vma; + CORE_ADDR a_end = a->vma + bfd_get_section_size_before_reloc (a); + CORE_ADDR b_start = b->vma; + CORE_ADDR b_end = b->vma + bfd_get_section_size_before_reloc (b); + + return (a_start < b_end && b_start < a_end); +} + +/* Function: overlay_unmapped_address (PC, SECTION) + Returns the address corresponding to PC in the unmapped (load) range. + May be the same as PC. */ + +CORE_ADDR +overlay_unmapped_address (CORE_ADDR pc, asection *section) +{ + /* FIXME: need bfd *, so we can use bfd_section_lma methods. */ + + if (overlay_debugging) + if (section && section_is_overlay (section) && + pc_in_mapped_range (pc, section)) + return pc + section->lma - section->vma; + + return pc; +} + +/* Function: overlay_mapped_address (PC, SECTION) + Returns the address corresponding to PC in the mapped (runtime) range. + May be the same as PC. */ + +CORE_ADDR +overlay_mapped_address (CORE_ADDR pc, asection *section) +{ + /* FIXME: need bfd *, so we can use bfd_section_vma methods. */ + + if (overlay_debugging) + if (section && section_is_overlay (section) && + pc_in_unmapped_range (pc, section)) + return pc + section->vma - section->lma; + + return pc; +} + + +/* Function: symbol_overlayed_address + Return one of two addresses (relative to the VMA or to the LMA), + depending on whether the section is mapped or not. */ + +CORE_ADDR +symbol_overlayed_address (CORE_ADDR address, asection *section) +{ + if (overlay_debugging) + { + /* If the symbol has no section, just return its regular address. */ + if (section == 0) + return address; + /* If the symbol's section is not an overlay, just return its address */ + if (!section_is_overlay (section)) + return address; + /* If the symbol's section is mapped, just return its address */ + if (section_is_mapped (section)) + return address; + /* + * HOWEVER: if the symbol is in an overlay section which is NOT mapped, + * then return its LOADED address rather than its vma address!! + */ + return overlay_unmapped_address (address, section); + } + return address; +} + +/* Function: find_pc_overlay (PC) + Return the best-match overlay section for PC: + If PC matches a mapped overlay section's VMA, return that section. + Else if PC matches an unmapped section's VMA, return that section. + Else if PC matches an unmapped section's LMA, return that section. */ + +asection * +find_pc_overlay (CORE_ADDR pc) +{ + struct objfile *objfile; + struct obj_section *osect, *best_match = NULL; + + if (overlay_debugging) + ALL_OBJSECTIONS (objfile, osect) + if (section_is_overlay (osect->the_bfd_section)) + { + if (pc_in_mapped_range (pc, osect->the_bfd_section)) + { + if (overlay_is_mapped (osect)) + return osect->the_bfd_section; + else + best_match = osect; + } + else if (pc_in_unmapped_range (pc, osect->the_bfd_section)) + best_match = osect; + } + return best_match ? best_match->the_bfd_section : NULL; +} + +/* Function: find_pc_mapped_section (PC) + If PC falls into the VMA address range of an overlay section that is + currently marked as MAPPED, return that section. Else return NULL. */ + +asection * +find_pc_mapped_section (CORE_ADDR pc) +{ + struct objfile *objfile; + struct obj_section *osect; + + if (overlay_debugging) + ALL_OBJSECTIONS (objfile, osect) + if (pc_in_mapped_range (pc, osect->the_bfd_section) && + overlay_is_mapped (osect)) + return osect->the_bfd_section; + + return NULL; +} + +/* Function: list_overlays_command + Print a list of mapped sections and their PC ranges */ + +void +list_overlays_command (char *args, int from_tty) +{ + int nmapped = 0; + struct objfile *objfile; + struct obj_section *osect; + + if (overlay_debugging) + ALL_OBJSECTIONS (objfile, osect) + if (overlay_is_mapped (osect)) + { + const char *name; + bfd_vma lma, vma; + int size; + + vma = bfd_section_vma (objfile->obfd, osect->the_bfd_section); + lma = bfd_section_lma (objfile->obfd, osect->the_bfd_section); + size = bfd_get_section_size_before_reloc (osect->the_bfd_section); + name = bfd_section_name (objfile->obfd, osect->the_bfd_section); + + printf_filtered ("Section %s, loaded at ", name); + print_address_numeric (lma, 1, gdb_stdout); + puts_filtered (" - "); + print_address_numeric (lma + size, 1, gdb_stdout); + printf_filtered (", mapped at "); + print_address_numeric (vma, 1, gdb_stdout); + puts_filtered (" - "); + print_address_numeric (vma + size, 1, gdb_stdout); + puts_filtered ("\n"); + + nmapped++; + } + if (nmapped == 0) + printf_filtered ("No sections are mapped.\n"); +} + +/* Function: map_overlay_command + Mark the named section as mapped (ie. residing at its VMA address). */ + +void +map_overlay_command (char *args, int from_tty) +{ + struct objfile *objfile, *objfile2; + struct obj_section *sec, *sec2; + asection *bfdsec; + + if (!overlay_debugging) + error ("\ +Overlay debugging not enabled. Use either the 'overlay auto' or\n\ +the 'overlay manual' command."); + + if (args == 0 || *args == 0) + error ("Argument required: name of an overlay section"); + + /* First, find a section matching the user supplied argument */ + ALL_OBJSECTIONS (objfile, sec) + if (!strcmp (bfd_section_name (objfile->obfd, sec->the_bfd_section), args)) + { + /* Now, check to see if the section is an overlay. */ + bfdsec = sec->the_bfd_section; + if (!section_is_overlay (bfdsec)) + continue; /* not an overlay section */ + + /* Mark the overlay as "mapped" */ + sec->ovly_mapped = 1; + + /* Next, make a pass and unmap any sections that are + overlapped by this new section: */ + ALL_OBJSECTIONS (objfile2, sec2) + if (sec2->ovly_mapped + && sec != sec2 + && sec->the_bfd_section != sec2->the_bfd_section + && sections_overlap (sec->the_bfd_section, + sec2->the_bfd_section)) + { + if (info_verbose) + printf_filtered ("Note: section %s unmapped by overlap\n", + bfd_section_name (objfile->obfd, + sec2->the_bfd_section)); + sec2->ovly_mapped = 0; /* sec2 overlaps sec: unmap sec2 */ + } + return; + } + error ("No overlay section called %s", args); +} + +/* Function: unmap_overlay_command + Mark the overlay section as unmapped + (ie. resident in its LMA address range, rather than the VMA range). */ + +void +unmap_overlay_command (char *args, int from_tty) +{ + struct objfile *objfile; + struct obj_section *sec; + + if (!overlay_debugging) + error ("\ +Overlay debugging not enabled. Use either the 'overlay auto' or\n\ +the 'overlay manual' command."); + + if (args == 0 || *args == 0) + error ("Argument required: name of an overlay section"); + + /* First, find a section matching the user supplied argument */ + ALL_OBJSECTIONS (objfile, sec) + if (!strcmp (bfd_section_name (objfile->obfd, sec->the_bfd_section), args)) + { + if (!sec->ovly_mapped) + error ("Section %s is not mapped", args); + sec->ovly_mapped = 0; + return; + } + error ("No overlay section called %s", args); +} + +/* Function: overlay_auto_command + A utility command to turn on overlay debugging. + Possibly this should be done via a set/show command. */ + +static void +overlay_auto_command (char *args, int from_tty) +{ + overlay_debugging = ovly_auto; + enable_overlay_breakpoints (); + if (info_verbose) + printf_filtered ("Automatic overlay debugging enabled."); +} + +/* Function: overlay_manual_command + A utility command to turn on overlay debugging. + Possibly this should be done via a set/show command. */ + +static void +overlay_manual_command (char *args, int from_tty) +{ + overlay_debugging = ovly_on; + disable_overlay_breakpoints (); + if (info_verbose) + printf_filtered ("Overlay debugging enabled."); +} + +/* Function: overlay_off_command + A utility command to turn on overlay debugging. + Possibly this should be done via a set/show command. */ + +static void +overlay_off_command (char *args, int from_tty) +{ + overlay_debugging = ovly_off; + disable_overlay_breakpoints (); + if (info_verbose) + printf_filtered ("Overlay debugging disabled."); +} + +static void +overlay_load_command (char *args, int from_tty) +{ + if (target_overlay_update) + (*target_overlay_update) (NULL); + else + error ("This target does not know how to read its overlay state."); +} + +/* Function: overlay_command + A place-holder for a mis-typed command */ + +/* Command list chain containing all defined "overlay" subcommands. */ +struct cmd_list_element *overlaylist; + +static void +overlay_command (char *args, int from_tty) +{ + printf_unfiltered + ("\"overlay\" must be followed by the name of an overlay command.\n"); + help_list (overlaylist, "overlay ", -1, gdb_stdout); +} + + +/* Target Overlays for the "Simplest" overlay manager: + + This is GDB's default target overlay layer. It works with the + minimal overlay manager supplied as an example by Cygnus. The + entry point is via a function pointer "target_overlay_update", + so targets that use a different runtime overlay manager can + substitute their own overlay_update function and take over the + function pointer. + + The overlay_update function pokes around in the target's data structures + to see what overlays are mapped, and updates GDB's overlay mapping with + this information. + + In this simple implementation, the target data structures are as follows: + unsigned _novlys; /# number of overlay sections #/ + unsigned _ovly_table[_novlys][4] = { + {VMA, SIZE, LMA, MAPPED}, /# one entry per overlay section #/ + {..., ..., ..., ...}, + } + unsigned _novly_regions; /# number of overlay regions #/ + unsigned _ovly_region_table[_novly_regions][3] = { + {VMA, SIZE, MAPPED_TO_LMA}, /# one entry per overlay region #/ + {..., ..., ...}, + } + These functions will attempt to update GDB's mappedness state in the + symbol section table, based on the target's mappedness state. + + To do this, we keep a cached copy of the target's _ovly_table, and + attempt to detect when the cached copy is invalidated. The main + entry point is "simple_overlay_update(SECT), which looks up SECT in + the cached table and re-reads only the entry for that section from + the target (whenever possible). + */ + +/* Cached, dynamically allocated copies of the target data structures: */ +static unsigned (*cache_ovly_table)[4] = 0; +#if 0 +static unsigned (*cache_ovly_region_table)[3] = 0; +#endif +static unsigned cache_novlys = 0; +#if 0 +static unsigned cache_novly_regions = 0; +#endif +static CORE_ADDR cache_ovly_table_base = 0; +#if 0 +static CORE_ADDR cache_ovly_region_table_base = 0; +#endif +enum ovly_index + { + VMA, SIZE, LMA, MAPPED + }; +#define TARGET_LONG_BYTES (TARGET_LONG_BIT / TARGET_CHAR_BIT) + +/* Throw away the cached copy of _ovly_table */ +static void +simple_free_overlay_table (void) +{ + if (cache_ovly_table) + xfree (cache_ovly_table); + cache_novlys = 0; + cache_ovly_table = NULL; + cache_ovly_table_base = 0; +} + +#if 0 +/* Throw away the cached copy of _ovly_region_table */ +static void +simple_free_overlay_region_table (void) +{ + if (cache_ovly_region_table) + xfree (cache_ovly_region_table); + cache_novly_regions = 0; + cache_ovly_region_table = NULL; + cache_ovly_region_table_base = 0; +} +#endif + +/* Read an array of ints from the target into a local buffer. + Convert to host order. int LEN is number of ints */ +static void +read_target_long_array (CORE_ADDR memaddr, unsigned int *myaddr, int len) +{ + /* FIXME (alloca): Not safe if array is very large. */ + char *buf = alloca (len * TARGET_LONG_BYTES); + int i; + + read_memory (memaddr, buf, len * TARGET_LONG_BYTES); + for (i = 0; i < len; i++) + myaddr[i] = extract_unsigned_integer (TARGET_LONG_BYTES * i + buf, + TARGET_LONG_BYTES); +} + +/* Find and grab a copy of the target _ovly_table + (and _novlys, which is needed for the table's size) */ +static int +simple_read_overlay_table (void) +{ + struct minimal_symbol *novlys_msym, *ovly_table_msym; + + simple_free_overlay_table (); + novlys_msym = lookup_minimal_symbol ("_novlys", NULL, NULL); + if (! novlys_msym) + { + error ("Error reading inferior's overlay table: " + "couldn't find `_novlys' variable\n" + "in inferior. Use `overlay manual' mode."); + return 0; + } + + ovly_table_msym = lookup_minimal_symbol ("_ovly_table", NULL, NULL); + if (! ovly_table_msym) + { + error ("Error reading inferior's overlay table: couldn't find " + "`_ovly_table' array\n" + "in inferior. Use `overlay manual' mode."); + return 0; + } + + cache_novlys = read_memory_integer (SYMBOL_VALUE_ADDRESS (novlys_msym), 4); + cache_ovly_table + = (void *) xmalloc (cache_novlys * sizeof (*cache_ovly_table)); + cache_ovly_table_base = SYMBOL_VALUE_ADDRESS (ovly_table_msym); + read_target_long_array (cache_ovly_table_base, + (int *) cache_ovly_table, + cache_novlys * 4); + + return 1; /* SUCCESS */ +} + +#if 0 +/* Find and grab a copy of the target _ovly_region_table + (and _novly_regions, which is needed for the table's size) */ +static int +simple_read_overlay_region_table (void) +{ + struct minimal_symbol *msym; + + simple_free_overlay_region_table (); + msym = lookup_minimal_symbol ("_novly_regions", NULL, NULL); + if (msym != NULL) + cache_novly_regions = read_memory_integer (SYMBOL_VALUE_ADDRESS (msym), 4); + else + return 0; /* failure */ + cache_ovly_region_table = (void *) xmalloc (cache_novly_regions * 12); + if (cache_ovly_region_table != NULL) + { + msym = lookup_minimal_symbol ("_ovly_region_table", NULL, NULL); + if (msym != NULL) + { + cache_ovly_region_table_base = SYMBOL_VALUE_ADDRESS (msym); + read_target_long_array (cache_ovly_region_table_base, + (int *) cache_ovly_region_table, + cache_novly_regions * 3); + } + else + return 0; /* failure */ + } + else + return 0; /* failure */ + return 1; /* SUCCESS */ +} +#endif + +/* Function: simple_overlay_update_1 + A helper function for simple_overlay_update. Assuming a cached copy + of _ovly_table exists, look through it to find an entry whose vma, + lma and size match those of OSECT. Re-read the entry and make sure + it still matches OSECT (else the table may no longer be valid). + Set OSECT's mapped state to match the entry. Return: 1 for + success, 0 for failure. */ + +static int +simple_overlay_update_1 (struct obj_section *osect) +{ + int i, size; + bfd *obfd = osect->objfile->obfd; + asection *bsect = osect->the_bfd_section; + + size = bfd_get_section_size_before_reloc (osect->the_bfd_section); + for (i = 0; i < cache_novlys; i++) + if (cache_ovly_table[i][VMA] == bfd_section_vma (obfd, bsect) + && cache_ovly_table[i][LMA] == bfd_section_lma (obfd, bsect) + /* && cache_ovly_table[i][SIZE] == size */ ) + { + read_target_long_array (cache_ovly_table_base + i * TARGET_LONG_BYTES, + (int *) cache_ovly_table[i], 4); + if (cache_ovly_table[i][VMA] == bfd_section_vma (obfd, bsect) + && cache_ovly_table[i][LMA] == bfd_section_lma (obfd, bsect) + /* && cache_ovly_table[i][SIZE] == size */ ) + { + osect->ovly_mapped = cache_ovly_table[i][MAPPED]; + return 1; + } + else /* Warning! Warning! Target's ovly table has changed! */ + return 0; + } + return 0; +} + +/* Function: simple_overlay_update + If OSECT is NULL, then update all sections' mapped state + (after re-reading the entire target _ovly_table). + If OSECT is non-NULL, then try to find a matching entry in the + cached ovly_table and update only OSECT's mapped state. + If a cached entry can't be found or the cache isn't valid, then + re-read the entire cache, and go ahead and update all sections. */ + +static void +simple_overlay_update (struct obj_section *osect) +{ + struct objfile *objfile; + + /* Were we given an osect to look up? NULL means do all of them. */ + if (osect) + /* Have we got a cached copy of the target's overlay table? */ + if (cache_ovly_table != NULL) + /* Does its cached location match what's currently in the symtab? */ + if (cache_ovly_table_base == + SYMBOL_VALUE_ADDRESS (lookup_minimal_symbol ("_ovly_table", NULL, NULL))) + /* Then go ahead and try to look up this single section in the cache */ + if (simple_overlay_update_1 (osect)) + /* Found it! We're done. */ + return; + + /* Cached table no good: need to read the entire table anew. + Or else we want all the sections, in which case it's actually + more efficient to read the whole table in one block anyway. */ + + if (! simple_read_overlay_table ()) + return; + + /* Now may as well update all sections, even if only one was requested. */ + ALL_OBJSECTIONS (objfile, osect) + if (section_is_overlay (osect->the_bfd_section)) + { + int i, size; + bfd *obfd = osect->objfile->obfd; + asection *bsect = osect->the_bfd_section; + + size = bfd_get_section_size_before_reloc (osect->the_bfd_section); + for (i = 0; i < cache_novlys; i++) + if (cache_ovly_table[i][VMA] == bfd_section_vma (obfd, bsect) + && cache_ovly_table[i][LMA] == bfd_section_lma (obfd, bsect) + /* && cache_ovly_table[i][SIZE] == size */ ) + { /* obj_section matches i'th entry in ovly_table */ + osect->ovly_mapped = cache_ovly_table[i][MAPPED]; + break; /* finished with inner for loop: break out */ + } + } +} + + +void +_initialize_symfile (void) +{ + struct cmd_list_element *c; + + c = add_cmd ("symbol-file", class_files, symbol_file_command, + "Load symbol table from executable file FILE.\n\ +The `file' command can also load symbol tables, as well as setting the file\n\ +to execute.", &cmdlist); + set_cmd_completer (c, filename_completer); + + c = add_cmd ("add-symbol-file", class_files, add_symbol_file_command, + "Usage: add-symbol-file FILE ADDR [-s <SECT> <SECT_ADDR> -s <SECT> <SECT_ADDR> ...]\n\ +Load the symbols from FILE, assuming FILE has been dynamically loaded.\n\ +ADDR is the starting address of the file's text.\n\ +The optional arguments are section-name section-address pairs and\n\ +should be specified if the data and bss segments are not contiguous\n\ +with the text. SECT is a section name to be loaded at SECT_ADDR.", + &cmdlist); + set_cmd_completer (c, filename_completer); + + c = add_cmd ("add-shared-symbol-files", class_files, + add_shared_symbol_files_command, + "Load the symbols from shared objects in the dynamic linker's link map.", + &cmdlist); + c = add_alias_cmd ("assf", "add-shared-symbol-files", class_files, 1, + &cmdlist); + + c = add_cmd ("load", class_files, load_command, + "Dynamically load FILE into the running program, and record its symbols\n\ +for access from GDB.", &cmdlist); + set_cmd_completer (c, filename_completer); + + add_show_from_set + (add_set_cmd ("symbol-reloading", class_support, var_boolean, + (char *) &symbol_reloading, + "Set dynamic symbol table reloading multiple times in one run.", + &setlist), + &showlist); + + add_prefix_cmd ("overlay", class_support, overlay_command, + "Commands for debugging overlays.", &overlaylist, + "overlay ", 0, &cmdlist); + + add_com_alias ("ovly", "overlay", class_alias, 1); + add_com_alias ("ov", "overlay", class_alias, 1); + + add_cmd ("map-overlay", class_support, map_overlay_command, + "Assert that an overlay section is mapped.", &overlaylist); + + add_cmd ("unmap-overlay", class_support, unmap_overlay_command, + "Assert that an overlay section is unmapped.", &overlaylist); + + add_cmd ("list-overlays", class_support, list_overlays_command, + "List mappings of overlay sections.", &overlaylist); + + add_cmd ("manual", class_support, overlay_manual_command, + "Enable overlay debugging.", &overlaylist); + add_cmd ("off", class_support, overlay_off_command, + "Disable overlay debugging.", &overlaylist); + add_cmd ("auto", class_support, overlay_auto_command, + "Enable automatic overlay debugging.", &overlaylist); + add_cmd ("load-target", class_support, overlay_load_command, + "Read the overlay mapping state from the target.", &overlaylist); + + /* Filename extension to source language lookup table: */ + init_filename_language_table (); + c = add_set_cmd ("extension-language", class_files, var_string_noescape, + (char *) &ext_args, + "Set mapping between filename extension and source language.\n\ +Usage: set extension-language .foo bar", + &setlist); + set_cmd_cfunc (c, set_ext_lang_command); + + add_info ("extensions", info_ext_lang_command, + "All filename extensions associated with a source language."); + + add_show_from_set + (add_set_cmd ("download-write-size", class_obscure, + var_integer, (char *) &download_write_size, + "Set the write size used when downloading a program.\n" + "Only used when downloading a program onto a remote\n" + "target. Specify zero, or a negative value, to disable\n" + "blocked writes. The actual size of each transfer is also\n" + "limited by the size of the target packet and the memory\n" + "cache.\n", + &setlist), + &showlist); +} diff --git a/gdb/symfile.h b/gdb/symfile.h new file mode 100644 index 0000000..39eb308 --- /dev/null +++ b/gdb/symfile.h @@ -0,0 +1,328 @@ +/* Definitions for reading symbol files into GDB. + Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, + 2000, 2001 + 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 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#if !defined (SYMFILE_H) +#define SYMFILE_H + +/* This file requires that you first include "bfd.h". */ + +/* Partial symbols are stored in the psymbol_cache and pointers to them + are kept in a dynamically grown array that is obtained from malloc and + grown as necessary via realloc. Each objfile typically has two of these, + one for global symbols and one for static symbols. Although this adds + a level of indirection for storing or accessing the partial symbols, + it allows us to throw away duplicate psymbols and set all pointers + to the single saved instance. */ + +struct psymbol_allocation_list + { + + /* Pointer to beginning of dynamically allocated array of pointers to + partial symbols. The array is dynamically expanded as necessary to + accommodate more pointers. */ + + struct partial_symbol **list; + + /* Pointer to next available slot in which to store a pointer to a partial + symbol. */ + + struct partial_symbol **next; + + /* Number of allocated pointer slots in current dynamic array (not the + number of bytes of storage). The "next" pointer will always point + somewhere between list[0] and list[size], and when at list[size] the + array will be expanded on the next attempt to store a pointer. */ + + int size; + }; + +/* Define an array of addresses to accommodate non-contiguous dynamic + loading of modules. This is for use when entering commands, so we + can keep track of the section names until we read the file and + can map them to bfd sections. This structure is also used by + solib.c to communicate the section addresses in shared objects to + symbol_file_add (). */ + +#define MAX_SECTIONS 64 +struct section_addr_info +{ + /* Sections whose names are file format dependent. */ + struct other_sections + { + CORE_ADDR addr; + char *name; + int sectindex; + } other[MAX_SECTIONS]; +}; + +/* Structure to keep track of symbol reading functions for various + object file types. */ + +struct sym_fns + { + + /* BFD flavour that we handle, or (as a special kludge, see xcoffread.c, + (enum bfd_flavour)-1 for xcoff). */ + + enum bfd_flavour sym_flavour; + + /* Initializes anything that is global to the entire symbol table. It is + called during symbol_file_add, when we begin debugging an entirely new + program. */ + + void (*sym_new_init) (struct objfile *); + + /* Reads any initial information from a symbol file, and initializes the + struct sym_fns SF in preparation for sym_read(). It is called every + time we read a symbol file for any reason. */ + + void (*sym_init) (struct objfile *); + + /* sym_read (objfile, mainline) + Reads a symbol file into a psymtab (or possibly a symtab). + OBJFILE is the objfile struct for the file we are reading. + MAINLINE is 1 if this is the + main symbol table being read, and 0 if a secondary + symbol file (e.g. shared library or dynamically loaded file) + is being read. */ + + void (*sym_read) (struct objfile *, int); + + /* Called when we are finished with an objfile. Should do all cleanup + that is specific to the object file format for the particular objfile. */ + + void (*sym_finish) (struct objfile *); + + /* This function produces a file-dependent section_offsets structure, + allocated in the objfile's storage, and based on the parameter. + The parameter is currently a CORE_ADDR (FIXME!) for backward compatibility + with the higher levels of GDB. It should probably be changed to + a string, where NULL means the default, and others are parsed in a file + dependent way. */ + + void (*sym_offsets) (struct objfile *, struct section_addr_info *); + + /* Finds the next struct sym_fns. They are allocated and initialized + in whatever module implements the functions pointed to; an + initializer calls add_symtab_fns to add them to the global chain. */ + + struct sym_fns *next; + + }; + +/* The default version of sym_fns.sym_offsets for readers that don't + do anything special. */ + +extern void +default_symfile_offsets (struct objfile *objfile, struct section_addr_info *); + + +extern void +extend_psymbol_list (struct psymbol_allocation_list *, struct objfile *); + +/* Add any kind of symbol to a psymbol_allocation_list. */ + +/* #include "demangle.h" */ + +extern void +add_psymbol_to_list (char *, int, namespace_enum, enum address_class, + struct psymbol_allocation_list *, long, CORE_ADDR, + enum language, struct objfile *); + +extern void +add_psymbol_with_dem_name_to_list (char *, int, char *, int, namespace_enum, + enum address_class, + struct psymbol_allocation_list *, + long, CORE_ADDR, + enum language, struct objfile *); + + +extern void init_psymbol_list (struct objfile *, int); + +extern void sort_pst_symbols (struct partial_symtab *); + +extern struct symtab *allocate_symtab (char *, struct objfile *); + +extern int free_named_symtabs (char *); + +extern void fill_in_vptr_fieldno (struct type *); + +extern void add_symtab_fns (struct sym_fns *); + +extern void init_entry_point_info (struct objfile *); + +extern void +syms_from_objfile (struct objfile *, struct section_addr_info *, int, int); + +extern void new_symfile_objfile (struct objfile *, int, int); + +extern struct objfile *symbol_file_add (char *, int, + struct section_addr_info *, int, int); + +/* Build (allocate and populate) a section_addr_info struct from + an existing section table. */ + +struct section_table; +extern struct section_addr_info * +build_section_addr_info_from_section_table (const struct section_table *start, + const struct section_table *end); + +/* Free all memory allocated by build_section_addr_info_from_section_table. */ + +extern void +free_section_addr_info (struct section_addr_info *); + + +extern struct partial_symtab *start_psymtab_common (struct objfile *, + struct section_offsets *, + char *, CORE_ADDR, + struct partial_symbol **, + struct partial_symbol **); + +/* Sorting your symbols for fast lookup or alphabetical printing. */ + +extern void sort_block_syms (struct block *); + +extern void sort_symtab_syms (struct symtab *); + +/* Make a copy of the string at PTR with SIZE characters in the symbol obstack + (and add a null character at the end in the copy). + Returns the address of the copy. */ + +extern char *obsavestring (char *, int, struct obstack *); + +/* Concatenate strings S1, S2 and S3; return the new string. + Space is found in the symbol_obstack. */ + +extern char *obconcat (struct obstack *obstackp, const char *, const char *, + const char *); + + /* Variables */ + +/* If non-zero, shared library symbols will be added automatically + when the inferior is created, new libraries are loaded, or when + attaching to the inferior. This is almost always what users will + want to have happen; but for very large programs, the startup time + will be excessive, and so if this is a problem, the user can clear + this flag and then add the shared library symbols as needed. Note + that there is a potential for confusion, since if the shared + library symbols are not loaded, commands like "info fun" will *not* + report all the functions that are actually present. */ + +extern int auto_solib_add; + +/* For systems that support it, a threshold size in megabytes. If + automatically adding a new library's symbol table to those already + known to the debugger would cause the total shared library symbol + size to exceed this threshhold, then the shlib's symbols are not + added. The threshold is ignored if the user explicitly asks for a + shlib to be added, such as when using the "sharedlibrary" + command. */ + +extern int auto_solib_limit; + +/* From symfile.c */ + +extern CORE_ADDR entry_point_address (void); + +extern struct partial_symtab *allocate_psymtab (char *, struct objfile *); + +extern void discard_psymtab (struct partial_symtab *); + +extern void find_lowest_section (bfd *, asection *, PTR); + +extern bfd *symfile_bfd_open (char *); + +extern int get_section_index (struct objfile *, char *); + +/* Utility functions for overlay sections: */ +extern enum overlay_debugging_state { + ovly_off, + ovly_on, + ovly_auto +} overlay_debugging; +extern int overlay_cache_invalid; + +/* return the "mapped" overlay section containing the PC */ +extern asection *find_pc_mapped_section (CORE_ADDR); + +/* return any overlay section containing the PC (even in its LMA region) */ +extern asection *find_pc_overlay (CORE_ADDR); + +/* return true if the section is an overlay */ +extern int section_is_overlay (asection *); + +/* return true if the overlay section is currently "mapped" */ +extern int section_is_mapped (asection *); + +/* return true if pc belongs to section's VMA */ +extern CORE_ADDR pc_in_mapped_range (CORE_ADDR, asection *); + +/* return true if pc belongs to section's LMA */ +extern CORE_ADDR pc_in_unmapped_range (CORE_ADDR, asection *); + +/* map an address from a section's LMA to its VMA */ +extern CORE_ADDR overlay_mapped_address (CORE_ADDR, asection *); + +/* map an address from a section's VMA to its LMA */ +extern CORE_ADDR overlay_unmapped_address (CORE_ADDR, asection *); + +/* convert an address in an overlay section (force into VMA range) */ +extern CORE_ADDR symbol_overlayed_address (CORE_ADDR, asection *); + +/* Load symbols from a file. */ +extern void symbol_file_add_main (char *args, int from_tty); + +/* Clear GDB symbol tables. */ +extern void symbol_file_clear (int from_tty); + +/* From dwarfread.c */ + +extern void +dwarf_build_psymtabs (struct objfile *, int, file_ptr, unsigned int, + file_ptr, unsigned int); + +/* From dwarf2read.c */ + +extern int dwarf2_has_info (bfd * abfd); + +extern void dwarf2_build_psymtabs (struct objfile *, int); +extern void dwarf2_build_frame_info (struct objfile *); + +/* From mdebugread.c */ + +/* Hack to force structures to exist before use in parameter list. */ +struct ecoff_debug_hack + { + struct ecoff_debug_swap *a; + struct ecoff_debug_info *b; + }; +extern void +mdebug_build_psymtabs (struct objfile *, + const struct ecoff_debug_swap *, + struct ecoff_debug_info *); + +extern void +elfmdebug_build_psymtabs (struct objfile *, + const struct ecoff_debug_swap *, asection *); + +#endif /* !defined(SYMFILE_H) */ diff --git a/gdb/symtab.c b/gdb/symtab.c new file mode 100644 index 0000000..a432292 --- /dev/null +++ b/gdb/symtab.c @@ -0,0 +1,4063 @@ +/* Symbol table lookup for the GNU debugger, GDB. + + Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, + 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 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 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "symtab.h" +#include "gdbtypes.h" +#include "gdbcore.h" +#include "frame.h" +#include "target.h" +#include "value.h" +#include "symfile.h" +#include "objfiles.h" +#include "gdbcmd.h" +#include "call-cmds.h" +#include "gdb_regex.h" +#include "expression.h" +#include "language.h" +#include "demangle.h" +#include "inferior.h" +#include "linespec.h" +#include "source.h" +#include "filenames.h" /* for FILENAME_CMP */ + +#include "gdb_obstack.h" + +#include <sys/types.h> +#include <fcntl.h> +#include "gdb_string.h" +#include "gdb_stat.h" +#include <ctype.h> +#include "cp-abi.h" + +/* Prototype for one function in parser-defs.h, + instead of including that entire file. */ + +extern char *find_template_name_end (char *); + +/* Prototypes for local functions */ + +static void completion_list_add_name (char *, char *, int, char *, char *); + +static void rbreak_command (char *, int); + +static void types_info (char *, int); + +static void functions_info (char *, int); + +static void variables_info (char *, int); + +static void sources_info (char *, int); + +static void output_source_filename (char *, int *); + +static int find_line_common (struct linetable *, int, int *); + +/* This one is used by linespec.c */ + +char *operator_chars (char *p, char **end); + +static struct partial_symbol *lookup_partial_symbol (struct partial_symtab *, + const char *, int, + namespace_enum); + +static struct symbol *lookup_symbol_aux (const char *name, + const char *mangled_name, + const struct block *block, + const namespace_enum namespace, + int *is_a_field_of_this, + struct symtab **symtab); + + +static struct symbol *find_active_alias (struct symbol *sym, CORE_ADDR addr); + +/* This flag is used in hppa-tdep.c, and set in hp-symtab-read.c */ +/* Signals the presence of objects compiled by HP compilers */ +int hp_som_som_object_present = 0; + +static void fixup_section (struct general_symbol_info *, struct objfile *); + +static int file_matches (char *, char **, int); + +static void print_symbol_info (namespace_enum, + struct symtab *, struct symbol *, int, char *); + +static void print_msymbol_info (struct minimal_symbol *); + +static void symtab_symbol_info (char *, namespace_enum, int); + +static void overload_list_add_symbol (struct symbol *sym, char *oload_name); + +void _initialize_symtab (void); + +/* */ + +/* The single non-language-specific builtin type */ +struct type *builtin_type_error; + +/* Block in which the most recently searched-for symbol was found. + Might be better to make this a parameter to lookup_symbol and + value_of_this. */ + +const struct block *block_found; + +/* While the C++ support is still in flux, issue a possibly helpful hint on + using the new command completion feature on single quoted demangled C++ + symbols. Remove when loose ends are cleaned up. FIXME -fnf */ + +static void +cplusplus_hint (char *name) +{ + while (*name == '\'') + name++; + printf_filtered ("Hint: try '%s<TAB> or '%s<ESC-?>\n", name, name); + printf_filtered ("(Note leading single quote.)\n"); +} + +/* Check for a symtab of a specific name; first in symtabs, then in + psymtabs. *If* there is no '/' in the name, a match after a '/' + in the symtab filename will also work. */ + +struct symtab * +lookup_symtab (const char *name) +{ + register struct symtab *s; + register struct partial_symtab *ps; + register struct objfile *objfile; + char *real_path = NULL; + char *full_path = NULL; + + /* Here we are interested in canonicalizing an absolute path, not + absolutizing a relative path. */ + if (IS_ABSOLUTE_PATH (name)) + { + full_path = xfullpath (name); + make_cleanup (xfree, full_path); + real_path = gdb_realpath (name); + make_cleanup (xfree, real_path); + } + +got_symtab: + + /* First, search for an exact match */ + + ALL_SYMTABS (objfile, s) + { + if (FILENAME_CMP (name, s->filename) == 0) + { + return s; + } + + /* If the user gave us an absolute path, try to find the file in + this symtab and use its absolute path. */ + + if (full_path != NULL) + { + const char *fp = symtab_to_filename (s); + if (FILENAME_CMP (full_path, fp) == 0) + { + return s; + } + } + + if (real_path != NULL) + { + char *rp = gdb_realpath (symtab_to_filename (s)); + make_cleanup (xfree, rp); + if (FILENAME_CMP (real_path, rp) == 0) + { + return s; + } + } + } + + /* Now, search for a matching tail (only if name doesn't have any dirs) */ + + if (lbasename (name) == name) + ALL_SYMTABS (objfile, s) + { + if (FILENAME_CMP (lbasename (s->filename), name) == 0) + return s; + } + + /* Same search rules as above apply here, but now we look thru the + psymtabs. */ + + ps = lookup_partial_symtab (name); + if (!ps) + return (NULL); + + if (ps->readin) + error ("Internal: readin %s pst for `%s' found when no symtab found.", + ps->filename, name); + + s = PSYMTAB_TO_SYMTAB (ps); + + if (s) + return s; + + /* At this point, we have located the psymtab for this file, but + the conversion to a symtab has failed. This usually happens + when we are looking up an include file. In this case, + PSYMTAB_TO_SYMTAB doesn't return a symtab, even though one has + been created. So, we need to run through the symtabs again in + order to find the file. + XXX - This is a crock, and should be fixed inside of the the + symbol parsing routines. */ + goto got_symtab; +} + +/* Lookup the partial symbol table of a source file named NAME. + *If* there is no '/' in the name, a match after a '/' + in the psymtab filename will also work. */ + +struct partial_symtab * +lookup_partial_symtab (const char *name) +{ + register struct partial_symtab *pst; + register struct objfile *objfile; + char *full_path = NULL; + char *real_path = NULL; + + /* Here we are interested in canonicalizing an absolute path, not + absolutizing a relative path. */ + if (IS_ABSOLUTE_PATH (name)) + { + full_path = xfullpath (name); + make_cleanup (xfree, full_path); + real_path = gdb_realpath (name); + make_cleanup (xfree, real_path); + } + + ALL_PSYMTABS (objfile, pst) + { + if (FILENAME_CMP (name, pst->filename) == 0) + { + return (pst); + } + + /* If the user gave us an absolute path, try to find the file in + this symtab and use its absolute path. */ + if (full_path != NULL) + { + if (pst->fullname == NULL) + source_full_path_of (pst->filename, &pst->fullname); + if (pst->fullname != NULL + && FILENAME_CMP (full_path, pst->fullname) == 0) + { + return pst; + } + } + + if (real_path != NULL) + { + char *rp = NULL; + if (pst->fullname == NULL) + source_full_path_of (pst->filename, &pst->fullname); + if (pst->fullname != NULL) + { + rp = gdb_realpath (pst->fullname); + make_cleanup (xfree, rp); + } + if (rp != NULL && FILENAME_CMP (real_path, rp) == 0) + { + return pst; + } + } + } + + /* Now, search for a matching tail (only if name doesn't have any dirs) */ + + if (lbasename (name) == name) + ALL_PSYMTABS (objfile, pst) + { + if (FILENAME_CMP (lbasename (pst->filename), name) == 0) + return (pst); + } + + return (NULL); +} + +/* Mangle a GDB method stub type. This actually reassembles the pieces of the + full method name, which consist of the class name (from T), the unadorned + method name from METHOD_ID, and the signature for the specific overload, + specified by SIGNATURE_ID. Note that this function is g++ specific. */ + +char * +gdb_mangle_name (struct type *type, int method_id, int signature_id) +{ + int mangled_name_len; + char *mangled_name; + struct fn_field *f = TYPE_FN_FIELDLIST1 (type, method_id); + struct fn_field *method = &f[signature_id]; + char *field_name = TYPE_FN_FIELDLIST_NAME (type, method_id); + char *physname = TYPE_FN_FIELD_PHYSNAME (f, signature_id); + char *newname = type_name_no_tag (type); + + /* Does the form of physname indicate that it is the full mangled name + of a constructor (not just the args)? */ + int is_full_physname_constructor; + + int is_constructor; + int is_destructor = is_destructor_name (physname); + /* Need a new type prefix. */ + char *const_prefix = method->is_const ? "C" : ""; + char *volatile_prefix = method->is_volatile ? "V" : ""; + char buf[20]; + int len = (newname == NULL ? 0 : strlen (newname)); + + /* Nothing to do if physname already contains a fully mangled v3 abi name + or an operator name. */ + if ((physname[0] == '_' && physname[1] == 'Z') + || is_operator_name (field_name)) + return xstrdup (physname); + + is_full_physname_constructor = is_constructor_name (physname); + + is_constructor = + is_full_physname_constructor || (newname && STREQ (field_name, newname)); + + if (!is_destructor) + is_destructor = (strncmp (physname, "__dt", 4) == 0); + + if (is_destructor || is_full_physname_constructor) + { + mangled_name = (char *) xmalloc (strlen (physname) + 1); + strcpy (mangled_name, physname); + return mangled_name; + } + + if (len == 0) + { + sprintf (buf, "__%s%s", const_prefix, volatile_prefix); + } + else if (physname[0] == 't' || physname[0] == 'Q') + { + /* The physname for template and qualified methods already includes + the class name. */ + sprintf (buf, "__%s%s", const_prefix, volatile_prefix); + newname = NULL; + len = 0; + } + else + { + sprintf (buf, "__%s%s%d", const_prefix, volatile_prefix, len); + } + mangled_name_len = ((is_constructor ? 0 : strlen (field_name)) + + strlen (buf) + len + strlen (physname) + 1); + + { + mangled_name = (char *) xmalloc (mangled_name_len); + if (is_constructor) + mangled_name[0] = '\0'; + else + strcpy (mangled_name, field_name); + } + strcat (mangled_name, buf); + /* If the class doesn't have a name, i.e. newname NULL, then we just + mangle it using 0 for the length of the class. Thus it gets mangled + as something starting with `::' rather than `classname::'. */ + if (newname != NULL) + strcat (mangled_name, newname); + + strcat (mangled_name, physname); + return (mangled_name); +} + + +/* Initialize a symbol's mangled name. */ + +/* Try to initialize the demangled name for a symbol, based on the + language of that symbol. If the language is set to language_auto, + it will attempt to find any demangling algorithm that works and + then set the language appropriately. If no demangling of any kind + is found, the language is set back to language_unknown, so we can + avoid doing this work again the next time we encounter the symbol. + Any required space to store the name is obtained from the specified + obstack. */ + +void +symbol_init_demangled_name (struct general_symbol_info *gsymbol, + struct obstack *obstack) +{ + char *mangled = gsymbol->name; + char *demangled = NULL; + + if (gsymbol->language == language_unknown) + gsymbol->language = language_auto; + if (gsymbol->language == language_cplus + || gsymbol->language == language_auto) + { + demangled = + cplus_demangle (gsymbol->name, DMGL_PARAMS | DMGL_ANSI); + if (demangled != NULL) + { + gsymbol->language = language_cplus; + gsymbol->language_specific.cplus_specific.demangled_name = + obsavestring (demangled, strlen (demangled), obstack); + xfree (demangled); + } + else + { + gsymbol->language_specific.cplus_specific.demangled_name = NULL; + } + } + if (gsymbol->language == language_java) + { + demangled = + cplus_demangle (gsymbol->name, + DMGL_PARAMS | DMGL_ANSI | DMGL_JAVA); + if (demangled != NULL) + { + gsymbol->language = language_java; + gsymbol->language_specific.cplus_specific.demangled_name = + obsavestring (demangled, strlen (demangled), obstack); + xfree (demangled); + } + else + { + gsymbol->language_specific.cplus_specific.demangled_name = NULL; + } + } +#if 0 + /* OBSOLETE if (demangled == NULL */ + /* OBSOLETE && (gsymbol->language == language_chill */ + /* OBSOLETE || gsymbol->language == language_auto)) */ + /* OBSOLETE { */ + /* OBSOLETE demangled = */ + /* OBSOLETE chill_demangle (gsymbol->name); */ + /* OBSOLETE if (demangled != NULL) */ + /* OBSOLETE { */ + /* OBSOLETE gsymbol->language = language_chill; */ + /* OBSOLETE gsymbol->language_specific.chill_specific.demangled_name = */ + /* OBSOLETE obsavestring (demangled, strlen (demangled), obstack); */ + /* OBSOLETE xfree (demangled); */ + /* OBSOLETE } */ + /* OBSOLETE else */ + /* OBSOLETE { */ + /* OBSOLETE gsymbol->language_specific.chill_specific.demangled_name = NULL; */ + /* OBSOLETE } */ + /* OBSOLETE } */ +#endif +} + + + + + +/* Find which partial symtab on contains PC and SECTION. Return 0 if none. */ + +struct partial_symtab * +find_pc_sect_psymtab (CORE_ADDR pc, asection *section) +{ + register struct partial_symtab *pst; + register struct objfile *objfile; + struct minimal_symbol *msymbol; + + /* If we know that this is not a text address, return failure. This is + necessary because we loop based on texthigh and textlow, which do + not include the data ranges. */ + msymbol = lookup_minimal_symbol_by_pc_section (pc, section); + if (msymbol + && (msymbol->type == mst_data + || msymbol->type == mst_bss + || msymbol->type == mst_abs + || msymbol->type == mst_file_data + || msymbol->type == mst_file_bss)) + return NULL; + + ALL_PSYMTABS (objfile, pst) + { + if (pc >= pst->textlow && pc < pst->texthigh) + { + struct partial_symtab *tpst; + + /* An objfile that has its functions reordered might have + many partial symbol tables containing the PC, but + we want the partial symbol table that contains the + function containing the PC. */ + if (!(objfile->flags & OBJF_REORDERED) && + section == 0) /* can't validate section this way */ + return (pst); + + if (msymbol == NULL) + return (pst); + + for (tpst = pst; tpst != NULL; tpst = tpst->next) + { + if (pc >= tpst->textlow && pc < tpst->texthigh) + { + struct partial_symbol *p; + + p = find_pc_sect_psymbol (tpst, pc, section); + if (p != NULL + && SYMBOL_VALUE_ADDRESS (p) + == SYMBOL_VALUE_ADDRESS (msymbol)) + return (tpst); + } + } + return (pst); + } + } + return (NULL); +} + +/* Find which partial symtab contains PC. Return 0 if none. + Backward compatibility, no section */ + +struct partial_symtab * +find_pc_psymtab (CORE_ADDR pc) +{ + return find_pc_sect_psymtab (pc, find_pc_mapped_section (pc)); +} + +/* Find which partial symbol within a psymtab matches PC and SECTION. + Return 0 if none. Check all psymtabs if PSYMTAB is 0. */ + +struct partial_symbol * +find_pc_sect_psymbol (struct partial_symtab *psymtab, CORE_ADDR pc, + asection *section) +{ + struct partial_symbol *best = NULL, *p, **pp; + CORE_ADDR best_pc; + + if (!psymtab) + psymtab = find_pc_sect_psymtab (pc, section); + if (!psymtab) + return 0; + + /* Cope with programs that start at address 0 */ + best_pc = (psymtab->textlow != 0) ? psymtab->textlow - 1 : 0; + + /* Search the global symbols as well as the static symbols, so that + find_pc_partial_function doesn't use a minimal symbol and thus + cache a bad endaddr. */ + for (pp = psymtab->objfile->global_psymbols.list + psymtab->globals_offset; + (pp - (psymtab->objfile->global_psymbols.list + psymtab->globals_offset) + < psymtab->n_global_syms); + pp++) + { + p = *pp; + if (SYMBOL_NAMESPACE (p) == VAR_NAMESPACE + && SYMBOL_CLASS (p) == LOC_BLOCK + && pc >= SYMBOL_VALUE_ADDRESS (p) + && (SYMBOL_VALUE_ADDRESS (p) > best_pc + || (psymtab->textlow == 0 + && best_pc == 0 && SYMBOL_VALUE_ADDRESS (p) == 0))) + { + if (section) /* match on a specific section */ + { + fixup_psymbol_section (p, psymtab->objfile); + if (SYMBOL_BFD_SECTION (p) != section) + continue; + } + best_pc = SYMBOL_VALUE_ADDRESS (p); + best = p; + } + } + + for (pp = psymtab->objfile->static_psymbols.list + psymtab->statics_offset; + (pp - (psymtab->objfile->static_psymbols.list + psymtab->statics_offset) + < psymtab->n_static_syms); + pp++) + { + p = *pp; + if (SYMBOL_NAMESPACE (p) == VAR_NAMESPACE + && SYMBOL_CLASS (p) == LOC_BLOCK + && pc >= SYMBOL_VALUE_ADDRESS (p) + && (SYMBOL_VALUE_ADDRESS (p) > best_pc + || (psymtab->textlow == 0 + && best_pc == 0 && SYMBOL_VALUE_ADDRESS (p) == 0))) + { + if (section) /* match on a specific section */ + { + fixup_psymbol_section (p, psymtab->objfile); + if (SYMBOL_BFD_SECTION (p) != section) + continue; + } + best_pc = SYMBOL_VALUE_ADDRESS (p); + best = p; + } + } + + return best; +} + +/* Find which partial symbol within a psymtab matches PC. Return 0 if none. + Check all psymtabs if PSYMTAB is 0. Backwards compatibility, no section. */ + +struct partial_symbol * +find_pc_psymbol (struct partial_symtab *psymtab, CORE_ADDR pc) +{ + return find_pc_sect_psymbol (psymtab, pc, find_pc_mapped_section (pc)); +} + +/* Debug symbols usually don't have section information. We need to dig that + out of the minimal symbols and stash that in the debug symbol. */ + +static void +fixup_section (struct general_symbol_info *ginfo, struct objfile *objfile) +{ + struct minimal_symbol *msym; + msym = lookup_minimal_symbol (ginfo->name, NULL, objfile); + + if (msym) + { + ginfo->bfd_section = SYMBOL_BFD_SECTION (msym); + ginfo->section = SYMBOL_SECTION (msym); + } +} + +struct symbol * +fixup_symbol_section (struct symbol *sym, struct objfile *objfile) +{ + if (!sym) + return NULL; + + if (SYMBOL_BFD_SECTION (sym)) + return sym; + + fixup_section (&sym->ginfo, objfile); + + return sym; +} + +struct partial_symbol * +fixup_psymbol_section (struct partial_symbol *psym, struct objfile *objfile) +{ + if (!psym) + return NULL; + + if (SYMBOL_BFD_SECTION (psym)) + return psym; + + fixup_section (&psym->ginfo, objfile); + + return psym; +} + +/* Find the definition for a specified symbol name NAME + in namespace NAMESPACE, visible from lexical block BLOCK. + Returns the struct symbol pointer, or zero if no symbol is found. + If SYMTAB is non-NULL, store the symbol table in which the + symbol was found there, or NULL if not found. + C++: if IS_A_FIELD_OF_THIS is nonzero on entry, check to see if + NAME is a field of the current implied argument `this'. If so set + *IS_A_FIELD_OF_THIS to 1, otherwise set it to zero. + BLOCK_FOUND is set to the block in which NAME is found (in the case of + a field of `this', value_of_this sets BLOCK_FOUND to the proper value.) */ + +/* This function has a bunch of loops in it and it would seem to be + attractive to put in some QUIT's (though I'm not really sure + whether it can run long enough to be really important). But there + are a few calls for which it would appear to be bad news to quit + out of here: find_proc_desc in alpha-tdep.c and mips-tdep.c, and + nindy_frame_chain_valid in nindy-tdep.c. (Note that there is C++ + code below which can error(), but that probably doesn't affect + these calls since they are looking for a known variable and thus + can probably assume it will never hit the C++ code). */ + +struct symbol * +lookup_symbol (const char *name, const struct block *block, + const namespace_enum namespace, int *is_a_field_of_this, + struct symtab **symtab) +{ + char *demangled_name = NULL; + const char *modified_name = NULL; + const char *mangled_name = NULL; + int needtofreename = 0; + struct symbol *returnval; + + modified_name = name; + + /* If we are using C++ language, demangle the name before doing a lookup, so + we can always binary search. */ + if (current_language->la_language == language_cplus) + { + demangled_name = cplus_demangle (name, DMGL_ANSI | DMGL_PARAMS); + if (demangled_name) + { + mangled_name = name; + modified_name = demangled_name; + needtofreename = 1; + } + } + + if (case_sensitivity == case_sensitive_off) + { + char *copy; + int len, i; + + len = strlen (name); + copy = (char *) alloca (len + 1); + for (i= 0; i < len; i++) + copy[i] = tolower (name[i]); + copy[len] = 0; + modified_name = copy; + } + + returnval = lookup_symbol_aux (modified_name, mangled_name, block, + namespace, is_a_field_of_this, symtab); + if (needtofreename) + xfree (demangled_name); + + return returnval; +} + +static struct symbol * +lookup_symbol_aux (const char *name, const char *mangled_name, + const struct block *block, const namespace_enum namespace, + int *is_a_field_of_this, struct symtab **symtab) +{ + register struct symbol *sym; + register struct symtab *s = NULL; + register struct partial_symtab *ps; + register struct blockvector *bv; + register struct objfile *objfile = NULL; + register struct block *b; + register struct minimal_symbol *msymbol; + + + /* Search specified block and its superiors. */ + + while (block != 0) + { + sym = lookup_block_symbol (block, name, mangled_name, namespace); + if (sym) + { + block_found = block; + if (symtab != NULL) + { + /* Search the list of symtabs for one which contains the + address of the start of this block. */ + ALL_SYMTABS (objfile, s) + { + bv = BLOCKVECTOR (s); + b = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK); + if (BLOCK_START (b) <= BLOCK_START (block) + && BLOCK_END (b) > BLOCK_START (block)) + goto found; + } + found: + *symtab = s; + } + + return fixup_symbol_section (sym, objfile); + } + block = BLOCK_SUPERBLOCK (block); + } + + /* FIXME: this code is never executed--block is always NULL at this + point. What is it trying to do, anyway? We already should have + checked the STATIC_BLOCK above (it is the superblock of top-level + blocks). Why is VAR_NAMESPACE special-cased? */ + /* Don't need to mess with the psymtabs; if we have a block, + that file is read in. If we don't, then we deal later with + all the psymtab stuff that needs checking. */ + /* Note (RT): The following never-executed code looks unnecessary to me also. + * If we change the code to use the original (passed-in) + * value of 'block', we could cause it to execute, but then what + * would it do? The STATIC_BLOCK of the symtab containing the passed-in + * 'block' was already searched by the above code. And the STATIC_BLOCK's + * of *other* symtabs (those files not containing 'block' lexically) + * should not contain 'block' address-wise. So we wouldn't expect this + * code to find any 'sym''s that were not found above. I vote for + * deleting the following paragraph of code. + */ + if (namespace == VAR_NAMESPACE && block != NULL) + { + struct block *b; + /* Find the right symtab. */ + ALL_SYMTABS (objfile, s) + { + bv = BLOCKVECTOR (s); + b = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK); + if (BLOCK_START (b) <= BLOCK_START (block) + && BLOCK_END (b) > BLOCK_START (block)) + { + sym = lookup_block_symbol (b, name, mangled_name, VAR_NAMESPACE); + if (sym) + { + block_found = b; + if (symtab != NULL) + *symtab = s; + return fixup_symbol_section (sym, objfile); + } + } + } + } + + + /* C++: If requested to do so by the caller, + check to see if NAME is a field of `this'. */ + if (is_a_field_of_this) + { + struct value *v = value_of_this (0); + + *is_a_field_of_this = 0; + if (v && check_field (v, name)) + { + *is_a_field_of_this = 1; + if (symtab != NULL) + *symtab = NULL; + return NULL; + } + } + + /* Now search all global blocks. Do the symtab's first, then + check the psymtab's. If a psymtab indicates the existence + of the desired name as a global, then do psymtab-to-symtab + conversion on the fly and return the found symbol. */ + + ALL_SYMTABS (objfile, s) + { + bv = BLOCKVECTOR (s); + block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK); + sym = lookup_block_symbol (block, name, mangled_name, namespace); + if (sym) + { + block_found = block; + if (symtab != NULL) + *symtab = s; + return fixup_symbol_section (sym, objfile); + } + } + +#ifndef HPUXHPPA + + /* Check for the possibility of the symbol being a function or + a mangled variable that is stored in one of the minimal symbol tables. + Eventually, all global symbols might be resolved in this way. */ + + if (namespace == VAR_NAMESPACE) + { + msymbol = lookup_minimal_symbol (name, NULL, NULL); + if (msymbol != NULL) + { + s = find_pc_sect_symtab (SYMBOL_VALUE_ADDRESS (msymbol), + SYMBOL_BFD_SECTION (msymbol)); + if (s != NULL) + { + /* This is a function which has a symtab for its address. */ + bv = BLOCKVECTOR (s); + block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK); + + /* This call used to pass `SYMBOL_NAME (msymbol)' as the + `name' argument to lookup_block_symbol. But the name + of a minimal symbol is always mangled, so that seems + to be clearly the wrong thing to pass as the + unmangled name. */ + sym = lookup_block_symbol (block, name, mangled_name, namespace); + /* We kept static functions in minimal symbol table as well as + in static scope. We want to find them in the symbol table. */ + if (!sym) + { + block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK); + sym = lookup_block_symbol (block, name, + mangled_name, namespace); + } + + /* sym == 0 if symbol was found in the minimal symbol table + but not in the symtab. + Return 0 to use the msymbol definition of "foo_". + + This happens for Fortran "foo_" symbols, + which are "foo" in the symtab. + + This can also happen if "asm" is used to make a + regular symbol but not a debugging symbol, e.g. + asm(".globl _main"); + asm("_main:"); + */ + + if (symtab != NULL) + *symtab = s; + return fixup_symbol_section (sym, objfile); + } + else if (MSYMBOL_TYPE (msymbol) != mst_text + && MSYMBOL_TYPE (msymbol) != mst_file_text + && !STREQ (name, SYMBOL_NAME (msymbol))) + { + /* This is a mangled variable, look it up by its + mangled name. */ + return lookup_symbol_aux (SYMBOL_NAME (msymbol), mangled_name, block, + namespace, is_a_field_of_this, symtab); + } + /* There are no debug symbols for this file, or we are looking + for an unmangled variable. + Try to find a matching static symbol below. */ + } + } + +#endif + + ALL_PSYMTABS (objfile, ps) + { + if (!ps->readin && lookup_partial_symbol (ps, name, 1, namespace)) + { + s = PSYMTAB_TO_SYMTAB (ps); + bv = BLOCKVECTOR (s); + block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK); + sym = lookup_block_symbol (block, name, mangled_name, namespace); + if (!sym) + { + /* This shouldn't be necessary, but as a last resort + * try looking in the statics even though the psymtab + * claimed the symbol was global. It's possible that + * the psymtab gets it wrong in some cases. + */ + block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK); + sym = lookup_block_symbol (block, name, mangled_name, namespace); + if (!sym) + error ("Internal: global symbol `%s' found in %s psymtab but not in symtab.\n\ +%s may be an inlined function, or may be a template function\n\ +(if a template, try specifying an instantiation: %s<type>).", + name, ps->filename, name, name); + } + if (symtab != NULL) + *symtab = s; + return fixup_symbol_section (sym, objfile); + } + } + + /* Now search all static file-level symbols. + Not strictly correct, but more useful than an error. + Do the symtabs first, then check the psymtabs. + If a psymtab indicates the existence + of the desired name as a file-level static, then do psymtab-to-symtab + conversion on the fly and return the found symbol. */ + + ALL_SYMTABS (objfile, s) + { + bv = BLOCKVECTOR (s); + block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK); + sym = lookup_block_symbol (block, name, mangled_name, namespace); + if (sym) + { + block_found = block; + if (symtab != NULL) + *symtab = s; + return fixup_symbol_section (sym, objfile); + } + } + + ALL_PSYMTABS (objfile, ps) + { + if (!ps->readin && lookup_partial_symbol (ps, name, 0, namespace)) + { + s = PSYMTAB_TO_SYMTAB (ps); + bv = BLOCKVECTOR (s); + block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK); + sym = lookup_block_symbol (block, name, mangled_name, namespace); + if (!sym) + { + /* This shouldn't be necessary, but as a last resort + * try looking in the globals even though the psymtab + * claimed the symbol was static. It's possible that + * the psymtab gets it wrong in some cases. + */ + block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK); + sym = lookup_block_symbol (block, name, mangled_name, namespace); + if (!sym) + error ("Internal: static symbol `%s' found in %s psymtab but not in symtab.\n\ +%s may be an inlined function, or may be a template function\n\ +(if a template, try specifying an instantiation: %s<type>).", + name, ps->filename, name, name); + } + if (symtab != NULL) + *symtab = s; + return fixup_symbol_section (sym, objfile); + } + } + +#ifdef HPUXHPPA + + /* Check for the possibility of the symbol being a function or + a global variable that is stored in one of the minimal symbol tables. + The "minimal symbol table" is built from linker-supplied info. + + RT: I moved this check to last, after the complete search of + the global (p)symtab's and static (p)symtab's. For HP-generated + symbol tables, this check was causing a premature exit from + lookup_symbol with NULL return, and thus messing up symbol lookups + of things like "c::f". It seems to me a check of the minimal + symbol table ought to be a last resort in any case. I'm vaguely + worried about the comment below which talks about FORTRAN routines "foo_" + though... is it saying we need to do the "minsym" check before + the static check in this case? + */ + + if (namespace == VAR_NAMESPACE) + { + msymbol = lookup_minimal_symbol (name, NULL, NULL); + if (msymbol != NULL) + { + /* OK, we found a minimal symbol in spite of not + * finding any symbol. There are various possible + * explanations for this. One possibility is the symbol + * exists in code not compiled -g. Another possibility + * is that the 'psymtab' isn't doing its job. + * A third possibility, related to #2, is that we were confused + * by name-mangling. For instance, maybe the psymtab isn't + * doing its job because it only know about demangled + * names, but we were given a mangled name... + */ + + /* We first use the address in the msymbol to try to + * locate the appropriate symtab. Note that find_pc_symtab() + * has a side-effect of doing psymtab-to-symtab expansion, + * for the found symtab. + */ + s = find_pc_symtab (SYMBOL_VALUE_ADDRESS (msymbol)); + if (s != NULL) + { + bv = BLOCKVECTOR (s); + block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK); + /* This call used to pass `SYMBOL_NAME (msymbol)' as the + `name' argument to lookup_block_symbol. But the name + of a minimal symbol is always mangled, so that seems + to be clearly the wrong thing to pass as the + unmangled name. */ + sym = lookup_block_symbol (block, name, mangled_name, namespace); + /* We kept static functions in minimal symbol table as well as + in static scope. We want to find them in the symbol table. */ + if (!sym) + { + block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK); + sym = lookup_block_symbol (block, name, + mangled_name, namespace); + } + /* If we found one, return it */ + if (sym) + { + if (symtab != NULL) + *symtab = s; + return sym; + } + + /* If we get here with sym == 0, the symbol was + found in the minimal symbol table + but not in the symtab. + Fall through and return 0 to use the msymbol + definition of "foo_". + (Note that outer code generally follows up a call + to this routine with a call to lookup_minimal_symbol(), + so a 0 return means we'll just flow into that other routine). + + This happens for Fortran "foo_" symbols, + which are "foo" in the symtab. + + This can also happen if "asm" is used to make a + regular symbol but not a debugging symbol, e.g. + asm(".globl _main"); + asm("_main:"); + */ + } + + /* If the lookup-by-address fails, try repeating the + * entire lookup process with the symbol name from + * the msymbol (if different from the original symbol name). + */ + else if (MSYMBOL_TYPE (msymbol) != mst_text + && MSYMBOL_TYPE (msymbol) != mst_file_text + && !STREQ (name, SYMBOL_NAME (msymbol))) + { + return lookup_symbol_aux (SYMBOL_NAME (msymbol), mangled_name, + block, namespace, is_a_field_of_this, + symtab); + } + } + } + +#endif + + if (symtab != NULL) + *symtab = NULL; + return 0; +} + +/* Look, in partial_symtab PST, for symbol NAME. Check the global + symbols if GLOBAL, the static symbols if not */ + +static struct partial_symbol * +lookup_partial_symbol (struct partial_symtab *pst, const char *name, int global, + namespace_enum namespace) +{ + struct partial_symbol *temp; + struct partial_symbol **start, **psym; + struct partial_symbol **top, **bottom, **center; + int length = (global ? pst->n_global_syms : pst->n_static_syms); + int do_linear_search = 1; + + if (length == 0) + { + return (NULL); + } + start = (global ? + pst->objfile->global_psymbols.list + pst->globals_offset : + pst->objfile->static_psymbols.list + pst->statics_offset); + + if (global) /* This means we can use a binary search. */ + { + do_linear_search = 0; + + /* Binary search. This search is guaranteed to end with center + pointing at the earliest partial symbol with the correct + name. At that point *all* partial symbols with that name + will be checked against the correct namespace. */ + + bottom = start; + top = start + length - 1; + while (top > bottom) + { + center = bottom + (top - bottom) / 2; + if (!(center < top)) + internal_error (__FILE__, __LINE__, "failed internal consistency check"); + if (!do_linear_search + && (SYMBOL_LANGUAGE (*center) == language_java)) + { + do_linear_search = 1; + } + if (strcmp (SYMBOL_SOURCE_NAME (*center), name) >= 0) + { + top = center; + } + else + { + bottom = center + 1; + } + } + if (!(top == bottom)) + internal_error (__FILE__, __LINE__, "failed internal consistency check"); + + /* djb - 2000-06-03 - Use SYMBOL_MATCHES_NAME, not a strcmp, so + we don't have to force a linear search on C++. Probably holds true + for JAVA as well, no way to check.*/ + while (SYMBOL_MATCHES_NAME (*top,name)) + { + if (SYMBOL_NAMESPACE (*top) == namespace) + { + return (*top); + } + top++; + } + } + + /* Can't use a binary search or else we found during the binary search that + we should also do a linear search. */ + + if (do_linear_search) + { + for (psym = start; psym < start + length; psym++) + { + if (namespace == SYMBOL_NAMESPACE (*psym)) + { + if (SYMBOL_MATCHES_NAME (*psym, name)) + { + return (*psym); + } + } + } + } + + return (NULL); +} + +/* Look up a type named NAME in the struct_namespace. The type returned + must not be opaque -- i.e., must have at least one field defined + + This code was modelled on lookup_symbol -- the parts not relevant to looking + up types were just left out. In particular it's assumed here that types + are available in struct_namespace and only at file-static or global blocks. */ + + +struct type * +lookup_transparent_type (const char *name) +{ + register struct symbol *sym; + register struct symtab *s = NULL; + register struct partial_symtab *ps; + struct blockvector *bv; + register struct objfile *objfile; + register struct block *block; + + /* Now search all the global symbols. Do the symtab's first, then + check the psymtab's. If a psymtab indicates the existence + of the desired name as a global, then do psymtab-to-symtab + conversion on the fly and return the found symbol. */ + + ALL_SYMTABS (objfile, s) + { + bv = BLOCKVECTOR (s); + block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK); + sym = lookup_block_symbol (block, name, NULL, STRUCT_NAMESPACE); + if (sym && !TYPE_IS_OPAQUE (SYMBOL_TYPE (sym))) + { + return SYMBOL_TYPE (sym); + } + } + + ALL_PSYMTABS (objfile, ps) + { + if (!ps->readin && lookup_partial_symbol (ps, name, 1, STRUCT_NAMESPACE)) + { + s = PSYMTAB_TO_SYMTAB (ps); + bv = BLOCKVECTOR (s); + block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK); + sym = lookup_block_symbol (block, name, NULL, STRUCT_NAMESPACE); + if (!sym) + { + /* This shouldn't be necessary, but as a last resort + * try looking in the statics even though the psymtab + * claimed the symbol was global. It's possible that + * the psymtab gets it wrong in some cases. + */ + block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK); + sym = lookup_block_symbol (block, name, NULL, STRUCT_NAMESPACE); + if (!sym) + error ("Internal: global symbol `%s' found in %s psymtab but not in symtab.\n\ +%s may be an inlined function, or may be a template function\n\ +(if a template, try specifying an instantiation: %s<type>).", + name, ps->filename, name, name); + } + if (!TYPE_IS_OPAQUE (SYMBOL_TYPE (sym))) + return SYMBOL_TYPE (sym); + } + } + + /* Now search the static file-level symbols. + Not strictly correct, but more useful than an error. + Do the symtab's first, then + check the psymtab's. If a psymtab indicates the existence + of the desired name as a file-level static, then do psymtab-to-symtab + conversion on the fly and return the found symbol. + */ + + ALL_SYMTABS (objfile, s) + { + bv = BLOCKVECTOR (s); + block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK); + sym = lookup_block_symbol (block, name, NULL, STRUCT_NAMESPACE); + if (sym && !TYPE_IS_OPAQUE (SYMBOL_TYPE (sym))) + { + return SYMBOL_TYPE (sym); + } + } + + ALL_PSYMTABS (objfile, ps) + { + if (!ps->readin && lookup_partial_symbol (ps, name, 0, STRUCT_NAMESPACE)) + { + s = PSYMTAB_TO_SYMTAB (ps); + bv = BLOCKVECTOR (s); + block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK); + sym = lookup_block_symbol (block, name, NULL, STRUCT_NAMESPACE); + if (!sym) + { + /* This shouldn't be necessary, but as a last resort + * try looking in the globals even though the psymtab + * claimed the symbol was static. It's possible that + * the psymtab gets it wrong in some cases. + */ + block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK); + sym = lookup_block_symbol (block, name, NULL, STRUCT_NAMESPACE); + if (!sym) + error ("Internal: static symbol `%s' found in %s psymtab but not in symtab.\n\ +%s may be an inlined function, or may be a template function\n\ +(if a template, try specifying an instantiation: %s<type>).", + name, ps->filename, name, name); + } + if (!TYPE_IS_OPAQUE (SYMBOL_TYPE (sym))) + return SYMBOL_TYPE (sym); + } + } + return (struct type *) 0; +} + + +/* Find the psymtab containing main(). */ +/* FIXME: What about languages without main() or specially linked + executables that have no main() ? */ + +struct partial_symtab * +find_main_psymtab (void) +{ + register struct partial_symtab *pst; + register struct objfile *objfile; + + ALL_PSYMTABS (objfile, pst) + { + if (lookup_partial_symbol (pst, main_name (), 1, VAR_NAMESPACE)) + { + return (pst); + } + } + return (NULL); +} + +/* Search BLOCK for symbol NAME in NAMESPACE. + + Note that if NAME is the demangled form of a C++ symbol, we will fail + to find a match during the binary search of the non-encoded names, but + for now we don't worry about the slight inefficiency of looking for + a match we'll never find, since it will go pretty quick. Once the + binary search terminates, we drop through and do a straight linear + search on the symbols. Each symbol which is marked as being a C++ + symbol (language_cplus set) has both the encoded and non-encoded names + tested for a match. + + If MANGLED_NAME is non-NULL, verify that any symbol we find has this + particular mangled name. +*/ + +struct symbol * +lookup_block_symbol (register const struct block *block, const char *name, + const char *mangled_name, + const namespace_enum namespace) +{ + register int bot, top, inc; + register struct symbol *sym; + register struct symbol *sym_found = NULL; + register int do_linear_search = 1; + + if (BLOCK_HASHTABLE (block)) + { + unsigned int hash_index; + hash_index = msymbol_hash_iw (name); + hash_index = hash_index % BLOCK_BUCKETS (block); + for (sym = BLOCK_BUCKET (block, hash_index); sym; sym = sym->hash_next) + { + if (SYMBOL_NAMESPACE (sym) == namespace + && (mangled_name + ? strcmp (SYMBOL_NAME (sym), mangled_name) == 0 + : SYMBOL_MATCHES_NAME (sym, name))) + return sym; + } + return NULL; + } + + /* If the blocks's symbols were sorted, start with a binary search. */ + + if (BLOCK_SHOULD_SORT (block)) + { + /* Reset the linear search flag so if the binary search fails, we + won't do the linear search once unless we find some reason to + do so */ + + do_linear_search = 0; + top = BLOCK_NSYMS (block); + bot = 0; + + /* Advance BOT to not far before the first symbol whose name is NAME. */ + + while (1) + { + inc = (top - bot + 1); + /* No need to keep binary searching for the last few bits worth. */ + if (inc < 4) + { + break; + } + inc = (inc >> 1) + bot; + sym = BLOCK_SYM (block, inc); + if (!do_linear_search && (SYMBOL_LANGUAGE (sym) == language_java)) + { + do_linear_search = 1; + } + if (SYMBOL_SOURCE_NAME (sym)[0] < name[0]) + { + bot = inc; + } + else if (SYMBOL_SOURCE_NAME (sym)[0] > name[0]) + { + top = inc; + } + else if (strcmp (SYMBOL_SOURCE_NAME (sym), name) < 0) + { + bot = inc; + } + else + { + top = inc; + } + } + + /* Now scan forward until we run out of symbols, find one whose + name is greater than NAME, or find one we want. If there is + more than one symbol with the right name and namespace, we + return the first one; I believe it is now impossible for us + to encounter two symbols with the same name and namespace + here, because blocks containing argument symbols are no + longer sorted. The exception is for C++, where multiple functions + (cloned constructors / destructors, in particular) can have + the same demangled name. So if we have a particular + mangled name to match, try to do so. */ + + top = BLOCK_NSYMS (block); + while (bot < top) + { + sym = BLOCK_SYM (block, bot); + if (SYMBOL_NAMESPACE (sym) == namespace + && (mangled_name + ? strcmp (SYMBOL_NAME (sym), mangled_name) == 0 + : SYMBOL_MATCHES_NAME (sym, name))) + { + return sym; + } + if (SYMBOL_SOURCE_NAME (sym)[0] > name[0]) + { + break; + } + bot++; + } + } + + /* Here if block isn't sorted, or we fail to find a match during the + binary search above. If during the binary search above, we find a + symbol which is a Java symbol, then we have re-enabled the linear + search flag which was reset when starting the binary search. + + This loop is equivalent to the loop above, but hacked greatly for speed. + + Note that parameter symbols do not always show up last in the + list; this loop makes sure to take anything else other than + parameter symbols first; it only uses parameter symbols as a + last resort. Note that this only takes up extra computation + time on a match. */ + + if (do_linear_search) + { + top = BLOCK_NSYMS (block); + bot = 0; + while (bot < top) + { + sym = BLOCK_SYM (block, bot); + if (SYMBOL_NAMESPACE (sym) == namespace + && (mangled_name + ? strcmp (SYMBOL_NAME (sym), mangled_name) == 0 + : SYMBOL_MATCHES_NAME (sym, name))) + { + /* If SYM has aliases, then use any alias that is active + at the current PC. If no alias is active at the current + PC, then use the main symbol. + + ?!? Is checking the current pc correct? Is this routine + ever called to look up a symbol from another context? + + FIXME: No, it's not correct. If someone sets a + conditional breakpoint at an address, then the + breakpoint's `struct expression' should refer to the + `struct symbol' appropriate for the breakpoint's + address, which may not be the PC. + + Even if it were never called from another context, + it's totally bizarre for lookup_symbol's behavior to + depend on the value of the inferior's current PC. We + should pass in the appropriate PC as well as the + block. The interface to lookup_symbol should change + to require the caller to provide a PC. */ + + if (SYMBOL_ALIASES (sym)) + sym = find_active_alias (sym, read_pc ()); + + sym_found = sym; + if (SYMBOL_CLASS (sym) != LOC_ARG && + SYMBOL_CLASS (sym) != LOC_LOCAL_ARG && + SYMBOL_CLASS (sym) != LOC_REF_ARG && + SYMBOL_CLASS (sym) != LOC_REGPARM && + SYMBOL_CLASS (sym) != LOC_REGPARM_ADDR && + SYMBOL_CLASS (sym) != LOC_BASEREG_ARG) + { + break; + } + } + bot++; + } + } + return (sym_found); /* Will be NULL if not found. */ +} + +/* Given a main symbol SYM and ADDR, search through the alias + list to determine if an alias is active at ADDR and return + the active alias. + + If no alias is active, then return SYM. */ + +static struct symbol * +find_active_alias (struct symbol *sym, CORE_ADDR addr) +{ + struct range_list *r; + struct alias_list *aliases; + + /* If we have aliases, check them first. */ + aliases = SYMBOL_ALIASES (sym); + + while (aliases) + { + if (!SYMBOL_RANGES (aliases->sym)) + return aliases->sym; + for (r = SYMBOL_RANGES (aliases->sym); r; r = r->next) + { + if (r->start <= addr && r->end > addr) + return aliases->sym; + } + aliases = aliases->next; + } + + /* Nothing found, return the main symbol. */ + return sym; +} + + +/* Return the symbol for the function which contains a specified + lexical block, described by a struct block BL. */ + +struct symbol * +block_function (struct block *bl) +{ + while (BLOCK_FUNCTION (bl) == 0 && BLOCK_SUPERBLOCK (bl) != 0) + bl = BLOCK_SUPERBLOCK (bl); + + return BLOCK_FUNCTION (bl); +} + +/* Find the symtab associated with PC and SECTION. Look through the + psymtabs and read in another symtab if necessary. */ + +struct symtab * +find_pc_sect_symtab (CORE_ADDR pc, asection *section) +{ + register struct block *b; + struct blockvector *bv; + register struct symtab *s = NULL; + register struct symtab *best_s = NULL; + register struct partial_symtab *ps; + register struct objfile *objfile; + CORE_ADDR distance = 0; + struct minimal_symbol *msymbol; + + /* If we know that this is not a text address, return failure. This is + necessary because we loop based on the block's high and low code + addresses, which do not include the data ranges, and because + we call find_pc_sect_psymtab which has a similar restriction based + on the partial_symtab's texthigh and textlow. */ + msymbol = lookup_minimal_symbol_by_pc_section (pc, section); + if (msymbol + && (msymbol->type == mst_data + || msymbol->type == mst_bss + || msymbol->type == mst_abs + || msymbol->type == mst_file_data + || msymbol->type == mst_file_bss)) + return NULL; + + /* Search all symtabs for the one whose file contains our address, and which + is the smallest of all the ones containing the address. This is designed + to deal with a case like symtab a is at 0x1000-0x2000 and 0x3000-0x4000 + and symtab b is at 0x2000-0x3000. So the GLOBAL_BLOCK for a is from + 0x1000-0x4000, but for address 0x2345 we want to return symtab b. + + This happens for native ecoff format, where code from included files + gets its own symtab. The symtab for the included file should have + been read in already via the dependency mechanism. + It might be swifter to create several symtabs with the same name + like xcoff does (I'm not sure). + + It also happens for objfiles that have their functions reordered. + For these, the symtab we are looking for is not necessarily read in. */ + + ALL_SYMTABS (objfile, s) + { + bv = BLOCKVECTOR (s); + b = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK); + + if (BLOCK_START (b) <= pc + && BLOCK_END (b) > pc + && (distance == 0 + || BLOCK_END (b) - BLOCK_START (b) < distance)) + { + /* For an objfile that has its functions reordered, + find_pc_psymtab will find the proper partial symbol table + and we simply return its corresponding symtab. */ + /* In order to better support objfiles that contain both + stabs and coff debugging info, we continue on if a psymtab + can't be found. */ + if ((objfile->flags & OBJF_REORDERED) && objfile->psymtabs) + { + ps = find_pc_sect_psymtab (pc, section); + if (ps) + return PSYMTAB_TO_SYMTAB (ps); + } + if (section != 0) + { + int i; + struct symbol *sym = NULL; + + ALL_BLOCK_SYMBOLS (b, i, sym) + { + fixup_symbol_section (sym, objfile); + if (section == SYMBOL_BFD_SECTION (sym)) + break; + } + if ((i >= BLOCK_BUCKETS (b)) && (sym == NULL)) + continue; /* no symbol in this symtab matches section */ + } + distance = BLOCK_END (b) - BLOCK_START (b); + best_s = s; + } + } + + if (best_s != NULL) + return (best_s); + + s = NULL; + ps = find_pc_sect_psymtab (pc, section); + if (ps) + { + if (ps->readin) + /* Might want to error() here (in case symtab is corrupt and + will cause a core dump), but maybe we can successfully + continue, so let's not. */ + warning ("\ +(Internal error: pc 0x%s in read in psymtab, but not in symtab.)\n", + paddr_nz (pc)); + s = PSYMTAB_TO_SYMTAB (ps); + } + return (s); +} + +/* Find the symtab associated with PC. Look through the psymtabs and + read in another symtab if necessary. Backward compatibility, no section */ + +struct symtab * +find_pc_symtab (CORE_ADDR pc) +{ + return find_pc_sect_symtab (pc, find_pc_mapped_section (pc)); +} + + +#if 0 + +/* Find the closest symbol value (of any sort -- function or variable) + for a given address value. Slow but complete. (currently unused, + mainly because it is too slow. We could fix it if each symtab and + psymtab had contained in it the addresses ranges of each of its + sections, which also would be required to make things like "info + line *0x2345" cause psymtabs to be converted to symtabs). */ + +struct symbol * +find_addr_symbol (CORE_ADDR addr, struct symtab **symtabp, CORE_ADDR *symaddrp) +{ + struct symtab *symtab, *best_symtab; + struct objfile *objfile; + register int bot, top; + register struct symbol *sym; + register CORE_ADDR sym_addr; + struct block *block; + int blocknum; + + /* Info on best symbol seen so far */ + + register CORE_ADDR best_sym_addr = 0; + struct symbol *best_sym = 0; + + /* FIXME -- we should pull in all the psymtabs, too! */ + ALL_SYMTABS (objfile, symtab) + { + /* Search the global and static blocks in this symtab for + the closest symbol-address to the desired address. */ + + for (blocknum = GLOBAL_BLOCK; blocknum <= STATIC_BLOCK; blocknum++) + { + QUIT; + block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), blocknum); + ALL_BLOCK_SYMBOLS (block, bot, sym) + { + switch (SYMBOL_CLASS (sym)) + { + case LOC_STATIC: + case LOC_LABEL: + sym_addr = SYMBOL_VALUE_ADDRESS (sym); + break; + + case LOC_INDIRECT: + sym_addr = SYMBOL_VALUE_ADDRESS (sym); + /* An indirect symbol really lives at *sym_addr, + * so an indirection needs to be done. + * However, I am leaving this commented out because it's + * expensive, and it's possible that symbolization + * could be done without an active process (in + * case this read_memory will fail). RT + sym_addr = read_memory_unsigned_integer + (sym_addr, TARGET_PTR_BIT / TARGET_CHAR_BIT); + */ + break; + + case LOC_BLOCK: + sym_addr = BLOCK_START (SYMBOL_BLOCK_VALUE (sym)); + break; + + default: + continue; + } + + if (sym_addr <= addr) + if (sym_addr > best_sym_addr) + { + /* Quit if we found an exact match. */ + best_sym = sym; + best_sym_addr = sym_addr; + best_symtab = symtab; + if (sym_addr == addr) + goto done; + } + } + } + } + +done: + if (symtabp) + *symtabp = best_symtab; + if (symaddrp) + *symaddrp = best_sym_addr; + return best_sym; +} +#endif /* 0 */ + +/* Find the source file and line number for a given PC value and SECTION. + Return a structure containing a symtab pointer, a line number, + and a pc range for the entire source line. + The value's .pc field is NOT the specified pc. + NOTCURRENT nonzero means, if specified pc is on a line boundary, + use the line that ends there. Otherwise, in that case, the line + that begins there is used. */ + +/* The big complication here is that a line may start in one file, and end just + before the start of another file. This usually occurs when you #include + code in the middle of a subroutine. To properly find the end of a line's PC + range, we must search all symtabs associated with this compilation unit, and + find the one whose first PC is closer than that of the next line in this + symtab. */ + +/* If it's worth the effort, we could be using a binary search. */ + +struct symtab_and_line +find_pc_sect_line (CORE_ADDR pc, struct sec *section, int notcurrent) +{ + struct symtab *s; + register struct linetable *l; + register int len; + register int i; + register struct linetable_entry *item; + struct symtab_and_line val; + struct blockvector *bv; + struct minimal_symbol *msymbol; + struct minimal_symbol *mfunsym; + + /* Info on best line seen so far, and where it starts, and its file. */ + + struct linetable_entry *best = NULL; + CORE_ADDR best_end = 0; + struct symtab *best_symtab = 0; + + /* Store here the first line number + of a file which contains the line at the smallest pc after PC. + If we don't find a line whose range contains PC, + we will use a line one less than this, + with a range from the start of that file to the first line's pc. */ + struct linetable_entry *alt = NULL; + struct symtab *alt_symtab = 0; + + /* Info on best line seen in this file. */ + + struct linetable_entry *prev; + + /* If this pc is not from the current frame, + it is the address of the end of a call instruction. + Quite likely that is the start of the following statement. + But what we want is the statement containing the instruction. + Fudge the pc to make sure we get that. */ + + INIT_SAL (&val); /* initialize to zeroes */ + + /* It's tempting to assume that, if we can't find debugging info for + any function enclosing PC, that we shouldn't search for line + number info, either. However, GAS can emit line number info for + assembly files --- very helpful when debugging hand-written + assembly code. In such a case, we'd have no debug info for the + function, but we would have line info. */ + + if (notcurrent) + pc -= 1; + + /* elz: added this because this function returned the wrong + information if the pc belongs to a stub (import/export) + to call a shlib function. This stub would be anywhere between + two functions in the target, and the line info was erroneously + taken to be the one of the line before the pc. + */ + /* RT: Further explanation: + + * We have stubs (trampolines) inserted between procedures. + * + * Example: "shr1" exists in a shared library, and a "shr1" stub also + * exists in the main image. + * + * In the minimal symbol table, we have a bunch of symbols + * sorted by start address. The stubs are marked as "trampoline", + * the others appear as text. E.g.: + * + * Minimal symbol table for main image + * main: code for main (text symbol) + * shr1: stub (trampoline symbol) + * foo: code for foo (text symbol) + * ... + * Minimal symbol table for "shr1" image: + * ... + * shr1: code for shr1 (text symbol) + * ... + * + * So the code below is trying to detect if we are in the stub + * ("shr1" stub), and if so, find the real code ("shr1" trampoline), + * and if found, do the symbolization from the real-code address + * rather than the stub address. + * + * Assumptions being made about the minimal symbol table: + * 1. lookup_minimal_symbol_by_pc() will return a trampoline only + * if we're really in the trampoline. If we're beyond it (say + * we're in "foo" in the above example), it'll have a closer + * symbol (the "foo" text symbol for example) and will not + * return the trampoline. + * 2. lookup_minimal_symbol_text() will find a real text symbol + * corresponding to the trampoline, and whose address will + * be different than the trampoline address. I put in a sanity + * check for the address being the same, to avoid an + * infinite recursion. + */ + msymbol = lookup_minimal_symbol_by_pc (pc); + if (msymbol != NULL) + if (MSYMBOL_TYPE (msymbol) == mst_solib_trampoline) + { + mfunsym = lookup_minimal_symbol_text (SYMBOL_NAME (msymbol), NULL, NULL); + if (mfunsym == NULL) + /* I eliminated this warning since it is coming out + * in the following situation: + * gdb shmain // test program with shared libraries + * (gdb) break shr1 // function in shared lib + * Warning: In stub for ... + * In the above situation, the shared lib is not loaded yet, + * so of course we can't find the real func/line info, + * but the "break" still works, and the warning is annoying. + * So I commented out the warning. RT */ + /* warning ("In stub for %s; unable to find real function/line info", SYMBOL_NAME(msymbol)) */ ; + /* fall through */ + else if (SYMBOL_VALUE (mfunsym) == SYMBOL_VALUE (msymbol)) + /* Avoid infinite recursion */ + /* See above comment about why warning is commented out */ + /* warning ("In stub for %s; unable to find real function/line info", SYMBOL_NAME(msymbol)) */ ; + /* fall through */ + else + return find_pc_line (SYMBOL_VALUE (mfunsym), 0); + } + + + s = find_pc_sect_symtab (pc, section); + if (!s) + { + /* if no symbol information, return previous pc */ + if (notcurrent) + pc++; + val.pc = pc; + return val; + } + + bv = BLOCKVECTOR (s); + + /* Look at all the symtabs that share this blockvector. + They all have the same apriori range, that we found was right; + but they have different line tables. */ + + for (; s && BLOCKVECTOR (s) == bv; s = s->next) + { + /* Find the best line in this symtab. */ + l = LINETABLE (s); + if (!l) + continue; + len = l->nitems; + if (len <= 0) + { + /* I think len can be zero if the symtab lacks line numbers + (e.g. gcc -g1). (Either that or the LINETABLE is NULL; + I'm not sure which, and maybe it depends on the symbol + reader). */ + continue; + } + + prev = NULL; + item = l->item; /* Get first line info */ + + /* Is this file's first line closer than the first lines of other files? + If so, record this file, and its first line, as best alternate. */ + if (item->pc > pc && (!alt || item->pc < alt->pc)) + { + alt = item; + alt_symtab = s; + } + + for (i = 0; i < len; i++, item++) + { + /* Leave prev pointing to the linetable entry for the last line + that started at or before PC. */ + if (item->pc > pc) + break; + + prev = item; + } + + /* At this point, prev points at the line whose start addr is <= pc, and + item points at the next line. If we ran off the end of the linetable + (pc >= start of the last line), then prev == item. If pc < start of + the first line, prev will not be set. */ + + /* Is this file's best line closer than the best in the other files? + If so, record this file, and its best line, as best so far. */ + + if (prev && (!best || prev->pc > best->pc)) + { + best = prev; + best_symtab = s; + + /* Discard BEST_END if it's before the PC of the current BEST. */ + if (best_end <= best->pc) + best_end = 0; + } + + /* If another line (denoted by ITEM) is in the linetable and its + PC is after BEST's PC, but before the current BEST_END, then + use ITEM's PC as the new best_end. */ + if (best && i < len && item->pc > best->pc + && (best_end == 0 || best_end > item->pc)) + best_end = item->pc; + } + + if (!best_symtab) + { + if (!alt_symtab) + { /* If we didn't find any line # info, just + return zeros. */ + val.pc = pc; + } + else + { + val.symtab = alt_symtab; + val.line = alt->line - 1; + + /* Don't return line 0, that means that we didn't find the line. */ + if (val.line == 0) + ++val.line; + + val.pc = BLOCK_END (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK)); + val.end = alt->pc; + } + } + else if (best->line == 0) + { + /* If our best fit is in a range of PC's for which no line + number info is available (line number is zero) then we didn't + find any valid line information. */ + val.pc = pc; + } + else + { + val.symtab = best_symtab; + val.line = best->line; + val.pc = best->pc; + if (best_end && (!alt || best_end < alt->pc)) + val.end = best_end; + else if (alt) + val.end = alt->pc; + else + val.end = BLOCK_END (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK)); + } + val.section = section; + return val; +} + +/* Backward compatibility (no section) */ + +struct symtab_and_line +find_pc_line (CORE_ADDR pc, int notcurrent) +{ + asection *section; + + section = find_pc_overlay (pc); + if (pc_in_unmapped_range (pc, section)) + pc = overlay_mapped_address (pc, section); + return find_pc_sect_line (pc, section, notcurrent); +} + +/* Find line number LINE in any symtab whose name is the same as + SYMTAB. + + If found, return the symtab that contains the linetable in which it was + found, set *INDEX to the index in the linetable of the best entry + found, and set *EXACT_MATCH nonzero if the value returned is an + exact match. + + If not found, return NULL. */ + +struct symtab * +find_line_symtab (struct symtab *symtab, int line, int *index, int *exact_match) +{ + int exact; + + /* BEST_INDEX and BEST_LINETABLE identify the smallest linenumber > LINE + so far seen. */ + + int best_index; + struct linetable *best_linetable; + struct symtab *best_symtab; + + /* First try looking it up in the given symtab. */ + best_linetable = LINETABLE (symtab); + best_symtab = symtab; + best_index = find_line_common (best_linetable, line, &exact); + if (best_index < 0 || !exact) + { + /* Didn't find an exact match. So we better keep looking for + another symtab with the same name. In the case of xcoff, + multiple csects for one source file (produced by IBM's FORTRAN + compiler) produce multiple symtabs (this is unavoidable + assuming csects can be at arbitrary places in memory and that + the GLOBAL_BLOCK of a symtab has a begin and end address). */ + + /* BEST is the smallest linenumber > LINE so far seen, + or 0 if none has been seen so far. + BEST_INDEX and BEST_LINETABLE identify the item for it. */ + int best; + + struct objfile *objfile; + struct symtab *s; + + if (best_index >= 0) + best = best_linetable->item[best_index].line; + else + best = 0; + + ALL_SYMTABS (objfile, s) + { + struct linetable *l; + int ind; + + if (!STREQ (symtab->filename, s->filename)) + continue; + l = LINETABLE (s); + ind = find_line_common (l, line, &exact); + if (ind >= 0) + { + if (exact) + { + best_index = ind; + best_linetable = l; + best_symtab = s; + goto done; + } + if (best == 0 || l->item[ind].line < best) + { + best = l->item[ind].line; + best_index = ind; + best_linetable = l; + best_symtab = s; + } + } + } + } +done: + if (best_index < 0) + return NULL; + + if (index) + *index = best_index; + if (exact_match) + *exact_match = exact; + + return best_symtab; +} + +/* Set the PC value for a given source file and line number and return true. + Returns zero for invalid line number (and sets the PC to 0). + The source file is specified with a struct symtab. */ + +int +find_line_pc (struct symtab *symtab, int line, CORE_ADDR *pc) +{ + struct linetable *l; + int ind; + + *pc = 0; + if (symtab == 0) + return 0; + + symtab = find_line_symtab (symtab, line, &ind, NULL); + if (symtab != NULL) + { + l = LINETABLE (symtab); + *pc = l->item[ind].pc; + return 1; + } + else + return 0; +} + +/* Find the range of pc values in a line. + Store the starting pc of the line into *STARTPTR + and the ending pc (start of next line) into *ENDPTR. + Returns 1 to indicate success. + Returns 0 if could not find the specified line. */ + +int +find_line_pc_range (struct symtab_and_line sal, CORE_ADDR *startptr, + CORE_ADDR *endptr) +{ + CORE_ADDR startaddr; + struct symtab_and_line found_sal; + + startaddr = sal.pc; + if (startaddr == 0 && !find_line_pc (sal.symtab, sal.line, &startaddr)) + return 0; + + /* This whole function is based on address. For example, if line 10 has + two parts, one from 0x100 to 0x200 and one from 0x300 to 0x400, then + "info line *0x123" should say the line goes from 0x100 to 0x200 + and "info line *0x355" should say the line goes from 0x300 to 0x400. + This also insures that we never give a range like "starts at 0x134 + and ends at 0x12c". */ + + found_sal = find_pc_sect_line (startaddr, sal.section, 0); + if (found_sal.line != sal.line) + { + /* The specified line (sal) has zero bytes. */ + *startptr = found_sal.pc; + *endptr = found_sal.pc; + } + else + { + *startptr = found_sal.pc; + *endptr = found_sal.end; + } + return 1; +} + +/* Given a line table and a line number, return the index into the line + table for the pc of the nearest line whose number is >= the specified one. + Return -1 if none is found. The value is >= 0 if it is an index. + + Set *EXACT_MATCH nonzero if the value returned is an exact match. */ + +static int +find_line_common (register struct linetable *l, register int lineno, + int *exact_match) +{ + register int i; + register int len; + + /* BEST is the smallest linenumber > LINENO so far seen, + or 0 if none has been seen so far. + BEST_INDEX identifies the item for it. */ + + int best_index = -1; + int best = 0; + + if (lineno <= 0) + return -1; + if (l == 0) + return -1; + + len = l->nitems; + for (i = 0; i < len; i++) + { + register struct linetable_entry *item = &(l->item[i]); + + if (item->line == lineno) + { + /* Return the first (lowest address) entry which matches. */ + *exact_match = 1; + return i; + } + + if (item->line > lineno && (best == 0 || item->line < best)) + { + best = item->line; + best_index = i; + } + } + + /* If we got here, we didn't get an exact match. */ + + *exact_match = 0; + return best_index; +} + +int +find_pc_line_pc_range (CORE_ADDR pc, CORE_ADDR *startptr, CORE_ADDR *endptr) +{ + struct symtab_and_line sal; + sal = find_pc_line (pc, 0); + *startptr = sal.pc; + *endptr = sal.end; + return sal.symtab != 0; +} + +/* Given a function symbol SYM, find the symtab and line for the start + of the function. + If the argument FUNFIRSTLINE is nonzero, we want the first line + of real code inside the function. */ + +struct symtab_and_line +find_function_start_sal (struct symbol *sym, int funfirstline) +{ + CORE_ADDR pc; + struct symtab_and_line sal; + + pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym)); + fixup_symbol_section (sym, NULL); + if (funfirstline) + { /* skip "first line" of function (which is actually its prologue) */ + asection *section = SYMBOL_BFD_SECTION (sym); + /* If function is in an unmapped overlay, use its unmapped LMA + address, so that SKIP_PROLOGUE has something unique to work on */ + if (section_is_overlay (section) && + !section_is_mapped (section)) + pc = overlay_unmapped_address (pc, section); + + pc += FUNCTION_START_OFFSET; + pc = SKIP_PROLOGUE (pc); + + /* For overlays, map pc back into its mapped VMA range */ + pc = overlay_mapped_address (pc, section); + } + sal = find_pc_sect_line (pc, SYMBOL_BFD_SECTION (sym), 0); + +#ifdef PROLOGUE_FIRSTLINE_OVERLAP + /* Convex: no need to suppress code on first line, if any */ + sal.pc = pc; +#else + /* Check if SKIP_PROLOGUE left us in mid-line, and the next + line is still part of the same function. */ + if (sal.pc != pc + && BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) <= sal.end + && sal.end < BLOCK_END (SYMBOL_BLOCK_VALUE (sym))) + { + /* First pc of next line */ + pc = sal.end; + /* Recalculate the line number (might not be N+1). */ + sal = find_pc_sect_line (pc, SYMBOL_BFD_SECTION (sym), 0); + } + sal.pc = pc; +#endif + + return sal; +} + +/* If P is of the form "operator[ \t]+..." where `...' is + some legitimate operator text, return a pointer to the + beginning of the substring of the operator text. + Otherwise, return "". */ +char * +operator_chars (char *p, char **end) +{ + *end = ""; + if (strncmp (p, "operator", 8)) + return *end; + p += 8; + + /* Don't get faked out by `operator' being part of a longer + identifier. */ + if (isalpha (*p) || *p == '_' || *p == '$' || *p == '\0') + return *end; + + /* Allow some whitespace between `operator' and the operator symbol. */ + while (*p == ' ' || *p == '\t') + p++; + + /* Recognize 'operator TYPENAME'. */ + + if (isalpha (*p) || *p == '_' || *p == '$') + { + register char *q = p + 1; + while (isalnum (*q) || *q == '_' || *q == '$') + q++; + *end = q; + return p; + } + + while (*p) + switch (*p) + { + case '\\': /* regexp quoting */ + if (p[1] == '*') + { + if (p[2] == '=') /* 'operator\*=' */ + *end = p + 3; + else /* 'operator\*' */ + *end = p + 2; + return p; + } + else if (p[1] == '[') + { + if (p[2] == ']') + error ("mismatched quoting on brackets, try 'operator\\[\\]'"); + else if (p[2] == '\\' && p[3] == ']') + { + *end = p + 4; /* 'operator\[\]' */ + return p; + } + else + error ("nothing is allowed between '[' and ']'"); + } + else + { + /* Gratuitous qoute: skip it and move on. */ + p++; + continue; + } + break; + case '!': + case '=': + case '*': + case '/': + case '%': + case '^': + if (p[1] == '=') + *end = p + 2; + else + *end = p + 1; + return p; + case '<': + case '>': + case '+': + case '-': + case '&': + case '|': + if (p[0] == '-' && p[1] == '>') + { + /* Struct pointer member operator 'operator->'. */ + if (p[2] == '*') + { + *end = p + 3; /* 'operator->*' */ + return p; + } + else if (p[2] == '\\') + { + *end = p + 4; /* Hopefully 'operator->\*' */ + return p; + } + else + { + *end = p + 2; /* 'operator->' */ + return p; + } + } + if (p[1] == '=' || p[1] == p[0]) + *end = p + 2; + else + *end = p + 1; + return p; + case '~': + case ',': + *end = p + 1; + return p; + case '(': + if (p[1] != ')') + error ("`operator ()' must be specified without whitespace in `()'"); + *end = p + 2; + return p; + case '?': + if (p[1] != ':') + error ("`operator ?:' must be specified without whitespace in `?:'"); + *end = p + 2; + return p; + case '[': + if (p[1] != ']') + error ("`operator []' must be specified without whitespace in `[]'"); + *end = p + 2; + return p; + default: + error ("`operator %s' not supported", p); + break; + } + + *end = ""; + return *end; +} + + +/* If FILE is not already in the table of files, return zero; + otherwise return non-zero. Optionally add FILE to the table if ADD + is non-zero. If *FIRST is non-zero, forget the old table + contents. */ +static int +filename_seen (const char *file, int add, int *first) +{ + /* Table of files seen so far. */ + static const char **tab = NULL; + /* Allocated size of tab in elements. + Start with one 256-byte block (when using GNU malloc.c). + 24 is the malloc overhead when range checking is in effect. */ + static int tab_alloc_size = (256 - 24) / sizeof (char *); + /* Current size of tab in elements. */ + static int tab_cur_size; + const char **p; + + if (*first) + { + if (tab == NULL) + tab = (const char **) xmalloc (tab_alloc_size * sizeof (*tab)); + tab_cur_size = 0; + } + + /* Is FILE in tab? */ + for (p = tab; p < tab + tab_cur_size; p++) + if (strcmp (*p, file) == 0) + return 1; + + /* No; maybe add it to tab. */ + if (add) + { + if (tab_cur_size == tab_alloc_size) + { + tab_alloc_size *= 2; + tab = (const char **) xrealloc ((char *) tab, + tab_alloc_size * sizeof (*tab)); + } + tab[tab_cur_size++] = file; + } + + return 0; +} + +/* Slave routine for sources_info. Force line breaks at ,'s. + NAME is the name to print and *FIRST is nonzero if this is the first + name printed. Set *FIRST to zero. */ +static void +output_source_filename (char *name, int *first) +{ + /* Since a single source file can result in several partial symbol + tables, we need to avoid printing it more than once. Note: if + some of the psymtabs are read in and some are not, it gets + printed both under "Source files for which symbols have been + read" and "Source files for which symbols will be read in on + demand". I consider this a reasonable way to deal with the + situation. I'm not sure whether this can also happen for + symtabs; it doesn't hurt to check. */ + + /* Was NAME already seen? */ + if (filename_seen (name, 1, first)) + { + /* Yes; don't print it again. */ + return; + } + /* No; print it and reset *FIRST. */ + if (*first) + { + *first = 0; + } + else + { + printf_filtered (", "); + } + + wrap_here (""); + fputs_filtered (name, gdb_stdout); +} + +static void +sources_info (char *ignore, int from_tty) +{ + register struct symtab *s; + register struct partial_symtab *ps; + register struct objfile *objfile; + int first; + + if (!have_full_symbols () && !have_partial_symbols ()) + { + error ("No symbol table is loaded. Use the \"file\" command."); + } + + printf_filtered ("Source files for which symbols have been read in:\n\n"); + + first = 1; + ALL_SYMTABS (objfile, s) + { + output_source_filename (s->filename, &first); + } + printf_filtered ("\n\n"); + + printf_filtered ("Source files for which symbols will be read in on demand:\n\n"); + + first = 1; + ALL_PSYMTABS (objfile, ps) + { + if (!ps->readin) + { + output_source_filename (ps->filename, &first); + } + } + printf_filtered ("\n"); +} + +static int +file_matches (char *file, char *files[], int nfiles) +{ + int i; + + if (file != NULL && nfiles != 0) + { + for (i = 0; i < nfiles; i++) + { + if (strcmp (files[i], lbasename (file)) == 0) + return 1; + } + } + else if (nfiles == 0) + return 1; + return 0; +} + +/* Free any memory associated with a search. */ +void +free_search_symbols (struct symbol_search *symbols) +{ + struct symbol_search *p; + struct symbol_search *next; + + for (p = symbols; p != NULL; p = next) + { + next = p->next; + xfree (p); + } +} + +static void +do_free_search_symbols_cleanup (void *symbols) +{ + free_search_symbols (symbols); +} + +struct cleanup * +make_cleanup_free_search_symbols (struct symbol_search *symbols) +{ + return make_cleanup (do_free_search_symbols_cleanup, symbols); +} + +/* Helper function for sort_search_symbols and qsort. Can only + sort symbols, not minimal symbols. */ +static int +compare_search_syms (const void *sa, const void *sb) +{ + struct symbol_search **sym_a = (struct symbol_search **) sa; + struct symbol_search **sym_b = (struct symbol_search **) sb; + + return strcmp (SYMBOL_SOURCE_NAME ((*sym_a)->symbol), + SYMBOL_SOURCE_NAME ((*sym_b)->symbol)); +} + +/* Sort the ``nfound'' symbols in the list after prevtail. Leave + prevtail where it is, but update its next pointer to point to + the first of the sorted symbols. */ +static struct symbol_search * +sort_search_symbols (struct symbol_search *prevtail, int nfound) +{ + struct symbol_search **symbols, *symp, *old_next; + int i; + + symbols = (struct symbol_search **) xmalloc (sizeof (struct symbol_search *) + * nfound); + symp = prevtail->next; + for (i = 0; i < nfound; i++) + { + symbols[i] = symp; + symp = symp->next; + } + /* Generally NULL. */ + old_next = symp; + + qsort (symbols, nfound, sizeof (struct symbol_search *), + compare_search_syms); + + symp = prevtail; + for (i = 0; i < nfound; i++) + { + symp->next = symbols[i]; + symp = symp->next; + } + symp->next = old_next; + + xfree (symbols); + return symp; +} + +/* Search the symbol table for matches to the regular expression REGEXP, + returning the results in *MATCHES. + + Only symbols of KIND are searched: + FUNCTIONS_NAMESPACE - search all functions + TYPES_NAMESPACE - search all type names + METHODS_NAMESPACE - search all methods NOT IMPLEMENTED + VARIABLES_NAMESPACE - search all symbols, excluding functions, type names, + and constants (enums) + + free_search_symbols should be called when *MATCHES is no longer needed. + + The results are sorted locally; each symtab's global and static blocks are + separately alphabetized. + */ +void +search_symbols (char *regexp, namespace_enum kind, int nfiles, char *files[], + struct symbol_search **matches) +{ + register struct symtab *s; + register struct partial_symtab *ps; + register struct blockvector *bv; + struct blockvector *prev_bv = 0; + register struct block *b; + register int i = 0; + register int j; + register struct symbol *sym; + struct partial_symbol **psym; + struct objfile *objfile; + struct minimal_symbol *msymbol; + char *val; + int found_misc = 0; + static enum minimal_symbol_type types[] + = + {mst_data, mst_text, mst_abs, mst_unknown}; + static enum minimal_symbol_type types2[] + = + {mst_bss, mst_file_text, mst_abs, mst_unknown}; + static enum minimal_symbol_type types3[] + = + {mst_file_data, mst_solib_trampoline, mst_abs, mst_unknown}; + static enum minimal_symbol_type types4[] + = + {mst_file_bss, mst_text, mst_abs, mst_unknown}; + enum minimal_symbol_type ourtype; + enum minimal_symbol_type ourtype2; + enum minimal_symbol_type ourtype3; + enum minimal_symbol_type ourtype4; + struct symbol_search *sr; + struct symbol_search *psr; + struct symbol_search *tail; + struct cleanup *old_chain = NULL; + + if (kind < VARIABLES_NAMESPACE) + error ("must search on specific namespace"); + + ourtype = types[(int) (kind - VARIABLES_NAMESPACE)]; + ourtype2 = types2[(int) (kind - VARIABLES_NAMESPACE)]; + ourtype3 = types3[(int) (kind - VARIABLES_NAMESPACE)]; + ourtype4 = types4[(int) (kind - VARIABLES_NAMESPACE)]; + + sr = *matches = NULL; + tail = NULL; + + if (regexp != NULL) + { + /* Make sure spacing is right for C++ operators. + This is just a courtesy to make the matching less sensitive + to how many spaces the user leaves between 'operator' + and <TYPENAME> or <OPERATOR>. */ + char *opend; + char *opname = operator_chars (regexp, &opend); + if (*opname) + { + int fix = -1; /* -1 means ok; otherwise number of spaces needed. */ + if (isalpha (*opname) || *opname == '_' || *opname == '$') + { + /* There should 1 space between 'operator' and 'TYPENAME'. */ + if (opname[-1] != ' ' || opname[-2] == ' ') + fix = 1; + } + else + { + /* There should 0 spaces between 'operator' and 'OPERATOR'. */ + if (opname[-1] == ' ') + fix = 0; + } + /* If wrong number of spaces, fix it. */ + if (fix >= 0) + { + char *tmp = (char *) alloca (8 + fix + strlen (opname) + 1); + sprintf (tmp, "operator%.*s%s", fix, " ", opname); + regexp = tmp; + } + } + + if (0 != (val = re_comp (regexp))) + error ("Invalid regexp (%s): %s", val, regexp); + } + + /* Search through the partial symtabs *first* for all symbols + matching the regexp. That way we don't have to reproduce all of + the machinery below. */ + + ALL_PSYMTABS (objfile, ps) + { + struct partial_symbol **bound, **gbound, **sbound; + int keep_going = 1; + + if (ps->readin) + continue; + + gbound = objfile->global_psymbols.list + ps->globals_offset + ps->n_global_syms; + sbound = objfile->static_psymbols.list + ps->statics_offset + ps->n_static_syms; + bound = gbound; + + /* Go through all of the symbols stored in a partial + symtab in one loop. */ + psym = objfile->global_psymbols.list + ps->globals_offset; + while (keep_going) + { + if (psym >= bound) + { + if (bound == gbound && ps->n_static_syms != 0) + { + psym = objfile->static_psymbols.list + ps->statics_offset; + bound = sbound; + } + else + keep_going = 0; + continue; + } + else + { + QUIT; + + /* If it would match (logic taken from loop below) + load the file and go on to the next one */ + if (file_matches (ps->filename, files, nfiles) + && ((regexp == NULL || SYMBOL_MATCHES_REGEXP (*psym)) + && ((kind == VARIABLES_NAMESPACE && SYMBOL_CLASS (*psym) != LOC_TYPEDEF + && SYMBOL_CLASS (*psym) != LOC_BLOCK) + || (kind == FUNCTIONS_NAMESPACE && SYMBOL_CLASS (*psym) == LOC_BLOCK) + || (kind == TYPES_NAMESPACE && SYMBOL_CLASS (*psym) == LOC_TYPEDEF) + || (kind == METHODS_NAMESPACE && SYMBOL_CLASS (*psym) == LOC_BLOCK)))) + { + PSYMTAB_TO_SYMTAB (ps); + keep_going = 0; + } + } + psym++; + } + } + + /* Here, we search through the minimal symbol tables for functions + and variables that match, and force their symbols to be read. + This is in particular necessary for demangled variable names, + which are no longer put into the partial symbol tables. + The symbol will then be found during the scan of symtabs below. + + For functions, find_pc_symtab should succeed if we have debug info + for the function, for variables we have to call lookup_symbol + to determine if the variable has debug info. + If the lookup fails, set found_misc so that we will rescan to print + any matching symbols without debug info. + */ + + if (nfiles == 0 && (kind == VARIABLES_NAMESPACE || kind == FUNCTIONS_NAMESPACE)) + { + ALL_MSYMBOLS (objfile, msymbol) + { + if (MSYMBOL_TYPE (msymbol) == ourtype || + MSYMBOL_TYPE (msymbol) == ourtype2 || + MSYMBOL_TYPE (msymbol) == ourtype3 || + MSYMBOL_TYPE (msymbol) == ourtype4) + { + if (regexp == NULL || SYMBOL_MATCHES_REGEXP (msymbol)) + { + if (0 == find_pc_symtab (SYMBOL_VALUE_ADDRESS (msymbol))) + { + if (kind == FUNCTIONS_NAMESPACE + || lookup_symbol (SYMBOL_NAME (msymbol), + (struct block *) NULL, + VAR_NAMESPACE, + 0, (struct symtab **) NULL) == NULL) + found_misc = 1; + } + } + } + } + } + + ALL_SYMTABS (objfile, s) + { + bv = BLOCKVECTOR (s); + /* Often many files share a blockvector. + Scan each blockvector only once so that + we don't get every symbol many times. + It happens that the first symtab in the list + for any given blockvector is the main file. */ + if (bv != prev_bv) + for (i = GLOBAL_BLOCK; i <= STATIC_BLOCK; i++) + { + struct symbol_search *prevtail = tail; + int nfound = 0; + b = BLOCKVECTOR_BLOCK (bv, i); + ALL_BLOCK_SYMBOLS (b, j, sym) + { + QUIT; + if (file_matches (s->filename, files, nfiles) + && ((regexp == NULL || SYMBOL_MATCHES_REGEXP (sym)) + && ((kind == VARIABLES_NAMESPACE && SYMBOL_CLASS (sym) != LOC_TYPEDEF + && SYMBOL_CLASS (sym) != LOC_BLOCK + && SYMBOL_CLASS (sym) != LOC_CONST) + || (kind == FUNCTIONS_NAMESPACE && SYMBOL_CLASS (sym) == LOC_BLOCK) + || (kind == TYPES_NAMESPACE && SYMBOL_CLASS (sym) == LOC_TYPEDEF) + || (kind == METHODS_NAMESPACE && SYMBOL_CLASS (sym) == LOC_BLOCK)))) + { + /* match */ + psr = (struct symbol_search *) xmalloc (sizeof (struct symbol_search)); + psr->block = i; + psr->symtab = s; + psr->symbol = sym; + psr->msymbol = NULL; + psr->next = NULL; + if (tail == NULL) + sr = psr; + else + tail->next = psr; + tail = psr; + nfound ++; + } + } + if (nfound > 0) + { + if (prevtail == NULL) + { + struct symbol_search dummy; + + dummy.next = sr; + tail = sort_search_symbols (&dummy, nfound); + sr = dummy.next; + + old_chain = make_cleanup_free_search_symbols (sr); + } + else + tail = sort_search_symbols (prevtail, nfound); + } + } + prev_bv = bv; + } + + /* If there are no eyes, avoid all contact. I mean, if there are + no debug symbols, then print directly from the msymbol_vector. */ + + if (found_misc || kind != FUNCTIONS_NAMESPACE) + { + ALL_MSYMBOLS (objfile, msymbol) + { + if (MSYMBOL_TYPE (msymbol) == ourtype || + MSYMBOL_TYPE (msymbol) == ourtype2 || + MSYMBOL_TYPE (msymbol) == ourtype3 || + MSYMBOL_TYPE (msymbol) == ourtype4) + { + if (regexp == NULL || SYMBOL_MATCHES_REGEXP (msymbol)) + { + /* Functions: Look up by address. */ + if (kind != FUNCTIONS_NAMESPACE || + (0 == find_pc_symtab (SYMBOL_VALUE_ADDRESS (msymbol)))) + { + /* Variables/Absolutes: Look up by name */ + if (lookup_symbol (SYMBOL_NAME (msymbol), + (struct block *) NULL, VAR_NAMESPACE, + 0, (struct symtab **) NULL) == NULL) + { + /* match */ + psr = (struct symbol_search *) xmalloc (sizeof (struct symbol_search)); + psr->block = i; + psr->msymbol = msymbol; + psr->symtab = NULL; + psr->symbol = NULL; + psr->next = NULL; + if (tail == NULL) + { + sr = psr; + old_chain = make_cleanup_free_search_symbols (sr); + } + else + tail->next = psr; + tail = psr; + } + } + } + } + } + } + + *matches = sr; + if (sr != NULL) + discard_cleanups (old_chain); +} + +/* Helper function for symtab_symbol_info, this function uses + the data returned from search_symbols() to print information + regarding the match to gdb_stdout. + */ +static void +print_symbol_info (namespace_enum kind, struct symtab *s, struct symbol *sym, + int block, char *last) +{ + if (last == NULL || strcmp (last, s->filename) != 0) + { + fputs_filtered ("\nFile ", gdb_stdout); + fputs_filtered (s->filename, gdb_stdout); + fputs_filtered (":\n", gdb_stdout); + } + + if (kind != TYPES_NAMESPACE && block == STATIC_BLOCK) + printf_filtered ("static "); + + /* Typedef that is not a C++ class */ + if (kind == TYPES_NAMESPACE + && SYMBOL_NAMESPACE (sym) != STRUCT_NAMESPACE) + typedef_print (SYMBOL_TYPE (sym), sym, gdb_stdout); + /* variable, func, or typedef-that-is-c++-class */ + else if (kind < TYPES_NAMESPACE || + (kind == TYPES_NAMESPACE && + SYMBOL_NAMESPACE (sym) == STRUCT_NAMESPACE)) + { + type_print (SYMBOL_TYPE (sym), + (SYMBOL_CLASS (sym) == LOC_TYPEDEF + ? "" : SYMBOL_SOURCE_NAME (sym)), + gdb_stdout, 0); + + printf_filtered (";\n"); + } + else + { +#if 0 + /* Tiemann says: "info methods was never implemented." */ + char *demangled_name; + c_type_print_base (TYPE_FN_FIELD_TYPE (t, block), + gdb_stdout, 0, 0); + c_type_print_varspec_prefix (TYPE_FN_FIELD_TYPE (t, block), + gdb_stdout, 0); + if (TYPE_FN_FIELD_STUB (t, block)) + check_stub_method (TYPE_DOMAIN_TYPE (type), j, block); + demangled_name = + cplus_demangle (TYPE_FN_FIELD_PHYSNAME (t, block), + DMGL_ANSI | DMGL_PARAMS); + if (demangled_name == NULL) + fprintf_filtered (stream, "<badly mangled name %s>", + TYPE_FN_FIELD_PHYSNAME (t, block)); + else + { + fputs_filtered (demangled_name, stream); + xfree (demangled_name); + } +#endif + } +} + +/* This help function for symtab_symbol_info() prints information + for non-debugging symbols to gdb_stdout. + */ +static void +print_msymbol_info (struct minimal_symbol *msymbol) +{ + char *tmp; + + if (TARGET_ADDR_BIT <= 32) + tmp = local_hex_string_custom (SYMBOL_VALUE_ADDRESS (msymbol) + & (CORE_ADDR) 0xffffffff, + "08l"); + else + tmp = local_hex_string_custom (SYMBOL_VALUE_ADDRESS (msymbol), + "016l"); + printf_filtered ("%s %s\n", + tmp, SYMBOL_SOURCE_NAME (msymbol)); +} + +/* This is the guts of the commands "info functions", "info types", and + "info variables". It calls search_symbols to find all matches and then + print_[m]symbol_info to print out some useful information about the + matches. + */ +static void +symtab_symbol_info (char *regexp, namespace_enum kind, int from_tty) +{ + static char *classnames[] + = + {"variable", "function", "type", "method"}; + struct symbol_search *symbols; + struct symbol_search *p; + struct cleanup *old_chain; + char *last_filename = NULL; + int first = 1; + + /* must make sure that if we're interrupted, symbols gets freed */ + search_symbols (regexp, kind, 0, (char **) NULL, &symbols); + old_chain = make_cleanup_free_search_symbols (symbols); + + printf_filtered (regexp + ? "All %ss matching regular expression \"%s\":\n" + : "All defined %ss:\n", + classnames[(int) (kind - VARIABLES_NAMESPACE)], regexp); + + for (p = symbols; p != NULL; p = p->next) + { + QUIT; + + if (p->msymbol != NULL) + { + if (first) + { + printf_filtered ("\nNon-debugging symbols:\n"); + first = 0; + } + print_msymbol_info (p->msymbol); + } + else + { + print_symbol_info (kind, + p->symtab, + p->symbol, + p->block, + last_filename); + last_filename = p->symtab->filename; + } + } + + do_cleanups (old_chain); +} + +static void +variables_info (char *regexp, int from_tty) +{ + symtab_symbol_info (regexp, VARIABLES_NAMESPACE, from_tty); +} + +static void +functions_info (char *regexp, int from_tty) +{ + symtab_symbol_info (regexp, FUNCTIONS_NAMESPACE, from_tty); +} + + +static void +types_info (char *regexp, int from_tty) +{ + symtab_symbol_info (regexp, TYPES_NAMESPACE, from_tty); +} + +#if 0 +/* Tiemann says: "info methods was never implemented." */ +static void +methods_info (char *regexp) +{ + symtab_symbol_info (regexp, METHODS_NAMESPACE, 0, from_tty); +} +#endif /* 0 */ + +/* Breakpoint all functions matching regular expression. */ + +void +rbreak_command_wrapper (char *regexp, int from_tty) +{ + rbreak_command (regexp, from_tty); +} + +static void +rbreak_command (char *regexp, int from_tty) +{ + struct symbol_search *ss; + struct symbol_search *p; + struct cleanup *old_chain; + + search_symbols (regexp, FUNCTIONS_NAMESPACE, 0, (char **) NULL, &ss); + old_chain = make_cleanup_free_search_symbols (ss); + + for (p = ss; p != NULL; p = p->next) + { + if (p->msymbol == NULL) + { + char *string = (char *) alloca (strlen (p->symtab->filename) + + strlen (SYMBOL_NAME (p->symbol)) + + 4); + strcpy (string, p->symtab->filename); + strcat (string, ":'"); + strcat (string, SYMBOL_NAME (p->symbol)); + strcat (string, "'"); + break_command (string, from_tty); + print_symbol_info (FUNCTIONS_NAMESPACE, + p->symtab, + p->symbol, + p->block, + p->symtab->filename); + } + else + { + break_command (SYMBOL_NAME (p->msymbol), from_tty); + printf_filtered ("<function, no debug info> %s;\n", + SYMBOL_SOURCE_NAME (p->msymbol)); + } + } + + do_cleanups (old_chain); +} + + +/* Return Nonzero if block a is lexically nested within block b, + or if a and b have the same pc range. + Return zero otherwise. */ +int +contained_in (struct block *a, struct block *b) +{ + if (!a || !b) + return 0; + return BLOCK_START (a) >= BLOCK_START (b) + && BLOCK_END (a) <= BLOCK_END (b); +} + + +/* Helper routine for make_symbol_completion_list. */ + +static int return_val_size; +static int return_val_index; +static char **return_val; + +#define COMPLETION_LIST_ADD_SYMBOL(symbol, sym_text, len, text, word) \ + do { \ + if (SYMBOL_DEMANGLED_NAME (symbol) != NULL) \ + /* Put only the mangled name on the list. */ \ + /* Advantage: "b foo<TAB>" completes to "b foo(int, int)" */ \ + /* Disadvantage: "b foo__i<TAB>" doesn't complete. */ \ + completion_list_add_name \ + (SYMBOL_DEMANGLED_NAME (symbol), (sym_text), (len), (text), (word)); \ + else \ + completion_list_add_name \ + (SYMBOL_NAME (symbol), (sym_text), (len), (text), (word)); \ + } while (0) + +/* Test to see if the symbol specified by SYMNAME (which is already + demangled for C++ symbols) matches SYM_TEXT in the first SYM_TEXT_LEN + characters. If so, add it to the current completion list. */ + +static void +completion_list_add_name (char *symname, char *sym_text, int sym_text_len, + char *text, char *word) +{ + int newsize; + int i; + + /* clip symbols that cannot match */ + + if (strncmp (symname, sym_text, sym_text_len) != 0) + { + return; + } + + /* We have a match for a completion, so add SYMNAME to the current list + of matches. Note that the name is moved to freshly malloc'd space. */ + + { + char *new; + if (word == sym_text) + { + new = xmalloc (strlen (symname) + 5); + strcpy (new, symname); + } + else if (word > sym_text) + { + /* Return some portion of symname. */ + new = xmalloc (strlen (symname) + 5); + strcpy (new, symname + (word - sym_text)); + } + else + { + /* Return some of SYM_TEXT plus symname. */ + new = xmalloc (strlen (symname) + (sym_text - word) + 5); + strncpy (new, word, sym_text - word); + new[sym_text - word] = '\0'; + strcat (new, symname); + } + + if (return_val_index + 3 > return_val_size) + { + newsize = (return_val_size *= 2) * sizeof (char *); + return_val = (char **) xrealloc ((char *) return_val, newsize); + } + return_val[return_val_index++] = new; + return_val[return_val_index] = NULL; + } +} + +/* Return a NULL terminated array of all symbols (regardless of class) + which begin by matching TEXT. If the answer is no symbols, then + the return value is an array which contains only a NULL pointer. + + Problem: All of the symbols have to be copied because readline frees them. + I'm not going to worry about this; hopefully there won't be that many. */ + +char ** +make_symbol_completion_list (char *text, char *word) +{ + register struct symbol *sym; + register struct symtab *s; + register struct partial_symtab *ps; + register struct minimal_symbol *msymbol; + register struct objfile *objfile; + register struct block *b, *surrounding_static_block = 0; + register int i, j; + struct partial_symbol **psym; + /* The symbol we are completing on. Points in same buffer as text. */ + char *sym_text; + /* Length of sym_text. */ + int sym_text_len; + + /* Now look for the symbol we are supposed to complete on. + FIXME: This should be language-specific. */ + { + char *p; + char quote_found; + char *quote_pos = NULL; + + /* First see if this is a quoted string. */ + quote_found = '\0'; + for (p = text; *p != '\0'; ++p) + { + if (quote_found != '\0') + { + if (*p == quote_found) + /* Found close quote. */ + quote_found = '\0'; + else if (*p == '\\' && p[1] == quote_found) + /* A backslash followed by the quote character + doesn't end the string. */ + ++p; + } + else if (*p == '\'' || *p == '"') + { + quote_found = *p; + quote_pos = p; + } + } + if (quote_found == '\'') + /* A string within single quotes can be a symbol, so complete on it. */ + sym_text = quote_pos + 1; + else if (quote_found == '"') + /* A double-quoted string is never a symbol, nor does it make sense + to complete it any other way. */ + { + return_val = (char **) xmalloc (sizeof (char *)); + return_val[0] = NULL; + return return_val; + } + else + { + /* It is not a quoted string. Break it based on the characters + which are in symbols. */ + while (p > text) + { + if (isalnum (p[-1]) || p[-1] == '_' || p[-1] == '\0') + --p; + else + break; + } + sym_text = p; + } + } + + sym_text_len = strlen (sym_text); + + return_val_size = 100; + return_val_index = 0; + return_val = (char **) xmalloc ((return_val_size + 1) * sizeof (char *)); + return_val[0] = NULL; + + /* Look through the partial symtabs for all symbols which begin + by matching SYM_TEXT. Add each one that you find to the list. */ + + ALL_PSYMTABS (objfile, ps) + { + /* If the psymtab's been read in we'll get it when we search + through the blockvector. */ + if (ps->readin) + continue; + + for (psym = objfile->global_psymbols.list + ps->globals_offset; + psym < (objfile->global_psymbols.list + ps->globals_offset + + ps->n_global_syms); + psym++) + { + /* If interrupted, then quit. */ + QUIT; + COMPLETION_LIST_ADD_SYMBOL (*psym, sym_text, sym_text_len, text, word); + } + + for (psym = objfile->static_psymbols.list + ps->statics_offset; + psym < (objfile->static_psymbols.list + ps->statics_offset + + ps->n_static_syms); + psym++) + { + QUIT; + COMPLETION_LIST_ADD_SYMBOL (*psym, sym_text, sym_text_len, text, word); + } + } + + /* At this point scan through the misc symbol vectors and add each + symbol you find to the list. Eventually we want to ignore + anything that isn't a text symbol (everything else will be + handled by the psymtab code above). */ + + ALL_MSYMBOLS (objfile, msymbol) + { + QUIT; + COMPLETION_LIST_ADD_SYMBOL (msymbol, sym_text, sym_text_len, text, word); + } + + /* Search upwards from currently selected frame (so that we can + complete on local vars. */ + + for (b = get_selected_block (0); b != NULL; b = BLOCK_SUPERBLOCK (b)) + { + if (!BLOCK_SUPERBLOCK (b)) + { + surrounding_static_block = b; /* For elmin of dups */ + } + + /* Also catch fields of types defined in this places which match our + text string. Only complete on types visible from current context. */ + + ALL_BLOCK_SYMBOLS (b, i, sym) + { + COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word); + if (SYMBOL_CLASS (sym) == LOC_TYPEDEF) + { + struct type *t = SYMBOL_TYPE (sym); + enum type_code c = TYPE_CODE (t); + + if (c == TYPE_CODE_UNION || c == TYPE_CODE_STRUCT) + { + for (j = TYPE_N_BASECLASSES (t); j < TYPE_NFIELDS (t); j++) + { + if (TYPE_FIELD_NAME (t, j)) + { + completion_list_add_name (TYPE_FIELD_NAME (t, j), + sym_text, sym_text_len, text, word); + } + } + } + } + } + } + + /* Go through the symtabs and check the externs and statics for + symbols which match. */ + + ALL_SYMTABS (objfile, s) + { + QUIT; + b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK); + ALL_BLOCK_SYMBOLS (b, i, sym) + { + COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word); + } + } + + ALL_SYMTABS (objfile, s) + { + QUIT; + b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK); + /* Don't do this block twice. */ + if (b == surrounding_static_block) + continue; + ALL_BLOCK_SYMBOLS (b, i, sym) + { + COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word); + } + } + + return (return_val); +} + +/* Like make_symbol_completion_list, but returns a list of symbols + defined in a source file FILE. */ + +char ** +make_file_symbol_completion_list (char *text, char *word, char *srcfile) +{ + register struct symbol *sym; + register struct symtab *s; + register struct block *b; + register int i; + /* The symbol we are completing on. Points in same buffer as text. */ + char *sym_text; + /* Length of sym_text. */ + int sym_text_len; + + /* Now look for the symbol we are supposed to complete on. + FIXME: This should be language-specific. */ + { + char *p; + char quote_found; + char *quote_pos = NULL; + + /* First see if this is a quoted string. */ + quote_found = '\0'; + for (p = text; *p != '\0'; ++p) + { + if (quote_found != '\0') + { + if (*p == quote_found) + /* Found close quote. */ + quote_found = '\0'; + else if (*p == '\\' && p[1] == quote_found) + /* A backslash followed by the quote character + doesn't end the string. */ + ++p; + } + else if (*p == '\'' || *p == '"') + { + quote_found = *p; + quote_pos = p; + } + } + if (quote_found == '\'') + /* A string within single quotes can be a symbol, so complete on it. */ + sym_text = quote_pos + 1; + else if (quote_found == '"') + /* A double-quoted string is never a symbol, nor does it make sense + to complete it any other way. */ + { + return_val = (char **) xmalloc (sizeof (char *)); + return_val[0] = NULL; + return return_val; + } + else + { + /* It is not a quoted string. Break it based on the characters + which are in symbols. */ + while (p > text) + { + if (isalnum (p[-1]) || p[-1] == '_' || p[-1] == '\0') + --p; + else + break; + } + sym_text = p; + } + } + + sym_text_len = strlen (sym_text); + + return_val_size = 10; + return_val_index = 0; + return_val = (char **) xmalloc ((return_val_size + 1) * sizeof (char *)); + return_val[0] = NULL; + + /* Find the symtab for SRCFILE (this loads it if it was not yet read + in). */ + s = lookup_symtab (srcfile); + if (s == NULL) + { + /* Maybe they typed the file with leading directories, while the + symbol tables record only its basename. */ + const char *tail = lbasename (srcfile); + + if (tail > srcfile) + s = lookup_symtab (tail); + } + + /* If we have no symtab for that file, return an empty list. */ + if (s == NULL) + return (return_val); + + /* Go through this symtab and check the externs and statics for + symbols which match. */ + + b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK); + ALL_BLOCK_SYMBOLS (b, i, sym) + { + COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word); + } + + b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK); + ALL_BLOCK_SYMBOLS (b, i, sym) + { + COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word); + } + + return (return_val); +} + +/* A helper function for make_source_files_completion_list. It adds + another file name to a list of possible completions, growing the + list as necessary. */ + +static void +add_filename_to_list (const char *fname, char *text, char *word, + char ***list, int *list_used, int *list_alloced) +{ + char *new; + size_t fnlen = strlen (fname); + + if (*list_used + 1 >= *list_alloced) + { + *list_alloced *= 2; + *list = (char **) xrealloc ((char *) *list, + *list_alloced * sizeof (char *)); + } + + if (word == text) + { + /* Return exactly fname. */ + new = xmalloc (fnlen + 5); + strcpy (new, fname); + } + else if (word > text) + { + /* Return some portion of fname. */ + new = xmalloc (fnlen + 5); + strcpy (new, fname + (word - text)); + } + else + { + /* Return some of TEXT plus fname. */ + new = xmalloc (fnlen + (text - word) + 5); + strncpy (new, word, text - word); + new[text - word] = '\0'; + strcat (new, fname); + } + (*list)[*list_used] = new; + (*list)[++*list_used] = NULL; +} + +static int +not_interesting_fname (const char *fname) +{ + static const char *illegal_aliens[] = { + "_globals_", /* inserted by coff_symtab_read */ + NULL + }; + int i; + + for (i = 0; illegal_aliens[i]; i++) + { + if (strcmp (fname, illegal_aliens[i]) == 0) + return 1; + } + return 0; +} + +/* Return a NULL terminated array of all source files whose names + begin with matching TEXT. The file names are looked up in the + symbol tables of this program. If the answer is no matchess, then + the return value is an array which contains only a NULL pointer. */ + +char ** +make_source_files_completion_list (char *text, char *word) +{ + register struct symtab *s; + register struct partial_symtab *ps; + register struct objfile *objfile; + int first = 1; + int list_alloced = 1; + int list_used = 0; + size_t text_len = strlen (text); + char **list = (char **) xmalloc (list_alloced * sizeof (char *)); + const char *base_name; + + list[0] = NULL; + + if (!have_full_symbols () && !have_partial_symbols ()) + return list; + + ALL_SYMTABS (objfile, s) + { + if (not_interesting_fname (s->filename)) + continue; + if (!filename_seen (s->filename, 1, &first) +#if HAVE_DOS_BASED_FILE_SYSTEM + && strncasecmp (s->filename, text, text_len) == 0 +#else + && strncmp (s->filename, text, text_len) == 0 +#endif + ) + { + /* This file matches for a completion; add it to the current + list of matches. */ + add_filename_to_list (s->filename, text, word, + &list, &list_used, &list_alloced); + } + else + { + /* NOTE: We allow the user to type a base name when the + debug info records leading directories, but not the other + way around. This is what subroutines of breakpoint + command do when they parse file names. */ + base_name = lbasename (s->filename); + if (base_name != s->filename + && !filename_seen (base_name, 1, &first) +#if HAVE_DOS_BASED_FILE_SYSTEM + && strncasecmp (base_name, text, text_len) == 0 +#else + && strncmp (base_name, text, text_len) == 0 +#endif + ) + add_filename_to_list (base_name, text, word, + &list, &list_used, &list_alloced); + } + } + + ALL_PSYMTABS (objfile, ps) + { + if (not_interesting_fname (ps->filename)) + continue; + if (!ps->readin) + { + if (!filename_seen (ps->filename, 1, &first) +#if HAVE_DOS_BASED_FILE_SYSTEM + && strncasecmp (ps->filename, text, text_len) == 0 +#else + && strncmp (ps->filename, text, text_len) == 0 +#endif + ) + { + /* This file matches for a completion; add it to the + current list of matches. */ + add_filename_to_list (ps->filename, text, word, + &list, &list_used, &list_alloced); + + } + else + { + base_name = lbasename (ps->filename); + if (base_name != ps->filename + && !filename_seen (base_name, 1, &first) +#if HAVE_DOS_BASED_FILE_SYSTEM + && strncasecmp (base_name, text, text_len) == 0 +#else + && strncmp (base_name, text, text_len) == 0 +#endif + ) + add_filename_to_list (base_name, text, word, + &list, &list_used, &list_alloced); + } + } + } + + return list; +} + +/* Determine if PC is in the prologue of a function. The prologue is the area + between the first instruction of a function, and the first executable line. + Returns 1 if PC *might* be in prologue, 0 if definately *not* in prologue. + + If non-zero, func_start is where we think the prologue starts, possibly + by previous examination of symbol table information. + */ + +int +in_prologue (CORE_ADDR pc, CORE_ADDR func_start) +{ + struct symtab_and_line sal; + CORE_ADDR func_addr, func_end; + + /* We have several sources of information we can consult to figure + this out. + - Compilers usually emit line number info that marks the prologue + as its own "source line". So the ending address of that "line" + is the end of the prologue. If available, this is the most + reliable method. + - The minimal symbols and partial symbols, which can usually tell + us the starting and ending addresses of a function. + - If we know the function's start address, we can call the + architecture-defined SKIP_PROLOGUE function to analyze the + instruction stream and guess where the prologue ends. + - Our `func_start' argument; if non-zero, this is the caller's + best guess as to the function's entry point. At the time of + this writing, handle_inferior_event doesn't get this right, so + it should be our last resort. */ + + /* Consult the partial symbol table, to find which function + the PC is in. */ + if (! find_pc_partial_function (pc, NULL, &func_addr, &func_end)) + { + CORE_ADDR prologue_end; + + /* We don't even have minsym information, so fall back to using + func_start, if given. */ + if (! func_start) + return 1; /* We *might* be in a prologue. */ + + prologue_end = SKIP_PROLOGUE (func_start); + + return func_start <= pc && pc < prologue_end; + } + + /* If we have line number information for the function, that's + usually pretty reliable. */ + sal = find_pc_line (func_addr, 0); + + /* Now sal describes the source line at the function's entry point, + which (by convention) is the prologue. The end of that "line", + sal.end, is the end of the prologue. + + Note that, for functions whose source code is all on a single + line, the line number information doesn't always end up this way. + So we must verify that our purported end-of-prologue address is + *within* the function, not at its start or end. */ + if (sal.line == 0 + || sal.end <= func_addr + || func_end <= sal.end) + { + /* We don't have any good line number info, so use the minsym + information, together with the architecture-specific prologue + scanning code. */ + CORE_ADDR prologue_end = SKIP_PROLOGUE (func_addr); + + return func_addr <= pc && pc < prologue_end; + } + + /* We have line number info, and it looks good. */ + return func_addr <= pc && pc < sal.end; +} + + +/* Begin overload resolution functions */ + +static char * +remove_params (const char *demangled_name) +{ + const char *argp; + char *new_name; + int depth; + + if (demangled_name == NULL) + return NULL; + + /* First find the end of the arg list. */ + argp = strrchr (demangled_name, ')'); + if (argp == NULL) + return NULL; + + /* Back up to the beginning. */ + depth = 1; + + while (argp-- > demangled_name) + { + if (*argp == ')') + depth ++; + else if (*argp == '(') + { + depth --; + + if (depth == 0) + break; + } + } + if (depth != 0) + internal_error (__FILE__, __LINE__, + "bad demangled name %s\n", demangled_name); + while (argp[-1] == ' ' && argp > demangled_name) + argp --; + + new_name = xmalloc (argp - demangled_name + 1); + memcpy (new_name, demangled_name, argp - demangled_name); + new_name[argp - demangled_name] = '\0'; + return new_name; +} + +/* Helper routine for make_symbol_completion_list. */ + +static int sym_return_val_size; +static int sym_return_val_index; +static struct symbol **sym_return_val; + +/* Test to see if the symbol specified by SYMNAME (which is already + demangled for C++ symbols) matches SYM_TEXT in the first SYM_TEXT_LEN + characters. If so, add it to the current completion list. */ + +static void +overload_list_add_symbol (struct symbol *sym, char *oload_name) +{ + int newsize; + int i; + char *sym_name; + + /* If there is no type information, we can't do anything, so skip */ + if (SYMBOL_TYPE (sym) == NULL) + return; + + /* skip any symbols that we've already considered. */ + for (i = 0; i < sym_return_val_index; ++i) + if (!strcmp (SYMBOL_NAME (sym), SYMBOL_NAME (sym_return_val[i]))) + return; + + /* Get the demangled name without parameters */ + sym_name = remove_params (SYMBOL_DEMANGLED_NAME (sym)); + if (!sym_name) + return; + + /* skip symbols that cannot match */ + if (strcmp (sym_name, oload_name) != 0) + { + xfree (sym_name); + return; + } + + xfree (sym_name); + + /* We have a match for an overload instance, so add SYM to the current list + * of overload instances */ + if (sym_return_val_index + 3 > sym_return_val_size) + { + newsize = (sym_return_val_size *= 2) * sizeof (struct symbol *); + sym_return_val = (struct symbol **) xrealloc ((char *) sym_return_val, newsize); + } + sym_return_val[sym_return_val_index++] = sym; + sym_return_val[sym_return_val_index] = NULL; +} + +/* Return a null-terminated list of pointers to function symbols that + * match name of the supplied symbol FSYM. + * This is used in finding all overloaded instances of a function name. + * This has been modified from make_symbol_completion_list. */ + + +struct symbol ** +make_symbol_overload_list (struct symbol *fsym) +{ + register struct symbol *sym; + register struct symtab *s; + register struct partial_symtab *ps; + register struct objfile *objfile; + register struct block *b, *surrounding_static_block = 0; + register int i; + /* The name we are completing on. */ + char *oload_name = NULL; + /* Length of name. */ + int oload_name_len = 0; + + /* Look for the symbol we are supposed to complete on. */ + + oload_name = remove_params (SYMBOL_DEMANGLED_NAME (fsym)); + if (!oload_name) + { + sym_return_val_size = 1; + sym_return_val = (struct symbol **) xmalloc (2 * sizeof (struct symbol *)); + sym_return_val[0] = fsym; + sym_return_val[1] = NULL; + + return sym_return_val; + } + oload_name_len = strlen (oload_name); + + sym_return_val_size = 100; + sym_return_val_index = 0; + sym_return_val = (struct symbol **) xmalloc ((sym_return_val_size + 1) * sizeof (struct symbol *)); + sym_return_val[0] = NULL; + + /* Look through the partial symtabs for all symbols which begin + by matching OLOAD_NAME. Make sure we read that symbol table in. */ + + ALL_PSYMTABS (objfile, ps) + { + struct partial_symbol **psym; + + /* If the psymtab's been read in we'll get it when we search + through the blockvector. */ + if (ps->readin) + continue; + + for (psym = objfile->global_psymbols.list + ps->globals_offset; + psym < (objfile->global_psymbols.list + ps->globals_offset + + ps->n_global_syms); + psym++) + { + /* If interrupted, then quit. */ + QUIT; + /* This will cause the symbol table to be read if it has not yet been */ + s = PSYMTAB_TO_SYMTAB (ps); + } + + for (psym = objfile->static_psymbols.list + ps->statics_offset; + psym < (objfile->static_psymbols.list + ps->statics_offset + + ps->n_static_syms); + psym++) + { + QUIT; + /* This will cause the symbol table to be read if it has not yet been */ + s = PSYMTAB_TO_SYMTAB (ps); + } + } + + /* Search upwards from currently selected frame (so that we can + complete on local vars. */ + + for (b = get_selected_block (0); b != NULL; b = BLOCK_SUPERBLOCK (b)) + { + if (!BLOCK_SUPERBLOCK (b)) + { + surrounding_static_block = b; /* For elimination of dups */ + } + + /* Also catch fields of types defined in this places which match our + text string. Only complete on types visible from current context. */ + + ALL_BLOCK_SYMBOLS (b, i, sym) + { + overload_list_add_symbol (sym, oload_name); + } + } + + /* Go through the symtabs and check the externs and statics for + symbols which match. */ + + ALL_SYMTABS (objfile, s) + { + QUIT; + b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK); + ALL_BLOCK_SYMBOLS (b, i, sym) + { + overload_list_add_symbol (sym, oload_name); + } + } + + ALL_SYMTABS (objfile, s) + { + QUIT; + b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK); + /* Don't do this block twice. */ + if (b == surrounding_static_block) + continue; + ALL_BLOCK_SYMBOLS (b, i, sym) + { + overload_list_add_symbol (sym, oload_name); + } + } + + xfree (oload_name); + + return (sym_return_val); +} + +/* End of overload resolution functions */ + +struct symtabs_and_lines +decode_line_spec (char *string, int funfirstline) +{ + struct symtabs_and_lines sals; + struct symtab_and_line cursal; + + if (string == 0) + error ("Empty line specification."); + + /* We use whatever is set as the current source line. We do not try + and get a default or it will recursively call us! */ + cursal = get_current_source_symtab_and_line (); + + sals = decode_line_1 (&string, funfirstline, + cursal.symtab, cursal.line, + (char ***) NULL); + + if (*string) + error ("Junk at end of line specification: %s", string); + return sals; +} + +/* Track MAIN */ +static char *name_of_main; + +void +set_main_name (const char *name) +{ + if (name_of_main != NULL) + { + xfree (name_of_main); + name_of_main = NULL; + } + if (name != NULL) + { + name_of_main = xstrdup (name); + } +} + +char * +main_name (void) +{ + if (name_of_main != NULL) + return name_of_main; + else + return "main"; +} + + +void +_initialize_symtab (void) +{ + add_info ("variables", variables_info, + "All global and static variable names, or those matching REGEXP."); + if (dbx_commands) + add_com ("whereis", class_info, variables_info, + "All global and static variable names, or those matching REGEXP."); + + add_info ("functions", functions_info, + "All function names, or those matching REGEXP."); + + + /* FIXME: This command has at least the following problems: + 1. It prints builtin types (in a very strange and confusing fashion). + 2. It doesn't print right, e.g. with + typedef struct foo *FOO + type_print prints "FOO" when we want to make it (in this situation) + print "struct foo *". + I also think "ptype" or "whatis" is more likely to be useful (but if + there is much disagreement "info types" can be fixed). */ + add_info ("types", types_info, + "All type names, or those matching REGEXP."); + +#if 0 + add_info ("methods", methods_info, + "All method names, or those matching REGEXP::REGEXP.\n\ +If the class qualifier is omitted, it is assumed to be the current scope.\n\ +If the first REGEXP is omitted, then all methods matching the second REGEXP\n\ +are listed."); +#endif + add_info ("sources", sources_info, + "Source files in the program."); + + add_com ("rbreak", class_breakpoint, rbreak_command, + "Set a breakpoint for all functions matching REGEXP."); + + if (xdb_commands) + { + add_com ("lf", class_info, sources_info, "Source files in the program"); + add_com ("lg", class_info, variables_info, + "All global and static variable names, or those matching REGEXP."); + } + + /* Initialize the one built-in type that isn't language dependent... */ + builtin_type_error = init_type (TYPE_CODE_ERROR, 0, 0, + "<unknown type>", (struct objfile *) NULL); +} diff --git a/gdb/symtab.h b/gdb/symtab.h new file mode 100644 index 0000000..a78607d --- /dev/null +++ b/gdb/symtab.h @@ -0,0 +1,1414 @@ +/* Symbol table definitions for GDB. + Copyright 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, + 1997, 1998, 1999, 2000, 2001, 2002 + 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 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#if !defined (SYMTAB_H) +#define SYMTAB_H 1 + +/* Opaque declarations. */ +struct obstack; + +/* Don't do this; it means that if some .o's are compiled with GNU C + and some are not (easy to do accidentally the way we configure + things; also it is a pain to have to "make clean" every time you + want to switch compilers), then GDB dies a horrible death. */ +/* GNU C supports enums that are bitfields. Some compilers don't. */ +#if 0 && defined(__GNUC__) && !defined(BYTE_BITFIELD) +#define BYTE_BITFIELD :8; +#else +#define BYTE_BITFIELD /*nothing */ +#endif + +/* Define a structure for the information that is common to all symbol types, + including minimal symbols, partial symbols, and full symbols. In a + multilanguage environment, some language specific information may need to + be recorded along with each symbol. + + These fields are ordered to encourage good packing, since we frequently + have tens or hundreds of thousands of these. */ + +struct general_symbol_info +{ + /* Name of the symbol. This is a required field. Storage for the name is + allocated on the psymbol_obstack or symbol_obstack for the associated + objfile. */ + + char *name; + + /* Value of the symbol. Which member of this union to use, and what + it means, depends on what kind of symbol this is and its + SYMBOL_CLASS. See comments there for more details. All of these + are in host byte order (though what they point to might be in + target byte order, e.g. LOC_CONST_BYTES). */ + + union + { + /* The fact that this is a long not a LONGEST mainly limits the + range of a LOC_CONST. Since LOC_CONST_BYTES exists, I'm not + sure that is a big deal. */ + long ivalue; + + struct block *block; + + char *bytes; + + CORE_ADDR address; + + /* for opaque typedef struct chain */ + + struct symbol *chain; + } + value; + + /* Since one and only one language can apply, wrap the language specific + information inside a union. */ + + union + { + struct cplus_specific /* For C++ */ + /* and Java */ + { + char *demangled_name; + } + cplus_specific; +#if 0 +/* OBSOLETE struct chill_specific *//* For Chill */ + /* OBSOLETE { */ + /* OBSOLETE char *demangled_name; */ + /* OBSOLETE } */ + /* OBSOLETE chill_specific; */ +#endif + } + language_specific; + + /* Record the source code language that applies to this symbol. + This is used to select one of the fields from the language specific + union above. */ + + enum language language BYTE_BITFIELD; + + /* Which section is this symbol in? This is an index into + section_offsets for this objfile. Negative means that the symbol + does not get relocated relative to a section. + Disclaimer: currently this is just used for xcoff, so don't + expect all symbol-reading code to set it correctly (the ELF code + also tries to set it correctly). */ + + short section; + + /* The bfd section associated with this symbol. */ + + asection *bfd_section; +}; + +extern CORE_ADDR symbol_overlayed_address (CORE_ADDR, asection *); + +#define SYMBOL_NAME(symbol) (symbol)->ginfo.name +#define SYMBOL_VALUE(symbol) (symbol)->ginfo.value.ivalue +#define SYMBOL_VALUE_ADDRESS(symbol) (symbol)->ginfo.value.address +#define SYMBOL_VALUE_BYTES(symbol) (symbol)->ginfo.value.bytes +#define SYMBOL_BLOCK_VALUE(symbol) (symbol)->ginfo.value.block +#define SYMBOL_VALUE_CHAIN(symbol) (symbol)->ginfo.value.chain +#define SYMBOL_LANGUAGE(symbol) (symbol)->ginfo.language +#define SYMBOL_SECTION(symbol) (symbol)->ginfo.section +#define SYMBOL_BFD_SECTION(symbol) (symbol)->ginfo.bfd_section + +#define SYMBOL_CPLUS_DEMANGLED_NAME(symbol) \ + (symbol)->ginfo.language_specific.cplus_specific.demangled_name + +/* Macro that initializes the language dependent portion of a symbol + depending upon the language for the symbol. */ + +#define SYMBOL_INIT_LANGUAGE_SPECIFIC(symbol,language) \ + do { \ + SYMBOL_LANGUAGE (symbol) = language; \ + if (SYMBOL_LANGUAGE (symbol) == language_cplus \ + || SYMBOL_LANGUAGE (symbol) == language_java \ + ) \ + { \ + SYMBOL_CPLUS_DEMANGLED_NAME (symbol) = NULL; \ + } \ + /* OBSOLETE else if (SYMBOL_LANGUAGE (symbol) == language_chill) */ \ + /* OBSOLETE { */ \ + /* OBSOLETE SYMBOL_CHILL_DEMANGLED_NAME (symbol) = NULL; */ \ + /* OBSOLETE } */ \ + else \ + { \ + memset (&(symbol)->ginfo.language_specific, 0, \ + sizeof ((symbol)->ginfo.language_specific)); \ + } \ + } while (0) + +#define SYMBOL_INIT_DEMANGLED_NAME(symbol,obstack) \ + (symbol_init_demangled_name (&symbol->ginfo, (obstack))) +extern void symbol_init_demangled_name (struct general_symbol_info *symbol, + struct obstack *obstack); + + +/* Macro that returns the demangled name for a symbol based on the language + for that symbol. If no demangled name exists, returns NULL. */ + +#define SYMBOL_DEMANGLED_NAME(symbol) \ + (SYMBOL_LANGUAGE (symbol) == language_cplus \ + || SYMBOL_LANGUAGE (symbol) == language_java \ + ? SYMBOL_CPLUS_DEMANGLED_NAME (symbol) \ + : /* OBSOLETE (SYMBOL_LANGUAGE (symbol) == language_chill */ \ + /* OBSOLETE ? SYMBOL_CHILL_DEMANGLED_NAME (symbol) */ \ + NULL) + +/* OBSOLETE #define SYMBOL_CHILL_DEMANGLED_NAME(symbol) */ +/* OBSOLETE (symbol)->ginfo.language_specific.chill_specific.demangled_name */ + +/* Macro that returns the "natural source name" of a symbol. In C++ this is + the "demangled" form of the name if demangle is on and the "mangled" form + of the name if demangle is off. In other languages this is just the + symbol name. The result should never be NULL. */ + +#define SYMBOL_SOURCE_NAME(symbol) \ + (demangle && SYMBOL_DEMANGLED_NAME (symbol) != NULL \ + ? SYMBOL_DEMANGLED_NAME (symbol) \ + : SYMBOL_NAME (symbol)) + +/* Macro that returns the "natural assembly name" of a symbol. In C++ this is + the "mangled" form of the name if demangle is off, or if demangle is on and + asm_demangle is off. Otherwise if asm_demangle is on it is the "demangled" + form. In other languages this is just the symbol name. The result should + never be NULL. */ + +#define SYMBOL_LINKAGE_NAME(symbol) \ + (demangle && asm_demangle && SYMBOL_DEMANGLED_NAME (symbol) != NULL \ + ? SYMBOL_DEMANGLED_NAME (symbol) \ + : SYMBOL_NAME (symbol)) + +/* Macro that tests a symbol for a match against a specified name string. + First test the unencoded name, then looks for and test a C++ encoded + name if it exists. Note that whitespace is ignored while attempting to + match a C++ encoded name, so that "foo::bar(int,long)" is the same as + "foo :: bar (int, long)". + Evaluates to zero if the match fails, or nonzero if it succeeds. */ + +#define SYMBOL_MATCHES_NAME(symbol, name) \ + (STREQ (SYMBOL_NAME (symbol), (name)) \ + || (SYMBOL_DEMANGLED_NAME (symbol) != NULL \ + && strcmp_iw (SYMBOL_DEMANGLED_NAME (symbol), (name)) == 0)) + +/* Macro that tests a symbol for an re-match against the last compiled regular + expression. First test the unencoded name, then look for and test a C++ + encoded name if it exists. + Evaluates to zero if the match fails, or nonzero if it succeeds. */ + +#define SYMBOL_MATCHES_REGEXP(symbol) \ + (re_exec (SYMBOL_NAME (symbol)) != 0 \ + || (SYMBOL_DEMANGLED_NAME (symbol) != NULL \ + && re_exec (SYMBOL_DEMANGLED_NAME (symbol)) != 0)) + +/* Define a simple structure used to hold some very basic information about + all defined global symbols (text, data, bss, abs, etc). The only required + information is the general_symbol_info. + + In many cases, even if a file was compiled with no special options for + debugging at all, as long as was not stripped it will contain sufficient + information to build a useful minimal symbol table using this structure. + Even when a file contains enough debugging information to build a full + symbol table, these minimal symbols are still useful for quickly mapping + between names and addresses, and vice versa. They are also sometimes + used to figure out what full symbol table entries need to be read in. */ + +struct minimal_symbol +{ + + /* The general symbol info required for all types of symbols. + + The SYMBOL_VALUE_ADDRESS contains the address that this symbol + corresponds to. */ + + struct general_symbol_info ginfo; + + /* The info field is available for caching machine-specific information + so it doesn't have to rederive the info constantly (over a serial line). + It is initialized to zero and stays that way until target-dependent code + sets it. Storage for any data pointed to by this field should be allo- + cated on the symbol_obstack for the associated objfile. + The type would be "void *" except for reasons of compatibility with older + compilers. This field is optional. + + Currently, the AMD 29000 tdep.c uses it to remember things it has decoded + from the instructions in the function header, and the MIPS-16 code uses + it to identify 16-bit procedures. */ + + char *info; + +#ifdef SOFUN_ADDRESS_MAYBE_MISSING + /* Which source file is this symbol in? Only relevant for mst_file_*. */ + char *filename; +#endif + + /* Classification types for this symbol. These should be taken as "advisory + only", since if gdb can't easily figure out a classification it simply + selects mst_unknown. It may also have to guess when it can't figure out + which is a better match between two types (mst_data versus mst_bss) for + example. Since the minimal symbol info is sometimes derived from the + BFD library's view of a file, we need to live with what information bfd + supplies. */ + + enum minimal_symbol_type + { + mst_unknown = 0, /* Unknown type, the default */ + mst_text, /* Generally executable instructions */ + mst_data, /* Generally initialized data */ + mst_bss, /* Generally uninitialized data */ + mst_abs, /* Generally absolute (nonrelocatable) */ + /* GDB uses mst_solib_trampoline for the start address of a shared + library trampoline entry. Breakpoints for shared library functions + are put there if the shared library is not yet loaded. + After the shared library is loaded, lookup_minimal_symbol will + prefer the minimal symbol from the shared library (usually + a mst_text symbol) over the mst_solib_trampoline symbol, and the + breakpoints will be moved to their true address in the shared + library via breakpoint_re_set. */ + mst_solib_trampoline, /* Shared library trampoline code */ + /* For the mst_file* types, the names are only guaranteed to be unique + within a given .o file. */ + mst_file_text, /* Static version of mst_text */ + mst_file_data, /* Static version of mst_data */ + mst_file_bss /* Static version of mst_bss */ + } + type BYTE_BITFIELD; + + /* Minimal symbols with the same hash key are kept on a linked + list. This is the link. */ + + struct minimal_symbol *hash_next; + + /* Minimal symbols are stored in two different hash tables. This is + the `next' pointer for the demangled hash table. */ + + struct minimal_symbol *demangled_hash_next; +}; + +#define MSYMBOL_INFO(msymbol) (msymbol)->info +#define MSYMBOL_TYPE(msymbol) (msymbol)->type + + + +/* All of the name-scope contours of the program + are represented by `struct block' objects. + All of these objects are pointed to by the blockvector. + + Each block represents one name scope. + Each lexical context has its own block. + + The blockvector begins with some special blocks. + The GLOBAL_BLOCK contains all the symbols defined in this compilation + whose scope is the entire program linked together. + The STATIC_BLOCK contains all the symbols whose scope is the + entire compilation excluding other separate compilations. + Blocks starting with the FIRST_LOCAL_BLOCK are not special. + + Each block records a range of core addresses for the code that + is in the scope of the block. The STATIC_BLOCK and GLOBAL_BLOCK + give, for the range of code, the entire range of code produced + by the compilation that the symbol segment belongs to. + + The blocks appear in the blockvector + in order of increasing starting-address, + and, within that, in order of decreasing ending-address. + + This implies that within the body of one function + the blocks appear in the order of a depth-first tree walk. */ + +struct blockvector +{ + /* Number of blocks in the list. */ + int nblocks; + /* The blocks themselves. */ + struct block *block[1]; +}; + +#define BLOCKVECTOR_NBLOCKS(blocklist) (blocklist)->nblocks +#define BLOCKVECTOR_BLOCK(blocklist,n) (blocklist)->block[n] + +/* Special block numbers */ + +#define GLOBAL_BLOCK 0 +#define STATIC_BLOCK 1 +#define FIRST_LOCAL_BLOCK 2 + +struct block +{ + + /* Addresses in the executable code that are in this block. */ + + CORE_ADDR startaddr; + CORE_ADDR endaddr; + + /* The symbol that names this block, if the block is the body of a + function; otherwise, zero. */ + + struct symbol *function; + + /* The `struct block' for the containing block, or 0 if none. + + The superblock of a top-level local block (i.e. a function in the + case of C) is the STATIC_BLOCK. The superblock of the + STATIC_BLOCK is the GLOBAL_BLOCK. */ + + struct block *superblock; + + /* Version of GCC used to compile the function corresponding + to this block, or 0 if not compiled with GCC. When possible, + GCC should be compatible with the native compiler, or if that + is not feasible, the differences should be fixed during symbol + reading. As of 16 Apr 93, this flag is never used to distinguish + between gcc2 and the native compiler. + + If there is no function corresponding to this block, this meaning + of this flag is undefined. */ + + unsigned char gcc_compile_flag; + + /* The symbols for this block are either in a simple linear list or + in a simple hashtable. Blocks which correspond to a function + (which have a list of symbols corresponding to arguments) use + a linear list, as do some older symbol readers (currently only + mdebugread and dstread). Other blocks are hashed. + + The hashtable uses the same hash function as the minsym hashtables, + found in minsyms.c:minsym_hash_iw. Symbols are hashed based on + their demangled name if appropriate, and on their name otherwise. + The hash function ignores space, and stops at the beginning of the + argument list if any. + + The table is laid out in NSYMS/5 buckets and symbols are chained via + their hash_next field. */ + + /* If this is really a hashtable of the symbols, this flag is 1. */ + + unsigned char hashtable; + + /* Number of local symbols. */ + + int nsyms; + + /* The symbols. If some of them are arguments, then they must be + in the order in which we would like to print them. */ + + struct symbol *sym[1]; +}; + +#define BLOCK_START(bl) (bl)->startaddr +#define BLOCK_END(bl) (bl)->endaddr +#define BLOCK_FUNCTION(bl) (bl)->function +#define BLOCK_SUPERBLOCK(bl) (bl)->superblock +#define BLOCK_GCC_COMPILED(bl) (bl)->gcc_compile_flag +#define BLOCK_HASHTABLE(bl) (bl)->hashtable + +/* For blocks without a hashtable (BLOCK_HASHTABLE (bl) == 0) only. */ +#define BLOCK_NSYMS(bl) (bl)->nsyms +#define BLOCK_SYM(bl, n) (bl)->sym[n] + +/* For blocks with a hashtable, but these are valid for non-hashed blocks as + well - each symbol will appear to be one bucket by itself. */ +#define BLOCK_BUCKETS(bl) (bl)->nsyms +#define BLOCK_BUCKET(bl, n) (bl)->sym[n] + +/* Macro used to set the size of a hashtable for N symbols. */ +#define BLOCK_HASHTABLE_SIZE(n) ((n)/5 + 1) + +/* Macro to loop through all symbols in a block BL, in no particular order. + i counts which bucket we are in, and sym points to the current symbol. */ + +#define ALL_BLOCK_SYMBOLS(bl, i, sym) \ + for ((i) = 0; (i) < BLOCK_BUCKETS ((bl)); (i)++) \ + for ((sym) = BLOCK_BUCKET ((bl), (i)); (sym); \ + (sym) = (sym)->hash_next) + +/* Nonzero if symbols of block BL should be sorted alphabetically. + Don't sort a block which corresponds to a function. If we did the + sorting would have to preserve the order of the symbols for the + arguments. Also don't sort any block that we chose to hash. */ + +#define BLOCK_SHOULD_SORT(bl) (! BLOCK_HASHTABLE (bl) \ + && BLOCK_FUNCTION (bl) == NULL) + + +/* Represent one symbol name; a variable, constant, function or typedef. */ + +/* Different name spaces for symbols. Looking up a symbol specifies a + namespace and ignores symbol definitions in other name spaces. */ + +typedef enum +{ + /* UNDEF_NAMESPACE is used when a namespace has not been discovered or + none of the following apply. This usually indicates an error either + in the symbol information or in gdb's handling of symbols. */ + + UNDEF_NAMESPACE, + + /* VAR_NAMESPACE is the usual namespace. In C, this contains variables, + function names, typedef names and enum type values. */ + + VAR_NAMESPACE, + + /* STRUCT_NAMESPACE is used in C to hold struct, union and enum type names. + Thus, if `struct foo' is used in a C program, it produces a symbol named + `foo' in the STRUCT_NAMESPACE. */ + + STRUCT_NAMESPACE, + + /* LABEL_NAMESPACE may be used for names of labels (for gotos); + currently it is not used and labels are not recorded at all. */ + + LABEL_NAMESPACE, + + /* Searching namespaces. These overlap with VAR_NAMESPACE, providing + some granularity with the search_symbols function. */ + + /* Everything in VAR_NAMESPACE minus FUNCTIONS_-, TYPES_-, and + METHODS_NAMESPACE */ + VARIABLES_NAMESPACE, + + /* All functions -- for some reason not methods, though. */ + FUNCTIONS_NAMESPACE, + + /* All defined types */ + TYPES_NAMESPACE, + + /* All class methods -- why is this separated out? */ + METHODS_NAMESPACE +} +namespace_enum; + +/* An address-class says where to find the value of a symbol. */ + +enum address_class +{ + /* Not used; catches errors */ + + LOC_UNDEF, + + /* Value is constant int SYMBOL_VALUE, host byteorder */ + + LOC_CONST, + + /* Value is at fixed address SYMBOL_VALUE_ADDRESS */ + + LOC_STATIC, + + /* Value is in register. SYMBOL_VALUE is the register number. */ + + LOC_REGISTER, + + /* It's an argument; the value is at SYMBOL_VALUE offset in arglist. */ + + LOC_ARG, + + /* Value address is at SYMBOL_VALUE offset in arglist. */ + + LOC_REF_ARG, + + /* Value is in register number SYMBOL_VALUE. Just like LOC_REGISTER + except this is an argument. Probably the cleaner way to handle + this would be to separate address_class (which would include + separate ARG and LOCAL to deal with FRAME_ARGS_ADDRESS versus + FRAME_LOCALS_ADDRESS), and an is_argument flag. + + For some symbol formats (stabs, for some compilers at least), + the compiler generates two symbols, an argument and a register. + In some cases we combine them to a single LOC_REGPARM in symbol + reading, but currently not for all cases (e.g. it's passed on the + stack and then loaded into a register). */ + + LOC_REGPARM, + + /* Value is in specified register. Just like LOC_REGPARM except the + register holds the address of the argument instead of the argument + itself. This is currently used for the passing of structs and unions + on sparc and hppa. It is also used for call by reference where the + address is in a register, at least by mipsread.c. */ + + LOC_REGPARM_ADDR, + + /* Value is a local variable at SYMBOL_VALUE offset in stack frame. */ + + LOC_LOCAL, + + /* Value not used; definition in SYMBOL_TYPE. Symbols in the namespace + STRUCT_NAMESPACE all have this class. */ + + LOC_TYPEDEF, + + /* Value is address SYMBOL_VALUE_ADDRESS in the code */ + + LOC_LABEL, + + /* In a symbol table, value is SYMBOL_BLOCK_VALUE of a `struct block'. + In a partial symbol table, SYMBOL_VALUE_ADDRESS is the start address + of the block. Function names have this class. */ + + LOC_BLOCK, + + /* Value is a constant byte-sequence pointed to by SYMBOL_VALUE_BYTES, in + target byte order. */ + + LOC_CONST_BYTES, + + /* Value is arg at SYMBOL_VALUE offset in stack frame. Differs from + LOC_LOCAL in that symbol is an argument; differs from LOC_ARG in + that we find it in the frame (FRAME_LOCALS_ADDRESS), not in the + arglist (FRAME_ARGS_ADDRESS). Added for i960, which passes args + in regs then copies to frame. */ + + LOC_LOCAL_ARG, + + /* Value is at SYMBOL_VALUE offset from the current value of + register number SYMBOL_BASEREG. This exists mainly for the same + things that LOC_LOCAL and LOC_ARG do; but we need to do this + instead because on 88k DWARF gives us the offset from the + frame/stack pointer, rather than the offset from the "canonical + frame address" used by COFF, stabs, etc., and we don't know how + to convert between these until we start examining prologues. + + Note that LOC_BASEREG is much less general than a DWARF expression. + We don't need the generality (at least not yet), and storing a general + DWARF expression would presumably take up more space than the existing + scheme. */ + + LOC_BASEREG, + + /* Same as LOC_BASEREG but it is an argument. */ + + LOC_BASEREG_ARG, + + /* Value is at fixed address, but the address of the variable has + to be determined from the minimal symbol table whenever the + variable is referenced. + This happens if debugging information for a global symbol is + emitted and the corresponding minimal symbol is defined + in another object file or runtime common storage. + The linker might even remove the minimal symbol if the global + symbol is never referenced, in which case the symbol remains + unresolved. */ + + LOC_UNRESOLVED, + + /* Value is at a thread-specific location calculated by a + target-specific method. */ + + LOC_THREAD_LOCAL_STATIC, + + /* The variable does not actually exist in the program. + The value is ignored. */ + + LOC_OPTIMIZED_OUT, + + /* The variable is static, but actually lives at * (address). + * I.e. do an extra indirection to get to it. + * This is used on HP-UX to get at globals that are allocated + * in shared libraries, where references from images other + * than the one where the global was allocated are done + * with a level of indirection. + */ + + LOC_INDIRECT +}; + +/* Linked list of symbol's live ranges. */ + +struct range_list +{ + CORE_ADDR start; + CORE_ADDR end; + struct range_list *next; +}; + +/* Linked list of aliases for a particular main/primary symbol. */ +struct alias_list +{ + struct symbol *sym; + struct alias_list *next; +}; + +struct symbol +{ + + /* The general symbol info required for all types of symbols. */ + + struct general_symbol_info ginfo; + + /* Data type of value */ + + struct type *type; + + /* Name space code. */ + +#ifdef __MFC4__ + /* FIXME: don't conflict with C++'s namespace */ + /* would be safer to do a global change for all namespace identifiers. */ +#define namespace _namespace +#endif + namespace_enum namespace BYTE_BITFIELD; + + /* Address class */ + + enum address_class aclass BYTE_BITFIELD; + + /* Line number of definition. FIXME: Should we really make the assumption + that nobody will try to debug files longer than 64K lines? What about + machine generated programs? */ + + unsigned short line; + + /* Some symbols require an additional value to be recorded on a per- + symbol basis. Stash those values here. */ + + union + { + /* Used by LOC_BASEREG and LOC_BASEREG_ARG. */ + short basereg; + } + aux_value; + + + /* Link to a list of aliases for this symbol. + Only a "primary/main symbol may have aliases. */ + struct alias_list *aliases; + + /* List of ranges where this symbol is active. This is only + used by alias symbols at the current time. */ + struct range_list *ranges; + + struct symbol *hash_next; +}; + + +#define SYMBOL_NAMESPACE(symbol) (symbol)->namespace +#define SYMBOL_CLASS(symbol) (symbol)->aclass +#define SYMBOL_TYPE(symbol) (symbol)->type +#define SYMBOL_LINE(symbol) (symbol)->line +#define SYMBOL_BASEREG(symbol) (symbol)->aux_value.basereg +#define SYMBOL_ALIASES(symbol) (symbol)->aliases +#define SYMBOL_RANGES(symbol) (symbol)->ranges + +/* A partial_symbol records the name, namespace, and address class of + symbols whose types we have not parsed yet. For functions, it also + contains their memory address, so we can find them from a PC value. + Each partial_symbol sits in a partial_symtab, all of which are chained + on a partial symtab list and which points to the corresponding + normal symtab once the partial_symtab has been referenced. */ + +struct partial_symbol +{ + + /* The general symbol info required for all types of symbols. */ + + struct general_symbol_info ginfo; + + /* Name space code. */ + + namespace_enum namespace BYTE_BITFIELD; + + /* Address class (for info_symbols) */ + + enum address_class aclass BYTE_BITFIELD; + +}; + +#define PSYMBOL_NAMESPACE(psymbol) (psymbol)->namespace +#define PSYMBOL_CLASS(psymbol) (psymbol)->aclass + + +/* Source-file information. This describes the relation between source files, + line numbers and addresses in the program text. */ + +struct sourcevector +{ + int length; /* Number of source files described */ + struct source *source[1]; /* Descriptions of the files */ +}; + +/* Each item represents a line-->pc (or the reverse) mapping. This is + somewhat more wasteful of space than one might wish, but since only + the files which are actually debugged are read in to core, we don't + waste much space. */ + +struct linetable_entry +{ + int line; + CORE_ADDR pc; +}; + +/* The order of entries in the linetable is significant. They should + be sorted by increasing values of the pc field. If there is more than + one entry for a given pc, then I'm not sure what should happen (and + I not sure whether we currently handle it the best way). + + Example: a C for statement generally looks like this + + 10 0x100 - for the init/test part of a for stmt. + 20 0x200 + 30 0x300 + 10 0x400 - for the increment part of a for stmt. + + If an entry has a line number of zero, it marks the start of a PC + range for which no line number information is available. It is + acceptable, though wasteful of table space, for such a range to be + zero length. */ + +struct linetable +{ + int nitems; + + /* Actually NITEMS elements. If you don't like this use of the + `struct hack', you can shove it up your ANSI (seriously, if the + committee tells us how to do it, we can probably go along). */ + struct linetable_entry item[1]; +}; + +/* All the information on one source file. */ + +struct source +{ + char *name; /* Name of file */ + struct linetable contents; +}; + +/* How to relocate the symbols from each section in a symbol file. + Each struct contains an array of offsets. + The ordering and meaning of the offsets is file-type-dependent; + typically it is indexed by section numbers or symbol types or + something like that. + + To give us flexibility in changing the internal representation + of these offsets, the ANOFFSET macro must be used to insert and + extract offset values in the struct. */ + +struct section_offsets +{ + CORE_ADDR offsets[1]; /* As many as needed. */ +}; + +#define ANOFFSET(secoff, whichone) \ + ((whichone == -1) \ + ? (internal_error (__FILE__, __LINE__, "Section index is uninitialized"), -1) \ + : secoff->offsets[whichone]) + +/* The maximum possible size of a section_offsets table. */ + +#define SIZEOF_SECTION_OFFSETS \ + (sizeof (struct section_offsets) \ + + sizeof (((struct section_offsets *) 0)->offsets) * (SECT_OFF_MAX-1)) + +/* Each source file or header is represented by a struct symtab. + These objects are chained through the `next' field. */ + +struct symtab +{ + + /* Chain of all existing symtabs. */ + + struct symtab *next; + + /* List of all symbol scope blocks for this symtab. May be shared + between different symtabs (and normally is for all the symtabs + in a given compilation unit). */ + + struct blockvector *blockvector; + + /* Table mapping core addresses to line numbers for this file. + Can be NULL if none. Never shared between different symtabs. */ + + struct linetable *linetable; + + /* Section in objfile->section_offsets for the blockvector and + the linetable. Probably always SECT_OFF_TEXT. */ + + int block_line_section; + + /* If several symtabs share a blockvector, exactly one of them + should be designated the primary, so that the blockvector + is relocated exactly once by objfile_relocate. */ + + int primary; + + /* The macro table for this symtab. Like the blockvector, this + may be shared between different symtabs --- and normally is for + all the symtabs in a given compilation unit. */ + struct macro_table *macro_table; + + /* Name of this source file. */ + + char *filename; + + /* Directory in which it was compiled, or NULL if we don't know. */ + + char *dirname; + + /* This component says how to free the data we point to: + free_contents => do a tree walk and free each object. + free_nothing => do nothing; some other symtab will free + the data this one uses. + free_linetable => free just the linetable. FIXME: Is this redundant + with the primary field? */ + + enum free_code + { + free_nothing, free_contents, free_linetable + } + free_code; + + /* Pointer to one block of storage to be freed, if nonzero. */ + /* This is IN ADDITION to the action indicated by free_code. */ + + char *free_ptr; + + /* Total number of lines found in source file. */ + + int nlines; + + /* line_charpos[N] is the position of the (N-1)th line of the + source file. "position" means something we can lseek() to; it + is not guaranteed to be useful any other way. */ + + int *line_charpos; + + /* Language of this source file. */ + + enum language language; + + /* String that identifies the format of the debugging information, such + as "stabs", "dwarf 1", "dwarf 2", "coff", etc. This is mostly useful + for automated testing of gdb but may also be information that is + useful to the user. */ + + char *debugformat; + + /* String of version information. May be zero. */ + + char *version; + + /* Full name of file as found by searching the source path. + NULL if not yet known. */ + + char *fullname; + + /* Object file from which this symbol information was read. */ + + struct objfile *objfile; + +}; + +#define BLOCKVECTOR(symtab) (symtab)->blockvector +#define LINETABLE(symtab) (symtab)->linetable + + +/* Each source file that has not been fully read in is represented by + a partial_symtab. This contains the information on where in the + executable the debugging symbols for a specific file are, and a + list of names of global symbols which are located in this file. + They are all chained on partial symtab lists. + + Even after the source file has been read into a symtab, the + partial_symtab remains around. They are allocated on an obstack, + psymbol_obstack. FIXME, this is bad for dynamic linking or VxWorks- + style execution of a bunch of .o's. */ + +struct partial_symtab +{ + + /* Chain of all existing partial symtabs. */ + + struct partial_symtab *next; + + /* Name of the source file which this partial_symtab defines */ + + char *filename; + + /* Full path of the source file. NULL if not known. */ + + char *fullname; + + /* Information about the object file from which symbols should be read. */ + + struct objfile *objfile; + + /* Set of relocation offsets to apply to each section. */ + + struct section_offsets *section_offsets; + + /* Range of text addresses covered by this file; texthigh is the + beginning of the next section. */ + + CORE_ADDR textlow; + CORE_ADDR texthigh; + + /* Array of pointers to all of the partial_symtab's which this one + depends on. Since this array can only be set to previous or + the current (?) psymtab, this dependency tree is guaranteed not + to have any loops. "depends on" means that symbols must be read + for the dependencies before being read for this psymtab; this is + for type references in stabs, where if foo.c includes foo.h, declarations + in foo.h may use type numbers defined in foo.c. For other debugging + formats there may be no need to use dependencies. */ + + struct partial_symtab **dependencies; + + int number_of_dependencies; + + /* Global symbol list. This list will be sorted after readin to + improve access. Binary search will be the usual method of + finding a symbol within it. globals_offset is an integer offset + within global_psymbols[]. */ + + int globals_offset; + int n_global_syms; + + /* Static symbol list. This list will *not* be sorted after readin; + to find a symbol in it, exhaustive search must be used. This is + reasonable because searches through this list will eventually + lead to either the read in of a files symbols for real (assumed + to take a *lot* of time; check) or an error (and we don't care + how long errors take). This is an offset and size within + static_psymbols[]. */ + + int statics_offset; + int n_static_syms; + + /* Pointer to symtab eventually allocated for this source file, 0 if + !readin or if we haven't looked for the symtab after it was readin. */ + + struct symtab *symtab; + + /* Pointer to function which will read in the symtab corresponding to + this psymtab. */ + + void (*read_symtab) (struct partial_symtab *); + + /* Information that lets read_symtab() locate the part of the symbol table + that this psymtab corresponds to. This information is private to the + format-dependent symbol reading routines. For further detail examine + the various symbol reading modules. Should really be (void *) but is + (char *) as with other such gdb variables. (FIXME) */ + + char *read_symtab_private; + + /* Non-zero if the symtab corresponding to this psymtab has been readin */ + + unsigned char readin; +}; + +/* A fast way to get from a psymtab to its symtab (after the first time). */ +#define PSYMTAB_TO_SYMTAB(pst) \ + ((pst) -> symtab != NULL ? (pst) -> symtab : psymtab_to_symtab (pst)) + + +/* The virtual function table is now an array of structures which have the + form { int16 offset, delta; void *pfn; }. + + In normal virtual function tables, OFFSET is unused. + DELTA is the amount which is added to the apparent object's base + address in order to point to the actual object to which the + virtual function should be applied. + PFN is a pointer to the virtual function. + + Note that this macro is g++ specific (FIXME). */ + +#define VTBL_FNADDR_OFFSET 2 + +/* External variables and functions for the objects described above. */ + +/* See the comment in symfile.c about how current_objfile is used. */ + +extern struct objfile *current_objfile; + +/* True if we are nested inside psymtab_to_symtab. */ + +extern int currently_reading_symtab; + +/* From utils.c. */ +extern int demangle; +extern int asm_demangle; + +/* symtab.c lookup functions */ + +/* lookup a symbol table by source file name */ + +extern struct symtab *lookup_symtab (const char *); + +/* lookup a symbol by name (optional block, optional symtab) */ + +extern struct symbol *lookup_symbol (const char *, const struct block *, + const namespace_enum, int *, + struct symtab **); + +/* lookup a symbol by name, within a specified block */ + +extern struct symbol *lookup_block_symbol (const struct block *, const char *, + const char *, + const namespace_enum); + +/* lookup a [struct, union, enum] by name, within a specified block */ + +extern struct type *lookup_struct (char *, struct block *); + +extern struct type *lookup_union (char *, struct block *); + +extern struct type *lookup_enum (char *, struct block *); + +/* lookup the function corresponding to the block */ + +extern struct symbol *block_function (struct block *); + +/* from blockframe.c: */ + +/* lookup the function symbol corresponding to the address */ + +extern struct symbol *find_pc_function (CORE_ADDR); + +/* lookup the function corresponding to the address and section */ + +extern struct symbol *find_pc_sect_function (CORE_ADDR, asection *); + +/* lookup function from address, return name, start addr and end addr */ + +extern int +find_pc_partial_function (CORE_ADDR, char **, CORE_ADDR *, CORE_ADDR *); + +extern void clear_pc_function_cache (void); + +extern int find_pc_sect_partial_function (CORE_ADDR, asection *, + char **, CORE_ADDR *, CORE_ADDR *); + +/* from symtab.c: */ + +/* lookup partial symbol table by filename */ + +extern struct partial_symtab *lookup_partial_symtab (const char *); + +/* lookup partial symbol table by address */ + +extern struct partial_symtab *find_pc_psymtab (CORE_ADDR); + +/* lookup partial symbol table by address and section */ + +extern struct partial_symtab *find_pc_sect_psymtab (CORE_ADDR, asection *); + +/* lookup full symbol table by address */ + +extern struct symtab *find_pc_symtab (CORE_ADDR); + +/* lookup full symbol table by address and section */ + +extern struct symtab *find_pc_sect_symtab (CORE_ADDR, asection *); + +/* lookup partial symbol by address */ + +extern struct partial_symbol *find_pc_psymbol (struct partial_symtab *, + CORE_ADDR); + +/* lookup partial symbol by address and section */ + +extern struct partial_symbol *find_pc_sect_psymbol (struct partial_symtab *, + CORE_ADDR, asection *); + +extern int find_pc_line_pc_range (CORE_ADDR, CORE_ADDR *, CORE_ADDR *); + +extern int contained_in (struct block *, struct block *); + +extern void reread_symbols (void); + +extern struct type *lookup_transparent_type (const char *); + + +/* Macro for name of symbol to indicate a file compiled with gcc. */ +#ifndef GCC_COMPILED_FLAG_SYMBOL +#define GCC_COMPILED_FLAG_SYMBOL "gcc_compiled." +#endif + +/* Macro for name of symbol to indicate a file compiled with gcc2. */ +#ifndef GCC2_COMPILED_FLAG_SYMBOL +#define GCC2_COMPILED_FLAG_SYMBOL "gcc2_compiled." +#endif + +/* Functions for dealing with the minimal symbol table, really a misc + address<->symbol mapping for things we don't have debug symbols for. */ + +extern void prim_record_minimal_symbol (const char *, CORE_ADDR, + enum minimal_symbol_type, + struct objfile *); + +extern struct minimal_symbol *prim_record_minimal_symbol_and_info + (const char *, CORE_ADDR, + enum minimal_symbol_type, + char *info, int section, asection * bfd_section, struct objfile *); + +extern unsigned int msymbol_hash_iw (const char *); + +extern unsigned int msymbol_hash (const char *); + +extern void +add_minsym_to_hash_table (struct minimal_symbol *sym, + struct minimal_symbol **table); + +extern struct minimal_symbol *lookup_minimal_symbol (const char *, + const char *, + struct objfile *); + +extern struct minimal_symbol *lookup_minimal_symbol_text (const char *, + const char *, + struct objfile *); + +struct minimal_symbol *lookup_minimal_symbol_solib_trampoline (const char *, + const char *, + struct objfile + *); + +extern struct minimal_symbol *lookup_minimal_symbol_by_pc (CORE_ADDR); + +extern struct minimal_symbol *lookup_minimal_symbol_by_pc_section (CORE_ADDR, + asection + *); + +extern struct minimal_symbol + *lookup_solib_trampoline_symbol_by_pc (CORE_ADDR); + +extern CORE_ADDR find_solib_trampoline_target (CORE_ADDR); + +extern void init_minimal_symbol_collection (void); + +extern struct cleanup *make_cleanup_discard_minimal_symbols (void); + +extern void install_minimal_symbols (struct objfile *); + +/* Sort all the minimal symbols in OBJFILE. */ + +extern void msymbols_sort (struct objfile *objfile); + +struct symtab_and_line +{ + struct symtab *symtab; + asection *section; + /* Line number. Line numbers start at 1 and proceed through symtab->nlines. + 0 is never a valid line number; it is used to indicate that line number + information is not available. */ + int line; + + CORE_ADDR pc; + CORE_ADDR end; +}; + +#define INIT_SAL(sal) { \ + (sal)->symtab = 0; \ + (sal)->section = 0; \ + (sal)->line = 0; \ + (sal)->pc = 0; \ + (sal)->end = 0; \ +} + +struct symtabs_and_lines +{ + struct symtab_and_line *sals; + int nelts; +}; + + + +/* Some types and macros needed for exception catchpoints. + Can't put these in target.h because symtab_and_line isn't + known there. This file will be included by breakpoint.c, + hppa-tdep.c, etc. */ + +/* Enums for exception-handling support */ +enum exception_event_kind +{ + EX_EVENT_THROW, + EX_EVENT_CATCH +}; + +/* Type for returning info about an exception */ +struct exception_event_record +{ + enum exception_event_kind kind; + struct symtab_and_line throw_sal; + struct symtab_and_line catch_sal; + /* This may need to be extended in the future, if + some platforms allow reporting more information, + such as point of rethrow, type of exception object, + type expected by catch clause, etc. */ +}; + +#define CURRENT_EXCEPTION_KIND (current_exception_event->kind) +#define CURRENT_EXCEPTION_CATCH_SAL (current_exception_event->catch_sal) +#define CURRENT_EXCEPTION_CATCH_LINE (current_exception_event->catch_sal.line) +#define CURRENT_EXCEPTION_CATCH_FILE (current_exception_event->catch_sal.symtab->filename) +#define CURRENT_EXCEPTION_CATCH_PC (current_exception_event->catch_sal.pc) +#define CURRENT_EXCEPTION_THROW_SAL (current_exception_event->throw_sal) +#define CURRENT_EXCEPTION_THROW_LINE (current_exception_event->throw_sal.line) +#define CURRENT_EXCEPTION_THROW_FILE (current_exception_event->throw_sal.symtab->filename) +#define CURRENT_EXCEPTION_THROW_PC (current_exception_event->throw_sal.pc) + + +/* Given a pc value, return line number it is in. Second arg nonzero means + if pc is on the boundary use the previous statement's line number. */ + +extern struct symtab_and_line find_pc_line (CORE_ADDR, int); + +/* Same function, but specify a section as well as an address */ + +extern struct symtab_and_line find_pc_sect_line (CORE_ADDR, asection *, int); + +/* Given an address, return the nearest symbol at or below it in memory. + Optionally return the symtab it's from through 2nd arg, and the + address in inferior memory of the symbol through 3rd arg. */ + +extern struct symbol *find_addr_symbol (CORE_ADDR, struct symtab **, + CORE_ADDR *); + +/* Given a symtab and line number, return the pc there. */ + +extern int find_line_pc (struct symtab *, int, CORE_ADDR *); + +extern int +find_line_pc_range (struct symtab_and_line, CORE_ADDR *, CORE_ADDR *); + +extern void resolve_sal_pc (struct symtab_and_line *); + +/* Given a string, return the line specified by it. For commands like "list" + and "breakpoint". */ + +extern struct symtabs_and_lines decode_line_spec (char *, int); + +extern struct symtabs_and_lines decode_line_spec_1 (char *, int); + +/* Symmisc.c */ + +void maintenance_print_symbols (char *, int); + +void maintenance_print_psymbols (char *, int); + +void maintenance_print_msymbols (char *, int); + +void maintenance_print_objfiles (char *, int); + +void maintenance_check_symtabs (char *, int); + +/* maint.c */ + +void maintenance_print_statistics (char *, int); + +extern void free_symtab (struct symtab *); + +/* Symbol-reading stuff in symfile.c and solib.c. */ + +extern struct symtab *psymtab_to_symtab (struct partial_symtab *); + +extern void clear_solib (void); + +/* source.c */ + +extern int identify_source_line (struct symtab *, int, int, CORE_ADDR); + +extern void print_source_lines (struct symtab *, int, int, int); + +extern void forget_cached_source_info (void); + +extern void select_source_symtab (struct symtab *); + +extern char **make_symbol_completion_list (char *, char *); + +extern char **make_file_symbol_completion_list (char *, char *, char *); + +extern struct symbol **make_symbol_overload_list (struct symbol *); + +extern char **make_source_files_completion_list (char *, char *); + +/* symtab.c */ + +extern struct partial_symtab *find_main_psymtab (void); + +extern struct symtab *find_line_symtab (struct symtab *, int, int *, int *); + +extern struct symtab_and_line find_function_start_sal (struct symbol *sym, + int); + +/* blockframe.c */ + +extern struct blockvector *blockvector_for_pc (CORE_ADDR, int *); + +extern struct blockvector *blockvector_for_pc_sect (CORE_ADDR, asection *, + int *, struct symtab *); + +/* symfile.c */ + +extern void clear_symtab_users (void); + +extern enum language deduce_language_from_filename (char *); + +/* symtab.c */ + +extern int in_prologue (CORE_ADDR pc, CORE_ADDR func_start); + +extern struct symbol *fixup_symbol_section (struct symbol *, + struct objfile *); + +extern struct partial_symbol *fixup_psymbol_section (struct partial_symbol + *psym, + struct objfile *objfile); + +/* Symbol searching */ + +/* When using search_symbols, a list of the following structs is returned. + Callers must free the search list using free_search_symbols! */ +struct symbol_search +{ + /* The block in which the match was found. Could be, for example, + STATIC_BLOCK or GLOBAL_BLOCK. */ + int block; + + /* Information describing what was found. + + If symtab abd symbol are NOT NULL, then information was found + for this match. */ + struct symtab *symtab; + struct symbol *symbol; + + /* If msymbol is non-null, then a match was made on something for + which only minimal_symbols exist. */ + struct minimal_symbol *msymbol; + + /* A link to the next match, or NULL for the end. */ + struct symbol_search *next; +}; + +extern void search_symbols (char *, namespace_enum, int, char **, + struct symbol_search **); +extern void free_search_symbols (struct symbol_search *); +extern struct cleanup *make_cleanup_free_search_symbols (struct symbol_search + *); + +/* The name of the ``main'' function. + FIXME: cagney/2001-03-20: Can't make main_name() const since some + of the calling code currently assumes that the string isn't + const. */ +extern void set_main_name (const char *name); +extern /*const */ char *main_name (void); + +#endif /* !defined(SYMTAB_H) */ diff --git a/gdb/xcoffread.c b/gdb/xcoffread.c new file mode 100644 index 0000000..0e85125 --- /dev/null +++ b/gdb/xcoffread.c @@ -0,0 +1,3049 @@ +/* Read AIX xcoff symbol tables and convert to internal format, for GDB. + Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, + 1996, 1997, 1998, 1999, 2000, 2001 + Free Software Foundation, Inc. + Derived from coffread.c, dbxread.c, and a lot of hacking. + Contributed by IBM Corporation. + + 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 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "bfd.h" + +#include <sys/types.h> +#include <fcntl.h> +#include <ctype.h> +#include "gdb_string.h" + +#include <sys/param.h> +#ifndef NO_SYS_FILE +#include <sys/file.h> +#endif +#include "gdb_stat.h" + +#include "coff/internal.h" +#include "libcoff.h" /* FIXME, internal data from BFD */ +#include "coff/xcoff.h" +#include "libxcoff.h" +#include "coff/rs6000.h" + +#include "symtab.h" +#include "gdbtypes.h" +#include "symfile.h" +#include "objfiles.h" +#include "buildsym.h" +#include "stabsread.h" +#include "expression.h" +#include "complaints.h" + +#include "gdb-stabs.h" + +/* For interface with stabsread.c. */ +#include "aout/stab_gnu.h" + + +/* We put a pointer to this structure in the read_symtab_private field + of the psymtab. */ + +struct symloc + { + + /* First symbol number for this file. */ + + int first_symnum; + + /* Number of symbols in the section of the symbol table devoted to + this file's symbols (actually, the section bracketed may contain + more than just this file's symbols). If numsyms is 0, the only + reason for this thing's existence is the dependency list. Nothing + else will happen when it is read in. */ + + int numsyms; + + /* Position of the start of the line number information for this psymtab. */ + unsigned int lineno_off; + }; + +/* Remember what we deduced to be the source language of this psymtab. */ + +static enum language psymtab_language = language_unknown; + + +/* Simplified internal version of coff symbol table information */ + +struct coff_symbol + { + char *c_name; + int c_symnum; /* symbol number of this entry */ + int c_naux; /* 0 if syment only, 1 if syment + auxent */ + long c_value; + unsigned char c_sclass; + int c_secnum; + unsigned int c_type; + }; + +/* last function's saved coff symbol `cs' */ + +static struct coff_symbol fcn_cs_saved; + +static bfd *symfile_bfd; + +/* Core address of start and end of text of current source file. + This is calculated from the first function seen after a C_FILE + symbol. */ + + +static CORE_ADDR cur_src_end_addr; + +/* Core address of the end of the first object file. */ + +static CORE_ADDR first_object_file_end; + +/* initial symbol-table-debug-string vector length */ + +#define INITIAL_STABVECTOR_LENGTH 40 + +/* Nonzero if within a function (so symbols should be local, + if nothing says specifically). */ + +int within_function; + +/* Size of a COFF symbol. I think it is always 18, so I'm not sure + there is any reason not to just use a #define, but might as well + ask BFD for the size and store it here, I guess. */ + +static unsigned local_symesz; + +struct coff_symfile_info + { + file_ptr min_lineno_offset; /* Where in file lowest line#s are */ + file_ptr max_lineno_offset; /* 1+last byte of line#s in file */ + + /* Pointer to the string table. */ + char *strtbl; + + /* Pointer to debug section. */ + char *debugsec; + + /* Pointer to the a.out symbol table. */ + char *symtbl; + + /* Number of symbols in symtbl. */ + int symtbl_num_syms; + + /* Offset in data section to TOC anchor. */ + CORE_ADDR toc_offset; + }; + +static struct complaint storclass_complaint = +{"Unexpected storage class: %d", 0, 0}; + +static struct complaint bf_notfound_complaint = +{"line numbers off, `.bf' symbol not found", 0, 0}; + +static struct complaint ef_complaint = +{"Mismatched .ef symbol ignored starting at symnum %d", 0, 0}; + +static struct complaint eb_complaint = +{"Mismatched .eb symbol ignored starting at symnum %d", 0, 0}; + +static void xcoff_initial_scan (struct objfile *, int); + +static void scan_xcoff_symtab (struct objfile *); + +static char *xcoff_next_symbol_text (struct objfile *); + +static void record_include_begin (struct coff_symbol *); + +static void +enter_line_range (struct subfile *, unsigned, unsigned, + CORE_ADDR, CORE_ADDR, unsigned *); + +static void init_stringtab (bfd *, file_ptr, struct objfile *); + +static void xcoff_symfile_init (struct objfile *); + +static void xcoff_new_init (struct objfile *); + +static void xcoff_symfile_finish (struct objfile *); + +static void +xcoff_symfile_offsets (struct objfile *, struct section_addr_info *addrs); + +static void find_linenos (bfd *, sec_ptr, PTR); + +static char *coff_getfilename (union internal_auxent *, struct objfile *); + +static void read_symbol (struct internal_syment *, int); + +static int read_symbol_lineno (int); + +static CORE_ADDR read_symbol_nvalue (int); + +static struct symbol *process_xcoff_symbol (struct coff_symbol *, + struct objfile *); + +static void read_xcoff_symtab (struct partial_symtab *); + +#if 0 +static void add_stab_to_list (char *, struct pending_stabs **); +#endif + +static int compare_lte (const void *, const void *); + +static struct linetable *arrange_linetable (struct linetable *); + +static void record_include_end (struct coff_symbol *); + +static void process_linenos (CORE_ADDR, CORE_ADDR); + + +/* Translate from a COFF section number (target_index) to a SECT_OFF_* + code. */ +static int secnum_to_section (int, struct objfile *); +static asection *secnum_to_bfd_section (int, struct objfile *); + +struct find_targ_sec_arg + { + int targ_index; + int *resultp; + asection **bfd_sect; + struct objfile *objfile; + }; + +static void find_targ_sec (bfd *, asection *, void *); + +static void +find_targ_sec (bfd *abfd, asection *sect, PTR obj) +{ + struct find_targ_sec_arg *args = (struct find_targ_sec_arg *) obj; + struct objfile *objfile = args->objfile; + if (sect->target_index == args->targ_index) + { + /* This is the section. Figure out what SECT_OFF_* code it is. */ + if (bfd_get_section_flags (abfd, sect) & SEC_CODE) + *args->resultp = SECT_OFF_TEXT (objfile); + else if (bfd_get_section_flags (abfd, sect) & SEC_LOAD) + *args->resultp = SECT_OFF_DATA (objfile); + else + *args->resultp = sect->index; + *args->bfd_sect = sect; + } +} + +/* Return the section number (SECT_OFF_*) that CS points to. */ +static int +secnum_to_section (int secnum, struct objfile *objfile) +{ + int off = SECT_OFF_TEXT (objfile); + asection *sect = NULL; + struct find_targ_sec_arg args; + args.targ_index = secnum; + args.resultp = &off; + args.bfd_sect = § + args.objfile = objfile; + bfd_map_over_sections (objfile->obfd, find_targ_sec, &args); + return off; +} + +/* Return the BFD section that CS points to. */ +static asection * +secnum_to_bfd_section (int secnum, struct objfile *objfile) +{ + int off = SECT_OFF_TEXT (objfile); + asection *sect = NULL; + struct find_targ_sec_arg args; + args.targ_index = secnum; + args.resultp = &off; + args.bfd_sect = § + args.objfile = objfile; + bfd_map_over_sections (objfile->obfd, find_targ_sec, &args); + return sect; +} + +/* add a given stab string into given stab vector. */ + +#if 0 + +static void +add_stab_to_list (char *stabname, struct pending_stabs **stabvector) +{ + if (*stabvector == NULL) + { + *stabvector = (struct pending_stabs *) + xmalloc (sizeof (struct pending_stabs) + + INITIAL_STABVECTOR_LENGTH * sizeof (char *)); + (*stabvector)->count = 0; + (*stabvector)->length = INITIAL_STABVECTOR_LENGTH; + } + else if ((*stabvector)->count >= (*stabvector)->length) + { + (*stabvector)->length += INITIAL_STABVECTOR_LENGTH; + *stabvector = (struct pending_stabs *) + xrealloc ((char *) *stabvector, sizeof (struct pending_stabs) + + (*stabvector)->length * sizeof (char *)); + } + (*stabvector)->stab[(*stabvector)->count++] = stabname; +} + +#endif +/* *INDENT-OFF* */ +/* Linenos are processed on a file-by-file basis. + + Two reasons: + + 1) xlc (IBM's native c compiler) postpones static function code + emission to the end of a compilation unit. This way it can + determine if those functions (statics) are needed or not, and + can do some garbage collection (I think). This makes line + numbers and corresponding addresses unordered, and we end up + with a line table like: + + + lineno addr + foo() 10 0x100 + 20 0x200 + 30 0x300 + + foo3() 70 0x400 + 80 0x500 + 90 0x600 + + static foo2() + 40 0x700 + 50 0x800 + 60 0x900 + + and that breaks gdb's binary search on line numbers, if the + above table is not sorted on line numbers. And that sort + should be on function based, since gcc can emit line numbers + like: + + 10 0x100 - for the init/test part of a for stmt. + 20 0x200 + 30 0x300 + 10 0x400 - for the increment part of a for stmt. + + arrange_linetable() will do this sorting. + + 2) aix symbol table might look like: + + c_file // beginning of a new file + .bi // beginning of include file + .ei // end of include file + .bi + .ei + + basically, .bi/.ei pairs do not necessarily encapsulate + their scope. They need to be recorded, and processed later + on when we come the end of the compilation unit. + Include table (inclTable) and process_linenos() handle + that. */ +/* *INDENT-ON* */ + + + +/* compare line table entry addresses. */ + +static int +compare_lte (const void *lte1p, const void *lte2p) +{ + struct linetable_entry *lte1 = (struct linetable_entry *) lte1p; + struct linetable_entry *lte2 = (struct linetable_entry *) lte2p; + return lte1->pc - lte2->pc; +} + +/* Given a line table with function entries are marked, arrange its functions + in ascending order and strip off function entry markers and return it in + a newly created table. If the old one is good enough, return the old one. */ +/* FIXME: I think all this stuff can be replaced by just passing + sort_linevec = 1 to end_symtab. */ + +static struct linetable * +arrange_linetable (struct linetable *oldLineTb) +{ + int ii, jj, newline, /* new line count */ + function_count; /* # of functions */ + + struct linetable_entry *fentry; /* function entry vector */ + int fentry_size; /* # of function entries */ + struct linetable *newLineTb; /* new line table */ + +#define NUM_OF_FUNCTIONS 20 + + fentry_size = NUM_OF_FUNCTIONS; + fentry = (struct linetable_entry *) + xmalloc (fentry_size * sizeof (struct linetable_entry)); + + for (function_count = 0, ii = 0; ii < oldLineTb->nitems; ++ii) + { + + if (oldLineTb->item[ii].line == 0) + { /* function entry found. */ + + if (function_count >= fentry_size) + { /* make sure you have room. */ + fentry_size *= 2; + fentry = (struct linetable_entry *) + xrealloc (fentry, fentry_size * sizeof (struct linetable_entry)); + } + fentry[function_count].line = ii; + fentry[function_count].pc = oldLineTb->item[ii].pc; + ++function_count; + } + } + + if (function_count == 0) + { + xfree (fentry); + return oldLineTb; + } + else if (function_count > 1) + qsort (fentry, function_count, sizeof (struct linetable_entry), compare_lte); + + /* allocate a new line table. */ + newLineTb = (struct linetable *) + xmalloc + (sizeof (struct linetable) + + (oldLineTb->nitems - function_count) * sizeof (struct linetable_entry)); + + /* if line table does not start with a function beginning, copy up until + a function begin. */ + + newline = 0; + if (oldLineTb->item[0].line != 0) + for (newline = 0; + newline < oldLineTb->nitems && oldLineTb->item[newline].line; ++newline) + newLineTb->item[newline] = oldLineTb->item[newline]; + + /* Now copy function lines one by one. */ + + for (ii = 0; ii < function_count; ++ii) + { + for (jj = fentry[ii].line + 1; + jj < oldLineTb->nitems && oldLineTb->item[jj].line != 0; + ++jj, ++newline) + newLineTb->item[newline] = oldLineTb->item[jj]; + } + xfree (fentry); + newLineTb->nitems = oldLineTb->nitems - function_count; + return newLineTb; +} + +/* include file support: C_BINCL/C_EINCL pairs will be kept in the + following `IncludeChain'. At the end of each symtab (end_symtab), + we will determine if we should create additional symtab's to + represent if (the include files. */ + + +typedef struct _inclTable +{ + char *name; /* include filename */ + + /* Offsets to the line table. end points to the last entry which is + part of this include file. */ + int begin, end; + + struct subfile *subfile; + unsigned funStartLine; /* start line # of its function */ +} +InclTable; + +#define INITIAL_INCLUDE_TABLE_LENGTH 20 +static InclTable *inclTable; /* global include table */ +static int inclIndx; /* last entry to table */ +static int inclLength; /* table length */ +static int inclDepth; /* nested include depth */ + +static void allocate_include_entry (void); + +static void +record_include_begin (struct coff_symbol *cs) +{ + if (inclDepth) + { + /* In xcoff, we assume include files cannot be nested (not in .c files + of course, but in corresponding .s files.). */ + + /* This can happen with old versions of GCC. + GCC 2.3.3-930426 does not exhibit this on a test case which + a user said produced the message for him. */ + static struct complaint msg = + {"Nested C_BINCL symbols", 0, 0}; + complain (&msg); + } + ++inclDepth; + + allocate_include_entry (); + + inclTable[inclIndx].name = cs->c_name; + inclTable[inclIndx].begin = cs->c_value; +} + +static void +record_include_end (struct coff_symbol *cs) +{ + InclTable *pTbl; + + if (inclDepth == 0) + { + static struct complaint msg = + {"Mismatched C_BINCL/C_EINCL pair", 0, 0}; + complain (&msg); + } + + allocate_include_entry (); + + pTbl = &inclTable[inclIndx]; + pTbl->end = cs->c_value; + + --inclDepth; + ++inclIndx; +} + +static void +allocate_include_entry (void) +{ + if (inclTable == NULL) + { + inclTable = (InclTable *) + xmalloc (sizeof (InclTable) * INITIAL_INCLUDE_TABLE_LENGTH); + memset (inclTable, + '\0', sizeof (InclTable) * INITIAL_INCLUDE_TABLE_LENGTH); + inclLength = INITIAL_INCLUDE_TABLE_LENGTH; + inclIndx = 0; + } + else if (inclIndx >= inclLength) + { + inclLength += INITIAL_INCLUDE_TABLE_LENGTH; + inclTable = (InclTable *) + xrealloc (inclTable, sizeof (InclTable) * inclLength); + memset (inclTable + inclLength - INITIAL_INCLUDE_TABLE_LENGTH, + '\0', sizeof (InclTable) * INITIAL_INCLUDE_TABLE_LENGTH); + } +} + +/* Global variable to pass the psymtab down to all the routines involved + in psymtab to symtab processing. */ +static struct partial_symtab *this_symtab_psymtab; + +/* given the start and end addresses of a compilation unit (or a csect, + at times) process its lines and create appropriate line vectors. */ + +static void +process_linenos (CORE_ADDR start, CORE_ADDR end) +{ + int offset, ii; + file_ptr max_offset = + ((struct coff_symfile_info *) this_symtab_psymtab->objfile->sym_private) + ->max_lineno_offset; + + /* subfile structure for the main compilation unit. */ + struct subfile main_subfile; + + /* In the main source file, any time we see a function entry, we + reset this variable to function's absolute starting line number. + All the following line numbers in the function are relative to + this, and we record absolute line numbers in record_line(). */ + + unsigned int main_source_baseline = 0; + + unsigned *firstLine; + + offset = + ((struct symloc *) this_symtab_psymtab->read_symtab_private)->lineno_off; + if (offset == 0) + goto return_after_cleanup; + + memset (&main_subfile, '\0', sizeof (main_subfile)); + + if (inclIndx == 0) + /* All source lines were in the main source file. None in include files. */ + + enter_line_range (&main_subfile, offset, 0, start, end, + &main_source_baseline); + + else + { + /* There was source with line numbers in include files. */ + + int linesz = + coff_data (this_symtab_psymtab->objfile->obfd)->local_linesz; + main_source_baseline = 0; + + for (ii = 0; ii < inclIndx; ++ii) + { + struct subfile *tmpSubfile; + + /* If there is main file source before include file, enter it. */ + if (offset < inclTable[ii].begin) + { + enter_line_range + (&main_subfile, offset, inclTable[ii].begin - linesz, + start, 0, &main_source_baseline); + } + + /* Have a new subfile for the include file. */ + + tmpSubfile = inclTable[ii].subfile = + (struct subfile *) xmalloc (sizeof (struct subfile)); + + memset (tmpSubfile, '\0', sizeof (struct subfile)); + firstLine = &(inclTable[ii].funStartLine); + + /* Enter include file's lines now. */ + enter_line_range (tmpSubfile, inclTable[ii].begin, + inclTable[ii].end, start, 0, firstLine); + + if (offset <= inclTable[ii].end) + offset = inclTable[ii].end + linesz; + } + + /* All the include files' line have been processed at this point. Now, + enter remaining lines of the main file, if any left. */ + if (offset < max_offset + 1 - linesz) + { + enter_line_range (&main_subfile, offset, 0, start, end, + &main_source_baseline); + } + } + + /* Process main file's line numbers. */ + if (main_subfile.line_vector) + { + struct linetable *lineTb, *lv; + + lv = main_subfile.line_vector; + + /* Line numbers are not necessarily ordered. xlc compilation will + put static function to the end. */ + + lineTb = arrange_linetable (lv); + if (lv == lineTb) + { + current_subfile->line_vector = (struct linetable *) + xrealloc (lv, (sizeof (struct linetable) + + lv->nitems * sizeof (struct linetable_entry))); + } + else + { + xfree (lv); + current_subfile->line_vector = lineTb; + } + + current_subfile->line_vector_length = + current_subfile->line_vector->nitems; + } + + /* Now, process included files' line numbers. */ + + for (ii = 0; ii < inclIndx; ++ii) + { + if ((inclTable[ii].subfile)->line_vector) /* Useless if!!! FIXMEmgo */ + { + struct linetable *lineTb, *lv; + + lv = (inclTable[ii].subfile)->line_vector; + + /* Line numbers are not necessarily ordered. xlc compilation will + put static function to the end. */ + + lineTb = arrange_linetable (lv); + + push_subfile (); + + /* For the same include file, we might want to have more than one + subfile. This happens if we have something like: + + ...... + #include "foo.h" + ...... + #include "foo.h" + ...... + + while foo.h including code in it. (stupid but possible) + Since start_subfile() looks at the name and uses an + existing one if finds, we need to provide a fake name and + fool it. */ + +#if 0 + start_subfile (inclTable[ii].name, (char *) 0); +#else + { + /* Pick a fake name that will produce the same results as this + one when passed to deduce_language_from_filename. Kludge on + top of kludge. */ + char *fakename = strrchr (inclTable[ii].name, '.'); + if (fakename == NULL) + fakename = " ?"; + start_subfile (fakename, (char *) 0); + xfree (current_subfile->name); + } + current_subfile->name = xstrdup (inclTable[ii].name); +#endif + + if (lv == lineTb) + { + current_subfile->line_vector = + (struct linetable *) xrealloc + (lv, (sizeof (struct linetable) + + lv->nitems * sizeof (struct linetable_entry))); + + } + else + { + xfree (lv); + current_subfile->line_vector = lineTb; + } + + current_subfile->line_vector_length = + current_subfile->line_vector->nitems; + start_subfile (pop_subfile (), (char *) 0); + } + } + +return_after_cleanup: + + /* We don't want to keep alloc/free'ing the global include file table. */ + inclIndx = 0; + + /* Start with a fresh subfile structure for the next file. */ + memset (&main_subfile, '\0', sizeof (struct subfile)); +} + +void +aix_process_linenos (void) +{ + /* process line numbers and enter them into line vector */ + process_linenos (last_source_start_addr, cur_src_end_addr); +} + + +/* Enter a given range of lines into the line vector. + can be called in the following two ways: + enter_line_range (subfile, beginoffset, endoffset, startaddr, 0, firstLine) or + enter_line_range (subfile, beginoffset, 0, startaddr, endaddr, firstLine) + + endoffset points to the last line table entry that we should pay + attention to. */ + +static void +enter_line_range (struct subfile *subfile, unsigned beginoffset, unsigned endoffset, /* offsets to line table */ + CORE_ADDR startaddr, /* offsets to line table */ + CORE_ADDR endaddr, unsigned *firstLine) +{ + unsigned int curoffset; + CORE_ADDR addr; + void *ext_lnno; + struct internal_lineno int_lnno; + unsigned int limit_offset; + bfd *abfd; + int linesz; + + if (endoffset == 0 && startaddr == 0 && endaddr == 0) + return; + curoffset = beginoffset; + limit_offset = + ((struct coff_symfile_info *) this_symtab_psymtab->objfile->sym_private) + ->max_lineno_offset; + + if (endoffset != 0) + { + if (endoffset >= limit_offset) + { + static struct complaint msg = + {"Bad line table offset in C_EINCL directive", 0, 0}; + complain (&msg); + return; + } + limit_offset = endoffset; + } + else + limit_offset -= 1; + + abfd = this_symtab_psymtab->objfile->obfd; + linesz = coff_data (abfd)->local_linesz; + ext_lnno = alloca (linesz); + + while (curoffset <= limit_offset) + { + bfd_seek (abfd, curoffset, SEEK_SET); + bfd_bread (ext_lnno, linesz, abfd); + bfd_coff_swap_lineno_in (abfd, ext_lnno, &int_lnno); + + /* Find the address this line represents. */ + addr = (int_lnno.l_lnno + ? int_lnno.l_addr.l_paddr + : read_symbol_nvalue (int_lnno.l_addr.l_symndx)); + addr += ANOFFSET (this_symtab_psymtab->objfile->section_offsets, + SECT_OFF_TEXT (this_symtab_psymtab->objfile)); + + if (addr < startaddr || (endaddr && addr >= endaddr)) + return; + + if (int_lnno.l_lnno == 0) + { + *firstLine = read_symbol_lineno (int_lnno.l_addr.l_symndx); + record_line (subfile, 0, addr); + --(*firstLine); + } + else + record_line (subfile, *firstLine + int_lnno.l_lnno, addr); + curoffset += linesz; + } +} + + +/* Save the vital information for use when closing off the current file. + NAME is the file name the symbols came from, START_ADDR is the first + text address for the file, and SIZE is the number of bytes of text. */ + +#define complete_symtab(name, start_addr) { \ + last_source_file = savestring (name, strlen (name)); \ + last_source_start_addr = start_addr; \ +} + + +/* Refill the symbol table input buffer + and set the variables that control fetching entries from it. + Reports an error if no data available. + This function can read past the end of the symbol table + (into the string table) but this does no harm. */ + +/* Reading symbol table has to be fast! Keep the followings as macros, rather + than functions. */ + +#define RECORD_MINIMAL_SYMBOL(NAME, ADDR, TYPE, SECTION, OBJFILE) \ +{ \ + char *namestr; \ + namestr = (NAME); \ + if (namestr[0] == '.') ++namestr; \ + prim_record_minimal_symbol_and_info (namestr, (ADDR), (TYPE), \ + (char *)NULL, (SECTION), (asection *)NULL, (OBJFILE)); \ + misc_func_recorded = 1; \ +} + + +/* xcoff has static blocks marked in `.bs', `.es' pairs. They cannot be + nested. At any given time, a symbol can only be in one static block. + This is the base address of current static block, zero if non exists. */ + +static int static_block_base = 0; + +/* Section number for the current static block. */ + +static int static_block_section = -1; + +/* true if space for symbol name has been allocated. */ + +static int symname_alloced = 0; + +/* Next symbol to read. Pointer into raw seething symbol table. */ + +static char *raw_symbol; + +/* This is the function which stabsread.c calls to get symbol + continuations. */ + +static char * +xcoff_next_symbol_text (struct objfile *objfile) +{ + struct internal_syment symbol; + static struct complaint msg = + {"Unexpected symbol continuation", 0, 0}; + char *retval; + /* FIXME: is this the same as the passed arg? */ + objfile = this_symtab_psymtab->objfile; + + bfd_coff_swap_sym_in (objfile->obfd, raw_symbol, &symbol); + if (symbol.n_zeroes) + { + complain (&msg); + + /* Return something which points to '\0' and hope the symbol reading + code does something reasonable. */ + retval = ""; + } + else if (symbol.n_sclass & 0x80) + { + retval = + ((struct coff_symfile_info *) objfile->sym_private)->debugsec + + symbol.n_offset; + raw_symbol += + coff_data (objfile->obfd)->local_symesz; + ++symnum; + } + else + { + complain (&msg); + + /* Return something which points to '\0' and hope the symbol reading + code does something reasonable. */ + retval = ""; + } + return retval; +} + +/* Read symbols for a given partial symbol table. */ + +static void +read_xcoff_symtab (struct partial_symtab *pst) +{ + struct objfile *objfile = pst->objfile; + bfd *abfd = objfile->obfd; + char *raw_auxptr; /* Pointer to first raw aux entry for sym */ + char *strtbl = ((struct coff_symfile_info *) objfile->sym_private)->strtbl; + char *debugsec = + ((struct coff_symfile_info *) objfile->sym_private)->debugsec; + char *debugfmt = bfd_xcoff_is_xcoff64 (abfd) ? "XCOFF64" : "XCOFF"; + + struct internal_syment symbol[1]; + union internal_auxent main_aux; + struct coff_symbol cs[1]; + CORE_ADDR file_start_addr = 0; + CORE_ADDR file_end_addr = 0; + + int next_file_symnum = -1; + unsigned int max_symnum; + int just_started = 1; + int depth = 0; + int fcn_start_addr = 0; + + struct coff_symbol fcn_stab_saved; + + /* fcn_cs_saved is global because process_xcoff_symbol needs it. */ + union internal_auxent fcn_aux_saved; + struct context_stack *new; + + char *filestring = " _start_ "; /* Name of the current file. */ + + char *last_csect_name; /* last seen csect's name and value */ + CORE_ADDR last_csect_val; + int last_csect_sec; + + this_symtab_psymtab = pst; + + /* Get the appropriate COFF "constants" related to the file we're + handling. */ + local_symesz = coff_data (abfd)->local_symesz; + + last_source_file = NULL; + last_csect_name = 0; + last_csect_val = 0; + + start_stabs (); + start_symtab (filestring, (char *) NULL, file_start_addr); + record_debugformat (debugfmt); + symnum = ((struct symloc *) pst->read_symtab_private)->first_symnum; + max_symnum = + symnum + ((struct symloc *) pst->read_symtab_private)->numsyms; + first_object_file_end = 0; + + raw_symbol = + ((struct coff_symfile_info *) objfile->sym_private)->symtbl + + symnum * local_symesz; + + while (symnum < max_symnum) + { + + QUIT; /* make this command interruptable. */ + + /* READ_ONE_SYMBOL (symbol, cs, symname_alloced); */ + /* read one symbol into `cs' structure. After processing the + whole symbol table, only string table will be kept in memory, + symbol table and debug section of xcoff will be freed. Thus + we can mark symbols with names in string table as + `alloced'. */ + { + int ii; + + /* Swap and align the symbol into a reasonable C structure. */ + bfd_coff_swap_sym_in (abfd, raw_symbol, symbol); + + cs->c_symnum = symnum; + cs->c_naux = symbol->n_numaux; + if (symbol->n_zeroes) + { + symname_alloced = 0; + /* We must use the original, unswapped, name here so the name field + pointed to by cs->c_name will persist throughout xcoffread. If + we use the new field, it gets overwritten for each symbol. */ + cs->c_name = ((struct external_syment *) raw_symbol)->e.e_name; + /* If it's exactly E_SYMNMLEN characters long it isn't + '\0'-terminated. */ + if (cs->c_name[E_SYMNMLEN - 1] != '\0') + { + char *p; + p = obstack_alloc (&objfile->symbol_obstack, E_SYMNMLEN + 1); + strncpy (p, cs->c_name, E_SYMNMLEN); + p[E_SYMNMLEN] = '\0'; + cs->c_name = p; + symname_alloced = 1; + } + } + else if (symbol->n_sclass & 0x80) + { + cs->c_name = debugsec + symbol->n_offset; + symname_alloced = 0; + } + else + { + /* in string table */ + cs->c_name = strtbl + (int) symbol->n_offset; + symname_alloced = 1; + } + cs->c_value = symbol->n_value; + cs->c_sclass = symbol->n_sclass; + cs->c_secnum = symbol->n_scnum; + cs->c_type = (unsigned) symbol->n_type; + + raw_symbol += local_symesz; + ++symnum; + + /* Save addr of first aux entry. */ + raw_auxptr = raw_symbol; + + /* Skip all the auxents associated with this symbol. */ + for (ii = symbol->n_numaux; ii; --ii) + { + raw_symbol += coff_data (abfd)->local_auxesz; + ++symnum; + } + } + + /* if symbol name starts with ".$" or "$", ignore it. */ + if (cs->c_name[0] == '$' + || (cs->c_name[1] == '$' && cs->c_name[0] == '.')) + continue; + + if (cs->c_symnum == next_file_symnum && cs->c_sclass != C_FILE) + { + if (last_source_file) + { + pst->symtab = + end_symtab (cur_src_end_addr, objfile, SECT_OFF_TEXT (objfile)); + end_stabs (); + } + + start_stabs (); + start_symtab ("_globals_", (char *) NULL, (CORE_ADDR) 0); + record_debugformat (debugfmt); + cur_src_end_addr = first_object_file_end; + /* done with all files, everything from here on is globals */ + } + + if ((cs->c_sclass == C_EXT || cs->c_sclass == C_HIDEXT) + && cs->c_naux == 1) + { + /* Dealing with a symbol with a csect entry. */ + +#define CSECT(PP) ((PP)->x_csect) +#define CSECT_LEN(PP) (CSECT(PP).x_scnlen.l) +#define CSECT_ALIGN(PP) (SMTYP_ALIGN(CSECT(PP).x_smtyp)) +#define CSECT_SMTYP(PP) (SMTYP_SMTYP(CSECT(PP).x_smtyp)) +#define CSECT_SCLAS(PP) (CSECT(PP).x_smclas) + + /* Convert the auxent to something we can access. */ + bfd_coff_swap_aux_in (abfd, raw_auxptr, cs->c_type, cs->c_sclass, + 0, cs->c_naux, &main_aux); + + switch (CSECT_SMTYP (&main_aux)) + { + + case XTY_ER: + /* Ignore all external references. */ + continue; + + case XTY_SD: + /* A section description. */ + { + switch (CSECT_SCLAS (&main_aux)) + { + + case XMC_PR: + { + + /* A program csect is seen. We have to allocate one + symbol table for each program csect. Normally gdb + prefers one symtab for each source file. In case + of AIX, one source file might include more than one + [PR] csect, and they don't have to be adjacent in + terms of the space they occupy in memory. Thus, one + single source file might get fragmented in the + memory and gdb's file start and end address + approach does not work! GCC (and I think xlc) seem + to put all the code in the unnamed program csect. */ + + if (last_csect_name) + { + complete_symtab (filestring, file_start_addr); + cur_src_end_addr = file_end_addr; + end_symtab (file_end_addr, objfile, SECT_OFF_TEXT (objfile)); + end_stabs (); + start_stabs (); + /* Give all csects for this source file the same + name. */ + start_symtab (filestring, NULL, (CORE_ADDR) 0); + record_debugformat (debugfmt); + } + + /* If this is the very first csect seen, + basically `__start'. */ + if (just_started) + { + first_object_file_end + = cs->c_value + CSECT_LEN (&main_aux); + just_started = 0; + } + + file_start_addr = + cs->c_value + ANOFFSET (objfile->section_offsets, + SECT_OFF_TEXT (objfile)); + file_end_addr = file_start_addr + CSECT_LEN (&main_aux); + + if (cs->c_name && (cs->c_name[0] == '.' + || cs->c_name[0] == '@')) + { + last_csect_name = cs->c_name; + last_csect_val = cs->c_value; + last_csect_sec = secnum_to_section (cs->c_secnum, objfile); + } + } + continue; + + /* All other symbols are put into the minimal symbol + table only. */ + + case XMC_RW: + continue; + + case XMC_TC0: + continue; + + case XMC_TC: + continue; + + default: + /* Ignore the symbol. */ + continue; + } + } + break; + + case XTY_LD: + + switch (CSECT_SCLAS (&main_aux)) + { + case XMC_PR: + /* a function entry point. */ + function_entry_point: + + fcn_start_addr = cs->c_value; + + /* save the function header info, which will be used + when `.bf' is seen. */ + fcn_cs_saved = *cs; + fcn_aux_saved = main_aux; + continue; + + case XMC_GL: + /* shared library function trampoline code entry point. */ + continue; + + case XMC_DS: + /* The symbols often have the same names as debug symbols for + functions, and confuse lookup_symbol. */ + continue; + + default: + /* xlc puts each variable in a separate csect, so we get + an XTY_SD for each variable. But gcc puts several + variables in a csect, so that each variable only gets + an XTY_LD. This will typically be XMC_RW; I suspect + XMC_RO and XMC_BS might be possible too. + These variables are put in the minimal symbol table + only. */ + continue; + } + break; + + case XTY_CM: + /* Common symbols are put into the minimal symbol table only. */ + continue; + + default: + break; + } + } + + /* If explicitly specified as a function, treat is as one. This check + evaluates to true for @FIX* bigtoc CSECT symbols, so it must occur + after the above CSECT check. */ + if (ISFCN (cs->c_type) && cs->c_sclass != C_TPDEF) + { + bfd_coff_swap_aux_in (abfd, raw_auxptr, cs->c_type, cs->c_sclass, + 0, cs->c_naux, &main_aux); + goto function_entry_point; + } + + switch (cs->c_sclass) + { + + case C_FILE: + + /* c_value field contains symnum of next .file entry in table + or symnum of first global after last .file. */ + + next_file_symnum = cs->c_value; + + /* Complete symbol table for last object file containing + debugging information. */ + + /* Whether or not there was a csect in the previous file, we + have to call `end_stabs' and `start_stabs' to reset + type_vector, line_vector, etc. structures. */ + + complete_symtab (filestring, file_start_addr); + cur_src_end_addr = file_end_addr; + end_symtab (file_end_addr, objfile, SECT_OFF_TEXT (objfile)); + end_stabs (); + + /* XCOFF, according to the AIX 3.2 documentation, puts the filename + in cs->c_name. But xlc 1.3.0.2 has decided to do things the + standard COFF way and put it in the auxent. We use the auxent if + the symbol is ".file" and an auxent exists, otherwise use the symbol + itself. Simple enough. */ + if (!strcmp (cs->c_name, ".file") && cs->c_naux > 0) + { + bfd_coff_swap_aux_in (abfd, raw_auxptr, cs->c_type, cs->c_sclass, + 0, cs->c_naux, &main_aux); + filestring = coff_getfilename (&main_aux, objfile); + } + else + filestring = cs->c_name; + + start_stabs (); + start_symtab (filestring, (char *) NULL, (CORE_ADDR) 0); + record_debugformat (debugfmt); + last_csect_name = 0; + + /* reset file start and end addresses. A compilation unit with no text + (only data) should have zero file boundaries. */ + file_start_addr = file_end_addr = 0; + break; + + case C_FUN: + fcn_stab_saved = *cs; + break; + + case C_FCN: + if (STREQ (cs->c_name, ".bf")) + { + CORE_ADDR off = ANOFFSET (objfile->section_offsets, + SECT_OFF_TEXT (objfile)); + bfd_coff_swap_aux_in (abfd, raw_auxptr, cs->c_type, cs->c_sclass, + 0, cs->c_naux, &main_aux); + + within_function = 1; + + new = push_context (0, fcn_start_addr + off); + + new->name = define_symbol + (fcn_cs_saved.c_value + off, + fcn_stab_saved.c_name, 0, 0, objfile); + if (new->name != NULL) + SYMBOL_SECTION (new->name) = SECT_OFF_TEXT (objfile); + } + else if (STREQ (cs->c_name, ".ef")) + { + + bfd_coff_swap_aux_in (abfd, raw_auxptr, cs->c_type, cs->c_sclass, + 0, cs->c_naux, &main_aux); + + /* The value of .ef is the address of epilogue code; + not useful for gdb. */ + /* { main_aux.x_sym.x_misc.x_lnsz.x_lnno + contains number of lines to '}' */ + + if (context_stack_depth <= 0) + { /* We attempted to pop an empty context stack */ + complain (&ef_complaint, cs->c_symnum); + within_function = 0; + break; + } + new = pop_context (); + /* Stack must be empty now. */ + if (context_stack_depth > 0 || new == NULL) + { + complain (&ef_complaint, cs->c_symnum); + within_function = 0; + break; + } + + finish_block (new->name, &local_symbols, new->old_blocks, + new->start_addr, + (fcn_cs_saved.c_value + + fcn_aux_saved.x_sym.x_misc.x_fsize + + ANOFFSET (objfile->section_offsets, + SECT_OFF_TEXT (objfile))), + objfile); + within_function = 0; + } + break; + + case C_BSTAT: + /* Begin static block. */ + { + struct internal_syment symbol; + + read_symbol (&symbol, cs->c_value); + static_block_base = symbol.n_value; + static_block_section = + secnum_to_section (symbol.n_scnum, objfile); + } + break; + + case C_ESTAT: + /* End of static block. */ + static_block_base = 0; + static_block_section = -1; + break; + + case C_ARG: + case C_REGPARM: + case C_REG: + case C_TPDEF: + case C_STRTAG: + case C_UNTAG: + case C_ENTAG: + { + static struct complaint msg = + {"Unrecognized storage class %d.", 0, 0}; + complain (&msg, cs->c_sclass); + } + break; + + case C_LABEL: + case C_NULL: + /* Ignore these. */ + break; + + case C_HIDEXT: + case C_STAT: + break; + + case C_BINCL: + /* beginning of include file */ + /* In xlc output, C_BINCL/C_EINCL pair doesn't show up in sorted + order. Thus, when wee see them, we might not know enough info + to process them. Thus, we'll be saving them into a table + (inclTable) and postpone their processing. */ + + record_include_begin (cs); + break; + + case C_EINCL: + /* End of include file. */ + /* See the comment after case C_BINCL. */ + record_include_end (cs); + break; + + case C_BLOCK: + if (STREQ (cs->c_name, ".bb")) + { + depth++; + new = push_context (depth, + (cs->c_value + + ANOFFSET (objfile->section_offsets, + SECT_OFF_TEXT (objfile)))); + } + else if (STREQ (cs->c_name, ".eb")) + { + if (context_stack_depth <= 0) + { /* We attempted to pop an empty context stack */ + complain (&eb_complaint, cs->c_symnum); + break; + } + new = pop_context (); + if (depth-- != new->depth) + { + complain (&eb_complaint, cs->c_symnum); + break; + } + if (local_symbols && context_stack_depth > 0) + { + /* Make a block for the local symbols within. */ + finish_block (new->name, &local_symbols, new->old_blocks, + new->start_addr, + (cs->c_value + + ANOFFSET (objfile->section_offsets, + SECT_OFF_TEXT (objfile))), + objfile); + } + local_symbols = new->locals; + } + break; + + default: + process_xcoff_symbol (cs, objfile); + break; + } + } + + if (last_source_file) + { + struct symtab *s; + + complete_symtab (filestring, file_start_addr); + cur_src_end_addr = file_end_addr; + s = end_symtab (file_end_addr, objfile, SECT_OFF_TEXT (objfile)); + /* When reading symbols for the last C_FILE of the objfile, try + to make sure that we set pst->symtab to the symtab for the + file, not to the _globals_ symtab. I'm not sure whether this + actually works right or when/if it comes up. */ + if (pst->symtab == NULL) + pst->symtab = s; + end_stabs (); + } +} + +#define SYMBOL_DUP(SYMBOL1, SYMBOL2) \ + (SYMBOL2) = (struct symbol *) \ + obstack_alloc (&objfile->symbol_obstack, sizeof (struct symbol)); \ + *(SYMBOL2) = *(SYMBOL1); + + +#define SYMNAME_ALLOC(NAME, ALLOCED) \ + (ALLOCED) ? (NAME) : obsavestring ((NAME), strlen (NAME), &objfile->symbol_obstack); + + +static struct type *func_symbol_type; +static struct type *var_symbol_type; + +/* process one xcoff symbol. */ + +static struct symbol * +process_xcoff_symbol (register struct coff_symbol *cs, struct objfile *objfile) +{ + struct symbol onesymbol; + register struct symbol *sym = &onesymbol; + struct symbol *sym2 = NULL; + char *name, *pp; + + int sec; + CORE_ADDR off; + + if (cs->c_secnum < 0) + { + /* The value is a register number, offset within a frame, etc., + and does not get relocated. */ + off = 0; + sec = -1; + } + else + { + sec = secnum_to_section (cs->c_secnum, objfile); + off = ANOFFSET (objfile->section_offsets, sec); + } + + name = cs->c_name; + if (name[0] == '.') + ++name; + + memset (sym, '\0', sizeof (struct symbol)); + + /* default assumptions */ + SYMBOL_VALUE_ADDRESS (sym) = cs->c_value + off; + SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; + SYMBOL_SECTION (sym) = secnum_to_section (cs->c_secnum, objfile); + + if (ISFCN (cs->c_type)) + { + /* At this point, we don't know the type of the function. This + will be patched with the type from its stab entry later on in + patch_block_stabs (), unless the file was compiled without -g. */ + + SYMBOL_NAME (sym) = SYMNAME_ALLOC (name, symname_alloced); + SYMBOL_TYPE (sym) = func_symbol_type; + + SYMBOL_CLASS (sym) = LOC_BLOCK; + SYMBOL_DUP (sym, sym2); + + if (cs->c_sclass == C_EXT) + add_symbol_to_list (sym2, &global_symbols); + else if (cs->c_sclass == C_HIDEXT || cs->c_sclass == C_STAT) + add_symbol_to_list (sym2, &file_symbols); + } + else + { + /* In case we can't figure out the type, provide default. */ + SYMBOL_TYPE (sym) = var_symbol_type; + + switch (cs->c_sclass) + { +#if 0 + /* The values of functions and global symbols are now resolved + via the global_sym_chain in stabsread.c. */ + case C_FUN: + if (fcn_cs_saved.c_sclass == C_EXT) + add_stab_to_list (name, &global_stabs); + else + add_stab_to_list (name, &file_stabs); + break; + + case C_GSYM: + add_stab_to_list (name, &global_stabs); + break; +#endif + + case C_BCOMM: + common_block_start (cs->c_name, objfile); + break; + + case C_ECOMM: + common_block_end (objfile); + break; + + default: + complain (&storclass_complaint, cs->c_sclass); + /* FALLTHROUGH */ + + case C_DECL: + case C_PSYM: + case C_RPSYM: + case C_ECOML: + case C_LSYM: + case C_RSYM: + case C_GSYM: + + { + sym = define_symbol (cs->c_value + off, cs->c_name, 0, 0, objfile); + if (sym != NULL) + { + SYMBOL_SECTION (sym) = sec; + } + return sym; + } + + case C_STSYM: + + /* For xlc (not GCC), the 'V' symbol descriptor is used for + all statics and we need to distinguish file-scope versus + function-scope using within_function. We do this by + changing the string we pass to define_symbol to use 'S' + where we need to, which is not necessarily super-clean, + but seems workable enough. */ + + if (*name == ':' || (pp = (char *) strchr (name, ':')) == NULL) + return NULL; + + ++pp; + if (*pp == 'V' && !within_function) + *pp = 'S'; + sym = define_symbol ((cs->c_value + + ANOFFSET (objfile->section_offsets, + static_block_section)), + cs->c_name, 0, 0, objfile); + if (sym != NULL) + { + SYMBOL_VALUE_ADDRESS (sym) += static_block_base; + SYMBOL_SECTION (sym) = static_block_section; + } + return sym; + + } + } + return sym2; +} + +/* Extract the file name from the aux entry of a C_FILE symbol. + Result is in static storage and is only good for temporary use. */ + +static char * +coff_getfilename (union internal_auxent *aux_entry, struct objfile *objfile) +{ + static char buffer[BUFSIZ]; + + if (aux_entry->x_file.x_n.x_zeroes == 0) + strcpy (buffer, + ((struct coff_symfile_info *) objfile->sym_private)->strtbl + + aux_entry->x_file.x_n.x_offset); + else + { + strncpy (buffer, aux_entry->x_file.x_fname, FILNMLEN); + buffer[FILNMLEN] = '\0'; + } + return (buffer); +} + +/* Set *SYMBOL to symbol number symno in symtbl. */ +static void +read_symbol (struct internal_syment *symbol, int symno) +{ + int nsyms = + ((struct coff_symfile_info *) this_symtab_psymtab->objfile->sym_private) + ->symtbl_num_syms; + char *stbl = + ((struct coff_symfile_info *) this_symtab_psymtab->objfile->sym_private) + ->symtbl; + if (symno < 0 || symno >= nsyms) + { + static struct complaint msg = + {"Invalid symbol offset", 0, 0}; + complain (&msg); + symbol->n_value = 0; + symbol->n_scnum = -1; + return; + } + bfd_coff_swap_sym_in (this_symtab_psymtab->objfile->obfd, + stbl + (symno * local_symesz), + symbol); +} + +/* Get value corresponding to symbol number symno in symtbl. */ + +static CORE_ADDR +read_symbol_nvalue (int symno) +{ + struct internal_syment symbol[1]; + + read_symbol (symbol, symno); + return symbol->n_value; +} + + +/* Find the address of the function corresponding to symno, where + symno is the symbol pointed to by the linetable. */ + +static int +read_symbol_lineno (int symno) +{ + struct objfile *objfile = this_symtab_psymtab->objfile; + boolean xcoff64 = bfd_xcoff_is_xcoff64 (objfile->obfd); + + struct coff_symfile_info *info = + (struct coff_symfile_info *)objfile->sym_private; + int nsyms = info->symtbl_num_syms; + char *stbl = info->symtbl; + char *strtbl = info->strtbl; + + struct internal_syment symbol[1]; + union internal_auxent main_aux[1]; + + if (symno < 0) + { + complain (&bf_notfound_complaint); + return 0; + } + + /* Note that just searching for a short distance (e.g. 50 symbols) + is not enough, at least in the following case. + + .extern foo + [many .stabx entries] + [a few functions, referring to foo] + .globl foo + .bf + + What happens here is that the assembler moves the .stabx entries + to right before the ".bf" for foo, but the symbol for "foo" is before + all the stabx entries. See PR gdb/2222. */ + + /* Maintaining a table of .bf entries might be preferable to this search. + If I understand things correctly it would need to be done only for + the duration of a single psymtab to symtab conversion. */ + while (symno < nsyms) + { + bfd_coff_swap_sym_in (symfile_bfd, + stbl + (symno * local_symesz), symbol); + if (symbol->n_sclass == C_FCN) + { + char *name = xcoff64 ? strtbl + symbol->n_offset : symbol->n_name; + if (STREQ (name, ".bf")) + goto gotit; + } + symno += symbol->n_numaux + 1; + } + + complain (&bf_notfound_complaint); + return 0; + +gotit: + /* take aux entry and return its lineno */ + symno++; + bfd_coff_swap_aux_in (objfile->obfd, stbl + symno * local_symesz, + symbol->n_type, symbol->n_sclass, + 0, symbol->n_numaux, main_aux); + + return main_aux->x_sym.x_misc.x_lnsz.x_lnno; +} + +/* Support for line number handling */ + +/* This function is called for every section; it finds the outer limits + * of the line table (minimum and maximum file offset) so that the + * mainline code can read the whole thing for efficiency. + */ +static void +find_linenos (bfd *abfd, sec_ptr asect, PTR vpinfo) +{ + struct coff_symfile_info *info; + int size, count; + file_ptr offset, maxoff; + + count = asect->lineno_count; + + if (!STREQ (asect->name, ".text") || count == 0) + return; + + size = count * coff_data (abfd)->local_linesz; + info = (struct coff_symfile_info *) vpinfo; + offset = asect->line_filepos; + maxoff = offset + size; + + if (offset < info->min_lineno_offset || info->min_lineno_offset == 0) + info->min_lineno_offset = offset; + + if (maxoff > info->max_lineno_offset) + info->max_lineno_offset = maxoff; +} + +static void xcoff_psymtab_to_symtab_1 (struct partial_symtab *); + +static void +xcoff_psymtab_to_symtab_1 (struct partial_symtab *pst) +{ + struct cleanup *old_chain; + int i; + + if (!pst) + return; + + if (pst->readin) + { + fprintf_unfiltered + (gdb_stderr, "Psymtab for %s already read in. Shouldn't happen.\n", + pst->filename); + return; + } + + /* Read in all partial symtabs on which this one is dependent */ + for (i = 0; i < pst->number_of_dependencies; i++) + if (!pst->dependencies[i]->readin) + { + /* Inform about additional files that need to be read in. */ + if (info_verbose) + { + fputs_filtered (" ", gdb_stdout); + wrap_here (""); + fputs_filtered ("and ", gdb_stdout); + wrap_here (""); + printf_filtered ("%s...", pst->dependencies[i]->filename); + wrap_here (""); /* Flush output */ + gdb_flush (gdb_stdout); + } + xcoff_psymtab_to_symtab_1 (pst->dependencies[i]); + } + + if (((struct symloc *) pst->read_symtab_private)->numsyms != 0) + { + /* Init stuff necessary for reading in symbols. */ + stabsread_init (); + buildsym_init (); + old_chain = make_cleanup (really_free_pendings, 0); + + read_xcoff_symtab (pst); + sort_symtab_syms (pst->symtab); + + do_cleanups (old_chain); + } + + pst->readin = 1; +} + +static void xcoff_psymtab_to_symtab (struct partial_symtab *); + +/* Read in all of the symbols for a given psymtab for real. + Be verbose about it if the user wants that. */ + +static void +xcoff_psymtab_to_symtab (struct partial_symtab *pst) +{ + bfd *sym_bfd; + + if (!pst) + return; + + if (pst->readin) + { + fprintf_unfiltered + (gdb_stderr, "Psymtab for %s already read in. Shouldn't happen.\n", + pst->filename); + return; + } + + if (((struct symloc *) pst->read_symtab_private)->numsyms != 0 + || pst->number_of_dependencies) + { + /* Print the message now, before reading the string table, + to avoid disconcerting pauses. */ + if (info_verbose) + { + printf_filtered ("Reading in symbols for %s...", pst->filename); + gdb_flush (gdb_stdout); + } + + sym_bfd = pst->objfile->obfd; + + next_symbol_text_func = xcoff_next_symbol_text; + + xcoff_psymtab_to_symtab_1 (pst); + + /* Match with global symbols. This only needs to be done once, + after all of the symtabs and dependencies have been read in. */ + scan_file_globals (pst->objfile); + + /* Finish up the debug error message. */ + if (info_verbose) + printf_filtered ("done.\n"); + } +} + +static void +xcoff_new_init (struct objfile *objfile) +{ + stabsread_new_init (); + buildsym_new_init (); +} + +/* Do initialization in preparation for reading symbols from OBJFILE. + + We will only be called if this is an XCOFF or XCOFF-like file. + BFD handles figuring out the format of the file, and code in symfile.c + uses BFD's determination to vector to us. */ + +static void +xcoff_symfile_init (struct objfile *objfile) +{ + /* Allocate struct to keep track of the symfile */ + objfile->sym_private = xmmalloc (objfile->md, + sizeof (struct coff_symfile_info)); + + /* XCOFF objects may be reordered, so set OBJF_REORDERED. If we + find this causes a significant slowdown in gdb then we could + set it in the debug symbol readers only when necessary. */ + objfile->flags |= OBJF_REORDERED; + + init_entry_point_info (objfile); +} + +/* Perform any local cleanups required when we are done with a particular + objfile. I.E, we are in the process of discarding all symbol information + for an objfile, freeing up all memory held for it, and unlinking the + objfile struct from the global list of known objfiles. */ + +static void +xcoff_symfile_finish (struct objfile *objfile) +{ + if (objfile->sym_private != NULL) + { + xmfree (objfile->md, objfile->sym_private); + } + + /* Start with a fresh include table for the next objfile. */ + if (inclTable) + { + xfree (inclTable); + inclTable = NULL; + } + inclIndx = inclLength = inclDepth = 0; +} + + +static void +init_stringtab (bfd *abfd, file_ptr offset, struct objfile *objfile) +{ + long length; + int val; + unsigned char lengthbuf[4]; + char *strtbl; + + ((struct coff_symfile_info *) objfile->sym_private)->strtbl = NULL; + + if (bfd_seek (abfd, offset, SEEK_SET) < 0) + error ("cannot seek to string table in %s: %s", + bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ())); + + val = bfd_bread ((char *) lengthbuf, sizeof lengthbuf, abfd); + length = bfd_h_get_32 (abfd, lengthbuf); + + /* If no string table is needed, then the file may end immediately + after the symbols. Just return with `strtbl' set to NULL. */ + + if (val != sizeof lengthbuf || length < sizeof lengthbuf) + return; + + /* Allocate string table from symbol_obstack. We will need this table + as long as we have its symbol table around. */ + + strtbl = (char *) obstack_alloc (&objfile->symbol_obstack, length); + ((struct coff_symfile_info *) objfile->sym_private)->strtbl = strtbl; + + /* Copy length buffer, the first byte is usually zero and is + used for stabs with a name length of zero. */ + memcpy (strtbl, lengthbuf, sizeof lengthbuf); + if (length == sizeof lengthbuf) + return; + + val = bfd_bread (strtbl + sizeof lengthbuf, length - sizeof lengthbuf, abfd); + + if (val != length - sizeof lengthbuf) + error ("cannot read string table from %s: %s", + bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ())); + if (strtbl[length - 1] != '\0') + error ("bad symbol file: string table does not end with null character"); + + return; +} + +/* If we have not yet seen a function for this psymtab, this is 0. If we + have seen one, it is the offset in the line numbers of the line numbers + for the psymtab. */ +static unsigned int first_fun_line_offset; + +static struct partial_symtab *xcoff_start_psymtab + (struct objfile *, char *, int, + struct partial_symbol **, struct partial_symbol **); + +/* Allocate and partially fill a partial symtab. It will be + completely filled at the end of the symbol list. + + SYMFILE_NAME is the name of the symbol-file we are reading from, and ADDR + is the address relative to which its symbols are (incremental) or 0 + (normal). */ + +static struct partial_symtab * +xcoff_start_psymtab (struct objfile *objfile, char *filename, int first_symnum, + struct partial_symbol **global_syms, + struct partial_symbol **static_syms) +{ + struct partial_symtab *result = + start_psymtab_common (objfile, objfile->section_offsets, + filename, + /* We fill in textlow later. */ + 0, + global_syms, static_syms); + + result->read_symtab_private = (char *) + obstack_alloc (&objfile->psymbol_obstack, sizeof (struct symloc)); + ((struct symloc *) result->read_symtab_private)->first_symnum = first_symnum; + result->read_symtab = xcoff_psymtab_to_symtab; + + /* Deduce the source language from the filename for this psymtab. */ + psymtab_language = deduce_language_from_filename (filename); + + return result; +} + +static struct partial_symtab *xcoff_end_psymtab + (struct partial_symtab *, char **, int, int, + struct partial_symtab **, int, int); + +/* Close off the current usage of PST. + Returns PST, or NULL if the partial symtab was empty and thrown away. + + CAPPING_SYMBOL_NUMBER is the end of pst (exclusive). + + INCLUDE_LIST, NUM_INCLUDES, DEPENDENCY_LIST, and NUMBER_DEPENDENCIES + are the information for includes and dependencies. */ + +static struct partial_symtab * +xcoff_end_psymtab (struct partial_symtab *pst, char **include_list, + int num_includes, int capping_symbol_number, + struct partial_symtab **dependency_list, + int number_dependencies, int textlow_not_set) +{ + int i; + struct objfile *objfile = pst->objfile; + + if (capping_symbol_number != -1) + ((struct symloc *) pst->read_symtab_private)->numsyms = + capping_symbol_number + - ((struct symloc *) pst->read_symtab_private)->first_symnum; + ((struct symloc *) pst->read_symtab_private)->lineno_off = + first_fun_line_offset; + first_fun_line_offset = 0; + pst->n_global_syms = + objfile->global_psymbols.next - (objfile->global_psymbols.list + pst->globals_offset); + pst->n_static_syms = + objfile->static_psymbols.next - (objfile->static_psymbols.list + pst->statics_offset); + + pst->number_of_dependencies = number_dependencies; + if (number_dependencies) + { + pst->dependencies = (struct partial_symtab **) + obstack_alloc (&objfile->psymbol_obstack, + number_dependencies * sizeof (struct partial_symtab *)); + memcpy (pst->dependencies, dependency_list, + number_dependencies * sizeof (struct partial_symtab *)); + } + else + pst->dependencies = 0; + + for (i = 0; i < num_includes; i++) + { + struct partial_symtab *subpst = + allocate_psymtab (include_list[i], objfile); + + subpst->section_offsets = pst->section_offsets; + subpst->read_symtab_private = + (char *) obstack_alloc (&objfile->psymbol_obstack, + sizeof (struct symloc)); + ((struct symloc *) subpst->read_symtab_private)->first_symnum = 0; + ((struct symloc *) subpst->read_symtab_private)->numsyms = 0; + subpst->textlow = 0; + subpst->texthigh = 0; + + /* We could save slight bits of space by only making one of these, + shared by the entire set of include files. FIXME-someday. */ + subpst->dependencies = (struct partial_symtab **) + obstack_alloc (&objfile->psymbol_obstack, + sizeof (struct partial_symtab *)); + subpst->dependencies[0] = pst; + subpst->number_of_dependencies = 1; + + subpst->globals_offset = + subpst->n_global_syms = + subpst->statics_offset = + subpst->n_static_syms = 0; + + subpst->readin = 0; + subpst->symtab = 0; + subpst->read_symtab = pst->read_symtab; + } + + sort_pst_symbols (pst); + + /* If there is already a psymtab or symtab for a file of this name, + remove it. (If there is a symtab, more drastic things also + happen.) This happens in VxWorks. */ + free_named_symtabs (pst->filename); + + if (num_includes == 0 + && number_dependencies == 0 + && pst->n_global_syms == 0 + && pst->n_static_syms == 0) + { + /* Throw away this psymtab, it's empty. We can't deallocate it, since + it is on the obstack, but we can forget to chain it on the list. */ + /* Empty psymtabs happen as a result of header files which don't have + any symbols in them. There can be a lot of them. */ + + discard_psymtab (pst); + + /* Indicate that psymtab was thrown away. */ + pst = (struct partial_symtab *) NULL; + } + return pst; +} + +static void swap_sym (struct internal_syment *, + union internal_auxent *, char **, char **, + unsigned int *, struct objfile *); + +/* Swap raw symbol at *RAW and put the name in *NAME, the symbol in + *SYMBOL, the first auxent in *AUX. Advance *RAW and *SYMNUMP over + the symbol and its auxents. */ + +static void +swap_sym (struct internal_syment *symbol, union internal_auxent *aux, + char **name, char **raw, unsigned int *symnump, + struct objfile *objfile) +{ + bfd_coff_swap_sym_in (objfile->obfd, *raw, symbol); + if (symbol->n_zeroes) + { + /* If it's exactly E_SYMNMLEN characters long it isn't + '\0'-terminated. */ + if (symbol->n_name[E_SYMNMLEN - 1] != '\0') + { + /* FIXME: wastes memory for symbols which we don't end up putting + into the minimal symbols. */ + char *p; + p = obstack_alloc (&objfile->psymbol_obstack, E_SYMNMLEN + 1); + strncpy (p, symbol->n_name, E_SYMNMLEN); + p[E_SYMNMLEN] = '\0'; + *name = p; + } + else + /* Point to the unswapped name as that persists as long as the + objfile does. */ + *name = ((struct external_syment *) *raw)->e.e_name; + } + else if (symbol->n_sclass & 0x80) + { + *name = ((struct coff_symfile_info *) objfile->sym_private)->debugsec + + symbol->n_offset; + } + else + { + *name = ((struct coff_symfile_info *) objfile->sym_private)->strtbl + + symbol->n_offset; + } + ++*symnump; + *raw += coff_data (objfile->obfd)->local_symesz; + if (symbol->n_numaux > 0) + { + bfd_coff_swap_aux_in (objfile->obfd, *raw, symbol->n_type, + symbol->n_sclass, 0, symbol->n_numaux, aux); + + *symnump += symbol->n_numaux; + *raw += coff_data (objfile->obfd)->local_symesz * symbol->n_numaux; + } +} + +static void +scan_xcoff_symtab (struct objfile *objfile) +{ + CORE_ADDR toc_offset = 0; /* toc offset value in data section. */ + char *filestring = NULL; + + char *namestring; + int past_first_source_file = 0; + bfd *abfd; + asection *bfd_sect; + unsigned int nsyms; + + /* Current partial symtab */ + struct partial_symtab *pst; + + /* List of current psymtab's include files */ + char **psymtab_include_list; + int includes_allocated; + int includes_used; + + /* Index within current psymtab dependency list */ + struct partial_symtab **dependency_list; + int dependencies_used, dependencies_allocated; + + char *sraw_symbol; + struct internal_syment symbol; + union internal_auxent main_aux[5]; + unsigned int ssymnum; + + char *last_csect_name = NULL; /* last seen csect's name and value */ + CORE_ADDR last_csect_val = 0; + int last_csect_sec = 0; + int misc_func_recorded = 0; /* true if any misc. function */ + int textlow_not_set = 1; + + pst = (struct partial_symtab *) 0; + + includes_allocated = 30; + includes_used = 0; + psymtab_include_list = (char **) alloca (includes_allocated * + sizeof (char *)); + + dependencies_allocated = 30; + dependencies_used = 0; + dependency_list = + (struct partial_symtab **) alloca (dependencies_allocated * + sizeof (struct partial_symtab *)); + + last_source_file = NULL; + + abfd = objfile->obfd; + + sraw_symbol = ((struct coff_symfile_info *) objfile->sym_private)->symtbl; + nsyms = ((struct coff_symfile_info *) objfile->sym_private)->symtbl_num_syms; + ssymnum = 0; + while (ssymnum < nsyms) + { + int sclass; + + QUIT; + + bfd_coff_swap_sym_in (abfd, sraw_symbol, &symbol); + sclass = symbol.n_sclass; + + switch (sclass) + { + case C_EXT: + case C_HIDEXT: + { + /* The CSECT auxent--always the last auxent. */ + union internal_auxent csect_aux; + unsigned int symnum_before = ssymnum; + + swap_sym (&symbol, &main_aux[0], &namestring, &sraw_symbol, + &ssymnum, objfile); + if (symbol.n_numaux > 1) + { + bfd_coff_swap_aux_in + (objfile->obfd, + sraw_symbol - coff_data (abfd)->local_symesz, + symbol.n_type, + symbol.n_sclass, + symbol.n_numaux - 1, + symbol.n_numaux, + &csect_aux); + } + else + csect_aux = main_aux[0]; + + /* If symbol name starts with ".$" or "$", ignore it. */ + if (namestring[0] == '$' + || (namestring[0] == '.' && namestring[1] == '$')) + break; + + switch (csect_aux.x_csect.x_smtyp & 0x7) + { + case XTY_SD: + switch (csect_aux.x_csect.x_smclas) + { + case XMC_PR: + if (last_csect_name) + { + /* If no misc. function recorded in the last + seen csect, enter it as a function. This + will take care of functions like strcmp() + compiled by xlc. */ + + if (!misc_func_recorded) + { + RECORD_MINIMAL_SYMBOL + (last_csect_name, last_csect_val, + mst_text, last_csect_sec, + objfile); + } + + if (pst != NULL) + { + /* We have to allocate one psymtab for + each program csect, because their text + sections need not be adjacent. */ + xcoff_end_psymtab + (pst, psymtab_include_list, includes_used, + symnum_before, dependency_list, + dependencies_used, textlow_not_set); + includes_used = 0; + dependencies_used = 0; + /* Give all psymtabs for this source file the same + name. */ + pst = xcoff_start_psymtab + (objfile, + filestring, + symnum_before, + objfile->global_psymbols.next, + objfile->static_psymbols.next); + } + } + /* Activate the misc_func_recorded mechanism for + compiler- and linker-generated CSECTs like ".strcmp" + and "@FIX1". */ + if (namestring && (namestring[0] == '.' + || namestring[0] == '@')) + { + last_csect_name = namestring; + last_csect_val = symbol.n_value; + last_csect_sec = + secnum_to_section (symbol.n_scnum, objfile); + } + if (pst != NULL) + { + CORE_ADDR highval = + symbol.n_value + csect_aux.x_csect.x_scnlen.l; + if (highval > pst->texthigh) + pst->texthigh = highval; + if (pst->textlow == 0 || symbol.n_value < pst->textlow) + pst->textlow = symbol.n_value; + } + misc_func_recorded = 0; + break; + + case XMC_RW: + case XMC_TD: + /* Data variables are recorded in the minimal symbol + table, except for section symbols. */ + if (*namestring != '.') + prim_record_minimal_symbol_and_info + (namestring, symbol.n_value, + sclass == C_HIDEXT ? mst_file_data : mst_data, + NULL, secnum_to_section (symbol.n_scnum, objfile), + NULL, objfile); + break; + + case XMC_TC0: + if (toc_offset) + warning ("More than one XMC_TC0 symbol found."); + toc_offset = symbol.n_value; + + /* Make TOC offset relative to start address of section. */ + bfd_sect = secnum_to_bfd_section (symbol.n_scnum, objfile); + if (bfd_sect) + toc_offset -= bfd_section_vma (objfile->obfd, bfd_sect); + break; + + case XMC_TC: + /* These symbols tell us where the TOC entry for a + variable is, not the variable itself. */ + break; + + default: + break; + } + break; + + case XTY_LD: + switch (csect_aux.x_csect.x_smclas) + { + case XMC_PR: + /* A function entry point. */ + + if (first_fun_line_offset == 0 && symbol.n_numaux > 1) + first_fun_line_offset = + main_aux[0].x_sym.x_fcnary.x_fcn.x_lnnoptr; + RECORD_MINIMAL_SYMBOL + (namestring, symbol.n_value, + sclass == C_HIDEXT ? mst_file_text : mst_text, + secnum_to_section (symbol.n_scnum, objfile), + objfile); + break; + + case XMC_GL: + /* shared library function trampoline code entry + point. */ + + /* record trampoline code entries as + mst_solib_trampoline symbol. When we lookup mst + symbols, we will choose mst_text over + mst_solib_trampoline. */ + RECORD_MINIMAL_SYMBOL + (namestring, symbol.n_value, + mst_solib_trampoline, + secnum_to_section (symbol.n_scnum, objfile), + objfile); + break; + + case XMC_DS: + /* The symbols often have the same names as + debug symbols for functions, and confuse + lookup_symbol. */ + break; + + default: + + /* xlc puts each variable in a separate csect, + so we get an XTY_SD for each variable. But + gcc puts several variables in a csect, so + that each variable only gets an XTY_LD. We + still need to record them. This will + typically be XMC_RW; I suspect XMC_RO and + XMC_BS might be possible too. */ + if (*namestring != '.') + prim_record_minimal_symbol_and_info + (namestring, symbol.n_value, + sclass == C_HIDEXT ? mst_file_data : mst_data, + NULL, secnum_to_section (symbol.n_scnum, objfile), + NULL, objfile); + break; + } + break; + + case XTY_CM: + switch (csect_aux.x_csect.x_smclas) + { + case XMC_RW: + case XMC_BS: + /* Common variables are recorded in the minimal symbol + table, except for section symbols. */ + if (*namestring != '.') + prim_record_minimal_symbol_and_info + (namestring, symbol.n_value, + sclass == C_HIDEXT ? mst_file_bss : mst_bss, + NULL, secnum_to_section (symbol.n_scnum, objfile), + NULL, objfile); + break; + } + break; + + default: + break; + } + } + break; + case C_FILE: + { + unsigned int symnum_before; + + symnum_before = ssymnum; + swap_sym (&symbol, &main_aux[0], &namestring, &sraw_symbol, + &ssymnum, objfile); + + /* See if the last csect needs to be recorded. */ + + if (last_csect_name && !misc_func_recorded) + { + + /* If no misc. function recorded in the last seen csect, enter + it as a function. This will take care of functions like + strcmp() compiled by xlc. */ + + RECORD_MINIMAL_SYMBOL + (last_csect_name, last_csect_val, + mst_text, last_csect_sec, objfile); + } + + if (pst) + { + xcoff_end_psymtab (pst, psymtab_include_list, includes_used, + symnum_before, dependency_list, + dependencies_used, textlow_not_set); + includes_used = 0; + dependencies_used = 0; + } + first_fun_line_offset = 0; + + /* XCOFF, according to the AIX 3.2 documentation, puts the + filename in cs->c_name. But xlc 1.3.0.2 has decided to + do things the standard COFF way and put it in the auxent. + We use the auxent if the symbol is ".file" and an auxent + exists, otherwise use the symbol itself. */ + if (!strcmp (namestring, ".file") && symbol.n_numaux > 0) + { + filestring = coff_getfilename (&main_aux[0], objfile); + } + else + filestring = namestring; + + pst = xcoff_start_psymtab (objfile, + filestring, + symnum_before, + objfile->global_psymbols.next, + objfile->static_psymbols.next); + last_csect_name = NULL; + } + break; + + default: + { + static struct complaint msg = + {"Storage class %d not recognized during scan", 0, 0}; + complain (&msg, sclass); + } + /* FALLTHROUGH */ + + /* C_FCN is .bf and .ef symbols. I think it is sufficient + to handle only the C_FUN and C_EXT. */ + case C_FCN: + + case C_BSTAT: + case C_ESTAT: + case C_ARG: + case C_REGPARM: + case C_REG: + case C_TPDEF: + case C_STRTAG: + case C_UNTAG: + case C_ENTAG: + case C_LABEL: + case C_NULL: + + /* C_EINCL means we are switching back to the main file. But there + is no reason to care; the only thing we want to know about + includes is the names of all the included (.h) files. */ + case C_EINCL: + + case C_BLOCK: + + /* I don't think C_STAT is used in xcoff; C_HIDEXT appears to be + used instead. */ + case C_STAT: + + /* I don't think the name of the common block (as opposed to the + variables within it) is something which is user visible + currently. */ + case C_BCOMM: + case C_ECOMM: + + case C_PSYM: + case C_RPSYM: + + /* I think we can ignore C_LSYM; types on xcoff seem to use C_DECL + so C_LSYM would appear to be only for locals. */ + case C_LSYM: + + case C_AUTO: + case C_RSYM: + { + /* We probably could save a few instructions by assuming that + C_LSYM, C_PSYM, etc., never have auxents. */ + int naux1 = symbol.n_numaux + 1; + ssymnum += naux1; + sraw_symbol += bfd_coff_symesz (abfd) * naux1; + } + break; + + case C_BINCL: + { + /* Mark down an include file in the current psymtab */ + enum language tmp_language; + swap_sym (&symbol, &main_aux[0], &namestring, &sraw_symbol, + &ssymnum, objfile); + + tmp_language = deduce_language_from_filename (namestring); + + /* Only change the psymtab's language if we've learned + something useful (eg. tmp_language is not language_unknown). + In addition, to match what start_subfile does, never change + from C++ to C. */ + if (tmp_language != language_unknown + && (tmp_language != language_c + || psymtab_language != language_cplus)) + psymtab_language = tmp_language; + + /* In C++, one may expect the same filename to come round many + times, when code is coming alternately from the main file + and from inline functions in other files. So I check to see + if this is a file we've seen before -- either the main + source file, or a previously included file. + + This seems to be a lot of time to be spending on N_SOL, but + things like "break c-exp.y:435" need to work (I + suppose the psymtab_include_list could be hashed or put + in a binary tree, if profiling shows this is a major hog). */ + if (pst && STREQ (namestring, pst->filename)) + continue; + { + register int i; + for (i = 0; i < includes_used; i++) + if (STREQ (namestring, psymtab_include_list[i])) + { + i = -1; + break; + } + if (i == -1) + continue; + } + psymtab_include_list[includes_used++] = namestring; + if (includes_used >= includes_allocated) + { + char **orig = psymtab_include_list; + + psymtab_include_list = (char **) + alloca ((includes_allocated *= 2) * + sizeof (char *)); + memcpy ((PTR) psymtab_include_list, (PTR) orig, + includes_used * sizeof (char *)); + } + continue; + } + case C_FUN: + /* The value of the C_FUN is not the address of the function (it + appears to be the address before linking), but as long as it + is smaller than the actual address, then find_pc_partial_function + will use the minimal symbols instead. I hope. */ + + case C_GSYM: + case C_ECOML: + case C_DECL: + case C_STSYM: + { + + static struct complaint function_outside_compilation_unit = { + "function `%s' appears to be defined outside of all compilation units", 0, 0 + }; + + char *p; + swap_sym (&symbol, &main_aux[0], &namestring, &sraw_symbol, + &ssymnum, objfile); + + p = (char *) strchr (namestring, ':'); + if (!p) + continue; /* Not a debugging symbol. */ + + /* Main processing section for debugging symbols which + the initial read through the symbol tables needs to worry + about. If we reach this point, the symbol which we are + considering is definitely one we are interested in. + p must also contain the (valid) index into the namestring + which indicates the debugging type symbol. */ + + switch (p[1]) + { + case 'S': + symbol.n_value += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile)); +#ifdef STATIC_TRANSFORM_NAME + namestring = STATIC_TRANSFORM_NAME (namestring); +#endif + add_psymbol_to_list (namestring, p - namestring, + VAR_NAMESPACE, LOC_STATIC, + &objfile->static_psymbols, + 0, symbol.n_value, + psymtab_language, objfile); + continue; + + case 'G': + symbol.n_value += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile)); + /* The addresses in these entries are reported to be + wrong. See the code that reads 'G's for symtabs. */ + add_psymbol_to_list (namestring, p - namestring, + VAR_NAMESPACE, LOC_STATIC, + &objfile->global_psymbols, + 0, symbol.n_value, + psymtab_language, objfile); + continue; + + case 'T': + /* When a 'T' entry is defining an anonymous enum, it + may have a name which is the empty string, or a + single space. Since they're not really defining a + symbol, those shouldn't go in the partial symbol + table. We do pick up the elements of such enums at + 'check_enum:', below. */ + if (p >= namestring + 2 + || (p == namestring + 1 + && namestring[0] != ' ')) + { + add_psymbol_to_list (namestring, p - namestring, + STRUCT_NAMESPACE, LOC_TYPEDEF, + &objfile->static_psymbols, + symbol.n_value, 0, + psymtab_language, objfile); + if (p[2] == 't') + { + /* Also a typedef with the same name. */ + add_psymbol_to_list (namestring, p - namestring, + VAR_NAMESPACE, LOC_TYPEDEF, + &objfile->static_psymbols, + symbol.n_value, 0, + psymtab_language, objfile); + p += 1; + } + /* The semantics of C++ state that "struct foo { ... }" + also defines a typedef for "foo". Unfortuantely, cfront + never makes the typedef when translating from C++ to C. + We make the typedef here so that "ptype foo" works as + expected for cfront translated code. */ + else if (psymtab_language == language_cplus) + { + /* Also a typedef with the same name. */ + add_psymbol_to_list (namestring, p - namestring, + VAR_NAMESPACE, LOC_TYPEDEF, + &objfile->static_psymbols, + symbol.n_value, 0, + psymtab_language, objfile); + } + } + goto check_enum; + + case 't': + if (p != namestring) /* a name is there, not just :T... */ + { + add_psymbol_to_list (namestring, p - namestring, + VAR_NAMESPACE, LOC_TYPEDEF, + &objfile->static_psymbols, + symbol.n_value, 0, + psymtab_language, objfile); + } + check_enum: + /* If this is an enumerated type, we need to + add all the enum constants to the partial symbol + table. This does not cover enums without names, e.g. + "enum {a, b} c;" in C, but fortunately those are + rare. There is no way for GDB to find those from the + enum type without spending too much time on it. Thus + to solve this problem, the compiler needs to put out the + enum in a nameless type. GCC2 does this. */ + + /* We are looking for something of the form + <name> ":" ("t" | "T") [<number> "="] "e" + {<constant> ":" <value> ","} ";". */ + + /* Skip over the colon and the 't' or 'T'. */ + p += 2; + /* This type may be given a number. Also, numbers can come + in pairs like (0,26). Skip over it. */ + while ((*p >= '0' && *p <= '9') + || *p == '(' || *p == ',' || *p == ')' + || *p == '=') + p++; + + if (*p++ == 'e') + { + /* The aix4 compiler emits extra crud before the members. */ + if (*p == '-') + { + /* Skip over the type (?). */ + while (*p != ':') + p++; + + /* Skip over the colon. */ + p++; + } + + /* We have found an enumerated type. */ + /* According to comments in read_enum_type + a comma could end it instead of a semicolon. + I don't know where that happens. + Accept either. */ + while (*p && *p != ';' && *p != ',') + { + char *q; + + /* Check for and handle cretinous dbx symbol name + continuation! */ + if (*p == '\\' || (*p == '?' && p[1] == '\0')) + p = next_symbol_text (objfile); + + /* Point to the character after the name + of the enum constant. */ + for (q = p; *q && *q != ':'; q++) + ; + /* Note that the value doesn't matter for + enum constants in psymtabs, just in symtabs. */ + add_psymbol_to_list (p, q - p, + VAR_NAMESPACE, LOC_CONST, + &objfile->static_psymbols, 0, + 0, psymtab_language, objfile); + /* Point past the name. */ + p = q; + /* Skip over the value. */ + while (*p && *p != ',') + p++; + /* Advance past the comma. */ + if (*p) + p++; + } + } + continue; + + case 'c': + /* Constant, e.g. from "const" in Pascal. */ + add_psymbol_to_list (namestring, p - namestring, + VAR_NAMESPACE, LOC_CONST, + &objfile->static_psymbols, symbol.n_value, + 0, psymtab_language, objfile); + continue; + + case 'f': + if (! pst) + { + int name_len = p - namestring; + char *name = xmalloc (name_len + 1); + memcpy (name, namestring, name_len); + name[name_len] = '\0'; + complain (&function_outside_compilation_unit, name); + xfree (name); + } + symbol.n_value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + add_psymbol_to_list (namestring, p - namestring, + VAR_NAMESPACE, LOC_BLOCK, + &objfile->static_psymbols, + 0, symbol.n_value, + psymtab_language, objfile); + continue; + + /* Global functions were ignored here, but now they + are put into the global psymtab like one would expect. + They're also in the minimal symbol table. */ + case 'F': + if (! pst) + { + int name_len = p - namestring; + char *name = xmalloc (name_len + 1); + memcpy (name, namestring, name_len); + name[name_len] = '\0'; + complain (&function_outside_compilation_unit, name); + xfree (name); + } + symbol.n_value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + add_psymbol_to_list (namestring, p - namestring, + VAR_NAMESPACE, LOC_BLOCK, + &objfile->global_psymbols, + 0, symbol.n_value, + psymtab_language, objfile); + continue; + + /* Two things show up here (hopefully); static symbols of + local scope (static used inside braces) or extensions + of structure symbols. We can ignore both. */ + case 'V': + case '(': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + case '#': /* for symbol identification (used in live ranges) */ + /* added to support cfront stabs strings */ + case 'Z': /* for definition continuations */ + case 'P': /* for prototypes */ + continue; + + case ':': + /* It is a C++ nested symbol. We don't need to record it + (I don't think); if we try to look up foo::bar::baz, + then symbols for the symtab containing foo should get + read in, I think. */ + /* Someone says sun cc puts out symbols like + /foo/baz/maclib::/usr/local/bin/maclib, + which would get here with a symbol type of ':'. */ + continue; + + default: + /* Unexpected symbol descriptor. The second and subsequent stabs + of a continued stab can show up here. The question is + whether they ever can mimic a normal stab--it would be + nice if not, since we certainly don't want to spend the + time searching to the end of every string looking for + a backslash. */ + + complain (&unknown_symchar_complaint, p[1]); + + /* Ignore it; perhaps it is an extension that we don't + know about. */ + continue; + } + } + } + } + + if (pst) + { + xcoff_end_psymtab (pst, psymtab_include_list, includes_used, + ssymnum, dependency_list, + dependencies_used, textlow_not_set); + } + + /* Record the toc offset value of this symbol table into objfile structure. + If no XMC_TC0 is found, toc_offset should be zero. Another place to obtain + this information would be file auxiliary header. */ + + ((struct coff_symfile_info *) objfile->sym_private)->toc_offset = toc_offset; +} + +/* Return the toc offset value for a given objfile. */ + +CORE_ADDR +get_toc_offset (struct objfile *objfile) +{ + if (objfile) + return ((struct coff_symfile_info *) objfile->sym_private)->toc_offset; + return 0; +} + +/* Scan and build partial symbols for a symbol file. + We have been initialized by a call to dbx_symfile_init, which + put all the relevant info into a "struct dbx_symfile_info", + hung off the objfile structure. + + SECTION_OFFSETS contains offsets relative to which the symbols in the + various sections are (depending where the sections were actually loaded). + MAINLINE is true if we are reading the main symbol + table (as opposed to a shared lib or dynamically loaded file). */ + +static void +xcoff_initial_scan (struct objfile *objfile, int mainline) +{ + bfd *abfd; + int val; + struct cleanup *back_to; + int num_symbols; /* # of symbols */ + file_ptr symtab_offset; /* symbol table and */ + file_ptr stringtab_offset; /* string table file offsets */ + struct coff_symfile_info *info; + char *name; + unsigned int size; + + info = (struct coff_symfile_info *) objfile->sym_private; + symfile_bfd = abfd = objfile->obfd; + name = objfile->name; + + num_symbols = bfd_get_symcount (abfd); /* # of symbols */ + symtab_offset = obj_sym_filepos (abfd); /* symbol table file offset */ + stringtab_offset = symtab_offset + + num_symbols * coff_data (abfd)->local_symesz; + + info->min_lineno_offset = 0; + info->max_lineno_offset = 0; + bfd_map_over_sections (abfd, find_linenos, info); + + if (num_symbols > 0) + { + /* Read the string table. */ + init_stringtab (abfd, stringtab_offset, objfile); + + /* Read the .debug section, if present. */ + { + sec_ptr secp; + bfd_size_type length; + char *debugsec = NULL; + + secp = bfd_get_section_by_name (abfd, ".debug"); + if (secp) + { + length = bfd_section_size (abfd, secp); + if (length) + { + debugsec = + (char *) obstack_alloc (&objfile->symbol_obstack, length); + + if (!bfd_get_section_contents (abfd, secp, debugsec, + (file_ptr) 0, length)) + { + error ("Error reading .debug section of `%s': %s", + name, bfd_errmsg (bfd_get_error ())); + } + } + } + ((struct coff_symfile_info *) objfile->sym_private)->debugsec = + debugsec; + } + } + + /* Read the symbols. We keep them in core because we will want to + access them randomly in read_symbol*. */ + val = bfd_seek (abfd, symtab_offset, SEEK_SET); + if (val < 0) + error ("Error reading symbols from %s: %s", + name, bfd_errmsg (bfd_get_error ())); + size = coff_data (abfd)->local_symesz * num_symbols; + ((struct coff_symfile_info *) objfile->sym_private)->symtbl = + obstack_alloc (&objfile->symbol_obstack, size); + ((struct coff_symfile_info *) objfile->sym_private)->symtbl_num_syms = + num_symbols; + + val = bfd_bread (((struct coff_symfile_info *) objfile->sym_private)->symtbl, + size, abfd); + if (val != size) + perror_with_name ("reading symbol table"); + + /* If we are reinitializing, or if we have never loaded syms yet, init */ + if (mainline + || (objfile->global_psymbols.size == 0 + && objfile->static_psymbols.size == 0)) + /* I'm not sure how how good num_symbols is; the rule of thumb in + init_psymbol_list was developed for a.out. On the one hand, + num_symbols includes auxents. On the other hand, it doesn't + include N_SLINE. */ + init_psymbol_list (objfile, num_symbols); + + free_pending_blocks (); + back_to = make_cleanup (really_free_pendings, 0); + + init_minimal_symbol_collection (); + make_cleanup_discard_minimal_symbols (); + + /* Now that the symbol table data of the executable file are all in core, + process them and define symbols accordingly. */ + + scan_xcoff_symtab (objfile); + + /* Install any minimal symbols that have been collected as the current + minimal symbols for this objfile. */ + + install_minimal_symbols (objfile); + + do_cleanups (back_to); +} + +static void +xcoff_symfile_offsets (struct objfile *objfile, struct section_addr_info *addrs) +{ + asection *sect = NULL; + int i; + + objfile->num_sections = SECT_OFF_MAX; + objfile->section_offsets = (struct section_offsets *) + obstack_alloc (&objfile->psymbol_obstack, SIZEOF_SECTION_OFFSETS); + + /* Initialize the section indexes for future use. */ + sect = bfd_get_section_by_name (objfile->obfd, ".text"); + if (sect) + objfile->sect_index_text = sect->index; + + sect = bfd_get_section_by_name (objfile->obfd, ".data"); + if (sect) + objfile->sect_index_data = sect->index; + + sect = bfd_get_section_by_name (objfile->obfd, ".bss"); + if (sect) + objfile->sect_index_bss = sect->index; + + sect = bfd_get_section_by_name (objfile->obfd, ".rodata"); + if (sect) + objfile->sect_index_rodata = sect->index; + + for (i = 0; i < objfile->num_sections; ++i) + { + /* syms_from_objfile kindly subtracts from addr the + bfd_section_vma of the .text section. This strikes me as + wrong--whether the offset to be applied to symbol reading is + relative to the start address of the section depends on the + symbol format. In any event, this whole "addr" concept is + pretty broken (it doesn't handle any section but .text + sensibly), so just ignore the addr parameter and use 0. + rs6000-nat.c will set the correct section offsets via + objfile_relocate. */ + (objfile->section_offsets)->offsets[i] = 0; + } +} + +/* Register our ability to parse symbols for xcoff BFD files. */ + +static struct sym_fns xcoff_sym_fns = +{ + + /* It is possible that coff and xcoff should be merged as + they do have fundamental similarities (for example, the extra storage + classes used for stabs could presumably be recognized in any COFF file). + However, in addition to obvious things like all the csect hair, there are + some subtler differences between xcoffread.c and coffread.c, notably + the fact that coffread.c has no need to read in all the symbols, but + xcoffread.c reads all the symbols and does in fact randomly access them + (in C_BSTAT and line number processing). */ + + bfd_target_xcoff_flavour, + + xcoff_new_init, /* sym_new_init: init anything gbl to entire symtab */ + xcoff_symfile_init, /* sym_init: read initial info, setup for sym_read() */ + xcoff_initial_scan, /* sym_read: read a symbol file into symtab */ + xcoff_symfile_finish, /* sym_finish: finished with file, cleanup */ + xcoff_symfile_offsets, /* sym_offsets: xlate offsets ext->int form */ + NULL /* next: pointer to next struct sym_fns */ +}; + +void +_initialize_xcoffread (void) +{ + add_symtab_fns (&xcoff_sym_fns); + + func_symbol_type = init_type (TYPE_CODE_FUNC, 1, 0, + "<function, no debug info>", NULL); + TYPE_TARGET_TYPE (func_symbol_type) = builtin_type_int; + var_symbol_type = + init_type (TYPE_CODE_INT, TARGET_INT_BIT / HOST_CHAR_BIT, 0, + "<variable, no debug info>", NULL); +} |