From: Stu Grossman Date: Wed, 22 Sep 1993 15:23:53 +0000 (+0000) Subject: * Makefile.in: Add i386lynx-tdep to the right places. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=b1eaba9ac4cd19372b06a7abba451eb8738be0bb;p=binutils-gdb.git * Makefile.in: Add i386lynx-tdep to the right places. (TARDIRS): Add gdbserver. * exec.c (print_section_info): Print entry point. * i386lynx-nat.c (i386lynx_saved_pc_after_call): Move into i386lynx-tdep.c. Add core file support. * i386lynx-tdep.c: New module for Lynx/386 target dependant code. * maint.c: Add `maint info sections' command to print info about all sections that BFD knows about for exec and core files. * sparc-tdep.c (sparc_push_dummy_frame): Update stack pointer before putting frame on the stack. Consolidate writes to reduce traffic for remote debugging. * config/i386/i386lynx.mh (NATDEPFILES): Remove exec.o. * config/i386/i386lynx.mt (TDEPFILES): Add exec.o, i386lynx-tdep.o. * config/i386/nm-i386lynx.h: Add target_pid_to_str(). * config/i386/tm-i386lynx.h: Remove target_pid_to_str(). * sparclite/Makefile.in: Add deps to keep Sun make happy. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 3008322e394..5bb5c79b69b 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,23 @@ +Wed Sep 22 08:02:57 1993 Stu Grossman (grossman at cygnus.com) + + * Makefile.in: Add i386lynx-tdep to the right places. + (TARDIRS): Add gdbserver. + + * exec.c (print_section_info): Print entry point. + * i386lynx-nat.c (i386lynx_saved_pc_after_call): Move into + i386lynx-tdep.c. Add core file support. + * i386lynx-tdep.c: New module for Lynx/386 target dependant code. + * maint.c: Add `maint info sections' command to print info about all + sections that BFD knows about for exec and core files. + * sparc-tdep.c (sparc_push_dummy_frame): Update stack pointer + before putting frame on the stack. Consolidate writes to reduce + traffic for remote debugging. + * config/i386/i386lynx.mh (NATDEPFILES): Remove exec.o. + * config/i386/i386lynx.mt (TDEPFILES): Add exec.o, i386lynx-tdep.o. + * config/i386/nm-i386lynx.h: Add target_pid_to_str(). + * config/i386/tm-i386lynx.h: Remove target_pid_to_str(). + * sparclite/Makefile.in: Add deps to keep Sun make happy. + Tue Sep 21 17:48:14 1993 Jim Kingdon (kingdon@lioth.cygnus.com) * breakpoint.h, breakpoint.c (bpstat_stop_status): Add new argument diff --git a/gdb/config/i386/i386lynx.mh b/gdb/config/i386/i386lynx.mh index 2e34bd81688..51b70baa9ca 100644 --- a/gdb/config/i386/i386lynx.mh +++ b/gdb/config/i386/i386lynx.mh @@ -1,6 +1,6 @@ # Host: Intel 386 running Lynx XDEPFILES= -NATDEPFILES= exec.o fork-child.o infptrace.o inftarg.o corelow.o i386lynx-nat.o +NATDEPFILES= fork-child.o infptrace.o inftarg.o corelow.o i386lynx-nat.o XM_FILE= xm-i386lynx.h NAT_FILE= nm-i386lynx.h REGEX=regex.o diff --git a/gdb/config/i386/i386lynx.mt b/gdb/config/i386/i386lynx.mt index 0af5657a2e9..2b83ad9f6cb 100644 --- a/gdb/config/i386/i386lynx.mt +++ b/gdb/config/i386/i386lynx.mt @@ -1,3 +1,3 @@ # Target: Intel 386 running Lynx -TDEPFILES= i386-tdep.o i386-pinsn.o +TDEPFILES= exec.o i386-tdep.o i386-pinsn.o i386lynx-tdep.o TM_FILE= tm-i386lynx.h diff --git a/gdb/config/i386/nm-i386lynx.h b/gdb/config/i386/nm-i386lynx.h index 3a2d318ef70..e67ec1dc9cb 100644 --- a/gdb/config/i386/nm-i386lynx.h +++ b/gdb/config/i386/nm-i386lynx.h @@ -20,6 +20,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef NM_I386LYNX_H #define NM_I386LYNX_H +#include #include #include #include @@ -55,4 +56,13 @@ i386_register_u_addr PARAMS ((int, int)); #define CHILD_WAIT extern int child_wait PARAMS ((int *status)); +/* Lynx needs a special definition of this so that we can + print out the pid and thread number seperatly. */ + +#undef target_pid_to_str + +#define target_pid_to_str(PID) \ + i386lynx_pid_to_str (PID) +extern char *i386lynx_pid_to_str PARAMS ((int pid)); + #endif /* NM_I386LYNX_H */ diff --git a/gdb/config/i386/tm-i386lynx.h b/gdb/config/i386/tm-i386lynx.h index adf5c7c98d8..d5db133848a 100644 --- a/gdb/config/i386/tm-i386lynx.h +++ b/gdb/config/i386/tm-i386lynx.h @@ -31,13 +31,4 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define SAVED_PC_AFTER_CALL i386lynx_saved_pc_after_call CORE_ADDR i386lynx_saved_pc_after_call (); -/* Lynx needs a special definition of this so that we can - print out the pid and thread number seperatly. */ - -#undef target_pid_to_str - -#define target_pid_to_str(PID) \ - i386lynx_pid_to_str (PID) -extern char *i386lynx_pid_to_str PARAMS ((int pid)); - #endif /* TM_I386LYNX_H */ diff --git a/gdb/exec.c b/gdb/exec.c index ef78097ea44..444c89ebec0 100644 --- a/gdb/exec.c +++ b/gdb/exec.c @@ -83,7 +83,9 @@ exec_close (quitting) int quitting; { if (exec_bfd) { + char *name = bfd_get_filename (exec_bfd); bfd_close (exec_bfd); + free (name); exec_bfd = NULL; } if (exec_ops.to_sections) { @@ -143,7 +145,7 @@ exec_file_command (args, from_tty) if (scratch_chan < 0) perror_with_name (filename); - exec_bfd = bfd_fdopenr (scratch_pathname, NULL, scratch_chan); + exec_bfd = bfd_fdopenr (scratch_pathname, gnutarget, scratch_chan); if (!exec_bfd) error ("Could not open `%s' as an executable file: %s", scratch_pathname, bfd_errmsg (bfd_error)); @@ -162,7 +164,7 @@ exec_file_command (args, from_tty) { struct section_table *p; for (p = exec_ops.to_sections; p < exec_ops.to_sections_end; p++) - if (!strcmp (".text", bfd_section_name (p->bfd, p->sec_ptr))) + if (STREQ (".text", bfd_section_name (p->bfd, p->sec_ptr))) { text_start = p->addr; text_end = p->endaddr; @@ -341,7 +343,8 @@ print_section_info (t, abfd) printf_filtered ("\t`%s', ", bfd_get_filename(abfd)); wrap_here (" "); printf_filtered ("file type %s.\n", bfd_get_target(abfd)); - + printf_filtered ("\tEntry point: %s\n", + local_hex_string (bfd_get_start_address (exec_bfd))); for (p = t->to_sections; p < t->to_sections_end; p++) { printf_filtered ("\t%s", local_hex_string_custom (p->addr, "08")); printf_filtered (" - %s", local_hex_string_custom (p->endaddr, "08")); @@ -403,6 +406,17 @@ set_section_command (args, from_tty) error ("Section %s not found", secprint); } +/* If mourn is being called in all the right places, this could be say + `gdb internal error' (since generic_mourn calls mark_breakpoints_out). */ + +static int +ignore (addr, contents) + CORE_ADDR addr; + char *contents; +{ + return 0; +} + struct target_ops exec_ops = { "exec", "Local exec file", "Use an executable file as a target.\n\ @@ -412,7 +426,7 @@ Specify the filename of the executable file.", 0, 0, /* fetch_registers, store_registers, */ 0, /* prepare_to_store, */ xfer_memory, exec_files_info, - 0, 0, /* insert_breakpoint, remove_breakpoint, */ + ignore, ignore, /* insert_breakpoint, remove_breakpoint, */ 0, 0, 0, 0, 0, /* terminal stuff */ 0, 0, /* kill, load */ 0, /* lookup sym */ @@ -429,20 +443,23 @@ Specify the filename of the executable file.", void _initialize_exec() { + struct cmd_list_element *c; - add_com ("file", class_files, file_command, - "Use FILE as program to be debugged.\n\ + c = add_cmd ("file", class_files, file_command, + "Use FILE as program to be debugged.\n\ It is read for its symbols, for getting the contents of pure memory,\n\ and it is the program executed when you use the `run' command.\n\ If FILE cannot be found as specified, your execution directory path\n\ ($PATH) is searched for a command of that name.\n\ -No arg means to have no executable file and no symbols."); +No arg means to have no executable file and no symbols.", &cmdlist); + c->completer = filename_completer; - add_com ("exec-file", class_files, exec_file_command, + c = add_cmd ("exec-file", class_files, exec_file_command, "Use FILE as program for getting contents of pure memory.\n\ If FILE cannot be found as specified, your execution directory path\n\ is searched for a command of that name.\n\ -No arg means have no executable file."); +No arg means have no executable file.", &cmdlist); + c->completer = filename_completer; add_com ("section", class_files, set_section_command, "Change the base address of section SECTION of the exec file to ADDR.\n\ diff --git a/gdb/i386lynx-nat.c b/gdb/i386lynx-nat.c index 204880a4127..63300f149ec 100644 --- a/gdb/i386lynx-nat.c +++ b/gdb/i386lynx-nat.c @@ -50,6 +50,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define FS 0 #define GS 0 +static struct target_ops lynx_core_ops; + /* this table must line up with REGISTER_NAMES in m-i386.h */ static unsigned int regmap[] = { @@ -184,36 +186,6 @@ store_inferior_registers (regno) store_register (regno, offset, inferior_pid); } -/* Extract the register values out of the core file and store - them where `read_register' will find them. - - CORE_REG_SECT points to the register values themselves, read into memory. - CORE_REG_SIZE is the size of that area. - WHICH says which set of registers we are handling (0 = int, 2 = float - on machines where they are discontiguous). - REG_ADDR is the offset from u.u_ar0 to the register values relative to - core_reg_sect. This is used with old-fashioned core files to - locate the registers in a large upage-plus-stack ".reg" section. - Original upage address X is at location core_reg_sect+x+reg_addr. - */ - -void -fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr) - char *core_reg_sect; - unsigned core_reg_size; - int which; - unsigned reg_addr; -{ - struct st_entry s; - unsigned int regno, addr; - - for (regno = 0; regno < NUM_REGS; regno++) - { - addr = register_addr (regno, (char *) &s.ec - (char *) &s); - supply_register (regno, core_reg_sect + addr); - } -} - /* Wait for child to do something. Return pid of child, or -1 in case of error; store status through argument pointer STATUS. */ @@ -269,26 +241,6 @@ child_wait (status) } } -/* Return the PC of the caller from the call frame. Assumes the subr prologue - has already been executed, and the frame pointer setup. If this is the - outermost frame, we check to see if we are in a system call by examining the - previous instruction. If so, then the return PC is actually at SP+4 because - system calls use a different calling sequence. */ - -CORE_ADDR -i386lynx_saved_pc_after_call (frame) - struct frame_info *frame; -{ - char opcode[7]; - static const char call_inst[] = {0x9a, 0, 0, 0, 0, 8, 0}; /* lcall 0x8,0x0 */ - - read_memory (frame->pc - 7, opcode, 7); - if (memcmp (opcode, call_inst, 7) == 0) - return read_memory_integer (read_register (SP_REGNUM) + 4, 4); - - return read_memory_integer (read_register (SP_REGNUM), 4); -} - /* Convert a Lynx process ID to a string. Returns the string in a static buffer. */ @@ -302,3 +254,274 @@ i386lynx_pid_to_str (pid) return buf; } + +/* Extract the register values out of the core file and store + them where `read_register' will find them. + + CORE_REG_SECT points to the register values themselves, read into memory. + CORE_REG_SIZE is the size of that area. + WHICH says which set of registers we are handling (0 = int, 2 = float + on machines where they are discontiguous). + REG_ADDR is the offset from u.u_ar0 to the register values relative to + core_reg_sect. This is used with old-fashioned core files to + locate the registers in a large upage-plus-stack ".reg" section. + Original upage address X is at location core_reg_sect+x+reg_addr. + */ + +void +fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr) + char *core_reg_sect; + unsigned core_reg_size; + int which; + unsigned reg_addr; +{ + struct st_entry s; + unsigned int regno, addr; + + for (regno = 0; regno < NUM_REGS; regno++) + { + addr = register_addr (regno, (char *) &s.ec - (char *) &s); + supply_register (regno, core_reg_sect + addr); + } +} + +#if 0 + +/* Discard all vestiges of any previous core file + and mark data and stack spaces as empty. */ + +/* ARGSUSED */ +static void +lynx_core_close (quitting) + int quitting; +{ + if (core_bfd) + { + free (bfd_get_filename (core_bfd)); + bfd_close (core_bfd); + core_bfd = NULL; + + if (core_ops.to_sections) + { + free ((PTR)lynx_core_ops.to_sections); + lynx_core_ops.to_sections = NULL; + lynx_core_ops.to_sections_end = NULL; + } + } +} + +/* This routine opens and sets up the core file bfd */ + +static void +lynx_core_open (filename, from_tty) + char *filename; + int from_tty; +{ + const char *p; + int siggy; + struct cleanup *old_chain; + char *temp; + bfd *temp_bfd; + int ontop; + int scratch_chan; + + target_preopen (from_tty); + if (!filename) + { + error (core_bfd ? + "No core file specified. (Use `detach' to stop debugging a core file.)" + : "No core file specified."); + } + + filename = tilde_expand (filename); + if (filename[0] != '/') + { + temp = concat (current_directory, "/", filename, NULL); + free (filename); + filename = temp; + } + + old_chain = make_cleanup (free, filename); + + scratch_chan = open (filename, write_files? O_RDWR: O_RDONLY, 0); + if (scratch_chan < 0) + perror_with_name (filename); + + temp_bfd = bfd_fdopenr (filename, NULL, scratch_chan); + if (temp_bfd == NULL) + perror_with_name (filename); + + if (!bfd_check_format (temp_bfd, bfd_core)) + { + /* Do it after the err msg */ + make_cleanup (bfd_close, temp_bfd); + error ("\"%s\" is not a core dump: %s", filename, bfd_errmsg(bfd_error)); + } + + /* Looks semi-reasonable. Toss the old core file and work on the new. */ + + discard_cleanups (old_chain); /* Don't free filename any more */ + unpush_target (&core_ops); + core_bfd = temp_bfd; + old_chain = make_cleanup (core_close, core_bfd); + + validate_files (); + + /* Find the data section */ + if (build_section_table (core_bfd, &core_ops.to_sections, + &core_ops.to_sections_end)) + error ("Can't find sections in `%s': %s", bfd_get_filename(core_bfd), + bfd_errmsg (bfd_error)); + + ontop = !push_target (&core_ops); + discard_cleanups (old_chain); + + p = bfd_core_file_failing_command (core_bfd); + if (p) + printf_filtered ("Core was generated by `%s'.\n", p); + + siggy = bfd_core_file_failing_signal (core_bfd); + if (siggy > 0) + printf_filtered ("Program terminated with signal %d, %s.\n", siggy, + safe_strsignal (siggy)); + + /* Locate all of the thread register sections. They have names like .regxx, + where xx is the thread-id. */ + + bfd_map_over_sections (core_bfd, grok_register_sections, + + if (ontop) + { + /* Fetch all registers from core file */ + target_fetch_registers (-1); + + /* Now, set up the frame cache, and print the top of stack */ + set_current_frame (create_new_frame (read_fp (), + read_pc ())); + select_frame (get_current_frame (), 0); + print_stack_frame (selected_frame, selected_frame_level, 1); + } + else + { + warning ( + "you won't be able to access this core file until you terminate\n\ +your %s; do ``info files''", current_target->to_longname); + } +} + +static void +lynx_core_detach (args, from_tty) + char *args; + int from_tty; +{ + if (args) + error ("Too many arguments"); + unpush_target (&core_ops); + if (from_tty) + printf_filtered ("No core file now.\n"); +} + +/* Get the registers out of a core file. This is the machine- + independent part. Fetch_core_registers is the machine-dependent + part, typically implemented in the xm-file for each architecture. */ + +/* We just get all the registers, so we don't use regno. */ +/* ARGSUSED */ +static void +get_core_registers (regno) + int regno; +{ + sec_ptr reg_sec; + unsigned size; + char *the_regs; + char regsecname[20]; + + sprintf (regsecname, ".reg%d", TIDGET (inferior_pid)); + + reg_sec = bfd_get_section_by_name (core_bfd, regsecname); + if (!reg_sec) + goto cant; + size = bfd_section_size (core_bfd, reg_sec); + the_regs = alloca (size); + if (bfd_get_section_contents (core_bfd, reg_sec, the_regs, (file_ptr)0, + size)) + { + fetch_core_registers (the_regs, size, 0, + (unsigned) bfd_section_vma (abfd,reg_sec)); + } + else + { +cant: + fprintf_filtered (stderr, "Couldn't fetch registers from core file: %s\n", + bfd_errmsg (bfd_error)); + } + + registers_fetched(); +} + +static void +core_files_info (t) + struct target_ops *t; +{ + print_section_info (t, core_bfd); +} + +/* If mourn is being called in all the right places, this could be say + `gdb internal error' (since generic_mourn calls mark_breakpoints_out). */ + +static int +ignore (addr, contents) + CORE_ADDR addr; + char *contents; +{ +} + +static struct target_ops +lynx_core_ops = +{ + "core", + "Local core dump file", + "Use a core file as a target. Specify the filename of the core file.", + lynx_core_open, + lynx_core_close, + find_default_attach, + lynx_core_detach, + 0, + 0, + get_core_registers, + 0, + 0, + xfer_memory, + lynx_core_files_info, + ignore, + ignore, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + find_default_create_inferior, + 0, /* mourn_inferior */ + 0, /* can_run */ + 0, /* notice_signals */ + core_stratum, + 0, /* next */ + 0, + 1, + 1, + 1, + 0, + 0, + 0, + OPS_MAGIC, /* Always the last thing */ +}; + +void +_initialize_i386lynx_nat() +{ + add_target (&lynx_core_ops); +} +#endif diff --git a/gdb/i386lynx-tdep.c b/gdb/i386lynx-tdep.c new file mode 100644 index 00000000000..87b0ac17f82 --- /dev/null +++ b/gdb/i386lynx-tdep.c @@ -0,0 +1,43 @@ +/* Target-dependent code for Lynx running on i386's, for GDB. + Copyright 1988, 1989, 1991, 1992, 1993 + 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 "defs.h" +#include "inferior.h" +#include "target.h" + +/* Return the PC of the caller from the call frame. Assumes the subr prologue + has already been executed, and the frame pointer setup. If this is the + outermost frame, we check to see if we are in a system call by examining the + previous instruction. If so, then the return PC is actually at SP+4 because + system calls use a different calling sequence. */ + +CORE_ADDR +i386lynx_saved_pc_after_call (frame) + struct frame_info *frame; +{ + char opcode[7]; + static const char call_inst[] = {0x9a, 0, 0, 0, 0, 8, 0}; /* lcall 0x8,0x0 */ + + read_memory (frame->pc - 7, opcode, 7); + if (memcmp (opcode, call_inst, 7) == 0) + return read_memory_integer (read_register (SP_REGNUM) + 4, 4); + + return read_memory_integer (read_register (SP_REGNUM), 4); +} diff --git a/gdb/maint.c b/gdb/maint.c index 9a37fe0f6bd..bc73bdc4c73 100644 --- a/gdb/maint.c +++ b/gdb/maint.c @@ -29,6 +29,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "symtab.h" #include "gdbtypes.h" #include "demangle.h" +#include "gdbcore.h" static void maintenance_command PARAMS ((char *, int)); @@ -124,6 +125,79 @@ maintenance_info_command (arg, from_tty) help_list (maintenanceinfolist, "maintenance info ", -1, stdout); } +static void +print_section_table (abfd, asect, ignore) + bfd *abfd; + asection *asect; + PTR ignore; +{ + flagword flags; + + flags = bfd_get_section_flags (abfd, asect); + + printf_filtered (" %s", + local_hex_string_custom (bfd_section_vma (abfd, asect), + "08")); + printf_filtered ("->%s", + local_hex_string_custom ((bfd_section_vma (abfd, asect) + + bfd_section_size (abfd, asect)), + "08")); + printf_filtered (" at %s", local_hex_string_custom (asect->filepos, "08")); + printf_filtered (": %s", bfd_section_name (abfd, asect)); + + if (flags & SEC_ALLOC) + printf_filtered (" ALLOC"); + if (flags & SEC_LOAD) + printf_filtered (" LOAD"); + if (flags & SEC_RELOC) + printf_filtered (" RELOC"); + if (flags & SEC_READONLY) + printf_filtered (" READONLY"); + if (flags & SEC_CODE) + printf_filtered (" CODE"); + if (flags & SEC_DATA) + printf_filtered (" DATA"); + if (flags & SEC_ROM) + printf_filtered (" ROM"); + if (flags & SEC_CONSTRUCTOR) + printf_filtered (" CONSTRUCTOR"); + if (flags & SEC_HAS_CONTENTS) + printf_filtered (" HAS_CONTENTS"); + if (flags & SEC_NEVER_LOAD) + printf_filtered (" NEVER_LOAD"); + if (flags & SEC_SHARED_LIBRARY) + printf_filtered (" SHARED_LIBRARY"); + if (flags & SEC_IS_COMMON) + printf_filtered (" IS_COMMON"); + + printf_filtered ("\n"); +} + +/* ARGSUSED */ +static void +maintenance_info_sections (arg, from_tty) + char *arg; + int from_tty; +{ + if (exec_bfd) + { + printf_filtered ("Exec file:\n"); + printf_filtered (" `%s', ", bfd_get_filename(exec_bfd)); + wrap_here (" "); + printf_filtered ("file type %s.\n", bfd_get_target(exec_bfd)); + bfd_map_over_sections(exec_bfd, print_section_table, 0); + } + + if (core_bfd) + { + printf_filtered ("Core file:\n"); + printf_filtered (" `%s', ", bfd_get_filename(core_bfd)); + wrap_here (" "); + printf_filtered ("file type %s.\n", bfd_get_target(core_bfd)); + bfd_map_over_sections(core_bfd, print_section_table, 0); + } +} + /* The "maintenance print" command is defined as a prefix, with allow_unknown 0. Therefore, its own definition is called only for "maintenance print" with no args. */ @@ -174,6 +248,10 @@ to test internal functions such as the C++ demangler, etc.", &maintenanceinfolist, "maintenance info ", 0, &maintenancelist); + add_cmd ("sections", class_maintenance, maintenance_info_sections, + "List the BFD sections of the exec and core files.", + &maintenanceinfolist); + add_prefix_cmd ("print", class_maintenance, maintenance_print_command, "Maintenance command for printing GDB internal state.", &maintenanceprintlist, "maintenance print ", 0,