(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.
+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
# 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
# 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
#ifndef NM_I386LYNX_H
#define NM_I386LYNX_H
+#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/mem.h>
#include <sys/signal.h>
#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 */
#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 */
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) {
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));
{
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;
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"));
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\
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 */
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\
#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[] =
{
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. */
}
}
-/* 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. */
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);
+}
+\f
+/* 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
--- /dev/null
+/* 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);
+}
#include "symtab.h"
#include "gdbtypes.h"
#include "demangle.h"
+#include "gdbcore.h"
static void
maintenance_command PARAMS ((char *, int));
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. */
&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,