* 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.
This commit is contained in:
Stu Grossman 1993-09-22 15:23:53 +00:00
parent bdb45162af
commit b1eaba9ac4
9 changed files with 452 additions and 70 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -20,6 +20,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef NM_I386LYNX_H
#define NM_I386LYNX_H
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/mem.h>
#include <sys/signal.h>
@ -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 */

View file

@ -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 */

View file

@ -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\

View file

@ -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

43
gdb/i386lynx-tdep.c Normal file
View file

@ -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);
}

View file

@ -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,