import gdb-2000-01-31 snapshot

This commit is contained in:
Jason Molenda 2000-02-01 03:19:29 +00:00
parent 557537a556
commit da59e08184
35 changed files with 1660 additions and 1239 deletions

View File

@ -1,3 +1,111 @@
2000-01-31 Jason Molenda (jsm@bugshack.cygnus.com)
* config/alpha/alpha-osf2.mh, config/alpha/alpha-osf3.mh,
config/i386/i386dgux.mh, config/i386/i386sol2.mh,
config/i386/i386v4.mh, config/i386/i386v42mp.mh,
config/i386/ncr3000.mh, config/m68k/m68kv4.mh,
config/m88k/delta88v4.mh, config/mips/irix4.mh,
config/mips/irix5.mh, config/mips/mipsv4.mh,
config/powerpc/solaris.mh (NATDEPFILES): Change references to
proc_api.o, proc_events.o, proc_flags.o, and proc_why.o to
proc-api.o, proc-events.o, proc-flags.o, and proc-why.o.
Mon Jan 31 17:14:52 2000 Andrew Cagney <cagney@b1.cygnus.com>
* top.c (fputs_unfiltered_hook): Moved to tui/tui-file.c.
* main.c (captured_main): Only use the legacy tui_file code when
linking in older code such as the TUI.
* gdb-file.h, gdb-file.c: New files.
* utils.c, defs.h (struct gdb_file, gdb_file_new, gdb_file_delete,
null_file_isatty, null_file_rewind, null_file_put,
null_file_flush, null_file_write, null_file_fputs,
null_file_delete, gdb_file_data, gdb_flush, gdb_file_isatty,
gdb_file_rewind, gdb_file_put, gdb_file_write, fputs_unfiltered,
set_gdb_file_flush, set_gdb_file_isatty, set_gdb_file_rewind,
set_gdb_file_put, set_gdb_file_write, set_gdb_file_fputs,
set_gdb_file_data, struct accumulated_gdb_file,
do_gdb_file_xstrdup, gdb_file_xstrdup, struct mem_file):
mem_file_new, mem_file_delete, mem_fileopen, mem_file_rewind,
mem_file_put, mem_file_write, struct stdio_file): stdio_file_new,
stdio_file_delete, stdio_file_flush, stdio_file_write,
stdio_file_fputs, stdio_file_isatty, stdio_fileopen, gdb_fopen):
Moved to gdb-file.h and gdb-file.c.
* utils.c (enum streamtype, struct tui_stream, tui_file_new,
tui_file_delete, tui_fileopen, tui_sfileopen, tui_file_isatty,
tui_file_rewind, tui_file_put, tui_file_fputs,
tui_file_get_strbuf, tui_file_adjust_strbuf, tui_file_flush,
fputs_unfiltered_hook):
Moved to tui/tui-file.c and tui/tui-file.h.
* Makefile.in (COMMON_OBS): Add gdb-file.o, tui-file.o.
(tui-file.o, gdb-file.o): Add dependencies.
(corefile.o, main.o, utils.o, simmisc.o): Update dependencies.
* main.c: #include tui/tui-file.h.
2000-01-28 Fred Fish <fnf@cygnus.com>
* findvar.c (value_from_register): Special case handling of D10V
pointer values fetched from registers.
2000-01-28 Fernando Nasser <fnasser@totem.to.cygnus.com>
* arm-tdep.c (thumb_skip_prologue, thumb_scan_prologue): Add
support for new style thumb prologues.
2000-01-28 Nick Clifton <nickc@redhat.com>
* arm-tdep.c: Remove extraneous dash at start of strings
introduced in previous delta.
2000-01-27 Nick Clifton <nickc@redhat.com>
* arm-tdep.c: Replace uses of arm_toggle_renames() with
parse_arm_disassembler_option().
2000-01-27 Jim Blandy <jimb@cygnus.com>
* symtab.c (decode_line_1): Don't let commas that are within
quotes or parenthesis terminate the line spec. Don't use pp when
removing the final double quote of a double-quoted string. Don't
forget to skip the opening double quote. I have no clue whether
this change is correct; probably we've just moved this function
from one buggy place to another buggy place, and never came within
an outhouse whiff of correctness.
(find_toplevel_char): New function.
2000-01-27 Fernando Nasser <fnasser@totem.to.cygnus.com>
* arm-tdep.c (arm_push_arguments): Set the thumb mode bit when
passing the pointer to a thumb function as an argument.
2000-01-27 Fernando Nasser <fnasser@totem.to.cygnus.com>
* remote-rdi.c (arm_rdi_mourn_inferior): Make sure breakpoints
are reinserted for another run.
2000-01-27 Fernando Nasser <fnasser@totem.to.cygnus.com>
* infcmd.c (run_stack_dummy): Account for a random signal stopping
the inferior as well as breakpoints being hit while performing an
inferior function call.
* valops.c (hand_function_call): Ditto.
2000-01-27 Elena Zannoni <ezannoni@kwikemart.cygnus.com>
From Mark Kettenis <kettenis@gnu.org>
* config/i386/tm-i386gnu.h (THREAD_STATE_FLAVOR): Define to
i386_REGS_SEGS_STATE.
(HAVE_I387_REGS): Define.
(FLOAT_INFO): Remove.
* i386gnu-nat.c: Almost completely rewritten to use new i386
register layout and `float info' implementation.
* gnu-nat.c (inf_update_procs, proc_get_state, proc_string):
Move prototypes from here.
* gnu-nat.h: To here.
2000-01-24 Kevin Buettner <kevinb@redhat.com>
* utils.c (get_field, put_field): Fix buffer underruns and

View File

@ -229,7 +229,7 @@ CDEPS = $(XM_CDEPS) $(TM_CDEPS) $(NAT_CDEPS) $(SIM) $(BFD) $(READLINE) \
ADD_FILES = $(REGEX) $(XM_ADD_FILES) $(TM_ADD_FILES) $(NAT_ADD_FILES)
ADD_DEPS = $(REGEX1) $(XM_ADD_FILES) $(TM_ADD_FILES) $(NAT_ADD_FILES)
VERSION = 20000126
VERSION = 20000131
DIST=gdb
LINT=/usr/5bin/lint
@ -402,7 +402,9 @@ SFILES = ax-general.c ax-gdb.c bcache.c blockframe.c breakpoint.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/tuiStack.c tui/tuiStack.h tui/tuiWin.c tui/tuiWin.h \
tui/tui-file.h tui/tui-file.c \
gdb-file.h gdb-file.c
LINTFILES = $(SFILES) $(YYFILES) @CONFIG_SRCS@ init.c
@ -451,7 +453,7 @@ command_h = command.h
gdbcmd_h = gdbcmd.h $(command_h)
call_cmds_h = call-cmds.h
defs_h = defs.h xm.h tm.h nm.h config.status config.h gdbarch.h
defs_h = defs.h xm.h tm.h nm.h config.status config.h gdbarch.h gdb-file.h
top_h = top.h
inferior_h = inferior.h $(breakpoint_h)
@ -532,7 +534,8 @@ COMMON_OBS = version.o blockframe.o breakpoint.o findvar.o stack.o thread.o \
scm-exp.o scm-lang.o scm-valprint.o complaints.o typeprint.o \
c-typeprint.o ch-typeprint.o f-typeprint.o m2-typeprint.o \
c-valprint.o cp-valprint.o ch-valprint.o f-valprint.o m2-valprint.o \
nlmread.o serial.o mdebugread.o os9kread.o top.o utils.o
nlmread.o serial.o mdebugread.o os9kread.o top.o utils.o \
gdb-file.o tui-file.o
OBS = $(COMMON_OBS) $(ANNOTATE_OBS)
@ -1300,7 +1303,7 @@ m88k-tdep.o: m88k-tdep.c $(defs_h) $(gdbcore_h) $(inferior_h)
mac-nat.o: mac-nat.c $(defs_h) gdb_string.h
main.o: main.c top.h $(defs_h) gdb_string.h $(event_loop_h)
main.o: main.c top.h $(defs_h) gdb_string.h $(event_loop_h) tui/tui-file.h
maint.o: maint.c $(defs_h) $(gdbcmd_h) $(gdbtypes_h) $(symtab_h) language.h \
$(expression_h) objfiles.h symfile.h
@ -1602,6 +1605,10 @@ stabsread.o: stabsread.c $(bfd_h) $(INCLUDE_DIR)/aout/stab.def \
stack.o: stack.c $(defs_h) $(gdbcmd_h) $(gdbcore_h) $(inferior_h) \
language.h target.h gdb_string.h
gdb-file.o: gdb-file.c $(defs_h) gdb-file.h
tui-file.o: $(srcdir)/tui/tui-file.c $(defs_h) $(srcdir)/tui/tui-file.h
$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/tui/tui-file.c
ax-general.o: ax-general.c $(ax_h) $(defs_h) $(value_h)
ax-gdb.o: ax-gdb.c $(defs_h) $(symtab_h) symfile.h $(gdbtypes_h) \
$(value_h) $(expression_h) $(command_h) $(ax_h) $(gdbcmd_h) ax-gdb.h

View File

@ -1,5 +1,5 @@
/* Common target dependent code for GDB on ARM systems.
Copyright 1988, 1989, 1991, 1992, 1993, 1995-1999
Copyright 1988, 1989, 1991, 1992, 1993, 1995, 1996, 1997, 1998, 1999, 2000
Free Software Foundation, Inc.
This file is part of GDB.
@ -45,33 +45,33 @@ extern void _initialize_arm_tdep (void);
#define UNMAKE_THUMB_ADDR(addr) ((addr) & ~1)
/* Default register names as specified by APCS. */
static char *apcs_register_names[] =
static char * atpcs_register_names[] =
{"a1", "a2", "a3", "a4", /* 0 1 2 3 */
"v1", "v2", "v3", "v4", /* 4 5 6 7 */
"v5", "v6", "sl", "fp", /* 8 9 10 11 */
"ip", "sp", "lr", "pc", /* 12 13 14 15 */
"v5", "v6", "v7", "v8", /* 8 9 10 11 */
"IP", "SP", "LR", "PC", /* 12 13 14 15 */
"f0", "f1", "f2", "f3", /* 16 17 18 19 */
"f4", "f5", "f6", "f7", /* 20 21 22 23 */
"fps", "ps"} /* 24 25 */ ;
"FPS", "PS" }; /* 24 25 */
/* Alternate set of registers names used by GCC. */
static char *additional_register_names[] =
{"r0", "r1", "r2", "r3", /* 0 1 2 3 */
"r4", "r5", "r6", "r7", /* 4 5 6 7 */
"r8", "r9", "r10", "r11", /* 8 9 10 11 */
"r12", "r13", "r14", "pc", /* 12 13 14 15 */
"f0", "f1", "f2", "f3", /* 16 17 18 19 */
"f4", "f5", "f6", "f7", /* 20 21 22 23 */
"fps", "ps"} /* 24 25 */ ;
static char * additional_register_names[] =
{"r0", "r1", "r2", "r3", /* 0 1 2 3 */
"r4", "r5", "r6", "r7", /* 4 5 6 7 */
"r8", "r9", "r10", "r11", /* 8 9 10 11 */
"r12", "sp", "lr", "pc", /* 12 13 14 15 */
"f0", "f1", "f2", "f3", /* 16 17 18 19 */
"f4", "f5", "f6", "f7", /* 20 21 22 23 */
"fps", "ps" }; /* 24 25 */
/* This is the variable that is set with "set disassembly-flavor".
By default use the APCS registers names. */
char **arm_register_names = apcs_register_names;
char ** arm_register_names = atpcs_register_names;
/* Valid register name flavours. */
static char apcs_flavor[] = "apcs";
static char r_prefix_flavor[] = "r-prefix";
static char *valid_flavors[] =
static char * valid_flavors[] =
{
apcs_flavor,
r_prefix_flavor,
@ -296,24 +296,65 @@ arm_frameless_function_invocation (struct frame_info *fi)
add sp, sp, #-28
add r7, sp, #12
Sometimes the latter instruction may be replaced by:
mov r7, sp
mov r7, sp
or like this:
push {r7, lr}
mov r7, sp
sub sp, #12
or, on tpcs, like this:
sub sp,#16
push {r7, lr}
(many instructions)
mov r7, sp
sub sp, #12
There is always one instruction of three classes:
1 - push
2 - setting of r7
3 - adjusting of sp
When we have found at least one of each class we are done with the prolog.
Note that the "sub sp, #NN" before the push does not count.
*/
static CORE_ADDR
thumb_skip_prologue (CORE_ADDR pc)
{
CORE_ADDR current_pc;
int findmask = 0; /* findmask:
bit 0 - push { rlist }
bit 1 - mov r7, sp OR add r7, sp, #imm (setting of r7)
bit 2 - sub sp, #simm OR add sp, #simm (adjusting of sp)
*/
for (current_pc = pc; current_pc < pc + 20; current_pc += 2)
for (current_pc = pc; current_pc < pc + 40; current_pc += 2)
{
unsigned short insn = read_memory_unsigned_integer (current_pc, 2);
if ((insn & 0xfe00) != 0xb400 /* push {..., r7, lr} */
&& (insn & 0xff00) != 0xb000 /* add sp, #simm */
&& (insn & 0xff00) != 0xaf00 /* add r7, sp, #imm */
&& insn != 0x466f /* mov r7, sp */
&& (insn & 0xffc0) != 0x4640) /* mov r0-r7, r8-r15 */
break;
if ((insn & 0xfe00) == 0xb400) /* push { rlist } */
{
findmask |= 1; /* push found */
}
else if ((insn & 0xff00) == 0xb000) /* add sp, #simm OR sub sp, #simm */
{
if ((findmask & 1) == 0) /* before push ? */
continue;
else
findmask |= 4; /* add/sub sp found */
}
else if ((insn & 0xff00) == 0xaf00) /* add r7, sp, #imm */
{
findmask |= 2; /* setting of r7 found */
}
else if (insn == 0x466f) /* mov r7, sp */
{
findmask |= 2; /* setting of r7 found */
}
else
continue; /* something in the prolog that we don't care about or some
instruction from outside the prolog scheduled here for optimization */
}
return current_pc;
@ -408,18 +449,18 @@ arm_skip_prologue (CORE_ADDR pc)
4) the offset from the stack pointer to the frame pointer
This information is stored in the "extra" fields of the frame_info.
A typical Thumb function prologue might look like this:
push {r7, lr}
sub sp, #28,
add r7, sp, #12
Which would create this stack frame (offsets relative to FP)
A typical Thumb function prologue would create this stack frame
(offsets relative to FP)
old SP -> 24 stack parameters
20 LR
16 R7
R7 -> 0 local variables (16 bytes)
SP -> -12 additional stack space (12 bytes)
The frame size would thus be 36 bytes, and the frame offset would be
12 bytes. The frame register is R7. */
12 bytes. The frame register is R7.
The comments for thumb_skip_prolog() describe the algorithm we use to detect
the end of the prolog */
/* *INDENT-ON* */
static void
@ -429,6 +470,11 @@ thumb_scan_prologue (struct frame_info *fi)
CORE_ADDR prologue_end;
CORE_ADDR current_pc;
int saved_reg[16]; /* which register has been copied to register n? */
int findmask = 0; /* findmask:
bit 0 - push { rlist }
bit 1 - mov r7, sp OR add r7, sp, #imm (setting of r7)
bit 2 - sub sp, #simm OR add sp, #simm (adjusting of sp)
*/
int i;
if (find_pc_partial_function (fi->pc, NULL, &prologue_start, &prologue_end))
@ -452,10 +498,13 @@ thumb_scan_prologue (struct frame_info *fi)
saved_reg[i] = i;
/* Search the prologue looking for instructions that set up the
frame pointer, adjust the stack pointer, and save registers. */
frame pointer, adjust the stack pointer, and save registers.
Do this until all basic prolog instructions are found. */
fi->framesize = 0;
for (current_pc = prologue_start; current_pc < prologue_end; current_pc += 2)
for (current_pc = prologue_start;
(current_pc < prologue_end) && ((findmask & 7) != 7);
current_pc += 2)
{
unsigned short insn;
int regno;
@ -465,9 +514,11 @@ thumb_scan_prologue (struct frame_info *fi)
if ((insn & 0xfe00) == 0xb400) /* push { rlist } */
{
int mask;
findmask |= 1; /* push found */
/* Bits 0-7 contain a mask for registers R0-R7. Bit 8 says
whether to save LR (R14). */
int mask = (insn & 0xff) | ((insn & 0x100) << 6);
mask = (insn & 0xff) | ((insn & 0x100) << 6);
/* Calculate offsets of saved R0-R7 and LR. */
for (regno = LR_REGNUM; regno >= 0; regno--)
@ -478,20 +529,30 @@ thumb_scan_prologue (struct frame_info *fi)
saved_reg[regno] = regno; /* reset saved register map */
}
}
else if ((insn & 0xff00) == 0xb000) /* add sp, #simm */
else if ((insn & 0xff00) == 0xb000) /* add sp, #simm OR sub sp, #simm */
{
if ((findmask & 1) == 0) /* before push ? */
continue;
else
findmask |= 4; /* add/sub sp found */
offset = (insn & 0x7f) << 2; /* get scaled offset */
if (insn & 0x80) /* is it signed? */
offset = -offset;
if (insn & 0x80) /* is it signed? (==subtracting) */
{
fi->frameoffset += offset;
offset = -offset;
}
fi->framesize -= offset;
}
else if ((insn & 0xff00) == 0xaf00) /* add r7, sp, #imm */
{
findmask |= 2; /* setting of r7 found */
fi->framereg = THUMB_FP_REGNUM;
fi->frameoffset = (insn & 0xff) << 2; /* get scaled offset */
}
else if (insn == 0x466f) /* mov r7, sp */
else if (insn == 0x466f) /* mov r7, sp */
{
findmask |= 2; /* setting of r7 found */
fi->framereg = THUMB_FP_REGNUM;
fi->frameoffset = 0;
saved_reg[THUMB_FP_REGNUM] = SP_REGNUM;
@ -503,7 +564,8 @@ thumb_scan_prologue (struct frame_info *fi)
saved_reg[lo_reg] = hi_reg; /* remember hi reg was saved */
}
else
break; /* anything else isn't prologue */
continue; /* something in the prolog that we don't care about or some
instruction from outside the prolog scheduled here for optimization */
}
}
@ -1170,7 +1232,10 @@ arm_push_arguments (int nargs, value_ptr * args, CORE_ADDR sp,
val = (char *) &dbl_arg;
len = sizeof (double);
}
#if 0
#if 1
/* I don't know why this code was disable. The only logical use
for a function pointer is to call that function, so setting
the mode bit is perfectly fine. FN */
/* If the argument is a pointer to a function, and it is a Thumb
function, set the low bit of the pointer. */
if (TYPE_CODE_PTR == typecode
@ -1278,14 +1343,12 @@ set_disassembly_flavor (void)
{
if (disassembly_flavor == apcs_flavor)
{
if (arm_toggle_regnames () == 0)
arm_toggle_regnames ();
arm_register_names = apcs_register_names;
parse_arm_disassembler_option ("reg-names-atpcs");
arm_register_names = atpcs_register_names;
}
else if (disassembly_flavor == r_prefix_flavor)
{
if (arm_toggle_regnames () == 1)
arm_toggle_regnames ();
parse_arm_disassembler_option ("reg-names-std");
arm_register_names = additional_register_names;
}
}
@ -1917,9 +1980,7 @@ _initialize_arm_tdep (void)
tm_print_insn = gdb_print_insn_arm;
/* Sync the opcode insn printer with our register viewer: */
if (arm_toggle_regnames () != 1)
arm_toggle_regnames ();
parse_arm_disassembler_option ("reg-names-atpcs");
/* Add the deprecated "othernames" command */

View File

@ -3,4 +3,4 @@ XDEPFILES=
XM_FILE= xm-alphaosf.h
NAT_FILE= nm-osf2.h
NATDEPFILES= infptrace.o inftarg.o corelow.o alpha-nat.o fork-child.o \
osfsolib.o procfs.o proc_api.o proc_events.o proc_flags.o proc_why.o
osfsolib.o procfs.o proc-api.o proc-events.o proc-flags.o proc-why.o

View File

@ -3,5 +3,5 @@ XDEPFILES=
XM_FILE= xm-alphaosf.h
NAT_FILE= nm-osf3.h
NATDEPFILES= infptrace.o inftarg.o corelow.o alpha-nat.o fork-child.o \
osfsolib.o procfs.o proc_api.o proc_events.o proc_flags.o proc_why.o
osfsolib.o procfs.o proc-api.o proc-events.o proc-flags.o proc-why.o

View File

@ -7,4 +7,4 @@ XM_CLIBS= -lsocket -lnsl
NAT_FILE= nm-i386v4.h
NATDEPFILES= corelow.o core-regset.o solib.o fork-child.o i386v4-nat.o \
procfs.o proc_api.o proc_events.o proc_flags.o proc_why.o
procfs.o proc-api.o proc-events.o proc-flags.o proc-why.o

View File

@ -5,4 +5,4 @@ XDEPFILES=
NAT_FILE= nm-i386sol2.h
NATDEPFILES= core-regset.o fork-child.o i386v4-nat.o corelow.o procfs.o \
proc_api.o proc_events.o proc_flags.o proc_why.o
proc-api.o proc-events.o proc-flags.o proc-why.o

View File

@ -7,4 +7,4 @@ XM_CLIBS= -lsocket -lnsl
NAT_FILE= nm-i386v4.h
NATDEPFILES= corelow.o core-regset.o solib.o fork-child.o i386v4-nat.o \
procfs.o proc_api.o proc_events.o proc_flags.o proc_why.o
procfs.o proc-api.o proc-events.o proc-flags.o proc-why.o

View File

@ -9,5 +9,5 @@ XM_CLIBS= -lsocket -lnsl
# appropriate for i386v42mp
NAT_FILE= nm-i386v42mp.h
NATDEPFILES= corelow.o core-regset.o solib.o fork-child.o i386v4-nat.o \
procfs.o proc_api.o proc_events.o proc_flags.o proc_why.o uw-thread.o
procfs.o proc-api.o proc-events.o proc-flags.o proc-why.o uw-thread.o

View File

@ -14,4 +14,4 @@ XDEPFILES=
NAT_FILE= nm-i386v4.h
NATDEPFILES= corelow.o core-regset.o fork-child.o i386v4-nat.o procfs.o \
proc_api.o proc_events.o proc_flags.o proc_why.o
proc-api.o proc-events.o proc-flags.o proc-why.o

View File

@ -1,4 +1,4 @@
/* Macro definitions for i386, GNU Hurd
/* Macro definitions for i386 running the GNU Hurd.
Copyright (C) 1992, 1999 Free Software Foundation, Inc.
This file is part of GDB.
@ -21,27 +21,27 @@
#ifndef TM_I386GNU_H
#define TM_I386GNU_H 1
/* Include common definitions for gnu systems */
/* Include common definitions for GNU systems.
FIXME: This does not belong here since this is supposed to contain
only native-dependent information. */
#include "nm-gnu.h"
/* Thread flavors used in re-setting the T bit.
* @@ this is also bad for cross debugging.
*/
#define THREAD_STATE_FLAVOR i386_THREAD_STATE
FIXME: This is native-dependent. */
#define THREAD_STATE_FLAVOR i386_REGS_SEGS_STATE
#define THREAD_STATE_SIZE i386_THREAD_STATE_COUNT
#define THREAD_STATE_SET_TRACED(state) \
((struct i386_thread_state *)state)->efl |= 0x100
#define THREAD_STATE_CLEAR_TRACED(state) \
((((struct i386_thread_state *)state)->efl &= ~0x100), 1)
/* we can do it */
/* We can attach and detach.
FIXME: This is probably native-dependent too. */
#define ATTACH_DETACH 1
#define HAVE_I387_REGS
#include "i386/tm-i386.h"
#undef FLOAT_INFO
#define FLOAT_INFO { i386_mach3_float_info (); }
/* Offset to saved PC in sigcontext. */
#define SIGCONTEXT_PC_OFFSET 68

View File

@ -5,4 +5,4 @@ XDEPFILES=
NAT_FILE= nm-sysv4.h
NATDEPFILES= corelow.o core-regset.o solib.o fork-child.o procfs.o \
proc_api.o proc_events.o proc_flags.o proc_why.o
proc-api.o proc-events.o proc-flags.o proc-why.o

View File

@ -5,4 +5,4 @@ XDEPFILES=
NAT_FILE= nm-delta88v4.h
NATDEPFILES= fork-child.o m88k-nat.o corelow.o core-regset.o solib.o \
procfs.o proc_api.o proc_events.o proc_flags.o proc_why.o
procfs.o proc-api.o proc-events.o proc-flags.o proc-why.o

View File

@ -3,7 +3,7 @@ XDEPFILES= ser-tcp.o
XM_FILE= xm-irix4.h
NAT_FILE= nm-irix4.h
NATDEPFILES= fork-child.o irix4-nat.o corelow.o procfs.o \
proc_api.o proc_events.o proc_flags.o proc_why.o
proc-api.o proc-events.o proc-flags.o proc-why.o
XM_CLIBS=-lbsd -lsun

View File

@ -3,6 +3,6 @@ XDEPFILES= ser-tcp.o
XM_FILE= xm-irix5.h
NAT_FILE= nm-irix5.h
NATDEPFILES= fork-child.o irix5-nat.o corelow.o procfs.o \
proc_api.o proc_events.o proc_flags.o proc_why.o
proc-api.o proc-events.o proc-flags.o proc-why.o
XM_CLIBS=-lbsd -lsun

View File

@ -2,4 +2,4 @@
XM_FILE= xm-mipsv4.h
NAT_FILE= ../nm-sysv4.h
NATDEPFILES= fork-child.o mipsv4-nat.o corelow.o core-regset.o solib.o \
procfs.o proc_api.o proc_events.o proc_flags.o proc_why.o
procfs.o proc-api.o proc-events.o proc-flags.o proc-why.o

View File

@ -6,7 +6,7 @@ XM_CLIBS= -lsocket -lnsl
NAT_FILE= nm-solaris.h
NATDEPFILES= corelow.o core-sol2.o solib.o fork-child.o procfs.o \
proc_api.o proc_events.o proc_flags.o proc_why.o
proc-api.o proc-events.o proc-flags.o proc-why.o
# If you are compiling with Sun's compiler, add the -xs option to CC
# (e.g. `make CC="cc -xs"').

View File

@ -386,68 +386,7 @@ extern GDB_FILE *gdb_stdtarg;
#include "tuiWin.h"
#endif
/* Create a generic gdb_file object with null methods. */
extern struct gdb_file *gdb_file_new (void);
/* Override methods used by specific implementations of a GDB_FILE
object. */
typedef void (gdb_file_flush_ftype) (struct gdb_file * stream);
extern void set_gdb_file_flush (struct gdb_file *stream, gdb_file_flush_ftype * flush);
/* NOTE: Both fputs and write methods are available. Default
implementations that mapping one onto the other are included. */
typedef void (gdb_file_write_ftype) (struct gdb_file * stream, const char *buf, long length_buf);
extern void set_gdb_file_write (struct gdb_file *stream, gdb_file_write_ftype *fputs);
typedef void (gdb_file_fputs_ftype) (const char *, struct gdb_file * stream);
extern void set_gdb_file_fputs (struct gdb_file *stream, gdb_file_fputs_ftype * fputs);
typedef int (gdb_file_isatty_ftype) (struct gdb_file * stream);
extern void set_gdb_file_isatty (struct gdb_file *stream, gdb_file_isatty_ftype * isatty);
typedef void (gdb_file_rewind_ftype) (struct gdb_file * stream);
extern void set_gdb_file_rewind (struct gdb_file *stream, gdb_file_rewind_ftype * rewind);
typedef void (gdb_file_put_method_ftype) (void *object, const char *buffer, long length_buffer);
typedef void (gdb_file_put_ftype) (struct gdb_file *stream, gdb_file_put_method_ftype * method, void *context);
extern void set_gdb_file_put (struct gdb_file *stream, gdb_file_put_ftype * put);
typedef void (gdb_file_delete_ftype) (struct gdb_file * stream);
extern void set_gdb_file_data (struct gdb_file *stream, void *data, gdb_file_delete_ftype * delete);
extern void *gdb_file_data (struct gdb_file *file);
/* Open the specified FILE as a gdb_file. */
extern struct gdb_file *stdio_fileopen (FILE *file);
/* Open NAME returning a GDB_FILE. */
extern GDB_FILE *gdb_fopen (char *name, char *mode);
/* Create/open a memory based file. Can be used as a scratch
buffer for collecting output. */
extern struct gdb_file *mem_fileopen (void);
extern void gdb_flush (GDB_FILE *);
extern void gdb_file_delete (struct gdb_file *stream);
extern void gdb_file_rewind (struct gdb_file *stream);
extern int gdb_file_isatty (GDB_FILE *);
extern void gdb_file_write (struct gdb_file *file, const char *buf, long length_buf);
/* NOTE: copies left to right */
extern void gdb_file_put (struct gdb_file *src, gdb_file_put_method_ftype *write, void *dest);
/* Returns a freshly allocated buffer containing the entire contents
of FILE (as determined by gdb_file_put()) with a NUL character
appended. LENGTH is set to the size of the buffer minus that
appended NUL. */
extern char *gdb_file_xstrdup (struct gdb_file *file, long *length);
#include "gdb-file.h"
/* More generic printf like operations */
@ -487,14 +426,6 @@ extern void fprintf_unfiltered (GDB_FILE *, const char *, ...) ATTR_FORMAT (prin
extern void printf_unfiltered (const char *, ...) ATTR_FORMAT (printf, 1, 2);
/* #if defined (TUI) */
/* DEPRECATED: Only the TUI should use these methods. */
extern struct gdb_file *tui_fileopen (FILE *);
extern struct gdb_file *tui_sfileopen (int);
extern char *tui_file_get_strbuf (struct gdb_file *);
extern void tui_file_adjust_strbuf (int, struct gdb_file *);
/* #endif */
extern void print_spaces (int, GDB_FILE *);
extern void print_spaces_filtered (int, GDB_FILE *);
@ -1199,11 +1130,6 @@ extern void (*show_load_progress) (const char *section,
unsigned long section_size,
unsigned long total_sent,
unsigned long total_size);
/* NOTE: cagney/1999-10-14: fputs_unfiltered_hook is deprecated.
Instead code wanting to control GDB's output should be overriding
the gdb_std* files. */
extern void (*fputs_unfiltered_hook) (const char *linebuffer,
GDB_FILE * stream);
extern void (*print_frame_info_listing_hook) (struct symtab * s,
int line, int stopline,
int noerror);

View File

@ -1545,6 +1545,39 @@ A function that inserts or removes (dependant on
the next instruction. See @code{sparc-tdep.c} and @code{rs6000-tdep.c}
for examples.
@item SOFUN_ADDRESS_MAYBE_MISSING
Somebody clever observed that, the more actual addresses you have in the
debug information, the more time the linker has to spend relocating
them. So whenever there's some other way the debugger could find the
address it needs, you should omit it from the debug info, to make
linking faster.
@code{SOFUN_ADDRESS_MAYBE_MISSING} indicates that a particular set of
hacks of this sort are in use, affecting @code{N_SO} and @code{N_FUN}
entries in stabs-format debugging information. @code{N_SO} stabs mark
the beginning and ending addresses of compilation units in the text
segment. @code{N_FUN} stabs mark the starts and ends of functions.
@code{SOFUN_ADDRESS_MAYBE_MISSING} means two things:
@itemize @bullet
@item
@code{N_FUN} stabs have an address of zero. Instead, you should find the
addresses where the function starts by taking the function name from
the stab, and then looking that up in the minsyms (the linker/
assembler symbol table). In other words, the stab has the name, and
the linker / assembler symbol table is the only place that carries
the address.
@item
@code{N_SO} stabs have an address of zero, too. You just look at the
@code{N_FUN} stabs that appear before and after the @code{N_SO} stab,
and guess the starting and ending addresses of the compilation unit from
them.
@end itemize
@item PCC_SOL_BROKEN
(Used only in the Convex target.)

View File

@ -1454,6 +1454,10 @@ value_from_register (type, regnum, frame)
CHECK_TYPEDEF (type);
len = TYPE_LENGTH (type);
/* Pointers on D10V are really only 16 bits, but we lie to gdb elsewhere... */
if (GDB_TARGET_IS_D10V && TYPE_CODE (type) == TYPE_CODE_PTR)
len = 2;
VALUE_REGNO (v) = regnum;
num_storage_locs = (len > REGISTER_VIRTUAL_SIZE (regnum) ?
@ -1652,6 +1656,29 @@ value_from_register (type, regnum, frame)
memcpy (VALUE_CONTENTS_RAW (v), raw_buffer + VALUE_OFFSET (v), len);
}
if (GDB_TARGET_IS_D10V
&& TYPE_CODE (type) == TYPE_CODE_PTR
&& TYPE_TARGET_TYPE (type)
&& (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC))
{
/* pointer to function */
unsigned long num;
unsigned short snum;
snum = (unsigned short) extract_unsigned_integer (VALUE_CONTENTS_RAW (v), 2);
num = D10V_MAKE_IADDR (snum);
store_address (VALUE_CONTENTS_RAW (v), 4, num);
}
else if (GDB_TARGET_IS_D10V
&& TYPE_CODE (type) == TYPE_CODE_PTR)
{
/* pointer to data */
unsigned long num;
unsigned short snum;
snum = (unsigned short) extract_unsigned_integer (VALUE_CONTENTS_RAW (v), 2);
num = D10V_MAKE_DADDR (snum);
store_address (VALUE_CONTENTS_RAW (v), 4, num);
}
return v;
}

511
gdb/gdb-file.c Normal file
View File

@ -0,0 +1,511 @@
/* GDB_FILE - a generic STDIO like output stream.
Copyright (C) 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., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* Implement the ``struct gdb_file'' object. */
#include "defs.h"
#include "gdb-file.h"
#undef XMALLOC
#define XMALLOC(TYPE) ((TYPE*) xmalloc (sizeof (TYPE)))
static gdb_file_isatty_ftype null_file_isatty;
static gdb_file_write_ftype null_file_write;
static gdb_file_fputs_ftype null_file_fputs;
static gdb_file_flush_ftype null_file_flush;
static gdb_file_delete_ftype null_file_delete;
static gdb_file_rewind_ftype null_file_rewind;
static gdb_file_put_ftype null_file_put;
struct gdb_file
{
int *magic;
gdb_file_flush_ftype *to_flush;
gdb_file_write_ftype *to_write;
gdb_file_fputs_ftype *to_fputs;
gdb_file_delete_ftype *to_delete;
gdb_file_isatty_ftype *to_isatty;
gdb_file_rewind_ftype *to_rewind;
gdb_file_put_ftype *to_put;
void *to_data;
};
int gdb_file_magic;
struct gdb_file *
gdb_file_new ()
{
struct gdb_file *file = xmalloc (sizeof (struct gdb_file));
file->magic = &gdb_file_magic;
set_gdb_file_data (file, NULL, null_file_delete);
set_gdb_file_flush (file, null_file_flush);
set_gdb_file_write (file, null_file_write);
set_gdb_file_fputs (file, null_file_fputs);
set_gdb_file_isatty (file, null_file_isatty);
set_gdb_file_rewind (file, null_file_rewind);
set_gdb_file_put (file, null_file_put);
return file;
}
void
gdb_file_delete (file)
struct gdb_file *file;
{
file->to_delete (file);
free (file);
}
static int
null_file_isatty (file)
struct gdb_file *file;
{
return 0;
}
static void
null_file_rewind (file)
struct gdb_file *file;
{
return;
}
static void
null_file_put (struct gdb_file *file,
gdb_file_put_method_ftype *write,
void *dest)
{
return;
}
static void
null_file_flush (file)
struct gdb_file *file;
{
return;
}
static void
null_file_write (struct gdb_file *file,
const char *buf,
long sizeof_buf)
{
if (file->to_fputs == null_file_fputs)
/* Both the write and fputs methods are null. Discard the
request. */
return;
else
{
/* The fputs method isn't null, slowly pass the write request
onto that. FYI, this isn't as bad as it may look - the
current (as of 1999-11-07) printf_* function calls fputc and
fputc does exactly the below. By having a write function it
is possible to clean up that code. */
int i;
char b[2];
b[1] = '\0';
for (i = 0; i < sizeof_buf; i++)
{
b[0] = buf[i];
file->to_fputs (b, file);
}
return;
}
}
static void
null_file_fputs (buf, file)
const char *buf;
struct gdb_file *file;
{
if (file->to_write == null_file_write)
/* Both the write and fputs methods are null. Discard the
request. */
return;
else
{
/* The write method was implemented, use that. */
file->to_write (file, buf, strlen (buf));
}
}
static void
null_file_delete (file)
struct gdb_file *file;
{
return;
}
void *
gdb_file_data (file)
struct gdb_file *file;
{
if (file->magic != &gdb_file_magic)
internal_error ("gdb_file_data: bad magic number");
return file->to_data;
}
void
gdb_flush (file)
struct gdb_file *file;
{
file->to_flush (file);
}
int
gdb_file_isatty (file)
struct gdb_file *file;
{
return file->to_isatty (file);
}
void
gdb_file_rewind (file)
struct gdb_file *file;
{
file->to_rewind (file);
}
void
gdb_file_put (struct gdb_file *file,
gdb_file_put_method_ftype *write,
void *dest)
{
file->to_put (file, write, dest);
}
void
gdb_file_write (struct gdb_file *file,
const char *buf,
long length_buf)
{
file->to_write (file, buf, length_buf);
}
void
fputs_unfiltered (buf, file)
const char *buf;
struct gdb_file *file;
{
file->to_fputs (buf, file);
}
void
set_gdb_file_flush (file, flush)
struct gdb_file *file;
gdb_file_flush_ftype *flush;
{
file->to_flush = flush;
}
void
set_gdb_file_isatty (file, isatty)
struct gdb_file *file;
gdb_file_isatty_ftype *isatty;
{
file->to_isatty = isatty;
}
void
set_gdb_file_rewind (file, rewind)
struct gdb_file *file;
gdb_file_rewind_ftype *rewind;
{
file->to_rewind = rewind;
}
void
set_gdb_file_put (file, put)
struct gdb_file *file;
gdb_file_put_ftype *put;
{
file->to_put = put;
}
void
set_gdb_file_write (struct gdb_file *file,
gdb_file_write_ftype *write)
{
file->to_write = write;
}
void
set_gdb_file_fputs (file, fputs)
struct gdb_file *file;
gdb_file_fputs_ftype *fputs;
{
file->to_fputs = fputs;
}
void
set_gdb_file_data (file, data, delete)
struct gdb_file *file;
void *data;
gdb_file_delete_ftype *delete;
{
file->to_data = data;
file->to_delete = delete;
}
/* gdb_file utility function for converting a ``struct gdb_file'' into
a memory buffer''. */
struct accumulated_gdb_file
{
char *buffer;
long length;
};
static void
do_gdb_file_xstrdup (void *context, const char *buffer, long length)
{
struct accumulated_gdb_file *acc = context;
if (acc->buffer == NULL)
acc->buffer = xmalloc (length + 1);
else
acc->buffer = xrealloc (acc->buffer, acc->length + length + 1);
memcpy (acc->buffer + acc->length, buffer, length);
acc->length += length;
acc->buffer[acc->length] = '\0';
}
char *
gdb_file_xstrdup (struct gdb_file *file,
long *length)
{
struct accumulated_gdb_file acc;
acc.buffer = NULL;
acc.length = 0;
gdb_file_put (file, do_gdb_file_xstrdup, &acc);
if (acc.buffer == NULL)
acc.buffer = xstrdup ("");
*length = acc.length;
return acc.buffer;
}
/* A pure memory based ``struct gdb_file'' that can be used an output
buffer. The buffers accumulated contents are available via
gdb_file_put(). */
struct mem_file
{
int *magic;
char *buffer;
int sizeof_buffer;
int length_buffer;
};
static gdb_file_rewind_ftype mem_file_rewind;
static gdb_file_put_ftype mem_file_put;
static gdb_file_write_ftype mem_file_write;
static gdb_file_delete_ftype mem_file_delete;
static struct gdb_file *mem_file_new PARAMS ((void));
static int mem_file_magic;
static struct gdb_file *
mem_file_new (void)
{
struct mem_file *stream = XMALLOC (struct mem_file);
struct gdb_file *file = gdb_file_new ();
set_gdb_file_data (file, stream, mem_file_delete);
set_gdb_file_rewind (file, mem_file_rewind);
set_gdb_file_put (file, mem_file_put);
set_gdb_file_write (file, mem_file_write);
stream->magic = &mem_file_magic;
stream->buffer = NULL;
stream->sizeof_buffer = 0;
stream->length_buffer = 0;
return file;
}
static void
mem_file_delete (struct gdb_file *file)
{
struct mem_file *stream = gdb_file_data (file);
if (stream->magic != &mem_file_magic)
internal_error ("mem_file_delete: bad magic number");
if (stream->buffer != NULL)
free (stream->buffer);
free (stream);
}
struct gdb_file *
mem_fileopen (void)
{
return mem_file_new ();
}
static void
mem_file_rewind (struct gdb_file *file)
{
struct mem_file *stream = gdb_file_data (file);
if (stream->magic != &mem_file_magic)
internal_error ("mem_file_rewind: bad magic number");
stream->length_buffer = 0;
}
static void
mem_file_put (struct gdb_file *file,
gdb_file_put_method_ftype *write,
void *dest)
{
struct mem_file *stream = gdb_file_data (file);
if (stream->magic != &mem_file_magic)
internal_error ("mem_file_put: bad magic number");
if (stream->length_buffer > 0)
write (dest, stream->buffer, stream->length_buffer);
}
void
mem_file_write (struct gdb_file *file,
const char *buffer,
long length_buffer)
{
struct mem_file *stream = gdb_file_data (file);
if (stream->magic != &mem_file_magic)
internal_error ("mem_file_write: bad magic number");
if (stream->buffer == NULL)
{
stream->length_buffer = length_buffer;
stream->sizeof_buffer = length_buffer;
stream->buffer = xmalloc (stream->sizeof_buffer);
memcpy (stream->buffer, buffer, length_buffer);
}
else
{
int new_length = stream->length_buffer + length_buffer;
if (new_length >= stream->sizeof_buffer)
{
stream->sizeof_buffer = new_length;
stream->buffer = xrealloc (stream->buffer, stream->sizeof_buffer);
}
memcpy (stream->buffer + stream->length_buffer, buffer, length_buffer);
stream->length_buffer = new_length;
}
}
/* ``struct gdb_file'' implementation that maps directly onto
<stdio.h>'s FILE. */
static gdb_file_write_ftype stdio_file_write;
static gdb_file_fputs_ftype stdio_file_fputs;
static gdb_file_isatty_ftype stdio_file_isatty;
static gdb_file_delete_ftype stdio_file_delete;
static struct gdb_file *stdio_file_new PARAMS ((FILE * file, int close_p));
static gdb_file_flush_ftype stdio_file_flush;
static int stdio_file_magic;
struct stdio_file
{
int *magic;
FILE *file;
int close_p;
};
static struct gdb_file *
stdio_file_new (file, close_p)
FILE *file;
int close_p;
{
struct gdb_file *gdb_file = gdb_file_new ();
struct stdio_file *stdio = xmalloc (sizeof (struct stdio_file));
stdio->magic = &stdio_file_magic;
stdio->file = file;
stdio->close_p = close_p;
set_gdb_file_data (gdb_file, stdio, stdio_file_delete);
set_gdb_file_flush (gdb_file, stdio_file_flush);
set_gdb_file_write (gdb_file, stdio_file_write);
set_gdb_file_fputs (gdb_file, stdio_file_fputs);
set_gdb_file_isatty (gdb_file, stdio_file_isatty);
return gdb_file;
}
static void
stdio_file_delete (file)
struct gdb_file *file;
{
struct stdio_file *stdio = gdb_file_data (file);
if (stdio->magic != &stdio_file_magic)
internal_error ("stdio_file_delete: bad magic number");
if (stdio->close_p)
{
fclose (stdio->file);
}
free (stdio);
}
static void
stdio_file_flush (file)
struct gdb_file *file;
{
struct stdio_file *stdio = gdb_file_data (file);
if (stdio->magic != &stdio_file_magic)
internal_error ("stdio_file_flush: bad magic number");
fflush (stdio->file);
}
static void
stdio_file_write (struct gdb_file *file, const char *buf, long length_buf)
{
struct stdio_file *stdio = gdb_file_data (file);
if (stdio->magic != &stdio_file_magic)
internal_error ("stdio_file_write: bad magic number");
fwrite (buf, length_buf, 1, stdio->file);
}
static void
stdio_file_fputs (linebuffer, file)
const char *linebuffer;
struct gdb_file *file;
{
struct stdio_file *stdio = gdb_file_data (file);
if (stdio->magic != &stdio_file_magic)
internal_error ("stdio_file_fputs: bad magic number");
fputs (linebuffer, stdio->file);
}
static int
stdio_file_isatty (file)
struct gdb_file *file;
{
struct stdio_file *stdio = gdb_file_data (file);
if (stdio->magic != &stdio_file_magic)
internal_error ("stdio_file_isatty: bad magic number");
return (isatty (fileno (stdio->file)));
}
/* Like fdopen(). Create a gdb_file from a previously opened FILE. */
struct gdb_file *
stdio_fileopen (file)
FILE *file;
{
return stdio_file_new (file, 0);
}
GDB_FILE *
gdb_fopen (name, mode)
char *name;
char *mode;
{
FILE *f = fopen (name, mode);
if (f == NULL)
return NULL;
return stdio_file_new (f, 1);
}

93
gdb/gdb-file.h Normal file
View File

@ -0,0 +1,93 @@
/* GDB_FILE - a generic STDIO like output stream.
Copyright (C) 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., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifndef GDB_FILE_H
#define GDB_FILE_H
struct gdb_file;
/* Create a generic gdb_file object with null methods. */
extern struct gdb_file *gdb_file_new (void);
/* Override methods used by specific implementations of a GDB_FILE
object. */
typedef void (gdb_file_flush_ftype) (struct gdb_file * stream);
extern void set_gdb_file_flush (struct gdb_file *stream, gdb_file_flush_ftype * flush);
/* NOTE: Both fputs and write methods are available. Default
implementations that mapping one onto the other are included. */
typedef void (gdb_file_write_ftype) (struct gdb_file * stream, const char *buf, long length_buf);
extern void set_gdb_file_write (struct gdb_file *stream, gdb_file_write_ftype *fputs);
typedef void (gdb_file_fputs_ftype) (const char *, struct gdb_file * stream);
extern void set_gdb_file_fputs (struct gdb_file *stream, gdb_file_fputs_ftype * fputs);
typedef int (gdb_file_isatty_ftype) (struct gdb_file * stream);
extern void set_gdb_file_isatty (struct gdb_file *stream, gdb_file_isatty_ftype * isatty);
typedef void (gdb_file_rewind_ftype) (struct gdb_file * stream);
extern void set_gdb_file_rewind (struct gdb_file *stream, gdb_file_rewind_ftype * rewind);
typedef void (gdb_file_put_method_ftype) (void *object, const char *buffer, long length_buffer);
typedef void (gdb_file_put_ftype) (struct gdb_file *stream, gdb_file_put_method_ftype * method, void *context);
extern void set_gdb_file_put (struct gdb_file *stream, gdb_file_put_ftype * put);
typedef void (gdb_file_delete_ftype) (struct gdb_file * stream);
extern void set_gdb_file_data (struct gdb_file *stream, void *data, gdb_file_delete_ftype * delete);
extern void *gdb_file_data (struct gdb_file *file);
extern void gdb_flush (struct gdb_file *);
extern void gdb_file_delete (struct gdb_file *stream);
extern void gdb_file_rewind (struct gdb_file *stream);
extern int gdb_file_isatty (struct gdb_file *);
extern void gdb_file_write (struct gdb_file *file, const char *buf, long length_buf);
/* NOTE: copies left to right */
extern void gdb_file_put (struct gdb_file *src, gdb_file_put_method_ftype *write, void *dest);
/* Returns a freshly allocated buffer containing the entire contents
of FILE (as determined by gdb_file_put()) with a NUL character
appended. LENGTH is set to the size of the buffer minus that
appended NUL. */
extern char *gdb_file_xstrdup (struct gdb_file *file, long *length);
/* Create/open a memory based file. Can be used as a scratch buffer
for collecting output. */
extern struct gdb_file *mem_fileopen (void);
/* Open/create a an STDIO based GDB_FILE using the already open FILE. */
extern struct gdb_file *stdio_fileopen (FILE *file);
/* Open NAME returning an STDIO based GDB_FILE. */
extern GDB_FILE *gdb_fopen (char *name, char *mode);
#endif

View File

@ -1,4 +1,4 @@
/* Interface GDB to the GNU Hurd
/* Interface GDB to the GNU Hurd.
Copyright (C) 1992, 1995, 1996, 1997, 1999 Free Software Foundation, Inc.
This file is part of GDB.
@ -88,7 +88,6 @@ int gnu_debug_flag = 0;
extern struct target_ops gnu_ops;
int inf_update_procs (struct inf *inf);
struct inf *make_inf ();
void inf_clear_wait (struct inf *inf);
void inf_cleanup (struct inf *inf);
@ -116,7 +115,6 @@ void inf_continue (struct inf *inf);
debug ("{inf %d %p}: " msg, __inf->pid, __inf , ##args); } while (0)
void proc_abort (struct proc *proc, int force);
thread_state_t proc_get_state (struct proc *proc, int force);
struct proc *make_proc (struct inf *inf, mach_port_t port, int tid);
struct proc *_proc_free (struct proc *proc);
int proc_update_sc (struct proc *proc);
@ -126,7 +124,6 @@ static mach_port_t _proc_get_exc_port (struct proc *proc);
void proc_steal_exc_port (struct proc *proc, mach_port_t exc_port);
void proc_restore_exc_port (struct proc *proc);
int proc_trace (struct proc *proc, int set);
char *proc_string (struct proc *proc);
/* Evaluate RPC_EXPR in a scope with the variables MSGPORT and REFPORT bound
to INF's msg port and task port respectively. If it has no msg port,

View File

@ -31,6 +31,9 @@ extern struct inf *current_inferior;
/* Converts a GDB pid to a struct proc. */
struct proc *inf_tid_to_thread (struct inf *inf, int tid);
/* Makes sure that INF's thread list is synced with the actual process. */
int inf_update_procs (struct inf *inf);
/* A proc is either a thread, or the task (there can only be one task proc
because it always has the same TID, PROC_TID_TASK). */
struct proc
@ -75,8 +78,15 @@ struct proc
extern int __proc_pid (struct proc *proc);
/* Make sure that the state field in PROC is up to date, and return a
pointer to it, or 0 if something is wrong. If WILL_MODIFY is true,
makes sure that the thread is stopped and aborted first, and sets
the state_changed field in PROC to true. */
extern thread_state_t proc_get_state (struct proc *proc, int will_modify);
/* Return printable description of proc. */
extern char *proc_string (struct proc *proc);
#define proc_debug(_proc, msg, args...) \
do { struct proc *__proc = (_proc); \
debug ("{proc %d/%d %p}: " msg, \

View File

@ -1,4 +1,4 @@
/* Low level interface to I386 running the GNU Hurd
/* Low level interface to i386 running the GNU Hurd.
Copyright (C) 1992, 1995, 1996 Free Software Foundation, Inc.
This file is part of GDB.
@ -22,171 +22,18 @@
#include "inferior.h"
#include "floatformat.h"
#include <assert.h>
#include <stdio.h>
#include <errno.h>
#include <mach.h>
#include <mach_error.h>
#include <mach/message.h>
#include <mach/exception.h>
#include <mach_error.h>
#include "gnu-nat.h"
/* Hmmm... Should this not be here?
* Now for i386_float_info() target_has_execution
*/
#include <target.h>
/* @@@ Should move print_387_status() to i387-tdep.c */
extern void print_387_control_word (); /* i387-tdep.h */
extern void print_387_status_word ();
/* Find offsets to thread states at compile time.
* If your compiler does not grok this, calculate offsets
* offsets yourself and use them (or get a compatible compiler :-)
*/
#define REG_OFFSET(reg) (int)(&((struct i386_thread_state *)0)->reg)
/* at reg_offset[i] is the offset to the i386_thread_state
* location where the gdb registers[i] is stored.
*/
static int reg_offset[] =
{
REG_OFFSET (eax), REG_OFFSET (ecx), REG_OFFSET (edx), REG_OFFSET (ebx),
REG_OFFSET (uesp), REG_OFFSET (ebp), REG_OFFSET (esi), REG_OFFSET (edi),
REG_OFFSET (eip), REG_OFFSET (efl), REG_OFFSET (cs), REG_OFFSET (ss),
REG_OFFSET (ds), REG_OFFSET (es), REG_OFFSET (fs), REG_OFFSET (gs)
};
#define REG_ADDR(state,regnum) ((char *)(state)+reg_offset[regnum])
/* Fetch COUNT contiguous registers from thread STATE starting from REGNUM
* Caller knows that the regs handled in one transaction are of same size.
*/
#define FETCH_REGS(state, regnum, count) \
memcpy (&registers[REGISTER_BYTE (regnum)], \
REG_ADDR (state, regnum), \
count * REGISTER_RAW_SIZE (regnum))
/* Store COUNT contiguous registers to thread STATE starting from REGNUM */
#define STORE_REGS(state, regnum, count) \
memcpy (REG_ADDR (state, regnum), \
&registers[REGISTER_BYTE (regnum)], \
count * REGISTER_RAW_SIZE (regnum))
/*
* Fetch inferiors registers for gdb.
* REG specifies which (as gdb views it) register, -1 for all.
*/
void
gnu_fetch_registers (int reg)
{
struct proc *thread;
thread_state_t state;
inf_update_procs (current_inferior); /* Make sure we know about new threads. */
thread = inf_tid_to_thread (current_inferior, inferior_pid);
if (!thread)
error ("fetch inferior registers: %d: Invalid thread", inferior_pid);
state = proc_get_state (thread, 0);
if (!state)
warning ("Couldn't fetch register %s from %s (invalid thread).",
REGISTER_NAME (reg), proc_string (thread));
else if (reg >= 0)
{
proc_debug (thread, "fetching register: %s", REGISTER_NAME (reg));
supply_register (reg, REG_ADDR (state, reg));
thread->fetched_regs |= (1 << reg);
}
else
{
proc_debug (thread, "fetching all registers");
for (reg = 0; reg < NUM_REGS; reg++)
supply_register (reg, REG_ADDR (state, reg));
thread->fetched_regs = ~0;
}
}
/* Store our register values back into the inferior.
* If REG is -1, do this for all registers.
* Otherwise, REG specifies which register
*
* On mach3 all registers are always saved in one call.
*/
void
gnu_store_registers (reg)
int reg;
{
struct proc *thread;
int was_aborted, was_valid;
thread_state_t state;
thread_state_data_t old_state;
inf_update_procs (current_inferior); /* Make sure we know about new threads. */
thread = inf_tid_to_thread (current_inferior, inferior_pid);
if (!thread)
error ("store inferior registers: %d: Invalid thread", inferior_pid);
proc_debug (thread, "storing register %s.", REGISTER_NAME (reg));
was_aborted = thread->aborted;
was_valid = thread->state_valid;
if (!was_aborted && was_valid)
bcopy (&thread->state, &old_state, sizeof (old_state));
state = proc_get_state (thread, 1);
if (!state)
warning ("Couldn't store register %s from %s (invalid thread).",
REGISTER_NAME (reg), proc_string (thread));
else
{
if (!was_aborted && was_valid)
/* See which registers have changed after aborting the thread. */
{
int check_reg;
for (check_reg = 0; check_reg < NUM_REGS; check_reg++)
if ((thread->fetched_regs & (1 << check_reg))
&& bcmp (REG_ADDR (&old_state, check_reg),
REG_ADDR (state, check_reg),
REGISTER_RAW_SIZE (check_reg)))
/* Register CHECK_REG has changed! Ack! */
{
warning ("Register %s changed after thread was aborted.",
REGISTER_NAME (check_reg));
if (reg >= 0 && reg != check_reg)
/* Update gdb's copy of the register. */
supply_register (check_reg, REG_ADDR (state, check_reg));
else
warning ("... also writing this register! Suspicious...");
}
}
if (reg >= 0)
{
proc_debug (thread, "storing register: %s", REGISTER_NAME (reg));
STORE_REGS (state, reg, 1);
}
else
{
proc_debug (thread, "storing all registers");
for (reg = 0; reg < NUM_REGS; reg++)
STORE_REGS (state, reg, 1);
}
}
}
/* jtv@hut.fi: I copied and modified this 387 code from
* gdb/i386-xdep.c. Modifications for Mach 3.0.
*
* i387 status dumper. See also i387-tdep.c
*/
/* The FPU hardware state. */
struct env387
{
unsigned short control;
@ -203,166 +50,283 @@ struct env387
unsigned short r3;
unsigned char regs[8][10];
};
/* This routine is machine independent?
* Should move it to i387-tdep.c but you need to export struct env387
*/
static
print_387_status (status, ep)
unsigned short status;
struct env387 *ep;
/* Offset to the thread_state_t location where REG is stored. */
#define REG_OFFSET(reg) offsetof (struct i386_thread_state, reg)
/* At reg_offset[i] is the offset to the thread_state_t location where
the gdb registers[i] is stored. */
static int reg_offset[] =
{
int i;
int bothstatus;
int top;
int fpreg;
unsigned char *p;
REG_OFFSET (eax), REG_OFFSET (ecx), REG_OFFSET (edx), REG_OFFSET (ebx),
REG_OFFSET (uesp), REG_OFFSET (ebp), REG_OFFSET (esi), REG_OFFSET (edi),
REG_OFFSET (eip), REG_OFFSET (efl), REG_OFFSET (cs), REG_OFFSET (ss),
REG_OFFSET (ds), REG_OFFSET (es), REG_OFFSET (fs), REG_OFFSET (gs)
};
bothstatus = ((status != 0) && (ep->status != 0));
if (status != 0)
{
if (bothstatus)
printf_unfiltered ("u: ");
print_387_status_word (status);
}
#define REG_ADDR(state, regnum) ((char *)(state) + reg_offset[regnum])
if (ep->status != 0)
{
if (bothstatus)
printf_unfiltered ("e: ");
print_387_status_word (ep->status);
}
print_387_control_word (ep->control);
printf_unfiltered ("last exception: ");
printf_unfiltered ("opcode %s; ", local_hex_string (ep->opcode));
printf_unfiltered ("pc %s:", local_hex_string (ep->code_seg));
printf_unfiltered ("%s; ", local_hex_string (ep->eip));
printf_unfiltered ("operand %s", local_hex_string (ep->operand_seg));
printf_unfiltered (":%s\n", local_hex_string (ep->operand));
top = (ep->status >> 11) & 7;
printf_unfiltered ("regno tag msb lsb value\n");
for (fpreg = 7; fpreg >= 0; fpreg--)
{
double val;
printf_unfiltered ("%s %d: ", fpreg == top ? "=>" : " ", fpreg);
switch ((ep->tag >> (fpreg * 2)) & 3)
{
case 0:
printf_unfiltered ("valid ");
break;
case 1:
printf_unfiltered ("zero ");
break;
case 2:
printf_unfiltered ("trap ");
break;
case 3:
printf_unfiltered ("empty ");
break;
}
for (i = 9; i >= 0; i--)
printf_unfiltered ("%02x", ep->regs[fpreg][i]);
floatformat_to_double (&floatformat_i387_ext, (char *) ep->regs[fpreg],
&val);
printf_unfiltered (" %g\n", val);
}
if (ep->r0)
printf_unfiltered ("warning: reserved0 is %s\n", local_hex_string (ep->r0));
if (ep->r1)
printf_unfiltered ("warning: reserved1 is %s\n", local_hex_string (ep->r1));
if (ep->r2)
printf_unfiltered ("warning: reserved2 is %s\n", local_hex_string (ep->r2));
if (ep->r3)
printf_unfiltered ("warning: reserved3 is %s\n", local_hex_string (ep->r3));
}
/*
* values that go into fp_kind (from <i386/fpreg.h>)
*/
#define FP_NO 0 /* no fp chip, no emulator (no fp support) */
#define FP_SW 1 /* no fp chip, using software emulator */
#define FP_HW 2 /* chip present bit */
#define FP_287 2 /* 80287 chip present */
#define FP_387 3 /* 80387 chip present */
typedef struct fpstate
{
#if 1
unsigned char state[FP_STATE_BYTES]; /* "hardware" state */
#else
struct env387 state; /* Actually this */
#endif
int status; /* Duplicate status */
}
*fpstate_t;
/* Mach 3 specific routines.
*/
static int
get_i387_state (fstate)
struct fpstate *fstate;
/* Get the whole floating-point state of THREAD and record the
values of the corresponding (pseudo) registers. */
static void
fetch_fpregs (struct proc *thread)
{
mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT;
struct i386_float_state state;
struct env387 *ep = (struct env387 *) state.hw_state;
error_t err;
thread_state_data_t state;
unsigned int fsCnt = i386_FLOAT_STATE_COUNT;
struct i386_float_state *fsp;
struct proc *thread = inf_tid_to_thread (current_inferior, inferior_pid);
int i;
if (!thread)
error ("get_i387_state: Invalid thread");
proc_abort (thread, 0); /* Make sure THREAD's in a reasonable state. */
err = thread_get_state (thread->port, i386_FLOAT_STATE, state, &fsCnt);
err = thread_get_state (thread->port, i386_FLOAT_STATE,
(thread_state_t) &state, &count);
if (err)
{
warning ("Can not get live floating point state: %s",
mach_error_string (err));
return 0;
}
fsp = (struct i386_float_state *) state;
/* The 387 chip (also 486 counts) or a software emulator? */
if (!fsp->initialized || (fsp->fpkind != FP_387 && fsp->fpkind != FP_SW))
return 0;
/* Clear the target then copy thread's float state there.
Make a copy of the status word, for some reason?
*/
memset (fstate, 0, sizeof (struct fpstate));
fstate->status = fsp->exc_status;
memcpy (fstate->state, (char *) &fsp->hw_state, FP_STATE_BYTES);
return 1;
}
/*
* This is called by "info float" command
*/
void
i386_mach3_float_info ()
{
char buf[sizeof (struct fpstate) + 2 * sizeof (int)];
int valid = 0;
fpstate_t fps;
if (target_has_execution)
valid = get_i387_state (buf);
if (!valid)
{
warning ("no floating point status saved");
warning ("Couldn't fetch floating-point state from %s",
proc_string (thread));
return;
}
fps = (fpstate_t) buf;
if (! state.initialized)
/* The floating-point state isn't initialized. */
{
for (i = FP0_REGNUM; i <= FP7_REGNUM; i++)
supply_register (i, NULL);
for (i = FIRST_FPU_CTRL_REGNUM; i <= LAST_FPU_CTRL_REGNUM; i++)
supply_register (i, NULL);
print_387_status (fps->status, (struct env387 *) fps->state);
return;
}
/* Supply the floating-point registers. */
for (i = 0; i < 8; i++)
supply_register (FP0_REGNUM + i, ep->regs[i]);
supply_register (FCTRL_REGNUM, (char *) &ep->control);
supply_register (FSTAT_REGNUM, (char *) &ep->status);
supply_register (FTAG_REGNUM, (char *) &ep->tag);
supply_register (FCOFF_REGNUM, (char *) &ep->eip);
supply_register (FDS_REGNUM, (char *) &ep->operand_seg);
supply_register (FDOFF_REGNUM, (char *) &ep->operand);
/* Store the code segment and opcode pseudo registers. */
{
long l;
l = ep->code_seg;
supply_register (FCS_REGNUM, (char *) &l);
l = ep->opcode & ((1 << 11) - 1);
supply_register (FOP_REGNUM, (char *) &l);
}
}
/* Fetch register REGNO, or all regs if REGNO is -1. */
void
gnu_fetch_registers (int regno)
{
struct proc *thread;
/* Make sure we know about new threads. */
inf_update_procs (current_inferior);
thread = inf_tid_to_thread (current_inferior, inferior_pid);
if (!thread)
error ("Can't fetch registers from thread %d: No such thread",
inferior_pid);
if (regno < NUM_GREGS || regno == -1)
{
thread_state_t state;
/* This does the dirty work for us. */
state = proc_get_state (thread, 0);
if (!state)
{
warning ("Couldn't fetch registers from %s",
proc_string (thread));
return;
}
if (regno == -1)
{
int i;
proc_debug (thread, "fetching all register");
for (i = 0; i < NUM_GREGS; i++)
supply_register (i, REG_ADDR (state, i));
thread->fetched_regs = ~0;
}
else
{
proc_debug (thread, "fetching register %s", REGISTER_NAME (regno));
supply_register (regno, REG_ADDR (state, regno));
thread->fetched_regs |= (1 << regno);
}
}
if (regno >= NUM_GREGS || regno == -1)
{
proc_debug (thread, "fetching floating-point registers");
fetch_fpregs (thread);
}
}
/* Fill the i387 hardware state EP with selected data from the set of
(pseudo) registers specified by REGS and VALID. VALID is an array
indicating which registers in REGS are valid. If VALID is zero,
all registers are assumed to be valid. */
static void
convert_to_env387 (struct env387 *ep, char *regs, signed char *valid)
{
int i;
/* Fill in the floating-point registers. */
for (i = 0; i < 8; i++)
if (!valid || valid[i])
memcpy (ep->regs[i], &regs[REGISTER_BYTE (FP0_REGNUM + i)],
REGISTER_RAW_SIZE (FP0_REGNUM + i));
#define fill(member, regno) \
if (!valid || valid[(regno)]) \
memcpy (&ep->member, &regs[REGISTER_BYTE (regno)], \
sizeof (ep->member));
fill (control, FCTRL_REGNUM);
fill (status, FSTAT_REGNUM);
fill (tag, FTAG_REGNUM);
fill (eip, FCOFF_REGNUM);
fill (operand, FDOFF_REGNUM);
fill (operand_seg, FDS_REGNUM);
#undef fill
if (!valid || valid[FCS_REGNUM])
ep->code_seg =
(* (int *) &registers[REGISTER_BYTE (FCS_REGNUM)] & 0xffff);
if (!valid || valid[FOP_REGNUM])
ep->opcode =
((* (int *) &registers[REGISTER_BYTE (FOP_REGNUM)] & ((1 << 11) - 1)));
}
/* Store the whole floating-point state into THREAD using information
from the corresponding (pseudo) registers. */
static void
store_fpregs (struct proc *thread)
{
mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT;
struct i386_float_state state;
error_t err;
err = thread_get_state (thread->port, i386_FLOAT_STATE,
(thread_state_t) &state, &count);
if (err)
{
warning ("Couldn't fetch floating-point state from %s",
proc_string (thread));
return;
}
convert_to_env387 ((struct env387 *) state.hw_state,
registers, register_valid);
err = thread_set_state (thread->port, i386_FLOAT_STATE,
(thread_state_t) &state, i386_FLOAT_STATE_COUNT);
if (err)
{
warning ("Couldn't store floating-point state into %s",
proc_string (thread));
return;
}
}
/* Store at least register REGNO, or all regs if REGNO == -1. */
void
gnu_store_registers (int regno)
{
struct proc *thread;
/* Make sure we know about new threads. */
inf_update_procs (current_inferior);
thread = inf_tid_to_thread (current_inferior, inferior_pid);
if (!thread)
error ("Couldn't store registers into thread %d: No such thread",
inferior_pid);
if (regno < NUM_GREGS || regno == -1)
{
thread_state_t state;
thread_state_data_t old_state;
int was_aborted = thread->aborted;
int was_valid = thread->state_valid;
if (!was_aborted && was_valid)
memcpy (&old_state, &thread->state, sizeof (old_state));
state = proc_get_state (thread, 1);
if (!state)
{
warning ("Couldn't store registers into %s", proc_string (thread));
return;
}
if (!was_aborted && was_valid)
/* See which registers have changed after aborting the thread. */
{
int check_regno;
for (check_regno = 0; check_regno < NUM_GREGS; check_regno++)
if ((thread->fetched_regs & (1 << check_regno))
&& memcpy (REG_ADDR (&old_state, check_regno),
REG_ADDR (state, check_regno),
REGISTER_RAW_SIZE (check_regno)))
/* Register CHECK_REGNO has changed! Ack! */
{
warning ("Register %s changed after the thread was aborted",
REGISTER_NAME (check_regno));
if (regno >= 0 && regno != check_regno)
/* Update gdb's copy of the register. */
supply_register (check_regno, REG_ADDR (state, check_regno));
else
warning ("... also writing this register! Suspicious...");
}
}
#define fill(state, regno) \
memcpy (REG_ADDR(state, regno), &registers[REGISTER_BYTE (regno)], \
REGISTER_RAW_SIZE (regno))
if (regno == -1)
{
int i;
proc_debug (thread, "storing all registers");
for (i = 0; i < NUM_GREGS; i++)
if (register_valid[i])
fill (state, i);
}
else
{
proc_debug (thread, "storing register %s", REGISTER_NAME (regno));
assert (register_valid[regno]);
fill (state, regno);
}
}
#undef fill
if (regno >= NUM_GREGS || regno == -1)
{
proc_debug (thread, "storing floating-point registers");
store_fpregs (thread);
}
}

View File

@ -838,8 +838,13 @@ breakpoint_auto_delete_contents (arg)
The dummy's frame is automatically popped whenever that break is hit.
If that is the first time the program stops, run_stack_dummy
returns to its caller with that frame already gone and returns 0.
Otherwise, run_stack-dummy returns 1 (the frame will eventually be popped
when we do hit that breakpoint). */
Otherwise, run_stack-dummy returns a non-zero value.
If the called function receives a random signal, we do not allow the user
to continue executing it as this may not work. The dummy frame is poped
and we return 1.
If we hit a breakpoint, we leave the frame in place and return 2 (the frame
will eventually be popped when we do hit the dummy end breakpoint). */
int
run_stack_dummy (addr, buffer)
@ -907,10 +912,24 @@ run_stack_dummy (addr, buffer)
discard_cleanups (old_cleanups);
if (stopped_by_random_signal)
{
/* If the inferior execution fails we need to restore our
stack. It is not done by proceed() in this case. */
/* Pop the empty frame that contains the stack dummy.
POP_FRAME ends with a setting of the current frame, so we
can use that next. */
POP_FRAME;
return 1;
}
/* We may also stop prematurely because we hit a breakpoint in the
called routine. We do not pop the frame as the user may wish
to single step or continue from there. */
if (!stop_stack_dummy)
return 1;
return 2;
/* On return, the stack dummy has been popped already. */
/* On normal return, the stack dummy has been popped already. */
memcpy (buffer, stop_registers, REGISTER_BYTES);
return 0;

View File

@ -33,6 +33,11 @@
#include "gdb_string.h"
#include "event-loop.h"
#if defined (TUI) || defined (GDBTK)
/* FIXME: cagney/2000-01-31: This #include is to allow older code such
as that found in the TUI to continue to build. */
#include "tui/tui-file.h"
#endif
/* If nonzero, display time usage both at startup and for each command. */
@ -187,17 +192,19 @@ captured_main (void *data)
getcwd (gdb_dirbuf, sizeof (gdb_dirbuf));
current_directory = gdb_dirbuf;
#if 0
/* not yet */
gdb_stdout = stdio_fileopen (stdout);
gdb_stderr = stdio_fileopen (stderr);
gdb_stdlog = gdb_stderr; /* for moment */
gdb_stdtarg = gdb_stderr; /* for moment */
#else
#if defined (TUI) || defined (GDBTK)
/* Older code uses the tui_file and fputs_unfiltered_hook(). It
should be using a customized GDB_FILE object and re-initializing
within its own _initialize function. */
gdb_stdout = tui_fileopen (stdout);
gdb_stderr = tui_fileopen (stderr);
gdb_stdlog = gdb_stdout; /* for moment */
gdb_stdtarg = gdb_stderr; /* for moment */
#else
gdb_stdout = stdio_fileopen (stdout);
gdb_stderr = stdio_fileopen (stderr);
gdb_stdlog = gdb_stderr; /* for moment */
gdb_stdtarg = gdb_stderr; /* for moment */
#endif
/* initialize error() */

View File

@ -32,6 +32,7 @@
#include "gdb-stabs.h"
#include "gdbthread.h"
#include "gdbcore.h"
#include "breakpoint.h"
#ifdef USG
#include <sys/types.h>
@ -738,6 +739,12 @@ arm_rdi_kill ()
static void
arm_rdi_mourn_inferior ()
{
/* We remove the inserted breakpoints in case the user wants to
issue another target and load commands to rerun his application;
This is something that wouldn't work on a native target, for instance,
as the process goes away when the inferior exits, but it works with
some remote targets like this one. That is why this is done here. */
remove_breakpoints();
unpush_target (&arm_rdi_ops);
generic_mourn_inferior ();
}

View File

@ -2400,6 +2400,43 @@ build_canonical_line_spec (sal, symname, canonical)
canonical_arr[0] = canonical_name;
}
/* Find an instance of the character C in the string S that is outside
of all parenthesis pairs, single-quoted strings, and double-quoted
strings. */
static char *
find_toplevel_char (char *s, char c)
{
int quoted = 0; /* zero if we're not in quotes;
'"' if we're in a double-quoted string;
'\'' if we're in a single-quoted string. */
int depth = 0; /* number of unclosed parens we've seen */
char *scan;
for (scan = s; *scan; scan++)
{
if (quoted)
{
if (*scan == quoted)
quoted = 0;
else if (*scan == '\\' && *(scan + 1))
scan++;
}
else if (*scan == c && ! quoted && depth == 0)
return scan;
else if (*scan == '"' || *scan == '\'')
quoted = *scan;
else if (*scan == '(')
depth++;
else if (*scan == ')' && depth > 0)
depth--;
}
return 0;
}
/* Parse a string that specifies a line number.
Pass the address of a char * variable; that variable will be
advanced over the characters actually parsed.
@ -2576,9 +2613,14 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line, canonical)
/* Maybe we were called with a line range FILENAME:LINENUM,FILENAME:LINENUM
and we must isolate the first half. Outer layers will call again later
for the second half */
if ((ii = strchr (*argptr, ',')) != NULL)
has_comma = 1;
for the second half.
Don't count commas that appear in argument lists of overloaded
functions, or in quoted strings. It's stupid to go to this much
trouble when the rest of the function is such an obvious roach hotel. */
ii = find_toplevel_char (*argptr, ',');
has_comma = (ii != 0);
/* Temporarily zap out second half to not
* confuse the code below.
* This is undone below. Do not change ii!!
@ -2632,10 +2674,14 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line, canonical)
}
while (p[0] == ' ' || p[0] == '\t')
p++;
/* if the closing double quote was left at the end, remove it */
if (is_quote_enclosed && ((pp = strchr (p, '"')) != NULL))
if (!*(pp + 1))
*pp = '\0';
if (is_quote_enclosed)
{
char *closing_quote = strchr (p, '"');
if (closing_quote && closing_quote[1] == '\0')
*closing_quote = '\0';
}
/* Now that we've safely parsed the first half,
* put back ',' so outer layers can see it
@ -3068,6 +3114,9 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line, canonical)
p = skip_quoted (*argptr);
}
if (is_quote_enclosed && **argptr == '"')
(*argptr)++;
copy = (char *) alloca (p - *argptr + 1);
memcpy (copy, *argptr, p - *argptr);
copy[p - *argptr] = '\0';

View File

@ -376,10 +376,6 @@ int (*ui_loop_hook) PARAMS ((int));
void (*command_loop_hook) PARAMS ((void));
/* Called instead of fputs for all output. */
void (*fputs_unfiltered_hook) PARAMS ((const char *linebuffer, GDB_FILE * stream));
/* Called from print_frame_info to list the line we stopped in. */
void (*print_frame_info_listing_hook) PARAMS ((struct symtab * s, int line,

View File

@ -1,3 +1,13 @@
Mon Jan 31 18:12:43 2000 Andrew Cagney <cagney@b1.cygnus.com>
* tui-file.c (enum streamtype, struct tui_stream, tui_file_new,
tui_file_delete, tui_fileopen, tui_sfileopen, tui_file_isatty,
tui_file_rewind, tui_file_put, tui_file_fputs,
tui_file_get_strbuf, tui_file_adjust_strbuf, tui_file_flush,
fputs_unfiltered_hook): Move to here from ../utils.c
* tui-file.h, tui-file.c: New files.
Mon Nov 8 17:47:37 1999 Andrew Cagney <cagney@b1.cygnus.com>
* tuiRegs.c (_tuiRegisterFormat), tuiDisassem.c

298
gdb/tui/tui-file.c Normal file
View File

@ -0,0 +1,298 @@
/* GDB_FILE - a generic STDIO like output stream.
Copyright (C) 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., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "gdb-file.h"
#include "tui/tui-file.h"
#include <string.h>
/* Called instead of fputs for all TUI_FILE output. */
void (*fputs_unfiltered_hook) (const char *linebuffer, GDB_FILE * stream);
/* A ``struct gdb_file'' that is compatible with all the legacy
code. */
/* new */
enum streamtype
{
afile,
astring
};
/* new */
struct tui_stream
{
int *ts_magic;
enum streamtype ts_streamtype;
FILE *ts_filestream;
char *ts_strbuf;
int ts_buflen;
};
static gdb_file_flush_ftype tui_file_flush;
extern gdb_file_fputs_ftype tui_file_fputs;
static gdb_file_isatty_ftype tui_file_isatty;
static gdb_file_rewind_ftype tui_file_rewind;
static gdb_file_put_ftype tui_file_put;
static gdb_file_delete_ftype tui_file_delete;
static struct gdb_file *tui_file_new PARAMS ((void));
static int tui_file_magic;
static struct gdb_file *
tui_file_new ()
{
struct tui_stream *tui = xmalloc (sizeof (struct tui_stream));
struct gdb_file *file = gdb_file_new ();
set_gdb_file_data (file, tui, tui_file_delete);
set_gdb_file_flush (file, tui_file_flush);
set_gdb_file_fputs (file, tui_file_fputs);
set_gdb_file_isatty (file, tui_file_isatty);
set_gdb_file_rewind (file, tui_file_rewind);
set_gdb_file_put (file, tui_file_put);
tui->ts_magic = &tui_file_magic;
return file;
}
static void
tui_file_delete (file)
struct gdb_file *file;
{
struct tui_stream *tmpstream = gdb_file_data (file);
if (tmpstream->ts_magic != &tui_file_magic)
internal_error ("tui_file_delete: bad magic number");
if ((tmpstream->ts_streamtype == astring) &&
(tmpstream->ts_strbuf != NULL))
{
free (tmpstream->ts_strbuf);
}
free (tmpstream);
}
struct gdb_file *
tui_fileopen (stream)
FILE *stream;
{
struct gdb_file *file = tui_file_new ();
struct tui_stream *tmpstream = gdb_file_data (file);
tmpstream->ts_streamtype = afile;
tmpstream->ts_filestream = stream;
tmpstream->ts_strbuf = NULL;
tmpstream->ts_buflen = 0;
return file;
}
struct gdb_file *
tui_sfileopen (n)
int n;
{
struct gdb_file *file = tui_file_new ();
struct tui_stream *tmpstream = gdb_file_data (file);
tmpstream->ts_streamtype = astring;
tmpstream->ts_filestream = NULL;
if (n > 0)
{
tmpstream->ts_strbuf = xmalloc ((n + 1) * sizeof (char));
tmpstream->ts_strbuf[0] = '\0';
}
else
/* Do not allocate the buffer now. The first time something is printed
one will be allocated by tui_file_adjust_strbuf() */
tmpstream->ts_strbuf = NULL;
tmpstream->ts_buflen = n;
return file;
}
static int
tui_file_isatty (file)
struct gdb_file *file;
{
struct tui_stream *stream = gdb_file_data (file);
if (stream->ts_magic != &tui_file_magic)
internal_error ("tui_file_isatty: bad magic number");
if (stream->ts_streamtype == afile)
return (isatty (fileno (stream->ts_filestream)));
else
return 0;
}
static void
tui_file_rewind (file)
struct gdb_file *file;
{
struct tui_stream *stream = gdb_file_data (file);
if (stream->ts_magic != &tui_file_magic)
internal_error ("tui_file_rewind: bad magic number");
stream->ts_strbuf[0] = '\0';
}
static void
tui_file_put (struct gdb_file *file,
gdb_file_put_method_ftype *write,
void *dest)
{
struct tui_stream *stream = gdb_file_data (file);
if (stream->ts_magic != &tui_file_magic)
internal_error ("tui_file_put: bad magic number");
if (stream->ts_streamtype == astring)
write (dest, stream->ts_strbuf, strlen (stream->ts_strbuf));
}
/* All TUI I/O sent to the *_filtered and *_unfiltered functions
eventually ends up here. The fputs_unfiltered_hook is primarily
used by GUIs to collect all output and send it to the GUI, instead
of the controlling terminal. Only output to gdb_stdout and
gdb_stderr are sent to the hook. Everything else is sent on to
fputs to allow file I/O to be handled appropriately. */
/* FIXME: Should be broken up and moved to a TUI specific file. */
void
tui_file_fputs (linebuffer, file)
const char *linebuffer;
GDB_FILE *file;
{
struct tui_stream *stream = gdb_file_data (file);
#if defined(TUI)
extern int tui_owns_terminal;
#endif
/* NOTE: cagney/1999-10-13: The use of fputs_unfiltered_hook is
seriously discouraged. Those wanting to hook output should
instead implement their own gdb_file object and install that. See
also tui_file_flush(). */
if (fputs_unfiltered_hook
&& (file == gdb_stdout
|| file == gdb_stderr))
fputs_unfiltered_hook (linebuffer, file);
else
{
#if defined(TUI)
if (tui_version && tui_owns_terminal)
{
/* If we get here somehow while updating the TUI (from
* within a tuiDo(), then we need to temporarily
* set up the terminal for GDB output. This probably just
* happens on error output.
*/
if (stream->ts_streamtype == astring)
{
tui_file_adjust_strbuf (strlen (linebuffer), stream);
strcat (stream->ts_strbuf, linebuffer);
}
else
{
tuiTermUnsetup (0, (tui_version) ? cmdWin->detail.commandInfo.curch : 0);
fputs (linebuffer, stream->ts_filestream);
tuiTermSetup (0);
if (linebuffer[strlen (linebuffer) - 1] == '\n')
tuiClearCommandCharCount ();
else
tuiIncrCommandCharCountBy (strlen (linebuffer));
}
}
else
{
/* The normal case - just do a fputs() */
if (stream->ts_streamtype == astring)
{
tui_file_adjust_strbuf (strlen (linebuffer), stream);
strcat (stream->ts_strbuf, linebuffer);
}
else
fputs (linebuffer, stream->ts_filestream);
}
#else
if (stream->ts_streamtype == astring)
{
tui_file_adjust_strbuf (strlen (linebuffer), file);
strcat (stream->ts_strbuf, linebuffer);
}
else
fputs (linebuffer, stream->ts_filestream);
#endif
}
}
char *
tui_file_get_strbuf (struct gdb_file *file)
{
struct tui_stream *stream = gdb_file_data (file);
if (stream->ts_magic != &tui_file_magic)
internal_error ("tui_file_get_strbuf: bad magic number");
return (stream->ts_strbuf);
}
/* adjust the length of the buffer by the amount necessary
to accomodate appending a string of length N to the buffer contents */
void
tui_file_adjust_strbuf (int n, struct gdb_file *file)
{
struct tui_stream *stream = gdb_file_data (file);
int non_null_chars;
if (stream->ts_magic != &tui_file_magic)
internal_error ("tui_file_adjust_strbuf: bad magic number");
if (stream->ts_streamtype != astring)
return;
if (stream->ts_strbuf)
{
/* There is already a buffer allocated */
non_null_chars = strlen (stream->ts_strbuf);
if (n > (stream->ts_buflen - non_null_chars - 1))
{
stream->ts_buflen = n + non_null_chars + 1;
stream->ts_strbuf = xrealloc (stream->ts_strbuf, stream->ts_buflen);
}
}
else
/* No buffer yet, so allocate one of the desired size */
stream->ts_strbuf = xmalloc ((n + 1) * sizeof (char));
}
static void
tui_file_flush (file)
GDB_FILE *file;
{
struct tui_stream *stream = gdb_file_data (file);
if (stream->ts_magic != &tui_file_magic)
internal_error ("tui_file_flush: bad magic number");
/* NOTE: cagney/1999-10-12: If we've been linked with code that uses
fputs_unfiltered_hook then we assume that it doesn't need to know
about flushes. Code that does need to know about flushes can
implement a proper gdb_file object. */
if (fputs_unfiltered_hook)
return;
switch (stream->ts_streamtype)
{
case astring:
break;
case afile:
fflush (stream->ts_filestream);
break;
}
}

34
gdb/tui/tui-file.h Normal file
View File

@ -0,0 +1,34 @@
/* GDB_FILE - a generic STDIO like output stream.
Copyright (C) 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., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifndef TUI_FILE_H
#define TUI_FILE_H
extern struct gdb_file *tui_fileopen (FILE *);
extern struct gdb_file *tui_sfileopen (int);
extern char *tui_file_get_strbuf (struct gdb_file *);
extern void tui_file_adjust_strbuf (int, struct gdb_file *);
/* NOTE: cagney/1999-10-14: fputs_unfiltered_hook is deprecated. Code
wanting to control GDB's output should override the gdb_std...
files. */
extern void (*fputs_unfiltered_hook) (const char *linebuffer,
GDB_FILE * stream);
#endif

View File

@ -1772,763 +1772,6 @@ begin_line ()
}
/* ``struct gdb_file'' implementation that maps directly onto
<stdio.h>'s FILE. */
static gdb_file_write_ftype stdio_file_write;
static gdb_file_fputs_ftype stdio_file_fputs;
static gdb_file_isatty_ftype stdio_file_isatty;
static gdb_file_delete_ftype stdio_file_delete;
static struct gdb_file *stdio_file_new PARAMS ((FILE * file, int close_p));
static gdb_file_flush_ftype stdio_file_flush;
static int stdio_file_magic;
struct stdio_file
{
int *magic;
FILE *file;
int close_p;
};
static struct gdb_file *
stdio_file_new (file, close_p)
FILE *file;
int close_p;
{
struct gdb_file *gdb_file = gdb_file_new ();
struct stdio_file *stdio = xmalloc (sizeof (struct stdio_file));
stdio->magic = &stdio_file_magic;
stdio->file = file;
stdio->close_p = close_p;
set_gdb_file_data (gdb_file, stdio, stdio_file_delete);
set_gdb_file_flush (gdb_file, stdio_file_flush);
set_gdb_file_write (gdb_file, stdio_file_write);
set_gdb_file_fputs (gdb_file, stdio_file_fputs);
set_gdb_file_isatty (gdb_file, stdio_file_isatty);
return gdb_file;
}
static void
stdio_file_delete (file)
struct gdb_file *file;
{
struct stdio_file *stdio = gdb_file_data (file);
if (stdio->magic != &stdio_file_magic)
internal_error ("stdio_file_delete: bad magic number");
if (stdio->close_p)
{
fclose (stdio->file);
}
free (stdio);
}
static void
stdio_file_flush (file)
struct gdb_file *file;
{
struct stdio_file *stdio = gdb_file_data (file);
if (stdio->magic != &stdio_file_magic)
internal_error ("stdio_file_flush: bad magic number");
fflush (stdio->file);
}
static void
stdio_file_write (struct gdb_file *file, const char *buf, long length_buf)
{
struct stdio_file *stdio = gdb_file_data (file);
if (stdio->magic != &stdio_file_magic)
internal_error ("stdio_file_write: bad magic number");
fwrite (buf, length_buf, 1, stdio->file);
}
static void
stdio_file_fputs (linebuffer, file)
const char *linebuffer;
struct gdb_file *file;
{
struct stdio_file *stdio = gdb_file_data (file);
if (stdio->magic != &stdio_file_magic)
internal_error ("stdio_file_fputs: bad magic number");
fputs (linebuffer, stdio->file);
}
static int
stdio_file_isatty (file)
struct gdb_file *file;
{
struct stdio_file *stdio = gdb_file_data (file);
if (stdio->magic != &stdio_file_magic)
internal_error ("stdio_file_isatty: bad magic number");
return (isatty (fileno (stdio->file)));
}
/* Like fdopen(). Create a gdb_file from a previously opened FILE. */
struct gdb_file *
stdio_fileopen (file)
FILE *file;
{
return stdio_file_new (file, 0);
}
/* A pure memory based ``struct gdb_file'' that can be used an output
buffer. The buffers accumulated contents are available via
gdb_file_put(). */
struct mem_file
{
int *magic;
char *buffer;
int sizeof_buffer;
int length_buffer;
};
static gdb_file_rewind_ftype mem_file_rewind;
static gdb_file_put_ftype mem_file_put;
static gdb_file_write_ftype mem_file_write;
static gdb_file_delete_ftype mem_file_delete;
static struct gdb_file *mem_file_new PARAMS ((void));
static int mem_file_magic;
static struct gdb_file *
mem_file_new (void)
{
struct mem_file *stream = XMALLOC (struct mem_file);
struct gdb_file *file = gdb_file_new ();
set_gdb_file_data (file, stream, mem_file_delete);
set_gdb_file_rewind (file, mem_file_rewind);
set_gdb_file_put (file, mem_file_put);
set_gdb_file_write (file, mem_file_write);
stream->magic = &mem_file_magic;
stream->buffer = NULL;
stream->sizeof_buffer = 0;
stream->length_buffer = 0;
return file;
}
static void
mem_file_delete (struct gdb_file *file)
{
struct mem_file *stream = gdb_file_data (file);
if (stream->magic != &mem_file_magic)
internal_error ("mem_file_delete: bad magic number");
if (stream->buffer != NULL)
free (stream->buffer);
free (stream);
}
struct gdb_file *
mem_fileopen (void)
{
return mem_file_new ();
}
static void
mem_file_rewind (struct gdb_file *file)
{
struct mem_file *stream = gdb_file_data (file);
if (stream->magic != &mem_file_magic)
internal_error ("mem_file_rewind: bad magic number");
stream->length_buffer = 0;
}
static void
mem_file_put (struct gdb_file *file,
gdb_file_put_method_ftype *write,
void *dest)
{
struct mem_file *stream = gdb_file_data (file);
if (stream->magic != &mem_file_magic)
internal_error ("mem_file_put: bad magic number");
if (stream->length_buffer > 0)
write (dest, stream->buffer, stream->length_buffer);
}
void
mem_file_write (struct gdb_file *file,
const char *buffer,
long length_buffer)
{
struct mem_file *stream = gdb_file_data (file);
if (stream->magic != &mem_file_magic)
internal_error ("mem_file_write: bad magic number");
if (stream->buffer == NULL)
{
stream->length_buffer = length_buffer;
stream->sizeof_buffer = length_buffer;
stream->buffer = xmalloc (stream->sizeof_buffer);
memcpy (stream->buffer, buffer, length_buffer);
}
else
{
int new_length = stream->length_buffer + length_buffer;
if (new_length >= stream->sizeof_buffer)
{
stream->sizeof_buffer = new_length;
stream->buffer = xrealloc (stream->buffer, stream->sizeof_buffer);
}
memcpy (stream->buffer + stream->length_buffer, buffer, length_buffer);
stream->length_buffer = new_length;
}
}
/* A ``struct gdb_file'' that is compatible with all the legacy
code. */
/* new */
enum streamtype
{
afile,
astring
};
/* new */
struct tui_stream
{
int *ts_magic;
enum streamtype ts_streamtype;
FILE *ts_filestream;
char *ts_strbuf;
int ts_buflen;
};
static gdb_file_flush_ftype tui_file_flush;
extern gdb_file_fputs_ftype tui_file_fputs;
static gdb_file_isatty_ftype tui_file_isatty;
static gdb_file_rewind_ftype tui_file_rewind;
static gdb_file_put_ftype tui_file_put;
static gdb_file_delete_ftype tui_file_delete;
static struct gdb_file *tui_file_new PARAMS ((void));
static int tui_file_magic;
static struct gdb_file *
tui_file_new ()
{
struct tui_stream *tui = xmalloc (sizeof (struct tui_stream));
struct gdb_file *file = gdb_file_new ();
set_gdb_file_data (file, tui, tui_file_delete);
set_gdb_file_flush (file, tui_file_flush);
set_gdb_file_fputs (file, tui_file_fputs);
set_gdb_file_isatty (file, tui_file_isatty);
set_gdb_file_rewind (file, tui_file_rewind);
set_gdb_file_put (file, tui_file_put);
tui->ts_magic = &tui_file_magic;
return file;
}
static void
tui_file_delete (file)
struct gdb_file *file;
{
struct tui_stream *tmpstream = gdb_file_data (file);
if (tmpstream->ts_magic != &tui_file_magic)
internal_error ("tui_file_delete: bad magic number");
if ((tmpstream->ts_streamtype == astring) &&
(tmpstream->ts_strbuf != NULL))
{
free (tmpstream->ts_strbuf);
}
free (tmpstream);
}
struct gdb_file *
tui_fileopen (stream)
FILE *stream;
{
struct gdb_file *file = tui_file_new ();
struct tui_stream *tmpstream = gdb_file_data (file);
tmpstream->ts_streamtype = afile;
tmpstream->ts_filestream = stream;
tmpstream->ts_strbuf = NULL;
tmpstream->ts_buflen = 0;
return file;
}
struct gdb_file *
tui_sfileopen (n)
int n;
{
struct gdb_file *file = tui_file_new ();
struct tui_stream *tmpstream = gdb_file_data (file);
tmpstream->ts_streamtype = astring;
tmpstream->ts_filestream = NULL;
if (n > 0)
{
tmpstream->ts_strbuf = xmalloc ((n + 1) * sizeof (char));
tmpstream->ts_strbuf[0] = '\0';
}
else
/* Do not allocate the buffer now. The first time something is printed
one will be allocated by tui_file_adjust_strbuf() */
tmpstream->ts_strbuf = NULL;
tmpstream->ts_buflen = n;
return file;
}
static int
tui_file_isatty (file)
struct gdb_file *file;
{
struct tui_stream *stream = gdb_file_data (file);
if (stream->ts_magic != &tui_file_magic)
internal_error ("tui_file_isatty: bad magic number");
if (stream->ts_streamtype == afile)
return (isatty (fileno (stream->ts_filestream)));
else
return 0;
}
static void
tui_file_rewind (file)
struct gdb_file *file;
{
struct tui_stream *stream = gdb_file_data (file);
if (stream->ts_magic != &tui_file_magic)
internal_error ("tui_file_rewind: bad magic number");
stream->ts_strbuf[0] = '\0';
}
static void
tui_file_put (struct gdb_file *file,
gdb_file_put_method_ftype *write,
void *dest)
{
struct tui_stream *stream = gdb_file_data (file);
if (stream->ts_magic != &tui_file_magic)
internal_error ("tui_file_put: bad magic number");
if (stream->ts_streamtype == astring)
write (dest, stream->ts_strbuf, strlen (stream->ts_strbuf));
}
/* All TUI I/O sent to the *_filtered and *_unfiltered functions
eventually ends up here. The fputs_unfiltered_hook is primarily
used by GUIs to collect all output and send it to the GUI, instead
of the controlling terminal. Only output to gdb_stdout and
gdb_stderr are sent to the hook. Everything else is sent on to
fputs to allow file I/O to be handled appropriately. */
/* FIXME: Should be broken up and moved to a TUI specific file. */
void
tui_file_fputs (linebuffer, file)
const char *linebuffer;
GDB_FILE *file;
{
struct tui_stream *stream = gdb_file_data (file);
#if defined(TUI)
extern int tui_owns_terminal;
#endif
/* NOTE: cagney/1999-10-13: The use of fputs_unfiltered_hook is
seriously discouraged. Those wanting to hook output should
instead implement their own gdb_file object and install that. See
also tui_file_flush(). */
if (fputs_unfiltered_hook
&& (file == gdb_stdout
|| file == gdb_stderr))
fputs_unfiltered_hook (linebuffer, file);
else
{
#if defined(TUI)
if (tui_version && tui_owns_terminal)
{
/* If we get here somehow while updating the TUI (from
* within a tuiDo(), then we need to temporarily
* set up the terminal for GDB output. This probably just
* happens on error output.
*/
if (stream->ts_streamtype == astring)
{
tui_file_adjust_strbuf (strlen (linebuffer), stream);
strcat (stream->ts_strbuf, linebuffer);
}
else
{
tuiTermUnsetup (0, (tui_version) ? cmdWin->detail.commandInfo.curch : 0);
fputs (linebuffer, stream->ts_filestream);
tuiTermSetup (0);
if (linebuffer[strlen (linebuffer) - 1] == '\n')
tuiClearCommandCharCount ();
else
tuiIncrCommandCharCountBy (strlen (linebuffer));
}
}
else
{
/* The normal case - just do a fputs() */
if (stream->ts_streamtype == astring)
{
tui_file_adjust_strbuf (strlen (linebuffer), stream);
strcat (stream->ts_strbuf, linebuffer);
}
else
fputs (linebuffer, stream->ts_filestream);
}
#else
if (stream->ts_streamtype == astring)
{
tui_file_adjust_strbuf (strlen (linebuffer), file);
strcat (stream->ts_strbuf, linebuffer);
}
else
fputs (linebuffer, stream->ts_filestream);
#endif
}
}
char *
tui_file_get_strbuf (struct gdb_file *file)
{
struct tui_stream *stream = gdb_file_data (file);
if (stream->ts_magic != &tui_file_magic)
internal_error ("tui_file_get_strbuf: bad magic number");
return (stream->ts_strbuf);
}
/* adjust the length of the buffer by the amount necessary
to accomodate appending a string of length N to the buffer contents */
void
tui_file_adjust_strbuf (int n, struct gdb_file *file)
{
struct tui_stream *stream = gdb_file_data (file);
int non_null_chars;
if (stream->ts_magic != &tui_file_magic)
internal_error ("tui_file_adjust_strbuf: bad magic number");
if (stream->ts_streamtype != astring)
return;
if (stream->ts_strbuf)
{
/* There is already a buffer allocated */
non_null_chars = strlen (stream->ts_strbuf);
if (n > (stream->ts_buflen - non_null_chars - 1))
{
stream->ts_buflen = n + non_null_chars + 1;
stream->ts_strbuf = xrealloc (stream->ts_strbuf, stream->ts_buflen);
}
}
else
/* No buffer yet, so allocate one of the desired size */
stream->ts_strbuf = xmalloc ((n + 1) * sizeof (char));
}
GDB_FILE *
gdb_fopen (name, mode)
char *name;
char *mode;
{
FILE *f = fopen (name, mode);
if (f == NULL)
return NULL;
return stdio_file_new (f, 1);
}
static void
tui_file_flush (file)
GDB_FILE *file;
{
struct tui_stream *stream = gdb_file_data (file);
if (stream->ts_magic != &tui_file_magic)
internal_error ("tui_file_flush: bad magic number");
/* NOTE: cagney/1999-10-12: If we've been linked with code that uses
fputs_unfiltered_hook then we assume that it doesn't need to know
about flushes. Code that does need to know about flushes can
implement a proper gdb_file object. */
if (fputs_unfiltered_hook)
return;
switch (stream->ts_streamtype)
{
case astring:
break;
case afile:
fflush (stream->ts_filestream);
break;
}
}
/* Implement the ``struct gdb_file'' object. */
static gdb_file_isatty_ftype null_file_isatty;
static gdb_file_write_ftype null_file_write;
static gdb_file_fputs_ftype null_file_fputs;
static gdb_file_flush_ftype null_file_flush;
static gdb_file_delete_ftype null_file_delete;
static gdb_file_rewind_ftype null_file_rewind;
static gdb_file_put_ftype null_file_put;
struct gdb_file
{
int *magic;
gdb_file_flush_ftype *to_flush;
gdb_file_write_ftype *to_write;
gdb_file_fputs_ftype *to_fputs;
gdb_file_delete_ftype *to_delete;
gdb_file_isatty_ftype *to_isatty;
gdb_file_rewind_ftype *to_rewind;
gdb_file_put_ftype *to_put;
void *to_data;
};
int gdb_file_magic;
struct gdb_file *
gdb_file_new ()
{
struct gdb_file *file = xmalloc (sizeof (struct gdb_file));
file->magic = &gdb_file_magic;
set_gdb_file_data (file, NULL, null_file_delete);
set_gdb_file_flush (file, null_file_flush);
set_gdb_file_write (file, null_file_write);
set_gdb_file_fputs (file, null_file_fputs);
set_gdb_file_isatty (file, null_file_isatty);
set_gdb_file_rewind (file, null_file_rewind);
set_gdb_file_put (file, null_file_put);
return file;
}
void
gdb_file_delete (file)
struct gdb_file *file;
{
file->to_delete (file);
free (file);
}
static int
null_file_isatty (file)
struct gdb_file *file;
{
return 0;
}
static void
null_file_rewind (file)
struct gdb_file *file;
{
return;
}
static void
null_file_put (struct gdb_file *file,
gdb_file_put_method_ftype *write,
void *dest)
{
return;
}
static void
null_file_flush (file)
struct gdb_file *file;
{
return;
}
static void
null_file_write (struct gdb_file *file,
const char *buf,
long sizeof_buf)
{
if (file->to_fputs == null_file_fputs)
/* Both the write and fputs methods are null. Discard the
request. */
return;
else
{
/* The fputs method isn't null, slowly pass the write request
onto that. FYI, this isn't as bad as it may look - the
current (as of 1999-11-07) printf_* function calls fputc and
fputc does exactly the below. By having a write function it
is possible to clean up that code. */
int i;
char b[2];
b[1] = '\0';
for (i = 0; i < sizeof_buf; i++)
{
b[0] = buf[i];
file->to_fputs (b, file);
}
return;
}
}
static void
null_file_fputs (buf, file)
const char *buf;
struct gdb_file *file;
{
if (file->to_write == null_file_write)
/* Both the write and fputs methods are null. Discard the
request. */
return;
else
{
/* The write method was implemented, use that. */
file->to_write (file, buf, strlen (buf));
}
}
static void
null_file_delete (file)
struct gdb_file *file;
{
return;
}
void *
gdb_file_data (file)
struct gdb_file *file;
{
if (file->magic != &gdb_file_magic)
internal_error ("gdb_file_data: bad magic number");
return file->to_data;
}
void
gdb_flush (file)
struct gdb_file *file;
{
file->to_flush (file);
}
int
gdb_file_isatty (file)
struct gdb_file *file;
{
return file->to_isatty (file);
}
void
gdb_file_rewind (file)
struct gdb_file *file;
{
file->to_rewind (file);
}
void
gdb_file_put (struct gdb_file *file,
gdb_file_put_method_ftype *write,
void *dest)
{
file->to_put (file, write, dest);
}
void
gdb_file_write (struct gdb_file *file,
const char *buf,
long length_buf)
{
file->to_write (file, buf, length_buf);
}
void
fputs_unfiltered (buf, file)
const char *buf;
struct gdb_file *file;
{
file->to_fputs (buf, file);
}
void
set_gdb_file_flush (file, flush)
struct gdb_file *file;
gdb_file_flush_ftype *flush;
{
file->to_flush = flush;
}
void
set_gdb_file_isatty (file, isatty)
struct gdb_file *file;
gdb_file_isatty_ftype *isatty;
{
file->to_isatty = isatty;
}
void
set_gdb_file_rewind (file, rewind)
struct gdb_file *file;
gdb_file_rewind_ftype *rewind;
{
file->to_rewind = rewind;
}
void
set_gdb_file_put (file, put)
struct gdb_file *file;
gdb_file_put_ftype *put;
{
file->to_put = put;
}
void
set_gdb_file_write (struct gdb_file *file,
gdb_file_write_ftype *write)
{
file->to_write = write;
}
void
set_gdb_file_fputs (file, fputs)
struct gdb_file *file;
gdb_file_fputs_ftype *fputs;
{
file->to_fputs = fputs;
}
void
set_gdb_file_data (file, data, delete)
struct gdb_file *file;
void *data;
gdb_file_delete_ftype *delete;
{
file->to_data = data;
file->to_delete = delete;
}
/* gdb_file utility function for converting a ``struct gdb_file'' into
a memory buffer''. */
struct accumulated_gdb_file
{
char *buffer;
long length;
};
static void
do_gdb_file_xstrdup (void *context, const char *buffer, long length)
{
struct accumulated_gdb_file *acc = context;
if (acc->buffer == NULL)
acc->buffer = xmalloc (length + 1);
else
acc->buffer = xrealloc (acc->buffer, acc->length + length + 1);
memcpy (acc->buffer + acc->length, buffer, length);
acc->length += length;
acc->buffer[acc->length] = '\0';
}
char *
gdb_file_xstrdup (struct gdb_file *file,
long *length)
{
struct accumulated_gdb_file acc;
acc.buffer = NULL;
acc.length = 0;
gdb_file_put (file, do_gdb_file_xstrdup, &acc);
if (acc.buffer == NULL)
acc.buffer = xstrdup ("");
*length = acc.length;
return acc.buffer;
}
/* Like fputs but if FILTER is true, pause after every screenful.
Regardless of FILTER can wrap at points other than the final

View File

@ -1292,6 +1292,7 @@ hand_function_call (function, nargs, args)
{
register CORE_ADDR sp;
register int i;
int rc;
CORE_ADDR start_sp;
/* CALL_DUMMY is an array of words (REGISTER_SIZE), but each word
is in host byte order. Before calling FIX_CALL_DUMMY, we byteswap it
@ -1687,9 +1688,28 @@ You must use a pointer to function type variable. Command ignored.", arg_name);
/* Execute the stack dummy routine, calling FUNCTION.
When it is done, discard the empty frame
after storing the contents of all regs into retbuf. */
if (run_stack_dummy (real_pc + CALL_DUMMY_START_OFFSET, retbuf))
rc = run_stack_dummy (real_pc + CALL_DUMMY_START_OFFSET, retbuf);
if (rc == 1)
{
/* We stopped somewhere besides the call dummy. */
/* We stopped inside the FUNCTION because of a random signal.
Further execution of the FUNCTION is not allowed. */
/* In this case, we must do the cleanups because we don't
want the dummy anymore (the dummy frame has been poped already. */
do_cleanups (old_chain);
/* FIXME: Insert a bunch of wrap_here; name can be very long if it's
a C++ name with arguments and stuff. */
error ("\
The program being debugged stopped while in a function called from GDB.\n\
Evaluation of the expression containing the function (%s) will be abandoned.",
name);
}
if (rc == 2)
{
/* We hit a breakpoint inside the FUNCTION. */
/* If we did the cleanups, we would print a spurious error
message (Unable to restore previously selected frame),
@ -1714,6 +1734,7 @@ stop (instead of continuing to evaluate the expression containing\n\
the function call).", name);
}
/* If we get here the called FUNCTION run to completion. */
do_cleanups (old_chain);
/* Figure out the value returned by the function. */