all remaining *.c *.h files from hp merge.

This commit is contained in:
David Taylor 1998-12-31 21:58:30 +00:00
parent c450a7fe3f
commit 65b07ddca8
62 changed files with 27574 additions and 1386 deletions

View file

@ -126,6 +126,7 @@ a29k-tdep.c
a68v-nat.c a68v-nat.c
abug-rom.c abug-rom.c
acconfig.h acconfig.h
acinclude.m4
aclocal.m4 aclocal.m4
alpha-nat.c alpha-nat.c
alpha-tdep.c alpha-tdep.c
@ -244,12 +245,15 @@ gould-tdep.c
gould-xdep.c gould-xdep.c
h8300-tdep.c h8300-tdep.c
h8500-tdep.c h8500-tdep.c
hp-psymtab-read.c
hp-symtab-read.c
hp300ux-nat.c hp300ux-nat.c
hppa-tdep.c hppa-tdep.c
hppab-nat.c hppab-nat.c
hppah-nat.c hppah-nat.c
hppam3-nat.c hppam3-nat.c
hpread.c hpread.c
hpread.h
hpux-thread.c hpux-thread.c
i386-stub.c i386-stub.c
i386-tdep.c i386-tdep.c
@ -269,6 +273,7 @@ inflow.c
infptrace.c infptrace.c
infrun.c infrun.c
inftarg.c inftarg.c
infttrace.c
irix4-nat.c irix4-nat.c
irix5-nat.c irix5-nat.c
isi-xdep.c isi-xdep.c
@ -435,6 +440,7 @@ top.c
top.h top.h
tracepoint.c tracepoint.c
tracepoint.h tracepoint.h
tui
typeprint.c typeprint.c
typeprint.h typeprint.h
ultra3-nat.c ultra3-nat.c

File diff suppressed because it is too large Load diff

View file

@ -64,6 +64,9 @@
/* Define if your locale.h file contains LC_MESSAGES. */ /* Define if your locale.h file contains LC_MESSAGES. */
#undef HAVE_LC_MESSAGES #undef HAVE_LC_MESSAGES
/* Define if you want to use the full-screen terminal user interface. */
#undef TUI
/* Define if <proc_service.h> on solaris uses int instead of /* Define if <proc_service.h> on solaris uses int instead of
size_t, and assorted other type changes. */ size_t, and assorted other type changes. */
#undef PROC_SERVICE_IS_OLD #undef PROC_SERVICE_IS_OLD

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
/* Data structures associated with breakpoints in GDB. /* Data structures associated with breakpoints in GDB.
Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc. Copyright (C) 1992, 93, 94, 95, 96, 1998 Free Software Foundation, Inc.
This file is part of GDB. This file is part of GDB.
@ -38,6 +38,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
possible like a single-step to wait_for_inferior). */ possible like a single-step to wait_for_inferior). */
enum bptype { enum bptype {
bp_none = 0, /* Eventpoint has been deleted. */
bp_breakpoint, /* Normal breakpoint */ bp_breakpoint, /* Normal breakpoint */
bp_hardware_breakpoint, /* Hardware assisted breakpoint */ bp_hardware_breakpoint, /* Hardware assisted breakpoint */
bp_until, /* used by until command */ bp_until, /* used by until command */
@ -87,12 +88,50 @@ enum bptype {
when these significant events occur. GDB can then re-examine when these significant events occur. GDB can then re-examine
the dynamic linker's data structures to discover any newly loaded the dynamic linker's data structures to discover any newly loaded
dynamic libraries. */ dynamic libraries. */
bp_shlib_event bp_shlib_event,
/* These breakpoints are used to implement the "catch load" command
on platforms whose dynamic linkers support such functionality. */
bp_catch_load,
/* These breakpoints are used to implement the "catch unload" command
on platforms whose dynamic linkers support such functionality. */
bp_catch_unload,
/* These are not really breakpoints, but are catchpoints that
implement the "catch fork", "catch vfork" and "catch exec" commands
on platforms whose kernel support such functionality. (I.e.,
kernels which can raise an event when a fork or exec occurs, as
opposed to the debugger setting breakpoints on functions named
"fork" or "exec".) */
bp_catch_fork,
bp_catch_vfork,
bp_catch_exec,
/* These are catchpoints to implement "catch catch" and "catch throw"
commands for C++ exception handling. */
bp_catch_catch,
bp_catch_throw,
}; };
/* States of enablement of breakpoint. */ /* States of enablement of breakpoint. */
enum enable { disabled, enabled, shlib_disabled}; enum enable {
disabled, /* The eventpoint is inactive, and cannot trigger. */
enabled, /* The eventpoint is active, and can trigger. */
shlib_disabled, /* The eventpoint's address is within an unloaded solib.
The eventpoint will be automatically enabled & reset
when that solib is loaded. */
call_disabled /* The eventpoint has been disabled while a call into
the inferior is "in flight", because some eventpoints
interfere with the implementation of a call on some
targets. The eventpoint will be automatically enabled
& reset when the call "lands" (either completes, or
stops at another eventpoint). */
};
/* Disposition of breakpoint. Ie: what to do after hitting it. */ /* Disposition of breakpoint. Ie: what to do after hitting it. */
@ -205,6 +244,24 @@ struct breakpoint
aborting, so you can back up to just before the abort. */ aborting, so you can back up to just before the abort. */
int hit_count; int hit_count;
/* Filename of a dynamically-linked library (dll), used for bp_catch_load
and bp_catch_unload (malloc'd), or NULL if any library is significant. */
char * dll_pathname;
/* Filename of a dll whose state change (e.g., load or unload)
triggered this catchpoint. This field is only vaid immediately
after this catchpoint has triggered. */
char * triggered_dll_pathname;
/* Process id of a child process whose forking triggered this catchpoint.
This field is only vaid immediately after this catchpoint has triggered. */
int forked_inferior_pid;
/* Filename of a program whose exec triggered this catchpoint. This
field is only vaid immediately after this catchpoint has triggered. */
char * exec_pathname;
asection *section;
}; };
/* The following stuff is an abstract data type "bpstat" ("breakpoint status"). /* The following stuff is an abstract data type "bpstat" ("breakpoint status").
@ -275,6 +332,10 @@ enum bpstat_what_main_action {
keep checking. */ keep checking. */
BPSTAT_WHAT_CHECK_SHLIBS, BPSTAT_WHAT_CHECK_SHLIBS,
/* Check the dynamic linker's data structures for new libraries, then
resume out of the dynamic linker's callback, stop and print. */
BPSTAT_WHAT_CHECK_SHLIBS_RESUME_FROM_HOOK,
/* This is just used to keep track of how many enums there are. */ /* This is just used to keep track of how many enums there are. */
BPSTAT_WHAT_LAST BPSTAT_WHAT_LAST
}; };
@ -295,6 +356,18 @@ struct bpstat_what bpstat_what PARAMS ((bpstat));
/* Find the bpstat associated with a breakpoint. NULL otherwise. */ /* Find the bpstat associated with a breakpoint. NULL otherwise. */
bpstat bpstat_find_breakpoint PARAMS ((bpstat, struct breakpoint *)); bpstat bpstat_find_breakpoint PARAMS ((bpstat, struct breakpoint *));
/* Find a step_resume breakpoint associated with this bpstat.
(If there are multiple step_resume bp's on the list, this function
will arbitrarily pick one.)
It is an error to use this function if BPSTAT doesn't contain a
step_resume breakpoint.
See wait_for_inferior's use of this function.
*/
extern struct breakpoint *
bpstat_find_step_resume_breakpoint PARAMS ((bpstat));
/* Nonzero if a signal that we got in wait() was due to circumstances /* Nonzero if a signal that we got in wait() was due to circumstances
explained by the BS. */ explained by the BS. */
/* Currently that is true if we have hit a breakpoint, or if there is /* Currently that is true if we have hit a breakpoint, or if there is
@ -306,6 +379,9 @@ bpstat bpstat_find_breakpoint PARAMS ((bpstat, struct breakpoint *));
just to things like whether watchpoints are set. */ just to things like whether watchpoints are set. */
extern int bpstat_should_step PARAMS ((void)); extern int bpstat_should_step PARAMS ((void));
/* Nonzero if there are enabled hardware watchpoints. */
extern int bpstat_have_active_hw_watchpoints PARAMS ((void));
/* Print a message indicating what happened. Returns nonzero to /* Print a message indicating what happened. Returns nonzero to
say that only the source line should be printed after this (zero say that only the source line should be printed after this (zero
return means print the frame as well as the source line). */ return means print the frame as well as the source line). */
@ -326,6 +402,12 @@ extern void bpstat_do_actions PARAMS ((bpstat *));
/* Modify BS so that the actions will not be performed. */ /* Modify BS so that the actions will not be performed. */
extern void bpstat_clear_actions PARAMS ((bpstat)); extern void bpstat_clear_actions PARAMS ((bpstat));
/* Given a bpstat that records zero or more triggered eventpoints, this
function returns another bpstat which contains only the catchpoints
on that first list, if any.
*/
extern void bpstat_get_triggered_catchpoints PARAMS ((bpstat, bpstat *));
/* Implementation: */ /* Implementation: */
struct bpstats struct bpstats
{ {
@ -350,6 +432,14 @@ struct bpstats
bpstat_print, or -1 if it can't deal with it. */ bpstat_print, or -1 if it can't deal with it. */
int (*print_it) PARAMS((bpstat bs)); int (*print_it) PARAMS((bpstat bs));
}; };
enum inf_context
{
inf_starting,
inf_running,
inf_exited
};
/* Prototypes for breakpoint-related functions. */ /* Prototypes for breakpoint-related functions. */
@ -359,6 +449,8 @@ struct frame_info;
extern int breakpoint_here_p PARAMS ((CORE_ADDR)); extern int breakpoint_here_p PARAMS ((CORE_ADDR));
extern int breakpoint_inserted_here_p PARAMS ((CORE_ADDR));
extern int frame_in_dummy PARAMS ((struct frame_info *)); extern int frame_in_dummy PARAMS ((struct frame_info *));
extern int breakpoint_thread_match PARAMS ((CORE_ADDR, int)); extern int breakpoint_thread_match PARAMS ((CORE_ADDR, int));
@ -367,7 +459,8 @@ extern void until_break_command PARAMS ((char *, int));
extern void breakpoint_re_set PARAMS ((void)); extern void breakpoint_re_set PARAMS ((void));
extern void clear_momentary_breakpoints PARAMS ((void)); extern void breakpoint_re_set_thread PARAMS ((struct breakpoint *));
extern struct breakpoint *set_momentary_breakpoint extern struct breakpoint *set_momentary_breakpoint
PARAMS ((struct symtab_and_line, struct frame_info *, enum bptype)); PARAMS ((struct symtab_and_line, struct frame_info *, enum bptype));
@ -378,7 +471,7 @@ extern void set_default_breakpoint PARAMS ((int, CORE_ADDR, struct symtab *, int
extern void mark_breakpoints_out PARAMS ((void)); extern void mark_breakpoints_out PARAMS ((void));
extern void breakpoint_init_inferior PARAMS ((void)); extern void breakpoint_init_inferior PARAMS ((enum inf_context));
extern void delete_breakpoint PARAMS ((struct breakpoint *)); extern void delete_breakpoint PARAMS ((struct breakpoint *));
@ -388,16 +481,80 @@ extern void breakpoint_clear_ignore_counts PARAMS ((void));
extern void break_command PARAMS ((char *, int)); extern void break_command PARAMS ((char *, int));
extern void tbreak_command PARAMS ((char *, int));
extern int insert_breakpoints PARAMS ((void)); extern int insert_breakpoints PARAMS ((void));
extern int remove_breakpoints PARAMS ((void)); extern int remove_breakpoints PARAMS ((void));
/* This function can be used to physically insert eventpoints from the
specified traced inferior process, without modifying the breakpoint
package's state. This can be useful for those targets which support
following the processes of a fork() or vfork() system call, when both
of the resulting two processes are to be followed. */
extern int reattach_breakpoints PARAMS ((int));
/* This function can be used to update the breakpoint package's state
after an exec() system call has been executed.
This function causes the following:
- All eventpoints are marked "not inserted".
- All eventpoints with a symbolic address are reset such that
the symbolic address must be reevaluated before the eventpoints
can be reinserted.
- The solib breakpoints are explicitly removed from the breakpoint
list.
- A step-resume breakpoint, if any, is explicitly removed from the
breakpoint list.
- All eventpoints without a symbolic address are removed from the
breakpoint list. */
extern void update_breakpoints_after_exec PARAMS ((void));
/* This function can be used to physically remove hardware breakpoints
and watchpoints from the specified traced inferior process, without
modifying the breakpoint package's state. This can be useful for
those targets which support following the processes of a fork() or
vfork() system call, when one of the resulting two processes is to
be detached and allowed to run free.
It is an error to use this function on the process whose id is
inferior_pid. */
extern int detach_breakpoints PARAMS ((int));
extern void enable_longjmp_breakpoint PARAMS ((void)); extern void enable_longjmp_breakpoint PARAMS ((void));
extern void disable_longjmp_breakpoint PARAMS ((void)); extern void disable_longjmp_breakpoint PARAMS ((void));
extern void set_longjmp_resume_breakpoint PARAMS ((CORE_ADDR, extern void set_longjmp_resume_breakpoint PARAMS ((CORE_ADDR,
struct frame_info *)); struct frame_info *));
/* These functions respectively disable or reenable all currently
enabled watchpoints. When disabled, the watchpoints are marked
call_disabled. When reenabled, they are marked enabled.
The intended client of these functions is infcmd.c\run_stack_dummy.
The inferior must be stopped, and all breakpoints removed, when
these functions are used.
The need for these functions is that on some targets (e.g., HP-UX),
gdb is unable to unwind through the dummy frame that is pushed as
part of the implementation of a call command. Watchpoints can
cause the inferior to stop in places where this frame is visible,
and that can cause execution control to become very confused.
Note that if a user sets breakpoints in an interactively call
function, the call_disabled watchpoints will have been reenabled
when the first such breakpoint is reached. However, on targets
that are unable to unwind through the call dummy frame, watches
of stack-based storage may then be deleted, because gdb will
believe that their watched storage is out of scope. (Sigh.) */
extern void
disable_watchpoints_before_interactive_call_start PARAMS ((void));
extern void
enable_watchpoints_after_interactive_call_stop PARAMS ((void));
extern void clear_breakpoint_hit_counts PARAMS ((void)); extern void clear_breakpoint_hit_counts PARAMS ((void));
@ -420,6 +577,28 @@ extern void create_solib_event_breakpoint PARAMS ((CORE_ADDR));
extern void remove_solib_event_breakpoints PARAMS ((void)); extern void remove_solib_event_breakpoints PARAMS ((void));
extern void disable_breakpoints_in_shlibs PARAMS ((void));
extern void re_enable_breakpoints_in_shlibs PARAMS ((void)); extern void re_enable_breakpoints_in_shlibs PARAMS ((void));
extern void create_solib_load_event_breakpoint PARAMS ((char *, int, char *, char *));
extern void create_solib_unload_event_breakpoint PARAMS ((char *, int, char *, char *));
extern void create_fork_event_catchpoint PARAMS ((int, char *));
extern void create_vfork_event_catchpoint PARAMS ((int, char *));
extern void create_exec_event_catchpoint PARAMS ((int, char *));
/* This function returns TRUE if ep is a catchpoint. */
extern int ep_is_catchpoint PARAMS ((struct breakpoint *));
/* This function returns TRUE if ep is a catchpoint of a
shared library (aka dynamically-linked library) event,
such as a library load or unload. */
extern int ep_is_shlib_catchpoint PARAMS ((struct breakpoint *));
extern struct breakpoint *set_breakpoint_sal PARAMS ((struct symtab_and_line));
#endif /* !defined (BREAKPOINT_H) */ #endif /* !defined (BREAKPOINT_H) */

View file

@ -244,6 +244,7 @@ finish_block (symbol, listhead, old_blocks, start, end, objfile)
BLOCK_END (block) = end; BLOCK_END (block) = end;
/* Superblock filled in when containing block is made */ /* Superblock filled in when containing block is made */
BLOCK_SUPERBLOCK (block) = NULL; BLOCK_SUPERBLOCK (block) = NULL;
BLOCK_GCC_COMPILED (block) = processing_gcc_compilation; BLOCK_GCC_COMPILED (block) = processing_gcc_compilation;
/* Put the block in as the value of the symbol that names it. */ /* Put the block in as the value of the symbol that names it. */
@ -276,6 +277,7 @@ finish_block (symbol, listhead, old_blocks, start, end, objfile)
case LOC_UNDEF: case LOC_UNDEF:
case LOC_CONST: case LOC_CONST:
case LOC_STATIC: case LOC_STATIC:
case LOC_INDIRECT:
case LOC_REGISTER: case LOC_REGISTER:
case LOC_LOCAL: case LOC_LOCAL:
case LOC_TYPEDEF: case LOC_TYPEDEF:
@ -312,6 +314,7 @@ finish_block (symbol, listhead, old_blocks, start, end, objfile)
case LOC_UNDEF: case LOC_UNDEF:
case LOC_CONST: case LOC_CONST:
case LOC_STATIC: case LOC_STATIC:
case LOC_INDIRECT:
case LOC_REGISTER: case LOC_REGISTER:
case LOC_LOCAL: case LOC_LOCAL:
case LOC_TYPEDEF: case LOC_TYPEDEF:
@ -1046,11 +1049,13 @@ push_context (desc, valu)
new = &context_stack[context_stack_depth++]; new = &context_stack[context_stack_depth++];
new->depth = desc; new->depth = desc;
new->locals = local_symbols; new->locals = local_symbols;
new->params = param_symbols;
new->old_blocks = pending_blocks; new->old_blocks = pending_blocks;
new->start_addr = valu; new->start_addr = valu;
new->name = NULL; new->name = NULL;
local_symbols = NULL; local_symbols = NULL;
param_symbols = NULL;
return (new); return (new);
} }
@ -1094,6 +1099,40 @@ record_debugformat (format)
current_subfile -> debugformat = savestring (format, strlen (format)); current_subfile -> debugformat = savestring (format, strlen (format));
} }
/* Merge the first symbol list SRCLIST into the second symbol list
TARGETLIST by repeated calls to add_symbol_to_list(). This
procedure "frees" each link of SRCLIST by adding it to the
free_pendings list. Caller must set SRCLIST to a null list after
calling this function.
Void return. */
void
merge_symbol_lists (srclist, targetlist)
struct pending ** srclist;
struct pending ** targetlist;
{
register int i;
register struct pending * link;
if (!srclist || !*srclist)
return;
/* Merge in elements from current link */
for (i=0; i < (*srclist)->nsyms; i++)
add_symbol_to_list ((*srclist)->symbol[i], targetlist);
/* Recurse on next */
merge_symbol_lists (&(*srclist)->next, targetlist);
/* "Free" the current link */
(*srclist)->next = free_pendings;
free_pendings = (*srclist);
}
/* Initialize anything that needs initializing when starting to read /* Initialize anything that needs initializing when starting to read
a fresh piece of a symbol file, e.g. reading in the stuff corresponding a fresh piece of a symbol file, e.g. reading in the stuff corresponding

View file

@ -245,10 +245,17 @@ c_create_fundamental_type (objfile, typeid)
TARGET_CHAR_BIT / TARGET_CHAR_BIT, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
0, "void", objfile); 0, "void", objfile);
break; break;
case FT_BOOLEAN:
type = init_type (TYPE_CODE_BOOL,
TARGET_CHAR_BIT / TARGET_CHAR_BIT,
0, "bool", objfile);
break;
case FT_CHAR: case FT_CHAR:
type = init_type (TYPE_CODE_INT, type = init_type (TYPE_CODE_INT,
TARGET_CHAR_BIT / TARGET_CHAR_BIT, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
0, "char", objfile); 0, "char", objfile);
TYPE_FLAGS (type) |= TYPE_FLAG_NOSIGN;
break; break;
case FT_SIGNED_CHAR: case FT_SIGNED_CHAR:
type = init_type (TYPE_CODE_INT, type = init_type (TYPE_CODE_INT,
@ -334,6 +341,12 @@ c_create_fundamental_type (objfile, typeid)
type = init_type (TYPE_CODE_FLT, type = init_type (TYPE_CODE_FLT,
TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT, TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
0, "long double", objfile); 0, "long double", objfile);
break;
case FT_TEMPLATE_ARG:
type = init_type (TYPE_CODE_TEMPLATE_ARG,
0,
0, "<template arg>", objfile);
break; break;
} }
return (type); return (type);
@ -428,10 +441,33 @@ const struct language_defn c_language_defn = {
LANG_MAGIC LANG_MAGIC
}; };
struct type ** const (cplus_builtin_types[]) =
{
&builtin_type_int,
&builtin_type_long,
&builtin_type_short,
&builtin_type_char,
&builtin_type_float,
&builtin_type_double,
&builtin_type_void,
&builtin_type_long_long,
&builtin_type_signed_char,
&builtin_type_unsigned_char,
&builtin_type_unsigned_short,
&builtin_type_unsigned_int,
&builtin_type_unsigned_long,
&builtin_type_unsigned_long_long,
&builtin_type_long_double,
&builtin_type_complex,
&builtin_type_double_complex,
&builtin_type_bool,
0
};
const struct language_defn cplus_language_defn = { const struct language_defn cplus_language_defn = {
"c++", /* Language name */ "c++", /* Language name */
language_cplus, language_cplus,
c_builtin_types, cplus_builtin_types,
range_check_off, range_check_off,
type_check_off, type_check_off,
c_parse, c_parse,

View file

@ -38,6 +38,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include <errno.h> #include <errno.h>
#include <ctype.h> #include <ctype.h>
/* Flag indicating target was compiled by HP compiler */
extern int hp_som_som_object_present;
static void static void
c_type_print_args PARAMS ((struct type *, GDB_FILE *)); c_type_print_args PARAMS ((struct type *, GDB_FILE *));
@ -50,6 +53,10 @@ cp_type_print_derivation_info PARAMS ((GDB_FILE *, struct type *));
void void
c_type_print_varspec_prefix PARAMS ((struct type *, GDB_FILE *, int, int)); c_type_print_varspec_prefix PARAMS ((struct type *, GDB_FILE *, int, int));
static void
c_type_print_cv_qualifier PARAMS ((struct type *, GDB_FILE *, int, int));
/* Print a description of a type in the format of a /* Print a description of a type in the format of a
typedef for the current language. typedef for the current language.
@ -169,7 +176,10 @@ c_print_type (type, varstring, stream, show, level)
} }
In general, gdb should try to print the types as closely as possible to In general, gdb should try to print the types as closely as possible to
the form that they appear in the source code. */ the form that they appear in the source code.
Note that in case of protected derivation gcc will not say 'protected'
but 'private'. The HP's aCC compiler emits specific information for
derivation via protected inheritance, so gdb can print it out */
static void static void
cp_type_print_derivation_info (stream, type) cp_type_print_derivation_info (stream, type)
@ -183,7 +193,8 @@ cp_type_print_derivation_info (stream, type)
{ {
fputs_filtered (i == 0 ? ": " : ", ", stream); fputs_filtered (i == 0 ? ": " : ", ", stream);
fprintf_filtered (stream, "%s%s ", fprintf_filtered (stream, "%s%s ",
BASETYPE_VIA_PUBLIC (type, i) ? "public" : "private", BASETYPE_VIA_PUBLIC (type, i) ? "public"
: (TYPE_FIELD_PROTECTED (type, i) ? "protected" : "private"),
BASETYPE_VIA_VIRTUAL(type, i) ? " virtual" : ""); BASETYPE_VIA_VIRTUAL(type, i) ? " virtual" : "");
name = type_name_no_tag (TYPE_BASECLASS (type, i)); name = type_name_no_tag (TYPE_BASECLASS (type, i));
fprintf_filtered (stream, "%s", name ? name : "(null)"); fprintf_filtered (stream, "%s", name ? name : "(null)");
@ -193,6 +204,47 @@ cp_type_print_derivation_info (stream, type)
fputs_filtered (" ", stream); fputs_filtered (" ", stream);
} }
} }
/* Print the C++ method arguments ARGS to the file STREAM. */
void
cp_type_print_method_args (args, prefix, varstring, staticp, stream)
struct type **args;
char *prefix;
char *varstring;
int staticp;
GDB_FILE *stream;
{
int i;
fprintf_symbol_filtered (stream, prefix, language_cplus, DMGL_ANSI);
fprintf_symbol_filtered (stream, varstring, language_cplus, DMGL_ANSI);
fputs_filtered ("(", stream);
if (args && args[!staticp] && args[!staticp]->code != TYPE_CODE_VOID)
{
i = !staticp; /* skip the class variable */
while (1)
{
type_print (args[i++], "", stream, 0);
if (!args[i])
{
fprintf_filtered (stream, " ...");
break;
}
else if (args[i]->code != TYPE_CODE_VOID)
{
fprintf_filtered (stream, ", ");
}
else break;
}
}
else if (current_language->la_language == language_cplus)
{
fprintf_filtered (stream, "void");
}
fprintf_filtered (stream, ")");
}
/* Print any asterisks or open-parentheses needed before the /* Print any asterisks or open-parentheses needed before the
variable name (to describe its type). variable name (to describe its type).
@ -223,6 +275,7 @@ c_type_print_varspec_prefix (type, stream, show, passed_a_ptr)
case TYPE_CODE_PTR: case TYPE_CODE_PTR:
c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1); c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1);
fprintf_filtered (stream, "*"); fprintf_filtered (stream, "*");
c_type_print_cv_qualifier (type, stream, 1, 0);
break; break;
case TYPE_CODE_MEMBER: case TYPE_CODE_MEMBER:
@ -253,6 +306,7 @@ c_type_print_varspec_prefix (type, stream, show, passed_a_ptr)
case TYPE_CODE_REF: case TYPE_CODE_REF:
c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1); c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1);
fprintf_filtered (stream, "&"); fprintf_filtered (stream, "&");
c_type_print_cv_qualifier (type, stream, 1, 0);
break; break;
case TYPE_CODE_FUNC: case TYPE_CODE_FUNC:
@ -289,6 +343,43 @@ c_type_print_varspec_prefix (type, stream, show, passed_a_ptr)
} }
} }
/* Print out "const" and "volatile" attributes.
TYPE is a pointer to the type being printed out.
STREAM is the output destination.
NEED_SPACE = 1 indicates an initial white space is needed */
static void
c_type_print_cv_qualifier (type, stream, need_pre_space, need_post_space)
struct type *type;
GDB_FILE *stream;
int need_pre_space;
int need_post_space;
{
int flag = 0;
if (TYPE_CONST (type))
{
if (need_pre_space)
fprintf_filtered (stream, " ");
fprintf_filtered (stream, "const");
flag = 1;
}
if (TYPE_VOLATILE (type))
{
if (flag || need_pre_space)
fprintf_filtered (stream, " ");
fprintf_filtered (stream, "volatile");
flag = 1;
}
if (flag && need_post_space)
fprintf_filtered (stream, " ");
}
static void static void
c_type_print_args (type, stream) c_type_print_args (type, stream)
struct type *type; struct type *type;
@ -305,6 +396,11 @@ c_type_print_args (type, stream)
{ {
fprintf_filtered (stream, "..."); fprintf_filtered (stream, "...");
} }
else if ((args[1]->code == TYPE_CODE_VOID) &&
(current_language->la_language == language_cplus))
{
fprintf_filtered (stream, "void");
}
else else
{ {
for (i = 1; for (i = 1;
@ -324,6 +420,11 @@ c_type_print_args (type, stream)
} }
} }
} }
else if (current_language->la_language == language_cplus)
{
fprintf_filtered (stream, "void");
}
fprintf_filtered (stream, ")"); fprintf_filtered (stream, ")");
} }
@ -391,15 +492,20 @@ c_type_print_varspec_suffix (type, stream, show, passed_a_ptr, demangled_args)
if (!demangled_args) if (!demangled_args)
{ int i, len = TYPE_NFIELDS (type); { int i, len = TYPE_NFIELDS (type);
fprintf_filtered (stream, "("); fprintf_filtered (stream, "(");
for (i = 0; i < len; i++) if ((len == 0) && (current_language->la_language == language_cplus))
{ {
if (i > 0) fprintf_filtered (stream, "void");
{ }
fputs_filtered (", ", stream); else
wrap_here (" "); for (i = 0; i < len; i++)
} {
c_print_type (TYPE_FIELD_TYPE (type, i), "", stream, -1, 0); if (i > 0)
} {
fputs_filtered (", ", stream);
wrap_here (" ");
}
c_print_type (TYPE_FIELD_TYPE (type, i), "", stream, -1, 0);
}
fprintf_filtered (stream, ")"); fprintf_filtered (stream, ")");
} }
c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0,
@ -456,7 +562,11 @@ c_type_print_base (type, stream, show, level)
register int lastval; register int lastval;
char *mangled_name; char *mangled_name;
char *demangled_name; char *demangled_name;
char *demangled_no_static;
enum {s_none, s_public, s_private, s_protected} section_type; enum {s_none, s_public, s_private, s_protected} section_type;
int need_access_label = 0;
int j, len2;
QUIT; QUIT;
wrap_here (" "); wrap_here (" ");
@ -475,6 +585,7 @@ c_type_print_base (type, stream, show, level)
if (show <= 0 if (show <= 0
&& TYPE_NAME (type) != NULL) && TYPE_NAME (type) != NULL)
{ {
c_type_print_cv_qualifier (type, stream, 0, 1);
fputs_filtered (TYPE_NAME (type), stream); fputs_filtered (TYPE_NAME (type), stream);
return; return;
} }
@ -494,21 +605,48 @@ c_type_print_base (type, stream, show, level)
break; break;
case TYPE_CODE_STRUCT: case TYPE_CODE_STRUCT:
if (HAVE_CPLUS_STRUCT (type)) c_type_print_cv_qualifier (type, stream, 0, 1);
{ /* Note TYPE_CODE_STRUCT and TYPE_CODE_CLASS have the same value,
fprintf_filtered (stream, "class "); * so we use another means for distinguishing them.
} */
else if (HAVE_CPLUS_STRUCT (type)) {
{ switch (TYPE_DECLARED_TYPE(type)) {
fprintf_filtered (stream, "struct "); case DECLARED_TYPE_CLASS:
} fprintf_filtered (stream, "class ");
break;
case DECLARED_TYPE_UNION:
fprintf_filtered (stream, "union ");
break;
case DECLARED_TYPE_STRUCT:
fprintf_filtered (stream, "struct ");
break;
default:
/* If there is a CPLUS_STRUCT, assume class if not
* otherwise specified in the declared_type field.
*/
fprintf_filtered (stream, "class ");
break;
} /* switch */
} else {
/* If not CPLUS_STRUCT, then assume it's a C struct */
fprintf_filtered (stream, "struct ");
}
goto struct_union; goto struct_union;
case TYPE_CODE_UNION: case TYPE_CODE_UNION:
c_type_print_cv_qualifier (type, stream, 0, 1);
fprintf_filtered (stream, "union "); fprintf_filtered (stream, "union ");
struct_union: struct_union:
if (TYPE_TAG_NAME (type) != NULL)
/* Print the tag if it exists.
* The HP aCC compiler emits
* a spurious "{unnamed struct}"/"{unnamed union}"/"{unnamed enum}"
* tag for unnamed struct/union/enum's, which we don't
* want to print.
*/
if (TYPE_TAG_NAME (type) != NULL &&
strncmp(TYPE_TAG_NAME(type), "{unnamed", 8))
{ {
fputs_filtered (TYPE_TAG_NAME (type), stream); fputs_filtered (TYPE_TAG_NAME (type), stream);
if (show > 0) if (show > 0)
@ -540,6 +678,72 @@ c_type_print_base (type, stream, show, level)
section_type = s_none; section_type = s_none;
/* For a class, if all members are private, there's no need
for a "private:" label; similarly, for a struct or union
masquerading as a class, if all members are public, there's
no need for a "public:" label. */
if ((TYPE_DECLARED_TYPE (type) == DECLARED_TYPE_CLASS) ||
(TYPE_DECLARED_TYPE (type) == DECLARED_TYPE_TEMPLATE))
{
QUIT;
len = TYPE_NFIELDS (type);
for (i = TYPE_N_BASECLASSES (type); i < len; i++)
if (!TYPE_FIELD_PRIVATE (type, i))
{
need_access_label = 1;
break;
}
QUIT;
if (!need_access_label)
{
len2 = TYPE_NFN_FIELDS (type);
for (j = 0; j < len2; j++)
{
len = TYPE_FN_FIELDLIST_LENGTH (type, j);
for (i = 0; i < len; i++)
if (!TYPE_FN_FIELD_PRIVATE (TYPE_FN_FIELDLIST1 (type, j), i))
{
need_access_label = 1;
break;
}
if (need_access_label)
break;
}
}
}
else if ((TYPE_DECLARED_TYPE (type) == DECLARED_TYPE_STRUCT) ||
(TYPE_DECLARED_TYPE (type) == DECLARED_TYPE_UNION))
{
QUIT;
len = TYPE_NFIELDS (type);
for (i = TYPE_N_BASECLASSES (type); i < len; i++)
if (TYPE_FIELD_PRIVATE (type, i) || TYPE_FIELD_PROTECTED (type, i))
{
need_access_label = 1;
break;
}
QUIT;
if (!need_access_label)
{
len2 = TYPE_NFN_FIELDS (type);
for (j = 0; j < len2; j++)
{
QUIT;
len = TYPE_FN_FIELDLIST_LENGTH (type, j);
for (i = 0; i < len; i++)
if (TYPE_FN_FIELD_PRIVATE (TYPE_FN_FIELDLIST1 (type, j), i) ||
TYPE_FN_FIELD_PROTECTED (TYPE_FN_FIELDLIST1 (type, j), i))
{
need_access_label = 1;
break;
}
if (need_access_label)
break;
}
}
}
/* If there is a base class for this type, /* If there is a base class for this type,
do not print the field that it occupies. */ do not print the field that it occupies. */
@ -548,6 +752,11 @@ c_type_print_base (type, stream, show, level)
{ {
QUIT; QUIT;
/* Don't print out virtual function table. */ /* Don't print out virtual function table. */
/* HP ANSI C++ case */
if (TYPE_HAS_VTABLE(type) && (STREQN (TYPE_FIELD_NAME (type, i), "__vfp", 5)))
continue;
/* Other compilers */
/* pai:: FIXME : check for has_vtable < 0 */
if (STREQN (TYPE_FIELD_NAME (type, i), "_vptr", 5) if (STREQN (TYPE_FIELD_NAME (type, i), "_vptr", 5)
&& is_cplus_marker ((TYPE_FIELD_NAME (type, i))[5])) && is_cplus_marker ((TYPE_FIELD_NAME (type, i))[5]))
continue; continue;
@ -555,7 +764,7 @@ c_type_print_base (type, stream, show, level)
/* If this is a C++ class we can print the various C++ section /* If this is a C++ class we can print the various C++ section
labels. */ labels. */
if (HAVE_CPLUS_STRUCT (type)) if (HAVE_CPLUS_STRUCT (type) && need_access_label)
{ {
if (TYPE_FIELD_PROTECTED (type, i)) if (TYPE_FIELD_PROTECTED (type, i))
{ {
@ -612,7 +821,6 @@ c_type_print_base (type, stream, show, level)
fprintf_filtered (stream, "\n"); fprintf_filtered (stream, "\n");
/* C++: print out the methods */ /* C++: print out the methods */
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
{ {
struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i); struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
@ -669,7 +877,10 @@ c_type_print_base (type, stream, show, level)
TYPE_FN_FIELD_PHYSNAME (f, j)); TYPE_FN_FIELD_PHYSNAME (f, j));
break; break;
} }
else if (!is_constructor && !is_full_physname_constructor) else if (!is_constructor && /* constructors don't have declared types */
!is_full_physname_constructor && /* " " */
!strstr (method_name, "operator ")) /* Not a type conversion operator */
/* (note space -- other operators don't have it) */
{ {
type_print (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)), type_print (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)),
"", stream, -1); "", stream, -1);
@ -685,21 +896,45 @@ c_type_print_base (type, stream, show, level)
cplus_demangle (mangled_name, cplus_demangle (mangled_name,
DMGL_ANSI | DMGL_PARAMS); DMGL_ANSI | DMGL_PARAMS);
if (demangled_name == NULL) if (demangled_name == NULL)
fprintf_filtered (stream, "<badly mangled name '%s'>", {
mangled_name); /* in some cases (for instance with the HP demangling),
if a function has more than 10 arguments,
the demangling will fail.
Let's try to reconstruct the function signature from
the symbol information */
if (!TYPE_FN_FIELD_STUB (f, j))
cp_type_print_method_args (TYPE_FN_FIELD_ARGS (f, j), "",
method_name,
TYPE_FN_FIELD_STATIC_P (f, j),
stream);
else
fprintf_filtered (stream, "<badly mangled name '%s'>",
mangled_name);
}
else else
{ {
char *demangled_no_class = char *p;
strchr (demangled_name, ':'); char *demangled_no_class = demangled_name;
if (demangled_no_class == NULL) while (p = strchr (demangled_no_class, ':'))
demangled_no_class = demangled_name;
else
{ {
demangled_no_class = p;
if (*++demangled_no_class == ':') if (*++demangled_no_class == ':')
++demangled_no_class; ++demangled_no_class;
} }
fputs_filtered (demangled_no_class, stream); /* get rid of the static word appended by the demangler */
p = strstr (demangled_no_class, " static");
if (p != NULL)
{
int length = p - demangled_no_class;
demangled_no_static = (char *) xmalloc (length + 1);
strncpy (demangled_no_static, demangled_no_class, length);
*(demangled_no_static + length) = '\0';
fputs_filtered (demangled_no_static, stream);
free (demangled_no_static);
}
else
fputs_filtered (demangled_no_class, stream);
free (demangled_name); free (demangled_name);
} }
@ -710,13 +945,41 @@ c_type_print_base (type, stream, show, level)
} }
} }
if (TYPE_LOCALTYPE_PTR (type) && show >= 0)
fprintfi_filtered (level, stream, " (Local at %s:%d)\n",
TYPE_LOCALTYPE_FILE (type),
TYPE_LOCALTYPE_LINE (type));
fprintfi_filtered (level, stream, "}"); fprintfi_filtered (level, stream, "}");
} }
if (TYPE_CODE(type) == TYPE_CODE_TEMPLATE)
goto go_back;
break; break;
case TYPE_CODE_ENUM: case TYPE_CODE_ENUM:
fprintf_filtered (stream, "enum "); c_type_print_cv_qualifier (type, stream, 0, 1);
if (TYPE_TAG_NAME (type) != NULL) /* HP C supports sized enums */
if (hp_som_som_object_present)
switch (TYPE_LENGTH (type))
{
case 1:
fputs_filtered ("char ", stream);
break;
case 2:
fputs_filtered ("short ", stream);
break;
default:
break;
}
fprintf_filtered (stream, "enum ");
/* Print the tag name if it exists.
* Fix for CHFts22718 (RT): The aCC compiler emits
* a spurious "{unnamed struct}"/"{unnamed union}"/"{unnamed enum}"
* tag for unnamed struct/union/enum's, which we don't
* want to print.
*/
if (TYPE_TAG_NAME (type) != NULL &&
strncmp(TYPE_TAG_NAME(type), "{unnamed", 8))
{ {
fputs_filtered (TYPE_TAG_NAME (type), stream); fputs_filtered (TYPE_TAG_NAME (type), stream);
if (show > 0) if (show > 0)
@ -769,6 +1032,38 @@ c_type_print_base (type, stream, show, level)
fprintf_filtered (stream, "<range type>"); fprintf_filtered (stream, "<range type>");
break; break;
case TYPE_CODE_TEMPLATE:
/* Called on "ptype t" where "t" is a template.
* Prints the template header (with args), e.g.:
* template <class T1, class T2> class "
* and then merges with the struct/union/class code to
* print the rest of the definition.
*/
c_type_print_cv_qualifier (type, stream, 0, 1);
fprintf_filtered (stream, "template <");
for (i = 0; i < TYPE_NTEMPLATE_ARGS(type); i++) {
struct template_arg templ_arg;
templ_arg = TYPE_TEMPLATE_ARG(type, i);
fprintf_filtered (stream, "class %s", templ_arg.name);
if (i < TYPE_NTEMPLATE_ARGS(type)-1)
fprintf_filtered (stream, ", ");
}
fprintf_filtered (stream, "> class ");
/* Yuck, factor this out to a subroutine so we can call
* it and return to the point marked with the "goback:" label... - RT
*/
goto struct_union;
go_back:
if (TYPE_NINSTANTIATIONS(type) > 0) {
fprintf_filtered (stream, "\ntemplate instantiations:\n");
for (i = 0; i < TYPE_NINSTANTIATIONS(type); i++) {
fprintf_filtered(stream, " ");
c_type_print_base (TYPE_INSTANTIATION(type, i), stream, 0, level);
if (i < TYPE_NINSTANTIATIONS(type)-1) fprintf_filtered(stream, "\n");
}
}
break;
default: default:
/* Handle types not explicitly handled by the other cases, /* Handle types not explicitly handled by the other cases,
such as fundamental types. For these, just print whatever such as fundamental types. For these, just print whatever
@ -776,6 +1071,7 @@ c_type_print_base (type, stream, show, level)
is no type name, then complain. */ is no type name, then complain. */
if (TYPE_NAME (type) != NULL) if (TYPE_NAME (type) != NULL)
{ {
c_type_print_cv_qualifier (type, stream, 0, 1);
fputs_filtered (TYPE_NAME (type), stream); fputs_filtered (TYPE_NAME (type), stream);
} }
else else
@ -789,3 +1085,6 @@ c_type_print_base (type, stream, show, level)
} }
} }

View file

@ -474,7 +474,11 @@ c_value_print (val, stream, format, pretty)
if (TYPE_CODE (type) == TYPE_CODE_PTR && if (TYPE_CODE (type) == TYPE_CODE_PTR &&
TYPE_NAME (type) == NULL && TYPE_NAME (type) == NULL &&
TYPE_NAME (TYPE_TARGET_TYPE (type)) != NULL && TYPE_NAME (TYPE_TARGET_TYPE (type)) != NULL &&
STREQ (TYPE_NAME (TYPE_TARGET_TYPE (type)), "char")) STREQ (TYPE_NAME (TYPE_TARGET_TYPE (type)), "char") &&
!TYPE_VOLATILE (TYPE_TARGET_TYPE (type)) &&
(TYPE_UNSIGNED (TYPE_TARGET_TYPE (type)) || TYPE_NOSIGN (TYPE_TARGET_TYPE (type))) &&
!TYPE_VOLATILE (type) &&
!TYPE_CONST (type))
{ {
/* Print nothing */ /* Print nothing */
} }

View file

@ -94,7 +94,10 @@ coff_solib_add (arg_string, from_tty, target)
0, /* addr */ 0, /* addr */
0, /* not mainline */ 0, /* not mainline */
0, /* not mapped */ 0, /* not mapped */
0); /* Not readnow */ 0, /* Not readnow */
0, /* Not user loaded */
1); /* Is a solib */
libsize -= len * 4; libsize -= len * 4;
lib += len * 4; lib += len * 4;
} }

View file

@ -559,7 +559,38 @@ help_cmd_list (list, class, prefix, recurse, stream)
help_cmd_list (*c->prefixlist, class, c->prefixname, 1, stream); help_cmd_list (*c->prefixlist, class, c->prefixname, 1, stream);
} }
} }
/* Search the input clist for 'command'. Return the command if
found (or NULL if not), and return the number of commands
found in nfound */
static struct cmd_list_element *
find_cmd(command, len, clist, ignore_help_classes, nfound)
char *command;
struct cmd_list_element *clist;
int ignore_help_classes;
int *nfound;
{
struct cmd_list_element *found, *c;
found = (struct cmd_list_element *)NULL;
*nfound = 0;
for (c = clist; c; c = c->next)
if (!strncmp (command, c->name, len)
&& (!ignore_help_classes || c->function.cfunc))
{
found = c;
(*nfound)++;
if (c->name[len] == '\0')
{
*nfound = 1;
break;
}
}
return found;
}
/* This routine takes a line of TEXT and a CLIST in which to start the /* This routine takes a line of TEXT and a CLIST in which to start the
lookup. When it returns it will have incremented the text pointer past lookup. When it returns it will have incremented the text pointer past
the section of text it matched, set *RESULT_LIST to point to the list in the section of text it matched, set *RESULT_LIST to point to the list in
@ -613,7 +644,10 @@ lookup_cmd_1 (text, clist, result_list, ignore_help_classes)
so that "set args_foo()" doesn't get interpreted as so that "set args_foo()" doesn't get interpreted as
"set args _foo()". */ "set args _foo()". */
for (p = *text; for (p = *text;
*p && (isalnum(*p) || *p == '-' || *p == '_'); *p && (isalnum(*p) || *p == '-' || *p == '_' ||
(tui_version &&
(*p == '+' || *p == '<' || *p == '>' || *p == '$')) ||
(xdb_commands && (*p == '!' || *p == '/' || *p == '?')));
p++) p++)
; ;
@ -624,32 +658,35 @@ lookup_cmd_1 (text, clist, result_list, ignore_help_classes)
len = p - *text; len = p - *text;
/* *text and p now bracket the first command word to lookup (and /* *text and p now bracket the first command word to lookup (and
it's length is len). We copy this into a local temporary, it's length is len). We copy this into a local temporary */
converting to lower case as we go. */
command = (char *) alloca (len + 1); command = (char *) alloca (len + 1);
for (tmp = 0; tmp < len; tmp++) for (tmp = 0; tmp < len; tmp++)
{ {
char x = (*text)[tmp]; char x = (*text)[tmp];
command[tmp] = isupper(x) ? tolower(x) : x; command[tmp] = x;
} }
command[len] = '\0'; command[len] = '\0';
/* Look it up. */ /* Look it up. */
found = 0; found = 0;
nfound = 0; nfound = 0;
for (c = clist; c; c = c->next) found = find_cmd(command, len, clist, ignore_help_classes, &nfound);
if (!strncmp (command, c->name, len)
&& (!ignore_help_classes || c->function.cfunc)) /*
{ ** We didn't find the command in the entered case, so lower case it
found = c; ** and search again.
nfound++; */
if (c->name[len] == '\0') if (!found || nfound == 0)
{ {
nfound = 1; for (tmp = 0; tmp < len; tmp++)
break; {
} char x = command[tmp];
} command[tmp] = isupper(x) ? tolower(x) : x;
}
found = find_cmd(command, len, clist, ignore_help_classes, &nfound);
}
/* If nothing matches, we have a simple failure. */ /* If nothing matches, we have a simple failure. */
if (nfound == 0) if (nfound == 0)
@ -1514,6 +1551,10 @@ _initialize_command ()
add_com ("shell", class_support, shell_escape, add_com ("shell", class_support, shell_escape,
"Execute the rest of the line as a shell command. \n\ "Execute the rest of the line as a shell command. \n\
With no arguments, run an inferior shell."); With no arguments, run an inferior shell.");
if (xdb_commands)
add_com_alias("!", "shell", class_support, 0);
add_com ("make", class_support, make_command, add_com ("make", class_support, make_command,
"Run the ``make'' program using the rest of the line as arguments."); "Run the ``make'' program using the rest of the line as arguments.");
add_cmd ("user", no_class, show_user, add_cmd ("user", no_class, show_user,

View file

@ -431,7 +431,7 @@ set_trapped_internalvar (var, val, bitpos, bitsize, offset)
If it looks like an address, print it in hex instead. */ If it looks like an address, print it in hex instead. */
decout (stream, type, val) decout (stream, type, val)
FILE *stream; GDB_FILE *stream;
struct type *type; struct type *type;
LONGEST val; LONGEST val;
{ {

View file

@ -34,6 +34,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "dis-asm.h" #include "dis-asm.h"
#include "language.h" #include "language.h"
#include "gdb_stat.h" #include "gdb_stat.h"
#include "symfile.h"
#include "objfiles.h"
extern char registers[]; extern char registers[];
@ -76,7 +78,29 @@ core_file_command (filename, from_tty)
if (!filename) if (!filename)
(t->to_detach) (filename, from_tty); (t->to_detach) (filename, from_tty);
else else
(t->to_open) (filename, from_tty); {
/* Yes, we were given the path of a core file. Do we already
have a symbol file? If not, can we determine it from the
core file? If we can, do so.
*/
#ifdef HPUXHPPA
if (symfile_objfile == NULL)
{
char * symfile;
symfile = t->to_core_file_to_sym_file (filename);
if (symfile)
{
char * symfile_copy = strdup (symfile);
make_cleanup (free, symfile_copy);
symbol_file_command (symfile_copy, from_tty);
}
else
warning ("Unknown symbols for '%s'; use the 'symbol-file' command.", filename);
}
#endif
(t->to_open) (filename, from_tty);
}
else else
error ("GDB can't read core files on this machine."); error ("GDB can't read core files on this machine.");
} }

View file

@ -368,7 +368,7 @@ add_shared_symbol_files ()
return; return;
} }
objfile = symbol_file_add (LIBC_FILE, 0, 0, 0, 0, 1); objfile = symbol_file_add (LIBC_FILE, 0, 0, 0, 0, 1, 0, 0);
minsym = lookup_minimal_symbol (LINKS_MAP_POINTER, objfile); minsym = lookup_minimal_symbol (LINKS_MAP_POINTER, objfile);
ld_map = (struct link_map *) ld_map = (struct link_map *)
@ -384,7 +384,7 @@ add_shared_symbol_files ()
if (target_read_string ((CORE_ADDR)lms.l_name, &path_name, if (target_read_string ((CORE_ADDR)lms.l_name, &path_name,
PATH_MAX, &local_errno)) PATH_MAX, &local_errno))
{ {
symbol_file_add (path_name, 1, lms.l_addr, 0, 0, 0); symbol_file_add (path_name, 1, lms.l_addr, 0, 0, 0, 0, 0);
free(path_name); free(path_name);
} }
} }

View file

@ -94,6 +94,16 @@ typedef bfd_vma CORE_ADDR;
/* Check if a character is one of the commonly used C++ marker characters. */ /* Check if a character is one of the commonly used C++ marker characters. */
extern int is_cplus_marker PARAMS ((int)); extern int is_cplus_marker PARAMS ((int));
/* use tui interface if non-zero */
extern int tui_version;
#if defined(TUI)
/* all invocations of TUIDO should have two sets of parens */
#define TUIDO(x) tuiDo x
#else
#define TUIDO(x)
#endif
/* enable xdb commands if set */ /* enable xdb commands if set */
extern int xdb_commands; extern int xdb_commands;
@ -156,6 +166,13 @@ enum language
language_scm /* Scheme / Guile */ language_scm /* Scheme / Guile */
}; };
enum precision_type
{
single_precision,
double_precision,
unspecified_precision
};
/* the cleanup list records things that have to be undone /* the cleanup list records things that have to be undone
if an error happens (descriptors to be closed, memory to be freed, etc.) if an error happens (descriptors to be closed, memory to be freed, etc.)
Each link in the chain records a function to call and an Each link in the chain records a function to call and an
@ -311,9 +328,41 @@ extern void wrap_here PARAMS ((char *));
extern void reinitialize_more_filter PARAMS ((void)); extern void reinitialize_more_filter PARAMS ((void));
/* new */
enum streamtype
{
afile,
astring
};
/* new */
typedef struct tui_stream
{
enum streamtype ts_streamtype;
FILE *ts_filestream;
char *ts_strbuf;
int ts_buflen;
} GDB_FILE;
extern GDB_FILE *gdb_stdout;
extern GDB_FILE *gdb_stderr;
#if 0
typedef FILE GDB_FILE; typedef FILE GDB_FILE;
#define gdb_stdout stdout #define gdb_stdout stdout
#define gdb_stderr stderr #define gdb_stderr stderr
#endif
#if defined(TUI)
#include "tui.h"
#include "tuiCommand.h"
#include "tuiData.h"
#include "tuiIO.h"
#include "tuiLayout.h"
#include "tuiWin.h"
#endif
extern void gdb_fclose PARAMS ((GDB_FILE **));
extern void gdb_flush PARAMS ((GDB_FILE *)); extern void gdb_flush PARAMS ((GDB_FILE *));
@ -338,13 +387,13 @@ extern void puts_debug PARAMS ((char *prefix, char *string, char *suffix));
extern void vprintf_filtered PARAMS ((const char *, va_list)) extern void vprintf_filtered PARAMS ((const char *, va_list))
ATTR_FORMAT(printf, 1, 0); ATTR_FORMAT(printf, 1, 0);
extern void vfprintf_filtered PARAMS ((FILE *, const char *, va_list)) extern void vfprintf_filtered PARAMS ((GDB_FILE *, const char *, va_list))
ATTR_FORMAT(printf, 2, 0); ATTR_FORMAT(printf, 2, 0);
extern void fprintf_filtered PARAMS ((FILE *, const char *, ...)) extern void fprintf_filtered PARAMS ((GDB_FILE *, const char *, ...))
ATTR_FORMAT(printf, 2, 3); ATTR_FORMAT(printf, 2, 3);
extern void fprintfi_filtered PARAMS ((int, FILE *, const char *, ...)) extern void fprintfi_filtered PARAMS ((int, GDB_FILE *, const char *, ...))
ATTR_FORMAT(printf, 3, 4); ATTR_FORMAT(printf, 3, 4);
extern void printf_filtered PARAMS ((const char *, ...)) extern void printf_filtered PARAMS ((const char *, ...))
@ -356,15 +405,25 @@ extern void printfi_filtered PARAMS ((int, const char *, ...))
extern void vprintf_unfiltered PARAMS ((const char *, va_list)) extern void vprintf_unfiltered PARAMS ((const char *, va_list))
ATTR_FORMAT(printf, 1, 0); ATTR_FORMAT(printf, 1, 0);
extern void vfprintf_unfiltered PARAMS ((FILE *, const char *, va_list)) extern void vfprintf_unfiltered PARAMS ((GDB_FILE *, const char *, va_list))
ATTR_FORMAT(printf, 2, 0); ATTR_FORMAT(printf, 2, 0);
extern void fprintf_unfiltered PARAMS ((FILE *, const char *, ...)) extern void fprintf_unfiltered PARAMS ((GDB_FILE *, const char *, ...))
ATTR_FORMAT(printf, 2, 3); ATTR_FORMAT(printf, 2, 3);
extern void printf_unfiltered PARAMS ((const char *, ...)) extern void printf_unfiltered PARAMS ((const char *, ...))
ATTR_FORMAT(printf, 1, 2); ATTR_FORMAT(printf, 1, 2);
extern int gdb_file_isatty PARAMS ((GDB_FILE *));
extern GDB_FILE *gdb_file_init_astring PARAMS ((int));
extern void gdb_file_deallocate PARAMS ((GDB_FILE **));
extern char *gdb_file_get_strbuf PARAMS ((GDB_FILE *));
extern void gdb_file_adjust_strbuf PARAMS ((int, GDB_FILE *));
extern void print_spaces PARAMS ((int, GDB_FILE *)); extern void print_spaces PARAMS ((int, GDB_FILE *));
extern void print_spaces_filtered PARAMS ((int, GDB_FILE *)); extern void print_spaces_filtered PARAMS ((int, GDB_FILE *));
@ -431,6 +490,8 @@ extern void print_address PARAMS ((CORE_ADDR, GDB_FILE *));
extern int openp PARAMS ((char *, int, char *, int, int, char **)); extern int openp PARAMS ((char *, int, char *, int, int, char **));
extern int source_full_path_of PARAMS ((char *, char **));
extern void mod_path PARAMS ((char *, char **)); extern void mod_path PARAMS ((char *, char **));
extern void directory_command PARAMS ((char *, int)); extern void directory_command PARAMS ((char *, int));
@ -785,7 +846,6 @@ extern void free ();
#endif #endif
/* Dynamic target-system-dependent parameters for GDB. */ /* Dynamic target-system-dependent parameters for GDB. */
#include "gdbarch.h" #include "gdbarch.h"
/* Static target-system-dependent parameters for GDB. */ /* Static target-system-dependent parameters for GDB. */
@ -865,11 +925,11 @@ extern int extract_long_unsigned_integer PARAMS ((void *, int, LONGEST *));
extern CORE_ADDR extract_address PARAMS ((void *, int)); extern CORE_ADDR extract_address PARAMS ((void *, int));
extern void store_signed_integer PARAMS ((void *, int, LONGEST)); extern void store_signed_integer PARAMS ((PTR, int, LONGEST));
extern void store_unsigned_integer PARAMS ((void *, int, ULONGEST)); extern void store_unsigned_integer PARAMS ((PTR, int, ULONGEST));
extern void store_address PARAMS ((void *, int, CORE_ADDR)); extern void store_address PARAMS ((PTR, int, LONGEST));
/* Setup definitions for host and target floating point formats. We need to /* Setup definitions for host and target floating point formats. We need to
consider the format for `float', `double', and `long double' for both target consider the format for `float', `double', and `long double' for both target
@ -989,13 +1049,14 @@ struct cmd_list_element;
extern void (*init_ui_hook) PARAMS ((char *argv0)); extern void (*init_ui_hook) PARAMS ((char *argv0));
extern void (*command_loop_hook) PARAMS ((void)); extern void (*command_loop_hook) PARAMS ((void));
extern void (*fputs_unfiltered_hook) PARAMS ((const char *linebuffer, extern void (*fputs_unfiltered_hook) PARAMS ((const char *linebuffer,
FILE *stream)); GDB_FILE *stream));
extern void (*print_frame_info_listing_hook) PARAMS ((struct symtab *s, extern void (*print_frame_info_listing_hook) PARAMS ((struct symtab *s,
int line, int stopline, int line, int stopline,
int noerror)); int noerror));
extern struct frame_info *parse_frame_specification PARAMS ((char *frame_exp));
extern int (*query_hook) PARAMS ((const char *, va_list)); extern int (*query_hook) PARAMS ((const char *, va_list));
extern void (*warning_hook) PARAMS ((const char *, va_list)); extern void (*warning_hook) PARAMS ((const char *, va_list));
extern void (*flush_hook) PARAMS ((FILE *stream)); extern void (*flush_hook) PARAMS ((GDB_FILE *stream));
extern void (*create_breakpoint_hook) PARAMS ((struct breakpoint *b)); extern void (*create_breakpoint_hook) PARAMS ((struct breakpoint *b));
extern void (*delete_breakpoint_hook) PARAMS ((struct breakpoint *bpt)); extern void (*delete_breakpoint_hook) PARAMS ((struct breakpoint *bpt));
extern void (*modify_breakpoint_hook) PARAMS ((struct breakpoint *bpt)); extern void (*modify_breakpoint_hook) PARAMS ((struct breakpoint *bpt));

View file

@ -31,7 +31,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Select the default C++ demangling style to use. The default is "auto", /* Select the default C++ demangling style to use. The default is "auto",
which allows gdb to attempt to pick an appropriate demangling style for which allows gdb to attempt to pick an appropriate demangling style for
the executable it has loaded. It can be set to a specific style ("gnu", the executable it has loaded. It can be set to a specific style ("gnu",
"lucid", "arm", etc.) in which case gdb will never attempt to do auto "lucid", "arm", "hp", etc.) in which case gdb will never attempt to do auto
selection of the style unless you do an explicit "set demangle auto". selection of the style unless you do an explicit "set demangle auto".
To select one of these as the default, set DEFAULT_DEMANGLING_STYLE in To select one of these as the default, set DEFAULT_DEMANGLING_STYLE in
the appropriate target configuration file. */ the appropriate target configuration file. */
@ -67,6 +67,12 @@ static const struct demangler
{ARM_DEMANGLING_STYLE_STRING, {ARM_DEMANGLING_STYLE_STRING,
arm_demangling, arm_demangling,
"ARM style demangling"}, "ARM style demangling"},
{HP_DEMANGLING_STYLE_STRING,
hp_demangling,
"HP (aCC) style demangling"},
{EDG_DEMANGLING_STYLE_STRING,
edg_demangling,
"EDG style demangling"},
{NULL, unknown_demangling, NULL} {NULL, unknown_demangling, NULL}
}; };

View file

@ -144,7 +144,7 @@ f_emit_char (c, stream, quoter)
static void static void
f_printchar (c, stream) f_printchar (c, stream)
int c; int c;
FILE *stream; GDB_FILE *stream;
{ {
fputs_filtered ("'", stream); fputs_filtered ("'", stream);
LA_EMIT_CHAR (c, stream, '\''); LA_EMIT_CHAR (c, stream, '\'');
@ -160,7 +160,7 @@ f_printchar (c, stream)
static void static void
f_printstr (stream, string, length, width, force_ellipses) f_printstr (stream, string, length, width, force_ellipses)
FILE *stream; GDB_FILE *stream;
char *string; char *string;
unsigned int length; unsigned int length;
int width; int width;
@ -176,7 +176,7 @@ f_printstr (stream, string, length, width, force_ellipses)
if (length == 0) if (length == 0)
{ {
fputs_filtered ("''", stdout); fputs_filtered ("''", gdb_stdout);
return; return;
} }

View file

@ -40,17 +40,19 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include <errno.h> #include <errno.h>
#if 0 /* Currently unused */ #if 0 /* Currently unused */
static void f_type_print_args PARAMS ((struct type *, FILE *)); static void f_type_print_args PARAMS ((struct type *, GDB_FILE *));
#endif #endif
static void print_equivalent_f77_float_type PARAMS ((struct type *, FILE *)); static void print_equivalent_f77_float_type PARAMS ((struct type *,
GDB_FILE *));
static void f_type_print_varspec_suffix PARAMS ((struct type *, FILE *, static void f_type_print_varspec_suffix PARAMS ((struct type *, GDB_FILE *,
int, int, int)); int, int, int));
void f_type_print_varspec_prefix PARAMS ((struct type *, FILE *, int, int)); void f_type_print_varspec_prefix PARAMS ((struct type *, GDB_FILE *,
int, int));
void f_type_print_base PARAMS ((struct type *, FILE *, int, int)); void f_type_print_base PARAMS ((struct type *, GDB_FILE *, int, int));
/* LEVEL is the depth to indent lines by. */ /* LEVEL is the depth to indent lines by. */
@ -59,7 +61,7 @@ void
f_print_type (type, varstring, stream, show, level) f_print_type (type, varstring, stream, show, level)
struct type *type; struct type *type;
char *varstring; char *varstring;
FILE *stream; GDB_FILE *stream;
int show; int show;
int level; int level;
{ {
@ -102,7 +104,7 @@ f_print_type (type, varstring, stream, show, level)
void void
f_type_print_varspec_prefix (type, stream, show, passed_a_ptr) f_type_print_varspec_prefix (type, stream, show, passed_a_ptr)
struct type *type; struct type *type;
FILE *stream; GDB_FILE *stream;
int show; int show;
int passed_a_ptr; int passed_a_ptr;
{ {
@ -160,7 +162,7 @@ f_type_print_varspec_prefix (type, stream, show, passed_a_ptr)
static void static void
f_type_print_args (type, stream) f_type_print_args (type, stream)
struct type *type; struct type *type;
FILE *stream; GDB_FILE *stream;
{ {
int i; int i;
struct type **args; struct type **args;
@ -200,7 +202,7 @@ f_type_print_args (type, stream)
static void static void
f_type_print_varspec_suffix (type, stream, show, passed_a_ptr, demangled_args) f_type_print_varspec_suffix (type, stream, show, passed_a_ptr, demangled_args)
struct type *type; struct type *type;
FILE *stream; GDB_FILE *stream;
int show; int show;
int passed_a_ptr; int passed_a_ptr;
int demangled_args; int demangled_args;
@ -312,7 +314,7 @@ f_type_print_varspec_suffix (type, stream, show, passed_a_ptr, demangled_args)
static void static void
print_equivalent_f77_float_type (type, stream) print_equivalent_f77_float_type (type, stream)
struct type *type; struct type *type;
FILE *stream; GDB_FILE *stream;
{ {
/* Override type name "float" and make it the /* Override type name "float" and make it the
appropriate real. XLC stupidly outputs -12 as a type appropriate real. XLC stupidly outputs -12 as a type
@ -337,7 +339,7 @@ print_equivalent_f77_float_type (type, stream)
void void
f_type_print_base (type, stream, show, level) f_type_print_base (type, stream, show, level)
struct type *type; struct type *type;
FILE *stream; GDB_FILE *stream;
int show; int show;
int level; int level;
{ {

View file

@ -33,12 +33,67 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include <unistd.h> #include <unistd.h>
#endif #endif
extern char **environ; #define DEBUGGING 0
/* This just gets used as a default if we can't find SHELL */
#ifndef SHELL_FILE #ifndef SHELL_FILE
#define SHELL_FILE "/bin/sh" #define SHELL_FILE "/bin/sh"
#endif #endif
extern char **environ;
/* This function breaks up an argument string into an argument
* vector suitable for passing to execvp().
* E.g., on "run a b c d" this routine would get as input
* the string "a b c d", and as output it would fill in argv with
* the four arguments "a", "b", "c", "d".
*/
static void
breakup_args (
scratch,
argv)
char *scratch;
char **argv;
{
char *cp = scratch;
#if DEBUGGING
printf("breakup_args: input = %s\n", scratch);
#endif
for (;;) {
/* Scan past leading separators */
while (*cp == ' ' || *cp == '\t' || *cp == '\n') {
cp++;
}
/* Break if at end of string */
if (*cp == '\0') break;
/* Take an arg */
*argv++ = cp;
/* Scan for next arg separator */
cp = strchr (cp, ' ');
if (cp == NULL)
cp = strchr (cp, '\t');
if (cp == NULL)
cp = strchr (cp, '\n');
/* No separators => end of string => break */
if (cp == NULL)
break;
/* Replace the separator with a terminator */
*cp++ = '\0';
}
/* execv requires a null-terminated arg vector */
*argv = NULL;
}
/* Start an inferior Unix child process and sets inferior_pid to its pid. /* Start an inferior Unix child process and sets inferior_pid to its pid.
EXEC_FILE is the file to run. EXEC_FILE is the file to run.
ALLARGS is a string containing the arguments to the program. ALLARGS is a string containing the arguments to the program.
@ -47,12 +102,13 @@ extern char **environ;
void void
fork_inferior (exec_file, allargs, env, traceme_fun, init_trace_fun, fork_inferior (exec_file, allargs, env, traceme_fun, init_trace_fun,
shell_file) pre_trace_fun, shell_file)
char *exec_file; char *exec_file;
char *allargs; char *allargs;
char **env; char **env;
void (*traceme_fun) PARAMS ((void)); void (*traceme_fun) PARAMS ((void));
int (*init_trace_fun) PARAMS ((int)); void (*init_trace_fun) PARAMS ((int));
void (*pre_trace_fun) PARAMS ((void));
char *shell_file; char *shell_file;
{ {
int pid; int pid;
@ -65,22 +121,31 @@ fork_inferior (exec_file, allargs, env, traceme_fun, init_trace_fun,
to you in the parent process. It's only used by humans for debugging. */ to you in the parent process. It's only used by humans for debugging. */
static int debug_setpgrp = 657473; static int debug_setpgrp = 657473;
char **save_our_env; char **save_our_env;
int shell = 0;
char **argv;
char *tryname;
/* If no exec file handed to us, get it from the exec-file command -- with /* If no exec file handed to us, get it from the exec-file command -- with
a good, common error message if none is specified. */ a good, common error message if none is specified. */
if (exec_file == 0) if (exec_file == 0)
exec_file = get_exec_file(1); exec_file = get_exec_file(1);
/* The user might want tilde-expansion, and in general probably wants /* STARTUP_WITH_SHELL is defined in inferior.h.
the program to behave the same way as if run from * If 0, we'll just do a fork/exec, no shell, so don't
his/her favorite shell. So we let the shell run it for us. * bother figuring out what shell.
FIXME-maybe, we might want a "set shell" command so the user can change */
the shell from within GDB (if so, change callers which pass in a non-NULL if (STARTUP_WITH_SHELL) {
shell_file too). */ /* Figure out what shell to start up the user program under. */
if (shell_file == NULL) if (shell_file == NULL)
shell_file = getenv ("SHELL"); shell_file = getenv ("SHELL");
if (shell_file == NULL) if (shell_file == NULL)
shell_file = default_shell_file; shell_file = default_shell_file;
shell = 1;
}
#if DEBUGGING
printf("shell is %s\n", shell_file);
#endif
/* Multiplying the length of exec_file by 4 is to account for the fact /* Multiplying the length of exec_file by 4 is to account for the fact
that it may expand when quoted; it is a worst-case number based on that it may expand when quoted; it is a worst-case number based on
@ -95,20 +160,40 @@ fork_inferior (exec_file, allargs, env, traceme_fun, init_trace_fun,
shell_command = (char *) alloca (len); shell_command = (char *) alloca (len);
shell_command[0] = '\0'; shell_command[0] = '\0';
#endif #endif
strcat (shell_command, "exec ");
/* Now add exec_file, quoting as necessary. */ if (!shell) {
{ /* We're going to call execvp. Create argv */
/* Largest case: every other character is a separate arg */
#if DEBUGGING
printf("allocating argv, length = %d\n",
(
(strlen (allargs) + 1) / (unsigned) 2
+ 2
) * sizeof (*argv)
);
#endif
argv = (char **) xmalloc(((strlen (allargs) + 1) / (unsigned) 2 + 2) * sizeof (*argv));
argv[0] = exec_file;
breakup_args(allargs, &argv[1]);
} else {
/* We're going to call a shell */
/* Now add exec_file, quoting as necessary. */
char *p; char *p;
int need_to_quote; int need_to_quote;
strcat (shell_command, "exec ");
/* Quoting in this style is said to work with all shells. But csh /* Quoting in this style is said to work with all shells. But csh
on IRIX 4.0.1 can't deal with it. So we only quote it if we need on IRIX 4.0.1 can't deal with it. So we only quote it if we need
to. */ to. */
p = exec_file; p = exec_file;
while (1) while (1)
{ {
switch (*p) switch (*p)
{ {
case '\'': case '\'':
case '"': case '"':
@ -137,8 +222,8 @@ fork_inferior (exec_file, allargs, env, traceme_fun, init_trace_fun,
end_scan: end_scan:
if (need_to_quote) if (need_to_quote)
{ {
strcat (shell_command, "'"); strcat (shell_command, "'");
for (p = exec_file; *p != '\0'; ++p) for (p = exec_file; *p != '\0'; ++p)
{ {
if (*p == '\'') if (*p == '\'')
strcat (shell_command, "'\\''"); strcat (shell_command, "'\\''");
@ -149,10 +234,11 @@ fork_inferior (exec_file, allargs, env, traceme_fun, init_trace_fun,
} }
else else
strcat (shell_command, exec_file); strcat (shell_command, exec_file);
}
strcat (shell_command, " ");
strcat (shell_command, allargs);
strcat (shell_command, " "); }
strcat (shell_command, allargs);
/* exec is said to fail if the executable is open. */ /* exec is said to fail if the executable is open. */
close_exec_file (); close_exec_file ();
@ -174,6 +260,12 @@ fork_inferior (exec_file, allargs, env, traceme_fun, init_trace_fun,
gdb_flush (gdb_stdout); gdb_flush (gdb_stdout);
gdb_flush (gdb_stderr); gdb_flush (gdb_stderr);
/* If there's any initialization of the target layers that must happen
to prepare to handle the child we're about fork, do it now...
*/
if (pre_trace_fun != NULL)
(*pre_trace_fun) ();
#if defined(USG) && !defined(HAVE_VFORK) #if defined(USG) && !defined(HAVE_VFORK)
pid = fork (); pid = fork ();
#else #else
@ -209,6 +301,14 @@ fork_inferior (exec_file, allargs, env, traceme_fun, init_trace_fun,
/* "Trace me, Dr. Memory!" */ /* "Trace me, Dr. Memory!" */
(*traceme_fun) (); (*traceme_fun) ();
/* The call above set this process (the "child") as debuggable
* by the original gdb process (the "parent"). Since processes
* (unlike people) can have only one parent, if you are
* debugging gdb itself (and your debugger is thus _already_ the
* controller/parent for this child), code from here on out
* is undebuggable. Indeed, you probably got an error message
* saying "not parent". Sorry--you'll have to use print statements!
*/
/* There is no execlpe call, so we have to set the environment /* There is no execlpe call, so we have to set the environment
for our child in the global variable. If we've vforked, this for our child in the global variable. If we've vforked, this
@ -216,12 +316,65 @@ fork_inferior (exec_file, allargs, env, traceme_fun, init_trace_fun,
in the parent. By the way, yes we do need to look down the in the parent. By the way, yes we do need to look down the
path to find $SHELL. Rich Pixley says so, and I agree. */ path to find $SHELL. Rich Pixley says so, and I agree. */
environ = env; environ = env;
execlp (shell_file, shell_file, "-c", shell_command, (char *)0);
fprintf_unfiltered (gdb_stderr, "Cannot exec %s: %s.\n", shell_file, /* If we decided above to start up with a shell,
safe_strerror (errno)); * we exec the shell,
gdb_flush (gdb_stderr); * "-c" says to interpret the next arg as a shell command
_exit (0177); * to execute, and this command is "exec <target-program> <args>".
* "-f" means "fast startup" to the c-shell, which means
* don't do .cshrc file. Doing .cshrc may cause fork/exec
* events which will confuse debugger start-up code.
*/
if (shell) {
#if 0
/* HP change is problematic. The -f option has different meanings
for different shells. It is particularly inappropriate for
bourne shells. */
execlp (shell_file, shell_file, "-f", "-c", shell_command, (char *)0);
#else
execlp (shell_file, shell_file, "-c", shell_command, (char *)0);
#endif
/* If we get here, it's an error */
fprintf_unfiltered (gdb_stderr, "Cannot exec %s: %s.\n", shell_file,
safe_strerror (errno));
gdb_flush (gdb_stderr);
_exit (0177);
} else {
/* Otherwise, we directly exec the target program with execvp. */
int i;
char * errstring;
#if DEBUGGING
printf("about to exec target, exec_file = %s\n", exec_file);
i = 0;
while (argv[i] != NULL) {
printf("strlen(argv[%d]) is %d\n", i, strlen(argv[i]));
printf("argv[%d] is %s\n", i, argv[i]);
i++;
}
#endif
execvp (exec_file, argv);
/* If we get here, it's an error */
errstring = safe_strerror (errno);
fprintf_unfiltered (gdb_stderr, "Cannot exec %s ", exec_file);
i = 1;
while (argv[i] != NULL) {
if (i != 1)
fprintf_unfiltered (gdb_stderr, " ");
fprintf_unfiltered (gdb_stderr, "%s", argv[i]);
i++;
}
fprintf_unfiltered (gdb_stderr, ".\n");
/* This extra info seems to be useless
fprintf_unfiltered (gdb_stderr, "Got error %s.\n", errstring);
*/
gdb_flush (gdb_stderr);
_exit (0177);
}
} }
/* Restore our environment in case a vforked child clob'd it. */ /* Restore our environment in case a vforked child clob'd it. */
@ -234,8 +387,7 @@ fork_inferior (exec_file, allargs, env, traceme_fun, init_trace_fun,
/* Now that we have a child process, make it our target, and /* Now that we have a child process, make it our target, and
initialize anything target-vector-specific that needs initializing. */ initialize anything target-vector-specific that needs initializing. */
/* Note that pid may be modified by this function. */ (*init_trace_fun)(pid);
inferior_pid = pid = (*init_trace_fun)(pid);
/* We are now in the child process of interest, having exec'd the /* We are now in the child process of interest, having exec'd the
correct program, and are poised at the first instruction of the correct program, and are poised at the first instruction of the
@ -251,6 +403,137 @@ fork_inferior (exec_file, allargs, env, traceme_fun, init_trace_fun,
#endif #endif
} }
/* An inferior Unix process CHILD_PID has been created by a call to
fork() (or variants like vfork). It is presently stopped, and waiting
to be resumed. clone_and_follow_inferior will fork the debugger,
and that clone will "follow" (attach to) CHILD_PID. The original copy
of the debugger will not touch CHILD_PID again.
Also, the original debugger will set FOLLOWED_CHILD FALSE, while the
clone will set it TRUE.
*/
void
clone_and_follow_inferior (child_pid, followed_child)
int child_pid;
int *followed_child;
{
extern int auto_solib_add;
int debugger_pid;
int status;
char pid_spelling [100]; /* Arbitrary but sufficient length. */
/* This semaphore is used to coordinate the two debuggers' handoff
of CHILD_PID. The original debugger will detach from CHILD_PID,
and then the clone debugger will attach to it. (It must be done
this way because on some targets, only one process at a time can
trace another. Thus, the original debugger must relinquish its
tracing rights before the clone can pick them up.)
*/
#define SEM_TALK (1)
#define SEM_LISTEN (0)
int handoff_semaphore[2]; /* Original "talks" to [1], clone "listens" to [0] */
int talk_value = 99;
int listen_value;
/* Set debug_fork then attach to the child while it sleeps, to debug. */
static int debug_fork = 0;
/* It is generally good practice to flush any possible pending stdio
output prior to doing a fork, to avoid the possibility of both the
parent and child flushing the same data after the fork. */
gdb_flush (gdb_stdout);
gdb_flush (gdb_stderr);
/* Open the semaphore pipes.
*/
status = pipe (handoff_semaphore);
if (status < 0)
error ("error getting pipe for handoff semaphore");
/* Clone the debugger. */
#if defined(USG) && !defined(HAVE_VFORK)
debugger_pid = fork ();
#else
if (debug_fork)
debugger_pid = fork ();
else
debugger_pid = vfork ();
#endif
if (debugger_pid < 0)
perror_with_name ("fork");
/* Are we the original debugger? If so, we must relinquish all claims
to CHILD_PID. */
if (debugger_pid != 0)
{
char signal_spelling[100]; /* Arbitrary but sufficient length */
/* Detach from CHILD_PID. Deliver a "stop" signal when we do, though,
so that it remains stopped until the clone debugger can attach
to it.
*/
detach_breakpoints (child_pid);
sprintf (signal_spelling, "%d", target_signal_to_host (TARGET_SIGNAL_STOP));
target_require_detach (child_pid, signal_spelling, 1);
/* Notify the clone debugger that it should attach to CHILD_PID. */
write (handoff_semaphore[SEM_TALK], &talk_value, sizeof (talk_value));
*followed_child = 0;
}
/* We're the child. */
else
{
if (debug_fork)
sleep (debug_fork);
/* The child (i.e., the cloned debugger) must now attach to
CHILD_PID. inferior_pid is presently set to the parent process
of the fork, while CHILD_PID should be the child process of the
fork.
Wait until the original debugger relinquishes control of CHILD_PID,
though.
*/
read (handoff_semaphore[SEM_LISTEN], &listen_value, sizeof (listen_value));
/* Note that we DON'T want to actually detach from inferior_pid,
because that would allow it to run free. The original
debugger wants to retain control of the process. So, we
just reset inferior_pid to CHILD_PID, and then ensure that all
breakpoints are really set in CHILD_PID.
*/
target_mourn_inferior ();
/* Ask the tty subsystem to switch to the one we specified earlier
(or to share the current terminal, if none was specified). */
new_tty ();
dont_repeat ();
sprintf(pid_spelling, "%d", child_pid);
target_require_attach (pid_spelling, 1);
/* Perform any necessary cleanup, after attachment. (This form
of attaching can behave differently on some targets than the
standard method, where a process formerly not under debugger
control was suddenly attached to..)
*/
target_post_follow_inferior_by_clone ();
*followed_child = 1;
}
/* Discard the handoff sempahore. */
(void) close (handoff_semaphore[SEM_LISTEN]);
(void) close (handoff_semaphore[SEM_TALK]);
}
/* Accept NTRAPS traps from the inferior. */ /* Accept NTRAPS traps from the inferior. */
void void
@ -270,6 +553,13 @@ startup_inferior (ntraps)
terminal_initted = 0; terminal_initted = 0;
if (STARTUP_WITH_SHELL)
inferior_ignoring_startup_exec_events = ntraps;
else
inferior_ignoring_startup_exec_events = 0;
inferior_ignoring_leading_exec_events =
target_reported_exec_events_per_exec_call () - 1;
#ifdef STARTUP_INFERIOR #ifdef STARTUP_INFERIOR
STARTUP_INFERIOR (pending_execs); STARTUP_INFERIOR (pending_execs);
#else #else
@ -301,9 +591,12 @@ startup_inferior (ntraps)
terminal_initted = 1; terminal_initted = 1;
} }
if (0 == --pending_execs)
pending_execs = pending_execs - 1;
if (0 == pending_execs)
break; break;
resume (0, TARGET_SIGNAL_0); /* Just make it go on */
resume (0, TARGET_SIGNAL_0); /* Just make it go on */
} }
} }
#endif /* STARTUP_INFERIOR */ #endif /* STARTUP_INFERIOR */

View file

@ -23,6 +23,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifndef GDBTHREAD_H #ifndef GDBTHREAD_H
#define GDBTHREAD_H #define GDBTHREAD_H
/* For bpstat */
#include "breakpoint.h"
extern void init_thread_list PARAMS ((void)); extern void init_thread_list PARAMS ((void));
extern void add_thread PARAMS ((int pid)); extern void add_thread PARAMS ((int pid));
@ -40,12 +43,14 @@ extern int valid_thread_id PARAMS ((int thread));
extern void load_infrun_state PARAMS ((int, CORE_ADDR *, CORE_ADDR *, char **, extern void load_infrun_state PARAMS ((int, CORE_ADDR *, CORE_ADDR *, char **,
int *, struct breakpoint **, int *, struct breakpoint **,
struct breakpoint **, CORE_ADDR *, struct breakpoint **, CORE_ADDR *,
CORE_ADDR *, CORE_ADDR *, int *, int *)); CORE_ADDR *, CORE_ADDR *, int *, int *,
int *, bpstat *, int *));
extern void save_infrun_state PARAMS ((int, CORE_ADDR, CORE_ADDR, char *, extern void save_infrun_state PARAMS ((int, CORE_ADDR, CORE_ADDR, char *,
int, struct breakpoint *, int, struct breakpoint *,
struct breakpoint *, CORE_ADDR, struct breakpoint *, CORE_ADDR,
CORE_ADDR, CORE_ADDR, int, int)); CORE_ADDR, CORE_ADDR, int, int,
int, bpstat, int));
/* Commands with a prefix of `thread'. */ /* Commands with a prefix of `thread'. */
extern struct cmd_list_element *thread_cmd_list; extern struct cmd_list_element *thread_cmd_list;

View file

@ -106,7 +106,7 @@ gdbtk_readline_begin (char *format, ...);
gdbtk_readline_begin (); gdbtk_readline_begin ();
#endif #endif
static void gdbtk_readline_end PARAMS ((void)); static void gdbtk_readline_end PARAMS ((void));
static void gdbtk_flush PARAMS ((FILE *)); static void gdbtk_flush PARAMS ((GDB_FILE *));
static void gdbtk_pre_add_symbol PARAMS ((char *)); static void gdbtk_pre_add_symbol PARAMS ((char *));
static void gdbtk_print_frame_info PARAMS ((struct symtab *, int, int, int)); static void gdbtk_print_frame_info PARAMS ((struct symtab *, int, int, int));
static void gdbtk_post_add_symbol PARAMS ((void)); static void gdbtk_post_add_symbol PARAMS ((void));
@ -120,7 +120,7 @@ static void gdbtk_context_change PARAMS ((int));
* See note there for details. * See note there for details.
*/ */
void gdbtk_fputs PARAMS ((const char *, FILE *)); void gdbtk_fputs PARAMS ((const char *, GDB_FILE *));
int gdbtk_load_hash PARAMS ((char *, unsigned long)); int gdbtk_load_hash PARAMS ((char *, unsigned long));
static void breakpoint_notify PARAMS ((struct breakpoint *, const char *)); static void breakpoint_notify PARAMS ((struct breakpoint *, const char *));
@ -214,7 +214,7 @@ int gdbtk_two_elem_cmd (cmd_name, argv1)
static void static void
gdbtk_flush (stream) gdbtk_flush (stream)
FILE *stream; GDB_FILE *stream;
{ {
#if 0 #if 0
/* Force immediate screen update */ /* Force immediate screen update */
@ -238,7 +238,7 @@ gdbtk_flush (stream)
* We place the data into the result_ptr, either as a string, * We place the data into the result_ptr, either as a string,
* or a list, depending whether the GDBTK_MAKES_LIST bit is set. * or a list, depending whether the GDBTK_MAKES_LIST bit is set.
* 3) The GDBTK_TO_RESULT flag is unset - We route the data to gdbtk_tcl_fputs * 3) The GDBTK_TO_RESULT flag is unset - We route the data to gdbtk_tcl_fputs
* UNLESS it was coming to stderr. Then we place it in the result_ptr * UNLESS it was coming to gdb_stderr. Then we place it in the result_ptr
* anyway, so it can be dealt with. * anyway, so it can be dealt with.
* *
*/ */
@ -246,7 +246,7 @@ gdbtk_flush (stream)
void void
gdbtk_fputs (ptr, stream) gdbtk_fputs (ptr, stream)
const char *ptr; const char *ptr;
FILE *stream; GDB_FILE *stream;
{ {
in_fputs = 1; in_fputs = 1;
@ -329,7 +329,7 @@ pc_changed()
static void static void
tk_command_loop () tk_command_loop ()
{ {
extern GDB_FILE *instream; extern FILE *instream;
/* We no longer want to use stdin as the command input stream */ /* We no longer want to use stdin as the command input stream */
instream = NULL; instream = NULL;

View file

@ -99,7 +99,7 @@ int gdbtk_test PARAMS ((char *));
* way errors will go to stdout. * way errors will go to stdout.
*/ */
extern void gdbtk_fputs PARAMS ((const char *, FILE *)); extern void gdbtk_fputs PARAMS ((const char *, GDB_FILE *));
/* Handle for TCL interpreter */ /* Handle for TCL interpreter */
Tcl_Interp *gdbtk_interp = NULL; Tcl_Interp *gdbtk_interp = NULL;
@ -569,14 +569,17 @@ gdbtk_find_main";
fputs_unfiltered_hook = NULL; /* Force errors to stdout/stderr */ fputs_unfiltered_hook = NULL; /* Force errors to stdout/stderr */
if (getenv("GDBTK_LIBRARY")) if (getenv("GDBTK_LIBRARY"))
{ {
fprintf_unfiltered (stderr, "Unable to find main.tcl in %s\n",getenv("GDBTK_LIBRARY")); fprintf_unfiltered (gdb_stderr, "Unable to find main.tcl in %s\n",
fprintf_unfiltered (stderr, getenv("GDBTK_LIBRARY"));
fprintf_unfiltered (gdb_stderr,
"Please set GDBTK_LIBRARY to a path that includes the GDB tcl files.\n"); "Please set GDBTK_LIBRARY to a path that includes the GDB tcl files.\n");
} }
else else
{ {
fprintf_unfiltered (stderr, "Unable to find main.tcl in %s\n", GDBTK_LIBRARY); fprintf_unfiltered (gdb_stderr,
fprintf_unfiltered (stderr, "You might want to set GDBTK_LIBRARY\n"); "Unable to find main.tcl in %s\n", GDBTK_LIBRARY);
fprintf_unfiltered (gdb_stderr,
"You might want to set GDBTK_LIBRARY\n");
} }
error(""); error("");
} }

View file

@ -1936,7 +1936,7 @@ gnu_create_inferior (exec_file, allargs, env)
inf_debug (inf, "creating inferior"); inf_debug (inf, "creating inferior");
fork_inferior (exec_file, allargs, env, trace_me, attach_to_child, NULL); fork_inferior (exec_file, allargs, env, trace_me, attach_to_child, NULL, NULL);
inf_update_signal_thread (inf); inf_update_signal_thread (inf);
inf_set_traced (inf, inf->want_signals); inf_set_traced (inf, inf->want_signals);

2425
gdb/hp-psymtab-read.c Normal file

File diff suppressed because it is too large Load diff

3988
gdb/hp-symtab-read.c Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,5 @@
/* Machine-dependent hooks for the unix child process stratum, for HPUX PA-RISC. /* Native support code for HPUX PA-RISC.
Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1998
Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993
Free Software Foundation, Inc. Free Software Foundation, Inc.
Contributed by the Center for Software Science at the Contributed by the Center for Software Science at the
@ -28,6 +27,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "target.h" #include "target.h"
#include <sys/ptrace.h> #include <sys/ptrace.h>
#include "gdbcore.h" #include "gdbcore.h"
#include <wait.h>
extern CORE_ADDR text_end; extern CORE_ADDR text_end;
@ -128,7 +128,8 @@ fetch_register (regno)
if (errno != 0) if (errno != 0)
{ {
/* Warning, not error, in case we are attached; sometimes the /* Warning, not error, in case we are attached; sometimes the
kernel doesn't let us at the registers. */ * kernel doesn't let us at the registers.
*/
char *err = safe_strerror (errno); char *err = safe_strerror (errno);
char *msg = alloca (strlen (err) + 128); char *msg = alloca (strlen (err) + 128);
sprintf (msg, "reading register %s: %s", REGISTER_NAME (regno), err); sprintf (msg, "reading register %s: %s", REGISTER_NAME (regno), err);
@ -165,8 +166,19 @@ child_xfer_memory (memaddr, myaddr, len, write, target)
/* Round ending address up; get number of longwords that makes. */ /* Round ending address up; get number of longwords that makes. */
register int count register int count
= (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int); = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
/* Allocate buffer of that many longwords. */ /* Allocate buffer of that many longwords. */
register int *buffer = (int *) alloca (count * sizeof (int)); /* Note (RT) - This code formerly used alloca, which I have
* replaced with xmalloc and a matching free() at the end.
* The problem with alloca() is that there is no guarantee of
* when it'll be freed, and we were seeing cases of memory
* leaks on:
* (gdb) watch x
* (gdb) cont
* where the piled-up alloca's for the child_xfer_memory buffers
* were not getting freed.
*/
register int *buffer = (int *) xmalloc (count * sizeof (int));
if (write) if (write)
{ {
@ -194,16 +206,38 @@ child_xfer_memory (memaddr, myaddr, len, write, target)
for (i = 0; i < count; i++, addr += sizeof (int)) for (i = 0; i < count; i++, addr += sizeof (int))
{ {
/* The HP-UX kernel crashes if you use PT_WDUSER to write into the text int pt_status;
segment. FIXME -- does it work to write into the data segment using int pt_request;
WIUSER, or do these idiots really expect us to figure out which segment /* The HP-UX kernel crashes if you use PT_WDUSER to write into the text
the address is in, so we can use a separate system call for it??! */ segment. FIXME -- does it work to write into the data segment using
WIUSER, or do these idiots really expect us to figure out which segment
the address is in, so we can use a separate system call for it??! */
errno = 0; errno = 0;
call_ptrace (addr < text_end ? PT_WIUSER : PT_WDUSER, inferior_pid, pt_request = (addr < text_end) ? PT_WIUSER : PT_WDUSER;
(PTRACE_ARG3_TYPE) addr, pt_status = call_ptrace (pt_request,
buffer[i]); inferior_pid,
if (errno) (PTRACE_ARG3_TYPE) addr,
return 0; buffer[i]);
/* Did we fail? Might we've guessed wrong about which
segment this address resides in? Try the other request,
and see if that works...
*/
if ((pt_status == -1) && errno) {
errno = 0;
pt_request = (pt_request == PT_WIUSER) ? PT_WDUSER : PT_WIUSER;
pt_status = call_ptrace (pt_request,
inferior_pid,
(PTRACE_ARG3_TYPE) addr,
buffer[i]);
/* No, we still fail. Okay, time to punt. */
if ((pt_status == -1) && errno)
{
free(buffer);
return 0;
}
}
} }
} }
else else
@ -214,13 +248,848 @@ child_xfer_memory (memaddr, myaddr, len, write, target)
errno = 0; errno = 0;
buffer[i] = call_ptrace (addr < text_end ? PT_RIUSER : PT_RDUSER, buffer[i] = call_ptrace (addr < text_end ? PT_RIUSER : PT_RDUSER,
inferior_pid, (PTRACE_ARG3_TYPE) addr, 0); inferior_pid, (PTRACE_ARG3_TYPE) addr, 0);
if (errno) if (errno) {
free(buffer);
return 0; return 0;
}
QUIT; QUIT;
} }
/* Copy appropriate bytes out of the buffer. */ /* Copy appropriate bytes out of the buffer. */
memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len); memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
} }
free(buffer);
return len; return len;
} }
void
child_post_follow_inferior_by_clone ()
{
int status;
/* This function is used when following both the parent and child
of a fork. In this case, the debugger clones itself. The original
debugger follows the parent, the clone follows the child. The
original detaches from the child, delivering a SIGSTOP to it to
keep it from running away until the clone can attach itself.
At this point, the clone has attached to the child. Because of
the SIGSTOP, we must now deliver a SIGCONT to the child, or it
won't behave properly. */
status = kill (inferior_pid, SIGCONT);
}
void
child_post_follow_vfork (parent_pid, followed_parent, child_pid, followed_child)
int parent_pid;
int followed_parent;
int child_pid;
int followed_child;
{
/* Are we a debugger that followed the parent of a vfork? If so,
then recall that the child's vfork event was delivered to us
first. And, that the parent was suspended by the OS until the
child's exec or exit events were received.
Upon receiving that child vfork, then, we were forced to remove
all breakpoints in the child and continue it so that it could
reach the exec or exit point.
But also recall that the parent and child of a vfork share the
same address space. Thus, removing bp's in the child also
removed them from the parent.
Now that the child has safely exec'd or exited, we must restore
the parent's breakpoints before we continue it. Else, we may
cause it run past expected stopping points. */
if (followed_parent)
{
reattach_breakpoints (parent_pid);
}
/* Are we a debugger that followed the child of a vfork? If so,
then recall that we don't actually acquire control of the child
until after it has exec'd or exited.
*/
if (followed_child)
{
/* If the child has exited, then there's nothing for us to do.
In the case of an exec event, we'll let that be handled by
the normal mechanism that notices and handles exec events, in
resume(). */
}
}
/* Format a process id, given a pid. Be sure to terminate
* this with a null--it's going to be printed via a "%s".
*/
char *
hppa_pid_to_str( pid )
pid_t pid;
{
static char buf[30]; /* Static because address returned */
sprintf( buf, "process %d\0\0\0\0", pid );
/* Extra NULLs for paranoia's sake */
return buf;
}
/* Format a thread id, given a tid. Be sure to terminate
* this with a null--it's going to be printed via a "%s".
*
* Note: This is a core-gdb tid, not the actual system tid.
* See infttrace.c for details.
*/
char *
hppa_tid_to_str( tid )
pid_t tid;
{
static char buf[30]; /* Static because address returned */
sprintf( buf, "system thread %d\0\0\0\0", tid );
/* Extra NULLs for paranoia's sake */
return buf;
}
#if !defined (GDB_NATIVE_HPUX_11)
/* The following code is a substitute for the infttrace.c versions used
with ttrace() in HPUX 11. */
/* This value is an arbitrary integer. */
#define PT_VERSION 123456
/* This semaphore is used to coordinate the child and parent processes
after a fork(), and before an exec() by the child. See
parent_attach_all for details. */
typedef struct {
int parent_channel[2]; /* Parent "talks" to [1], child "listens" to [0] */
int child_channel[2]; /* Child "talks" to [1], parent "listens" to [0] */
} startup_semaphore_t;
#define SEM_TALK (1)
#define SEM_LISTEN (0)
static startup_semaphore_t startup_semaphore;
extern int parent_attach_all PARAMS ((int, PTRACE_ARG3_TYPE, int));
#ifdef PT_SETTRC
/* This function causes the caller's process to be traced by its
parent. This is intended to be called after GDB forks itself,
and before the child execs the target.
Note that HP-UX ptrace is rather funky in how this is done.
If the parent wants to get the initial exec event of a child,
it must set the ptrace event mask of the child to include execs.
(The child cannot do this itself.) This must be done after the
child is forked, but before it execs.
To coordinate the parent and child, we implement a semaphore using
pipes. After SETTRC'ing itself, the child tells the parent that
it is now traceable by the parent, and waits for the parent's
acknowledgement. The parent can then set the child's event mask,
and notify the child that it can now exec.
(The acknowledgement by parent happens as a result of a call to
child_acknowledge_created_inferior.) */
int
parent_attach_all (pid, addr, data)
int pid;
PTRACE_ARG3_TYPE addr;
int data;
{
int pt_status = 0;
/* We need a memory home for a constant. */
int tc_magic_child = PT_VERSION;
int tc_magic_parent = 0;
/* The remainder of this function is only useful for HPUX 10.0 and
later, as it depends upon the ability to request notification
of specific kinds of events by the kernel. */
#if defined(PT_SET_EVENT_MASK)
/* Notify the parent that we're potentially ready to exec(). */
write (startup_semaphore.child_channel[SEM_TALK],
&tc_magic_child,
sizeof (tc_magic_child));
/* Wait for acknowledgement from the parent. */
read (startup_semaphore.parent_channel[SEM_LISTEN],
&tc_magic_parent,
sizeof (tc_magic_parent));
if (tc_magic_child != tc_magic_parent)
warning ("mismatched semaphore magic");
/* Discard our copy of the semaphore. */
(void) close (startup_semaphore.parent_channel[SEM_LISTEN]);
(void) close (startup_semaphore.parent_channel[SEM_TALK]);
(void) close (startup_semaphore.child_channel[SEM_LISTEN]);
(void) close (startup_semaphore.child_channel[SEM_TALK]);
#endif
return 0;
}
#endif
int
hppa_require_attach (pid)
int pid;
{
int pt_status;
CORE_ADDR pc;
CORE_ADDR pc_addr;
unsigned int regs_offset;
/* Are we already attached? There appears to be no explicit way to
answer this via ptrace, so we try something which should be
innocuous if we are attached. If that fails, then we assume
we're not attached, and so attempt to make it so. */
errno = 0;
regs_offset = U_REGS_OFFSET;
pc_addr = register_addr (PC_REGNUM, regs_offset);
pc = call_ptrace (PT_READ_U, pid, (PTRACE_ARG3_TYPE) pc_addr, 0);
if (errno)
{
errno = 0;
pt_status = call_ptrace (PT_ATTACH, pid, (PTRACE_ARG3_TYPE) 0, 0);
if (errno)
return -1;
/* Now we really are attached. */
errno = 0;
}
attach_flag = 1;
return pid;
}
int
hppa_require_detach (pid, signal)
int pid;
int signal;
{
errno = 0;
call_ptrace (PT_DETACH, pid, (PTRACE_ARG3_TYPE) 1, signal);
errno = 0; /* Ignore any errors. */
return pid;
}
/* Since ptrace doesn't support memory page-protection events, which
are used to implement "hardware" watchpoints on HP-UX, these are
dummy versions, which perform no useful work. */
void
hppa_enable_page_protection_events (pid)
int pid;
{
}
void
hppa_disable_page_protection_events (pid)
int pid;
{
}
int
hppa_insert_hw_watchpoint (pid, start, len, type)
int pid;
CORE_ADDR start;
LONGEST len;
int type;
{
error ("Hardware watchpoints not implemented on this platform.");
}
int
hppa_remove_hw_watchpoint (pid, start, len, type)
int pid;
CORE_ADDR start;
LONGEST len;
enum bptype type;
{
error ("Hardware watchpoints not implemented on this platform.");
}
int
hppa_can_use_hw_watchpoint (type, cnt, ot)
enum bptype type;
int cnt;
enum bptype ot;
{
return 0;
}
int
hppa_range_profitable_for_hw_watchpoint (pid, start, len)
int pid;
CORE_ADDR start;
LONGEST len;
{
error ("Hardware watchpoints not implemented on this platform.");
}
char *
hppa_pid_or_tid_to_str (id)
pid_t id;
{
/* In the ptrace world, there are only processes. */
return hppa_pid_to_str (id);
}
/* This function has no meaning in a non-threaded world. Thus, we
return 0 (FALSE). See the use of "hppa_prepare_to_proceed" in
hppa-tdep.c. */
pid_t
hppa_switched_threads (pid)
pid_t pid;
{
return (pid_t) 0;
}
void
hppa_ensure_vforking_parent_remains_stopped (pid)
int pid;
{
/* This assumes that the vforked parent is presently stopped, and
that the vforked child has just delivered its first exec event.
Calling kill() this way will cause the SIGTRAP to be delivered as
soon as the parent is resumed, which happens as soon as the
vforked child is resumed. See wait_for_inferior for the use of
this function. */
kill (pid, SIGTRAP);
}
int
hppa_resume_execd_vforking_child_to_get_parent_vfork ()
{
return 1; /* Yes, the child must be resumed. */
}
#if defined(HPPA_GET_PROCESS_EVENTS)
process_event_vector
hppa_get_process_events (pid, wait_status, must_continue_pid_after)
int pid;
int wait_status;
int * must_continue_pid_after;
{
int pt_status;
ptrace_state_t ptrace_state;
process_event_vector events = PEVT_NONE;
/* This is always TRUE with ptrace. */
*must_continue_pid_after = 1;
errno = 0;
pt_status = call_ptrace (PT_GET_PROCESS_STATE,
pid,
(PTRACE_ARG3_TYPE) &ptrace_state,
sizeof (ptrace_state));
if (errno)
perror_with_name ("ptrace");
if (pt_status < 0)
return events;
if (ptrace_state.pe_report_event & PTRACE_SIGNAL)
events |= PEVT_SIGNAL;
if (ptrace_state.pe_report_event & PTRACE_FORK)
events |= PEVT_FORK;
if (ptrace_state.pe_report_event & PTRACE_VFORK)
events |= PEVT_VFORK;
if (ptrace_state.pe_report_event & PTRACE_EXEC)
events |= PEVT_EXEC;
if (ptrace_state.pe_report_event & PTRACE_EXIT)
events |= PEVT_EXIT;
return events;
}
#endif /* HPPA_GET_PROCESS_EVENTS */
void
require_notification_of_events (pid)
int pid;
{
#if defined(PT_SET_EVENT_MASK)
int pt_status;
ptrace_event_t ptrace_events;
/* Instruct the kernel as to the set of events we wish to be
informed of. (This support does not exist before HPUX 10.0.
We'll assume if PT_SET_EVENT_MASK has not been defined by
<sys/ptrace.h>, then we're being built on pre-10.0.)
*/
memset (&ptrace_events, 0, sizeof (ptrace_events));
/* Note: By default, all signals are visible to us. If we wish
the kernel to keep certain signals hidden from us, we do it
by calling sigdelset (ptrace_events.pe_signals, signal) for
each such signal here, before doing PT_SET_EVENT_MASK.
*/
sigemptyset (&ptrace_events.pe_signals);
ptrace_events.pe_set_event = 0;
ptrace_events.pe_set_event |= PTRACE_SIGNAL;
ptrace_events.pe_set_event |= PTRACE_EXEC;
ptrace_events.pe_set_event |= PTRACE_FORK;
ptrace_events.pe_set_event |= PTRACE_VFORK;
/* ??rehrauer: Add this one when we're prepared to catch it...
ptrace_events.pe_set_event |= PTRACE_EXIT;
*/
errno = 0;
pt_status = call_ptrace (PT_SET_EVENT_MASK,
pid,
(PTRACE_ARG3_TYPE) &ptrace_events,
sizeof (ptrace_events));
if (errno)
perror_with_name ("ptrace");
if (pt_status < 0)
return;
#endif
}
void
require_notification_of_exec_events (pid)
int pid;
{
#if defined(PT_SET_EVENT_MASK)
int pt_status;
ptrace_event_t ptrace_events;
/* Instruct the kernel as to the set of events we wish to be
informed of. (This support does not exist before HPUX 10.0.
We'll assume if PT_SET_EVENT_MASK has not been defined by
<sys/ptrace.h>, then we're being built on pre-10.0.)
*/
memset (&ptrace_events, 0, sizeof (ptrace_events));
/* Note: By default, all signals are visible to us. If we wish
the kernel to keep certain signals hidden from us, we do it
by calling sigdelset (ptrace_events.pe_signals, signal) for
each such signal here, before doing PT_SET_EVENT_MASK.
*/
sigemptyset (&ptrace_events.pe_signals);
ptrace_events.pe_set_event = 0;
ptrace_events.pe_set_event |= PTRACE_EXEC;
/* ??rehrauer: Add this one when we're prepared to catch it...
ptrace_events.pe_set_event |= PTRACE_EXIT;
*/
errno = 0;
pt_status = call_ptrace (PT_SET_EVENT_MASK,
pid,
(PTRACE_ARG3_TYPE) &ptrace_events,
sizeof (ptrace_events));
if (errno)
perror_with_name ("ptrace");
if (pt_status < 0)
return;
#endif
}
/* This function is called by the parent process, with pid being the
ID of the child process, after the debugger has forked. */
void
child_acknowledge_created_inferior (pid)
int pid;
{
/* We need a memory home for a constant. */
int tc_magic_parent = PT_VERSION;
int tc_magic_child = 0;
/* Wait for the child to tell us that it has forked. */
read (startup_semaphore.child_channel[SEM_LISTEN],
&tc_magic_child,
sizeof(tc_magic_child));
/* Notify the child that it can exec.
In the infttrace.c variant of this function, we set the child's
event mask after the fork but before the exec. In the ptrace
world, it seems we can't set the event mask until after the exec. */
write (startup_semaphore.parent_channel[SEM_TALK],
&tc_magic_parent,
sizeof (tc_magic_parent));
/* We'd better pause a bit before trying to set the event mask,
though, to ensure that the exec has happened. We don't want to
wait() on the child, because that'll screw up the upper layers
of gdb's execution control that expect to see the exec event.
After an exec, the child is no longer executing gdb code. Hence,
we can't have yet another synchronization via the pipes. We'll
just sleep for a second, and hope that's enough delay... */
sleep (1);
/* Instruct the kernel as to the set of events we wish to be
informed of. */
require_notification_of_exec_events (pid);
/* Discard our copy of the semaphore. */
(void) close (startup_semaphore.parent_channel[SEM_LISTEN]);
(void) close (startup_semaphore.parent_channel[SEM_TALK]);
(void) close (startup_semaphore.child_channel[SEM_LISTEN]);
(void) close (startup_semaphore.child_channel[SEM_TALK]);
}
void
child_post_startup_inferior (pid)
int pid;
{
require_notification_of_events (pid);
}
void
child_post_attach (pid)
int pid;
{
require_notification_of_events (pid);
}
int
child_insert_fork_catchpoint (pid)
int pid;
{
/* This request is only available on HPUX 10.0 and later. */
#if !defined(PT_SET_EVENT_MASK)
error ("Unable to catch forks prior to HPUX 10.0");
#else
/* Enable reporting of fork events from the kernel. */
/* ??rehrauer: For the moment, we're always enabling these events,
and just ignoring them if there's no catchpoint to catch them.
*/
return 0;
#endif
}
int
child_remove_fork_catchpoint (pid)
int pid;
{
/* This request is only available on HPUX 10.0 and later. */
#if !defined(PT_SET_EVENT_MASK)
error ("Unable to catch forks prior to HPUX 10.0");
#else
/* Disable reporting of fork events from the kernel. */
/* ??rehrauer: For the moment, we're always enabling these events,
and just ignoring them if there's no catchpoint to catch them. */
return 0;
#endif
}
int
child_insert_vfork_catchpoint (pid)
int pid;
{
/* This request is only available on HPUX 10.0 and later. */
#if !defined(PT_SET_EVENT_MASK)
error ("Unable to catch vforks prior to HPUX 10.0");
#else
/* Enable reporting of vfork events from the kernel. */
/* ??rehrauer: For the moment, we're always enabling these events,
and just ignoring them if there's no catchpoint to catch them. */
return 0;
#endif
}
int
child_remove_vfork_catchpoint (pid)
int pid;
{
/* This request is only available on HPUX 10.0 and later. */
#if !defined(PT_SET_EVENT_MASK)
error ("Unable to catch vforks prior to HPUX 10.0");
#else
/* Disable reporting of vfork events from the kernel. */
/* ??rehrauer: For the moment, we're always enabling these events,
and just ignoring them if there's no catchpoint to catch them. */
return 0;
#endif
}
int
child_has_forked (pid, childpid)
int pid;
int * childpid;
{
/* This request is only available on HPUX 10.0 and later. */
#if !defined(PT_GET_PROCESS_STATE)
*childpid = 0;
return 0;
#else
int pt_status;
ptrace_state_t ptrace_state;
errno = 0;
pt_status = call_ptrace (PT_GET_PROCESS_STATE,
pid,
(PTRACE_ARG3_TYPE) &ptrace_state,
sizeof (ptrace_state));
if (errno)
perror_with_name ("ptrace");
if (pt_status < 0)
return 0;
if (ptrace_state.pe_report_event & PTRACE_FORK)
{
*childpid = ptrace_state.pe_other_pid;
return 1;
}
return 0;
#endif
}
int
child_has_vforked (pid, childpid)
int pid;
int * childpid;
{
/* This request is only available on HPUX 10.0 and later. */
#if !defined(PT_GET_PROCESS_STATE)
*childpid = 0;
return 0;
#else
int pt_status;
ptrace_state_t ptrace_state;
errno = 0;
pt_status = call_ptrace (PT_GET_PROCESS_STATE,
pid,
(PTRACE_ARG3_TYPE) &ptrace_state,
sizeof (ptrace_state));
if (errno)
perror_with_name ("ptrace");
if (pt_status < 0)
return 0;
if (ptrace_state.pe_report_event & PTRACE_VFORK)
{
*childpid = ptrace_state.pe_other_pid;
return 1;
}
return 0;
#endif
}
int
child_can_follow_vfork_prior_to_exec ()
{
/* ptrace doesn't allow this. */
return 0;
}
int
child_insert_exec_catchpoint (pid)
int pid;
{
/* This request is only available on HPUX 10.0 and later.
*/
#if !defined(PT_SET_EVENT_MASK)
error ("Unable to catch execs prior to HPUX 10.0");
#else
/* Enable reporting of exec events from the kernel. */
/* ??rehrauer: For the moment, we're always enabling these events,
and just ignoring them if there's no catchpoint to catch them.
*/
return 0;
#endif
}
int
child_remove_exec_catchpoint (pid)
int pid;
{
/* This request is only available on HPUX 10.0 and later.
*/
#if !defined(PT_SET_EVENT_MASK)
error ("Unable to catch execs prior to HPUX 10.0");
#else
/* Disable reporting of exec events from the kernel. */
/* ??rehrauer: For the moment, we're always enabling these events,
and just ignoring them if there's no catchpoint to catch them.
*/
return 0;
#endif
}
int
child_has_execd (pid, execd_pathname)
int pid;
char ** execd_pathname;
{
/* This request is only available on HPUX 10.0 and later.
*/
#if !defined(PT_GET_PROCESS_STATE)
*execd_pathname = NULL;
return 0;
#else
int pt_status;
ptrace_state_t ptrace_state;
errno = 0;
pt_status = call_ptrace (PT_GET_PROCESS_STATE,
pid,
(PTRACE_ARG3_TYPE) &ptrace_state,
sizeof (ptrace_state));
if (errno)
perror_with_name ("ptrace");
if (pt_status < 0)
return 0;
if (ptrace_state.pe_report_event & PTRACE_EXEC)
{
char * exec_file = target_pid_to_exec_file (pid);
*execd_pathname = savestring (exec_file, strlen (exec_file));
return 1;
}
return 0;
#endif
}
int
child_reported_exec_events_per_exec_call ()
{
return 2; /* ptrace reports the event twice per call. */
}
int
child_has_syscall_event (pid, kind, syscall_id)
int pid;
enum target_waitkind *kind;
int *syscall_id;
{
/* This request is only available on HPUX 10.30 and later, via
the ttrace interface. */
*kind = TARGET_WAITKIND_SPURIOUS;
*syscall_id = -1;
return 0;
}
char *
child_pid_to_exec_file (pid)
int pid;
{
static char exec_file_buffer[1024];
int pt_status;
CORE_ADDR top_of_stack;
char four_chars[4];
int name_index;
int i;
int saved_inferior_pid;
boolean done;
/* As of 10.x HP-UX, there's an explicit request to get the pathname. */
pt_status = call_ptrace (PT_GET_PROCESS_PATHNAME,
pid,
(PTRACE_ARG3_TYPE) exec_file_buffer,
sizeof (exec_file_buffer) - 1);
if (pt_status == 0)
return exec_file_buffer;
/* It appears that this request is broken prior to 10.30.
If it fails, try a really, truly amazingly gross hack
that DDE uses, of pawing through the process' data
segment to find the pathname. */
top_of_stack = 0x7b03a000;
name_index = 0;
done = 0;
/* On the chance that pid != inferior_pid, set inferior_pid
to pid, so that (grrrr!) implicit uses of inferior_pid get
the right id. */
saved_inferior_pid = inferior_pid;
inferior_pid = pid;
/* Try to grab a null-terminated string. */
while (! done)
{
if (target_read_memory (top_of_stack, four_chars, 4) != 0)
{
inferior_pid = saved_inferior_pid;
return NULL;
}
for (i = 0; i < 4; i++)
{
exec_file_buffer[name_index++] = four_chars[i];
done = (four_chars[i] == '\0');
if (done)
break;
}
top_of_stack += 4;
}
if (exec_file_buffer[0] == '\0')
{
inferior_pid = saved_inferior_pid;
return NULL;
}
inferior_pid = saved_inferior_pid;
return exec_file_buffer;
}
void
pre_fork_inferior ()
{
int status;
status = pipe (startup_semaphore.parent_channel);
if (status < 0)
{
warning ("error getting parent pipe for startup semaphore");
return;
}
status = pipe (startup_semaphore.child_channel);
if (status < 0)
{
warning ("error getting child pipe for startup semaphore");
return;
}
}
/* Check to see if the given thread is alive.
This is a no-op, as ptrace doesn't support threads, so we just
return "TRUE". */
int
child_thread_alive (pid)
int pid;
{
return 1;
}
#endif /* ! GDB_NATIVE_HPUX_11 */

View file

@ -976,13 +976,13 @@ hpread_psymtab_to_symtab_1 (pst)
/* Inform about additional files that need to be read in. */ /* Inform about additional files that need to be read in. */
if (info_verbose) if (info_verbose)
{ {
fputs_filtered (" ", stdout); fputs_filtered (" ", gdb_stdout);
wrap_here (""); wrap_here ("");
fputs_filtered ("and ", stdout); fputs_filtered ("and ", gdb_stdout);
wrap_here (""); wrap_here ("");
printf_filtered ("%s...", pst->dependencies[i]->filename); printf_filtered ("%s...", pst->dependencies[i]->filename);
wrap_here (""); /* Flush output */ wrap_here (""); /* Flush output */
fflush (stdout); gdb_flush (gdb_stdout);
} }
hpread_psymtab_to_symtab_1 (pst->dependencies[i]); hpread_psymtab_to_symtab_1 (pst->dependencies[i]);
} }
@ -1032,7 +1032,7 @@ hpread_psymtab_to_symtab (pst)
if (info_verbose) if (info_verbose)
{ {
printf_filtered ("Reading in symbols for %s...", pst->filename); printf_filtered ("Reading in symbols for %s...", pst->filename);
fflush (stdout); gdb_flush (gdb_stdout);
} }
hpread_psymtab_to_symtab_1 (pst); hpread_psymtab_to_symtab_1 (pst);

150
gdb/hpread.h Normal file
View file

@ -0,0 +1,150 @@
/* hpread.h
* Common include file for:
* hp_symtab_read.c
* hp_psymtab_read.c
*/
/* Copyright 1993, 1996 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Written by the Center for Software Science at the University of Utah
and by Cygnus Support. */
#include "defs.h"
#include "bfd.h"
#include "gdb_string.h"
#include "hp-symtab.h"
#include "syms.h"
#include "symtab.h"
#include "symfile.h"
#include "objfiles.h"
#include "buildsym.h"
#include "complaints.h"
#include "gdb-stabs.h"
#include "gdbtypes.h"
#include "demangle.h"
/* Private information attached to an objfile which we use to find
and internalize the HP C debug symbols within that objfile. */
struct hpread_symfile_info
{
/* The contents of each of the debug sections (there are 4 of them). */
char *gntt;
char *lntt;
char *slt;
char *vt;
/* We keep the size of the $VT$ section for range checking. */
unsigned int vt_size;
/* Some routines still need to know the number of symbols in the
main debug sections ($LNTT$ and $GNTT$). */
unsigned int lntt_symcount;
unsigned int gntt_symcount;
/* To keep track of all the types we've processed. */
struct type **type_vector;
int type_vector_length;
/* Keeps track of the beginning of a range of source lines. */
sltpointer sl_index;
/* Some state variables we'll need. */
int within_function;
/* Keep track of the current function's address. We may need to look
up something based on this address. */
unsigned int current_function_value;
};
/* Accessor macros to get at the fields. */
#define HPUX_SYMFILE_INFO(o) \
((struct hpread_symfile_info *)((o)->sym_private))
#define GNTT(o) (HPUX_SYMFILE_INFO(o)->gntt)
#define LNTT(o) (HPUX_SYMFILE_INFO(o)->lntt)
#define SLT(o) (HPUX_SYMFILE_INFO(o)->slt)
#define VT(o) (HPUX_SYMFILE_INFO(o)->vt)
#define VT_SIZE(o) (HPUX_SYMFILE_INFO(o)->vt_size)
#define LNTT_SYMCOUNT(o) (HPUX_SYMFILE_INFO(o)->lntt_symcount)
#define GNTT_SYMCOUNT(o) (HPUX_SYMFILE_INFO(o)->gntt_symcount)
#define TYPE_VECTOR(o) (HPUX_SYMFILE_INFO(o)->type_vector)
#define TYPE_VECTOR_LENGTH(o) (HPUX_SYMFILE_INFO(o)->type_vector_length)
#define SL_INDEX(o) (HPUX_SYMFILE_INFO(o)->sl_index)
#define WITHIN_FUNCTION(o) (HPUX_SYMFILE_INFO(o)->within_function)
#define CURRENT_FUNCTION_VALUE(o) (HPUX_SYMFILE_INFO(o)->current_function_value)
/* Given the native debug symbol SYM, set NAMEP to the name associated
with the debug symbol. Note we may be called with a debug symbol which
has no associated name, in that case we return an empty string.
Also note we "know" that the name for any symbol is always in the
same place. Hence we don't have to conditionalize on the symbol type. */
#define SET_NAMESTRING(SYM, NAMEP, OBJFILE) \
if (! hpread_has_name ((SYM)->dblock.kind)) \
*NAMEP = ""; \
else if (((unsigned)(SYM)->dsfile.name) >= VT_SIZE (OBJFILE)) \
{ \
complain (&string_table_offset_complaint, (char *) symnum); \
*NAMEP = ""; \
} \
else \
*NAMEP = (SYM)->dsfile.name + VT (OBJFILE)
/* We put a pointer to this structure in the read_symtab_private field
of the psymtab. */
struct symloc
{
/* The offset within the file symbol table of first local symbol for
this file. */
int ldsymoff;
/* Length (in bytes) of the section of the symbol table devoted to
this file's symbols (actually, the section bracketed may contain
more than just this file's symbols). If ldsymlen is 0, the only
reason for this thing's existence is the dependency list.
Nothing else will happen when it is read in. */
int ldsymlen;
};
#define LDSYMOFF(p) (((struct symloc *)((p)->read_symtab_private))->ldsymoff)
#define LDSYMLEN(p) (((struct symloc *)((p)->read_symtab_private))->ldsymlen)
#define SYMLOC(p) ((struct symloc *)((p)->read_symtab_private))
/* FIXME: Shouldn't this stuff be in a .h file somewhere? */
/* Nonzero means give verbose info on gdb action. */
extern int info_verbose;
/* Complaints about the symbols we have encountered. */
extern struct complaint string_table_offset_complaint;
extern struct complaint lbrac_unmatched_complaint;
extern struct complaint lbrac_mismatch_complaint;
extern union sltentry *hpread_get_slt
PARAMS ((int, struct objfile *));
extern union dnttentry *hpread_get_lntt
PARAMS ((int, struct objfile *));
int hpread_has_name
PARAMS ((enum dntt_entry_type));
/* end of hpread.h */

View file

@ -32,6 +32,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "target.h" #include "target.h"
#include "language.h" #include "language.h"
#include "symfile.h" #include "symfile.h"
#include "objfiles.h"
/* Functions exported for general use: */ /* Functions exported for general use: */
@ -91,6 +92,8 @@ static void run_command PARAMS ((char *, int));
void _initialize_infcmd PARAMS ((void)); void _initialize_infcmd PARAMS ((void));
#define GO_USAGE "Usage: go <location>\n"
#ifdef CALL_DUMMY_BREAKPOINT_OFFSET #ifdef CALL_DUMMY_BREAKPOINT_OFFSET
static void breakpoint_auto_delete_contents PARAMS ((PTR)); static void breakpoint_auto_delete_contents PARAMS ((PTR));
#endif #endif
@ -207,12 +210,19 @@ run_command (args, from_tty)
Start it from the beginning? ")) Start it from the beginning? "))
error ("Program not restarted."); error ("Program not restarted.");
target_kill (); target_kill ();
#if defined(SOLIB_RESTART)
SOLIB_RESTART ();
#endif
init_wait_for_inferior ();
} }
clear_breakpoint_hit_counts (); clear_breakpoint_hit_counts ();
exec_file = (char *) get_exec_file (0); exec_file = (char *) get_exec_file (0);
/* Purge old solib objfiles. */
objfile_purge_solibs ();
do_run_cleanups (NULL); do_run_cleanups (NULL);
/* The exec file is re-read every time we do a generic_mourn_inferior, so /* The exec file is re-read every time we do a generic_mourn_inferior, so
@ -249,6 +259,17 @@ Start it from the beginning? "))
target_create_inferior (exec_file, inferior_args, target_create_inferior (exec_file, inferior_args,
environ_vector (inferior_environ)); environ_vector (inferior_environ));
} }
static void
run_no_args_command (args, from_tty)
char *args;
int from_tty;
{
execute_command("set args", from_tty);
run_command((char *)NULL, from_tty);
}
void void
continue_command (proc_count_exp, from_tty) continue_command (proc_count_exp, from_tty)
@ -481,6 +502,23 @@ jump_command (arg, from_tty)
proceed (addr, TARGET_SIGNAL_0, 0); proceed (addr, TARGET_SIGNAL_0, 0);
} }
/* Go to line or address in current procedure */
static void
go_command(line_no, from_tty)
char *line_no;
int from_tty;
{
if (line_no == (char *)NULL || !*line_no)
printf_filtered(GO_USAGE);
else
{
tbreak_command(line_no, from_tty);
jump_command(line_no, from_tty);
}
}
/* Continue program giving it specified signal. */ /* Continue program giving it specified signal. */
static void static void
@ -615,8 +653,10 @@ run_stack_dummy (addr, buffer)
} }
#endif /* CALL_DUMMY_BREAKPOINT_OFFSET. */ #endif /* CALL_DUMMY_BREAKPOINT_OFFSET. */
disable_watchpoints_before_interactive_call_start ();
proceed_to_finish = 1; /* We want stop_registers, please... */ proceed_to_finish = 1; /* We want stop_registers, please... */
proceed (addr, TARGET_SIGNAL_0, 0); proceed (addr, TARGET_SIGNAL_0, 0);
enable_watchpoints_after_interactive_call_stop ();
discard_cleanups (old_cleanups); discard_cleanups (old_cleanups);
@ -754,6 +794,7 @@ finish_command (arg, from_tty)
struct type *value_type; struct type *value_type;
register value_ptr val; register value_ptr val;
CORE_ADDR funcaddr; CORE_ADDR funcaddr;
int struct_return;
value_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (function)); value_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (function));
if (!value_type) if (!value_type)
@ -764,15 +805,36 @@ finish_command (arg, from_tty)
funcaddr = BLOCK_START (SYMBOL_BLOCK_VALUE (function)); funcaddr = BLOCK_START (SYMBOL_BLOCK_VALUE (function));
val = value_being_returned (value_type, stop_registers, struct_return = using_struct_return (value_of_variable (function, NULL),
using_struct_return (value_of_variable (function, NULL),
funcaddr, funcaddr,
check_typedef (value_type), check_typedef (value_type),
BLOCK_GCC_COMPILED (SYMBOL_BLOCK_VALUE (function)))); BLOCK_GCC_COMPILED (SYMBOL_BLOCK_VALUE (function)));
printf_filtered ("Value returned is $%d = ", record_latest_value (val)); if (!struct_return)
value_print (val, gdb_stdout, 0, Val_no_prettyprint); {
printf_filtered ("\n"); val = value_being_returned (value_type, stop_registers, struct_return);
printf_filtered ("Value returned is $%d = ", record_latest_value (val));
value_print (val, gdb_stdout, 0, Val_no_prettyprint);
printf_filtered ("\n");
}
else
{
/* elz: we cannot determine the contents of the structure because
it is on the stack, and we don't know where, since we did not
initiate the call, as opposed to the call_function_by_hand case */
#ifdef VALUE_RETURNED_FROM_STACK
val = 0;
printf_filtered ("Value returned has type: %s.", TYPE_NAME (value_type));
printf_filtered (" Cannot determine contents\n");
#else
val = value_being_returned (value_type, stop_registers, struct_return);
printf_filtered ("Value returned is $%d = ", record_latest_value (val));
value_print (val, gdb_stdout, 0, Val_no_prettyprint);
printf_filtered ("\n");
#endif
}
} }
do_cleanups(old_chain); do_cleanups(old_chain);
} }
@ -971,6 +1033,7 @@ path_command (dirname, from_tty)
if (from_tty) if (from_tty)
path_info ((char *)NULL, from_tty); path_info ((char *)NULL, from_tty);
} }
#ifdef REGISTER_NAMES #ifdef REGISTER_NAMES
char *gdb_register_names[] = REGISTER_NAMES; char *gdb_register_names[] = REGISTER_NAMES;
@ -1186,6 +1249,9 @@ attach_command (args, from_tty)
extern int auto_solib_add; extern int auto_solib_add;
#endif #endif
char * exec_file;
char * full_exec_path = NULL;
dont_repeat (); /* Not for the faint of heart */ dont_repeat (); /* Not for the faint of heart */
if (target_has_execution) if (target_has_execution)
@ -1217,15 +1283,43 @@ attach_command (args, from_tty)
wait_for_inferior (); wait_for_inferior ();
#endif #endif
/*
* If no exec file is yet known, try to determine it from the
* process itself.
*/
exec_file = (char *) get_exec_file (0);
if (! exec_file) {
exec_file = target_pid_to_exec_file (inferior_pid);
if (exec_file) {
/* It's possible we don't have a full path, but rather just a
filename. Some targets, such as HP-UX, don't provide the
full path, sigh.
Attempt to qualify the filename against the source path.
(If that fails, we'll just fall back on the original
filename. Not much more we can do...)
*/
if (!source_full_path_of (exec_file, &full_exec_path))
full_exec_path = savestring (exec_file, strlen (exec_file));
exec_file_attach (full_exec_path, from_tty);
symbol_file_command (full_exec_path, from_tty);
}
}
#ifdef SOLIB_ADD #ifdef SOLIB_ADD
if (auto_solib_add) if (auto_solib_add)
{ {
/* Add shared library symbols from the newly attached process, if any. */ /* Add shared library symbols from the newly attached process, if any. */
SOLIB_ADD ((char *)0, from_tty, (struct target_ops *)0); SOLIB_ADD ((char *)0, from_tty, &current_target);
re_enable_breakpoints_in_shlibs (); re_enable_breakpoints_in_shlibs ();
} }
#endif #endif
/* Take any necessary post-attaching actions for this platform.
*/
target_post_attach (inferior_pid);
normal_stop (); normal_stop ();
} }
@ -1247,6 +1341,9 @@ detach_command (args, from_tty)
{ {
dont_repeat (); /* Not for the faint of heart */ dont_repeat (); /* Not for the faint of heart */
target_detach (args, from_tty); target_detach (args, from_tty);
#if defined(SOLIB_RESTART)
SOLIB_RESTART ();
#endif
} }
/* ARGSUSED */ /* ARGSUSED */
@ -1332,12 +1429,15 @@ fully linked executable files and separately compiled object files as needed.",
add_com ("attach", class_run, attach_command, add_com ("attach", class_run, attach_command,
"Attach to a process or file outside of GDB.\n\ "Attach to a process or file outside of GDB.\n\
This command attaches to another target, of the same type as your last\n\ This command attaches to another target, of the same type as your last\n\
`target' command (`info files' will show your target stack).\n\ \"target\" command (\"info files\" will show your target stack).\n\
The command may take as argument a process id or a device file.\n\ The command may take as argument a process id or a device file.\n\
For a process id, you must have permission to send the process a signal,\n\ For a process id, you must have permission to send the process a signal,\n\
and it must have the same effective uid as the debugger.\n\ and it must have the same effective uid as the debugger.\n\
When using \"attach\", you should use the \"file\" command to specify\n\ When using \"attach\" with a process id, the debugger finds the\n\
the program running in the process, and to load its symbol table."); program running in the process, looking first in the current working\n\
directory, or (if not found there) using the source file search path\n\
(see the \"directory\" command). You can also use the \"file\" command\n\
to specify the program, and to load its symbol table.");
add_com ("detach", class_run, detach_command, add_com ("detach", class_run, detach_command,
"Detach a process or file previously attached.\n\ "Detach a process or file previously attached.\n\
@ -1368,6 +1468,8 @@ Like the \"step\" command as long as subroutine calls do not happen;\n\
when they do, the call is treated as one instruction.\n\ when they do, the call is treated as one instruction.\n\
Argument N means do this N times (or till program stops for another reason)."); Argument N means do this N times (or till program stops for another reason).");
add_com_alias ("n", "next", class_run, 1); add_com_alias ("n", "next", class_run, 1);
if (xdb_commands)
add_com_alias("S", "next", class_run, 1);
add_com ("step", class_run, step_command, add_com ("step", class_run, step_command,
"Step program until it reaches a different source line.\n\ "Step program until it reaches a different source line.\n\
@ -1385,6 +1487,16 @@ Execution will also stop upon exit from the current stack frame.");
Give as argument either LINENUM or *ADDR, where ADDR is an expression\n\ Give as argument either LINENUM or *ADDR, where ADDR is an expression\n\
for an address to start at."); for an address to start at.");
add_com ("go", class_run, go_command,
"Usage: go <location>\n\
Continue program being debugged, stopping at specified line or \n\
address.\n\
Give as argument either LINENUM or *ADDR, where ADDR is an \n\
expression for an address to start at.\n\
This command is a combination of tbreak and jump.");
if (xdb_commands)
add_com_alias("g", "g", class_run, 1);
add_com ("continue", class_run, continue_command, add_com ("continue", class_run, continue_command,
"Continue program being debugged, after signal or breakpoint.\n\ "Continue program being debugged, after signal or breakpoint.\n\
If proceeding from breakpoint, a number N may be used as an argument,\n\ If proceeding from breakpoint, a number N may be used as an argument,\n\
@ -1401,11 +1513,18 @@ With no arguments, uses arguments last specified (with \"run\" or \"set args\").
To cancel previous arguments and run with no arguments,\n\ To cancel previous arguments and run with no arguments,\n\
use \"set args\" without arguments."); use \"set args\" without arguments.");
add_com_alias ("r", "run", class_run, 1); add_com_alias ("r", "run", class_run, 1);
if (xdb_commands)
add_com ("R", class_run, run_no_args_command,
"Start debugged program with no arguments.");
add_info ("registers", nofp_registers_info, add_info ("registers", nofp_registers_info,
"List of integer registers and their contents, for selected stack frame.\n\ "List of integer registers and their contents, for selected stack frame.\n\
Register name as argument means describe only that register."); Register name as argument means describe only that register.");
if (xdb_commands)
add_com("lr", class_info, nofp_registers_info,
"List of integer registers and their contents, for selected stack frame.\n\
Register name as argument means describe only that register.");
add_info ("all-registers", all_registers_info, add_info ("all-registers", all_registers_info,
"List of all registers and their contents, for selected stack frame.\n\ "List of all registers and their contents, for selected stack frame.\n\
Register name as argument means describe only that register."); Register name as argument means describe only that register.");

View file

@ -1,6 +1,6 @@
/* Variables that describe the inferior process running under GDB: /* Variables that describe the inferior process running under GDB:
Where it is, why it stopped, and how to step it. Where it is, why it stopped, and how to step it.
Copyright 1986, 1989, 1992, 1996 Free Software Foundation, Inc. Copyright 1986, 1989, 1992, 1996, 1998 Free Software Foundation, Inc.
This file is part of GDB. This file is part of GDB.
@ -50,7 +50,6 @@ struct inferior_status {
int stop_after_trap; int stop_after_trap;
int stop_soon_quietly; int stop_soon_quietly;
CORE_ADDR selected_frame_address; CORE_ADDR selected_frame_address;
int selected_level;
char stop_registers[REGISTER_BYTES]; char stop_registers[REGISTER_BYTES];
/* These are here because if call_function_by_hand has written some /* These are here because if call_function_by_hand has written some
@ -58,6 +57,7 @@ struct inferior_status {
any registers. */ any registers. */
char registers[REGISTER_BYTES]; char registers[REGISTER_BYTES];
int selected_level;
int breakpoint_proceeded; int breakpoint_proceeded;
int restore_stack_info; int restore_stack_info;
int proceed_to_finish; int proceed_to_finish;
@ -91,6 +91,27 @@ extern char *inferior_io_terminal;
extern int inferior_pid; extern int inferior_pid;
/* This is only valid when inferior_pid is non-zero.
If this is 0, then exec events should be noticed and responded to
by the debugger (i.e., be reported to the user).
If this is > 0, then that many subsequent exec events should be
ignored (i.e., not be reported to the user).
*/
extern int inferior_ignoring_startup_exec_events;
/* This is only valid when inferior_ignoring_startup_exec_events is
zero.
Some targets (stupidly) report more than one exec event per actual
call to an event() system call. If only the last such exec event
need actually be noticed and responded to by the debugger (i.e.,
be reported to the user), then this is the number of "leading"
exec events which should be ignored.
*/
extern int inferior_ignoring_leading_exec_events;
/* Inferior environment. */ /* Inferior environment. */
extern struct environ *inferior_environ; extern struct environ *inferior_environ;
@ -100,9 +121,10 @@ extern struct environ *inferior_environ;
extern char registers[]; extern char registers[];
/* Array of validity bits (one per register). Nonzero at position XXX_REGNUM /* Array of validity bits (one per register). Nonzero at position XXX_REGNUM
means that `registers' contains a valid copy of inferior register XXX. */ means that `registers' contains a valid copy of inferior register XXX.
-1 if register value is not available. */
extern char register_valid[NUM_REGS]; extern SIGNED char register_valid[NUM_REGS];
extern void clear_proceed_status PARAMS ((void)); extern void clear_proceed_status PARAMS ((void));
@ -122,6 +144,8 @@ extern CORE_ADDR read_pc_pid PARAMS ((int));
extern void write_pc PARAMS ((CORE_ADDR)); extern void write_pc PARAMS ((CORE_ADDR));
extern void write_pc_pid PARAMS ((CORE_ADDR, int));
extern CORE_ADDR read_sp PARAMS ((void)); extern CORE_ADDR read_sp PARAMS ((void));
extern void write_sp PARAMS ((CORE_ADDR)); extern void write_sp PARAMS ((CORE_ADDR));
@ -161,15 +185,23 @@ extern void terminal_inferior PARAMS ((void));
extern void terminal_init_inferior PARAMS ((void)); extern void terminal_init_inferior PARAMS ((void));
#ifdef PROCESS_GROUP_TYPE extern void terminal_init_inferior_with_pgrp PARAMS ((int pgrp));
extern void terminal_init_inferior_with_pgrp PARAMS ((PROCESS_GROUP_TYPE pgrp));
#endif
/* From infptrace.c */ /* From infptrace.c or infttrace.c */
extern int attach PARAMS ((int)); extern int attach PARAMS ((int));
void detach PARAMS ((int)); #if !defined(REQUIRE_ATTACH)
#define REQUIRE_ATTACH attach
#endif
#if !defined(REQUIRE_DETACH)
#define REQUIRE_DETACH(pid,siggnal) detach (siggnal)
#endif
extern void detach PARAMS ((int));
int proc_wait PARAMS ((int, int *));
extern void child_resume PARAMS ((int, int, enum target_signal)); extern void child_resume PARAMS ((int, int, enum target_signal));
@ -179,15 +211,27 @@ extern void child_resume PARAMS ((int, int, enum target_signal));
extern int call_ptrace PARAMS ((int, int, PTRACE_ARG3_TYPE, int)); extern int call_ptrace PARAMS ((int, int, PTRACE_ARG3_TYPE, int));
extern void pre_fork_inferior PARAMS ((void));
/* From procfs.c */ /* From procfs.c */
extern int proc_iterate_over_mappings PARAMS ((int (*) (int, CORE_ADDR))); extern int proc_iterate_over_mappings PARAMS ((int (*) (int, CORE_ADDR)));
extern int procfs_first_available PARAMS ((void));
extern int procfs_get_pid_fd PARAMS ((int));
/* From fork-child.c */ /* From fork-child.c */
extern void fork_inferior PARAMS ((char *, char *, char **, extern void fork_inferior PARAMS ((char *, char *, char **,
void (*) (void), void (*) (void),
int (*) (int), char *)); void (*) (int),
void (*) (void),
char *));
extern void
clone_and_follow_inferior PARAMS ((int, int *));
extern void startup_inferior PARAMS ((int)); extern void startup_inferior PARAMS ((int));
@ -316,8 +360,8 @@ extern int attach_flag;
#if !defined (IN_SIGTRAMP) #if !defined (IN_SIGTRAMP)
# if defined (SIGTRAMP_START) # if defined (SIGTRAMP_START)
# define IN_SIGTRAMP(pc, name) \ # define IN_SIGTRAMP(pc, name) \
((pc) >= SIGTRAMP_START \ ((pc) >= SIGTRAMP_START(pc) \
&& (pc) < SIGTRAMP_END \ && (pc) < SIGTRAMP_END(pc) \
) )
# else # else
# define IN_SIGTRAMP(pc, name) \ # define IN_SIGTRAMP(pc, name) \
@ -373,7 +417,7 @@ extern CORE_ADDR text_end;
allocate other kinds of code on the stack. */ allocate other kinds of code on the stack. */
#define PC_IN_CALL_DUMMY(pc, sp, frame_address) \ #define PC_IN_CALL_DUMMY(pc, sp, frame_address) \
((sp) INNER_THAN (pc) && (frame_address != 0) && (pc) INNER_THAN (frame_address)) (INNER_THAN ((sp), (pc)) && (frame_address != 0) && INNER_THAN ((pc), (frame_address)))
#endif /* On stack. */ #endif /* On stack. */
#if CALL_DUMMY_LOCATION == AT_ENTRY_POINT #if CALL_DUMMY_LOCATION == AT_ENTRY_POINT
@ -383,4 +427,45 @@ extern CORE_ADDR text_end;
#endif /* At entry point. */ #endif /* At entry point. */
#endif /* No PC_IN_CALL_DUMMY. */ #endif /* No PC_IN_CALL_DUMMY. */
/* It's often not enough for our clients to know whether the PC is merely
somewhere within the call dummy. They may need to know whether the
call dummy has actually completed. (For example, wait_for_inferior
wants to know when it should truly stop because the call dummy has
completed. If we're single-stepping because of slow watchpoints,
then we may find ourselves stopped at the entry of the call dummy,
and want to continue stepping until we reach the end.)
Note that this macro is intended for targets (like HP-UX) which
require more than a single breakpoint in their call dummies, and
therefore cannot use the CALL_DUMMY_BREAKPOINT_OFFSET mechanism.
If a target does define CALL_DUMMY_BREAKPOINT_OFFSET, then this
default implementation of CALL_DUMMY_HAS_COMPLETED is sufficient.
Else, a target may wish to supply an implementation that works in
the presense of multiple breakpoints in its call dummy.
*/
#if !defined(CALL_DUMMY_HAS_COMPLETED)
#define CALL_DUMMY_HAS_COMPLETED(pc, sp, frame_address) \
PC_IN_CALL_DUMMY((pc), (sp), (frame_address))
#endif
/* If STARTUP_WITH_SHELL is set, GDB's "run"
* will attempts to start up the debugee under a shell.
* This is in order for argument-expansion to occur. E.g.,
* (gdb) run *
* The "*" gets expanded by the shell into a list of files.
* While this is a nice feature, it turns out to interact badly
* with some of the catch-fork/catch-exec features we have added.
* In particular, if the shell does any fork/exec's before
* the exec of the target program, that can confuse GDB.
* To disable this feature, set STARTUP_WITH_SHELL to 0.
* To enable this feature, set STARTUP_WITH_SHELL to 1.
* The catch-exec traps expected during start-up will
* be 1 if target is not started up with a shell, 2 if it is.
* - RT
*/
#define STARTUP_WITH_SHELL 1
#define START_INFERIOR_TRAPS_EXPECTED (STARTUP_WITH_SHELL + 1)
#endif /* !defined (INFERIOR_H) */ #endif /* !defined (INFERIOR_H) */

File diff suppressed because it is too large Load diff

View file

@ -3,6 +3,8 @@
Free Software Foundation, Inc. Free Software Foundation, Inc.
Contributed by Cygnus Support. Contributed by Cygnus Support.
## Contains temporary hacks..
This file is part of GDB. This file is part of GDB.
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
@ -25,6 +27,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "target.h" #include "target.h"
#include "gdbcore.h" #include "gdbcore.h"
#include "command.h" #include "command.h"
#include "gdb_stat.h"
#include <signal.h> #include <signal.h>
#include <sys/types.h> #include <sys/types.h>
#include <fcntl.h> #include <fcntl.h>
@ -39,6 +42,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* "wait.h" fills in the gaps left by <wait.h> */ /* "wait.h" fills in the gaps left by <wait.h> */
#include "wait.h" #include "wait.h"
#include <sys/unistd.h>
extern struct symtab_and_line *
child_enable_exception_callback PARAMS ((enum exception_event_kind, int));
extern struct exception_event_record *
child_get_current_exception_event PARAMS ((void));
static void static void
child_prepare_to_store PARAMS ((void)); child_prepare_to_store PARAMS ((void));
@ -47,6 +57,11 @@ child_prepare_to_store PARAMS ((void));
static int child_wait PARAMS ((int, struct target_waitstatus *)); static int child_wait PARAMS ((int, struct target_waitstatus *));
#endif /* CHILD_WAIT */ #endif /* CHILD_WAIT */
#if !defined(CHILD_POST_WAIT)
void
child_post_wait PARAMS ((int, int));
#endif
static void child_open PARAMS ((char *, int)); static void child_open PARAMS ((char *, int));
static void static void
@ -55,16 +70,34 @@ child_files_info PARAMS ((struct target_ops *));
static void static void
child_detach PARAMS ((char *, int)); child_detach PARAMS ((char *, int));
static void
child_detach_from_process PARAMS ((int, char *, int, int));
static void static void
child_attach PARAMS ((char *, int)); child_attach PARAMS ((char *, int));
static void
child_attach_to_process PARAMS ((char *, int, int));
#if !defined(CHILD_POST_ATTACH)
static void
child_post_attach PARAMS ((int));
#endif
static void
child_require_attach PARAMS ((char *, int));
static void
child_require_detach PARAMS ((int, char *, int));
static void static void
ptrace_me PARAMS ((void)); ptrace_me PARAMS ((void));
static int static void
ptrace_him PARAMS ((int)); ptrace_him PARAMS ((int));
static void child_create_inferior PARAMS ((char *, char *, char **)); static void
child_create_inferior PARAMS ((char *, char *, char **));
static void static void
child_mourn_inferior PARAMS ((void)); child_mourn_inferior PARAMS ((void));
@ -72,14 +105,11 @@ child_mourn_inferior PARAMS ((void));
static int static int
child_can_run PARAMS ((void)); child_can_run PARAMS ((void));
static int
proc_wait PARAMS ((int, int*));
static void static void
child_stop PARAMS ((void)); child_stop PARAMS ((void));
#ifndef CHILD_THREAD_ALIVE #ifndef CHILD_THREAD_ALIVE
static int child_thread_alive PARAMS ((int)); int child_thread_alive PARAMS ((int));
#endif #endif
extern char **environ; extern char **environ;
@ -91,18 +121,19 @@ int child_suppress_run = 0; /* Non-zero if inftarg should pretend not to
be a runnable target. Used by targets be a runnable target. Used by targets
that can sit atop inftarg, such as HPUX that can sit atop inftarg, such as HPUX
thread support. */ thread support. */
static int
proc_wait (pid, status)
int pid;
int *status;
{
#ifndef __GO32__
return wait (status);
#endif
}
#ifndef CHILD_WAIT #ifndef CHILD_WAIT
/*##*/
/* Enable HACK for ttrace work. In
* infttrace.c/require_notification_of_events,
* this is set to 0 so that the loop in child_wait
* won't loop.
*/
int not_same_real_pid = 1;
/*##*/
/* Wait for child to do something. Return pid of child, or -1 in case /* Wait for child to do something. Return pid of child, or -1 in case
of error; store status through argument pointer OURSTATUS. */ of error; store status through argument pointer OURSTATUS. */
@ -113,6 +144,11 @@ child_wait (pid, ourstatus)
{ {
int save_errno; int save_errno;
int status; int status;
char * execd_pathname;
int exit_status;
int related_pid;
int syscall_id;
enum target_waitkind kind;
do { do {
set_sigint_trap(); /* Causes SIGINT to be passed on to the set_sigint_trap(); /* Causes SIGINT to be passed on to the
@ -120,6 +156,7 @@ child_wait (pid, ourstatus)
set_sigio_trap (); set_sigio_trap ();
pid = proc_wait (inferior_pid, &status); pid = proc_wait (inferior_pid, &status);
save_errno = errno; save_errno = errno;
clear_sigio_trap (); clear_sigio_trap ();
@ -130,19 +167,98 @@ child_wait (pid, ourstatus)
{ {
if (save_errno == EINTR) if (save_errno == EINTR)
continue; continue;
fprintf_unfiltered (gdb_stderr, "Child process unexpectedly missing: %s.\n", fprintf_unfiltered (gdb_stderr, "Child process unexpectedly missing: %s.\n",
safe_strerror (save_errno)); safe_strerror (save_errno));
/* Claim it exited with unknown signal. */ /* Claim it exited with unknown signal. */
ourstatus->kind = TARGET_WAITKIND_SIGNALLED; ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN; ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
return -1; return -1;
} }
} while (pid != inferior_pid); /* Some other child died or stopped */
/* Did it exit?
*/
if (target_has_exited (pid, status, &exit_status))
{
/* ??rehrauer: For now, ignore this. */
continue;
}
if (!target_thread_alive (pid))
{
ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
return pid;
}
if (target_has_forked (pid, &related_pid)
&& (pid == inferior_pid) || (related_pid == inferior_pid))
{
ourstatus->kind = TARGET_WAITKIND_FORKED;
ourstatus->value.related_pid = related_pid;
return pid;
}
if (target_has_vforked (pid, &related_pid)
&& (pid == inferior_pid) || (related_pid == inferior_pid))
{
ourstatus->kind = TARGET_WAITKIND_VFORKED;
ourstatus->value.related_pid = related_pid;
return pid;
}
if (target_has_execd (pid, &execd_pathname))
{
/* Are we ignoring initial exec events? (This is likely because
we're in the process of starting up the inferior, and another
(older) mechanism handles those.) If so, we'll report this
as a regular stop, not an exec.
*/
if (inferior_ignoring_startup_exec_events)
{
inferior_ignoring_startup_exec_events--;
}
else
{
ourstatus->kind = TARGET_WAITKIND_EXECD;
ourstatus->value.execd_pathname = execd_pathname;
return pid;
}
}
/* All we must do with these is communicate their occurrence
to wait_for_inferior...
*/
if (target_has_syscall_event (pid, &kind, &syscall_id))
{
ourstatus->kind = kind;
ourstatus->value.syscall_id = syscall_id;
return pid;
}
/*## } while (pid != inferior_pid); ##*/ /* Some other child died or stopped */
/* hack for thread testing */
} while( (pid != inferior_pid) && not_same_real_pid );
/*##*/
store_waitstatus (ourstatus, status); store_waitstatus (ourstatus, status);
return pid; return pid;
} }
#endif /* CHILD_WAIT */ #endif /* CHILD_WAIT */
#if !defined(CHILD_POST_WAIT)
void
child_post_wait (pid, wait_status)
int pid;
int wait_status;
{
/* This version of Unix doesn't require a meaningful "post wait"
operation.
*/
}
#endif
#ifndef CHILD_THREAD_ALIVE #ifndef CHILD_THREAD_ALIVE
/* Check to see if the given thread is alive. /* Check to see if the given thread is alive.
@ -150,7 +266,7 @@ child_wait (pid, ourstatus)
FIXME: Is kill() ever the right way to do this? I doubt it, but FIXME: Is kill() ever the right way to do this? I doubt it, but
for now we're going to try and be compatable with the old thread for now we're going to try and be compatable with the old thread
code. */ code. */
static int int
child_thread_alive (pid) child_thread_alive (pid)
int pid; int pid;
{ {
@ -159,12 +275,11 @@ child_thread_alive (pid)
#endif #endif
/* Attach to process PID, then initialize for debugging it. */
static void static void
child_attach (args, from_tty) child_attach_to_process (args, from_tty, after_fork)
char *args; char * args;
int from_tty; int from_tty;
int after_fork;
{ {
if (!args) if (!args)
error_no_arg ("process-id to attach"); error_no_arg ("process-id to attach");
@ -175,8 +290,14 @@ child_attach (args, from_tty)
{ {
char *exec_file; char *exec_file;
int pid; int pid;
struct target_waitstatus *wstatus;
char * dummy;
pid = atoi (args); dummy = args;
pid = strtol (args, &dummy, 0);
/* Some targets don't set errno on errors, grrr! */
if ((pid == 0) && (args == dummy))
error ("Illegal process-id: %s\n", args);
if (pid == getpid()) /* Trying to masturbate? */ if (pid == getpid()) /* Trying to masturbate? */
error ("I refuse to debug myself!"); error ("I refuse to debug myself!");
@ -185,16 +306,23 @@ child_attach (args, from_tty)
{ {
exec_file = (char *) get_exec_file (0); exec_file = (char *) get_exec_file (0);
if (exec_file) if (after_fork)
printf_unfiltered ("Attaching to program `%s', %s\n", exec_file, printf_unfiltered ("Attaching after fork to %s\n",
target_pid_to_str (pid)); target_pid_to_str (pid));
else else if (exec_file)
printf_unfiltered ("Attaching to %s\n", target_pid_to_str (pid)); printf_unfiltered ("Attaching to program: %s, %s\n", exec_file,
target_pid_to_str (pid));
else
printf_unfiltered ("Attaching to %s\n", target_pid_to_str (pid));
gdb_flush (gdb_stdout); gdb_flush (gdb_stdout);
} }
attach (pid); if (!after_fork)
attach (pid);
else
REQUIRE_ATTACH (pid);
inferior_pid = pid; inferior_pid = pid;
push_target (&child_ops); push_target (&child_ops);
} }
@ -202,6 +330,73 @@ child_attach (args, from_tty)
} }
/* Attach to process PID, then initialize for debugging it. */
static void
child_attach (args, from_tty)
char *args;
int from_tty;
{
child_attach_to_process (args, from_tty, 0);
}
#if !defined(CHILD_POST_ATTACH)
static void
child_post_attach (pid)
int pid;
{
/* This version of Unix doesn't require a meaningful "post attach"
operation by a debugger.
*/
}
#endif
static void
child_require_attach (args, from_tty)
char *args;
int from_tty;
{
child_attach_to_process (args, from_tty, 1);
}
static void
child_detach_from_process (pid, args, from_tty, after_fork)
int pid;
char * args;
int from_tty;
int after_fork;
{
#ifdef ATTACH_DETACH
{
int siggnal = 0;
if (from_tty)
{
char *exec_file = get_exec_file (0);
if (exec_file == 0)
exec_file = "";
if (after_fork)
printf_unfiltered ("Detaching after fork from %s\n",
target_pid_to_str (pid));
else
printf_unfiltered ("Detaching from program: %s, %s\n", exec_file,
target_pid_to_str (pid));
gdb_flush (gdb_stdout);
}
if (args)
siggnal = atoi (args);
if (!after_fork)
detach (siggnal);
else
REQUIRE_DETACH (pid, siggnal);
}
#else
error ("This version of Unix does not support detaching a process.");
#endif
}
/* Take a program previously attached to and detaches it. /* Take a program previously attached to and detaches it.
The program resumes execution and will no longer stop The program resumes execution and will no longer stop
on signals, etc. We'd better not have left any breakpoints on signals, etc. We'd better not have left any breakpoints
@ -215,31 +410,21 @@ child_detach (args, from_tty)
char *args; char *args;
int from_tty; int from_tty;
{ {
#ifdef ATTACH_DETACH child_detach_from_process (inferior_pid, args, from_tty, 0);
{ inferior_pid = 0;
int siggnal = 0; unpush_target (&child_ops);
if (from_tty)
{
char *exec_file = get_exec_file (0);
if (exec_file == 0)
exec_file = "";
printf_unfiltered ("Detaching from program: %s %s\n", exec_file,
target_pid_to_str (inferior_pid));
gdb_flush (gdb_stdout);
}
if (args)
siggnal = atoi (args);
detach (siggnal);
inferior_pid = 0;
unpush_target (&child_ops);
}
#else
error ("This version of Unix does not support detaching a process.");
#endif
} }
static void
child_require_detach (pid, args, from_tty)
int pid;
char * args;
int from_tty;
{
child_detach_from_process (pid, args, from_tty, 1);
}
/* Get ready to modify the registers array. On machines which store /* Get ready to modify the registers array. On machines which store
individual registers, this doesn't need to do anything. On machines individual registers, this doesn't need to do anything. On machines
which store all the registers in one fell swoop, this makes sure which store all the registers in one fell swoop, this makes sure
@ -286,20 +471,30 @@ ptrace_me ()
/* Stub function which causes the GDB that runs it, to start ptrace-ing /* Stub function which causes the GDB that runs it, to start ptrace-ing
the child process. */ the child process. */
static int static void
ptrace_him (pid) ptrace_him (pid)
int pid; int pid;
{ {
push_target (&child_ops); push_target (&child_ops);
#ifdef START_INFERIOR_TRAPS_EXPECTED /* On some targets, there must be some explicit synchronization
startup_inferior (START_INFERIOR_TRAPS_EXPECTED); between the parent and child processes after the debugger
#else forks, and before the child execs the debuggee program. This
/* One trap to exec the shell, one to exec the program being debugged. */ call basically gives permission for the child to exec.
startup_inferior (2); */
#endif
return pid; target_acknowledge_created_inferior (pid);
/* START_INFERIOR_TRAPS_EXPECTED is defined in inferior.h,
* and will be 1 or 2 depending on whether we're starting
* without or with a shell.
*/
startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
/* On some targets, there must be some explicit actions taken after
the inferior has been started up.
*/
target_post_startup_inferior (pid);
} }
/* Start an inferior Unix child process and sets inferior_pid to its pid. /* Start an inferior Unix child process and sets inferior_pid to its pid.
@ -313,12 +508,307 @@ child_create_inferior (exec_file, allargs, env)
char *allargs; char *allargs;
char **env; char **env;
{ {
fork_inferior (exec_file, allargs, env, ptrace_me, ptrace_him, NULL);
#ifdef HPUXHPPA
char *tryname;
char *shell_file;
char *p;
char *p1;
char *path = getenv ("PATH");
int len;
struct stat statbuf;
/* On HP-UX, we have a possible bad interaction between
* the start-up-with-shell code and our catch-fork/catch-exec
* logic. To avoid the bad interaction, we start up with the
* C shell ("csh") and pass it the "-f" flag (fast start-up,
* don't run .cshrc code).
* See further comments in inferior.h toward the bottom
* (STARTUP_WITH_SHELL flag) and in fork-child.c
*/
/* Rather than passing in a hard-wired path like "/bin/csh",
* we look down the PATH to find csh. I took this code from
* procfs.c, which is the file in the Sun-specific part of GDB
* analogous to inftarg.c. See procfs.c for more detailed
* comments. - RT
*/
shell_file = "csh";
if (path == NULL)
path = "/bin:/usr/bin";
tryname = alloca (strlen (path) + strlen (shell_file) + 2);
for (p = path; p != NULL; p = p1 ? p1 + 1: NULL)
{
p1 = strchr (p, ':');
if (p1 != NULL)
len = p1 - p;
else
len = strlen (p);
strncpy (tryname, p, len);
tryname[len] = '\0';
strcat (tryname, "/");
strcat (tryname, shell_file);
if (access (tryname, X_OK) < 0)
continue;
if (stat (tryname, &statbuf) < 0)
continue;
if (!S_ISREG (statbuf.st_mode))
/* We certainly need to reject directories. I'm not quite
as sure about FIFOs, sockets, etc., but I kind of doubt
that people want to exec() these things. */
continue;
break;
}
if (p == NULL)
/* Not found. I replaced the error() which existed in procfs.c
* with simply passing in NULL and hoping fork_inferior()
* can deal with it. - RT
*/
/* error ("Can't find shell %s in PATH", shell_file); */
shell_file = NULL;
else
shell_file = tryname;
fork_inferior (exec_file, allargs, env, ptrace_me, ptrace_him, pre_fork_inferior, shell_file);
#else
fork_inferior (exec_file, allargs, env, ptrace_me, ptrace_him, NULL, NULL);
#endif
/* We are at the first instruction we care about. */ /* We are at the first instruction we care about. */
/* Pedal to the metal... */ /* Pedal to the metal... */
proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0); proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0);
} }
#if !defined(CHILD_POST_STARTUP_INFERIOR)
void
child_post_startup_inferior (pid)
int pid;
{
/* This version of Unix doesn't require a meaningful "post startup inferior"
operation by a debugger.
*/
}
#endif
#if !defined(CHILD_ACKNOWLEDGE_CREATED_INFERIOR)
void
child_acknowledge_created_inferior (pid)
int pid;
{
/* This version of Unix doesn't require a meaningful "acknowledge created inferior"
operation by a debugger.
*/
}
#endif
void
child_clone_and_follow_inferior (child_pid, followed_child)
int child_pid;
int *followed_child;
{
clone_and_follow_inferior (child_pid, followed_child);
/* Don't resume CHILD_PID; it's stopped where it ought to be, until
the decision gets made elsewhere how to continue it.
*/
}
#if !defined(CHILD_POST_FOLLOW_INFERIOR_BY_CLONE)
void
child_post_follow_inferior_by_clone ()
{
/* This version of Unix doesn't require a meaningful "post follow inferior"
operation by a clone debugger.
*/
}
#endif
#if !defined(CHILD_INSERT_FORK_CATCHPOINT)
int
child_insert_fork_catchpoint (pid)
int pid;
{
/* This version of Unix doesn't support notification of fork events.
*/
}
#endif
#if !defined(CHILD_REMOVE_FORK_CATCHPOINT)
int
child_remove_fork_catchpoint (pid)
int pid;
{
/* This version of Unix doesn't support notification of fork events.
*/
}
#endif
#if !defined(CHILD_INSERT_VFORK_CATCHPOINT)
int
child_insert_vfork_catchpoint (pid)
int pid;
{
/* This version of Unix doesn't support notification of vfork events.
*/
}
#endif
#if !defined(CHILD_REMOVE_VFORK_CATCHPOINT)
int
child_remove_vfork_catchpoint (pid)
int pid;
{
/* This version of Unix doesn't support notification of vfork events.
*/
}
#endif
#if !defined(CHILD_HAS_FORKED)
int
child_has_forked (pid, child_pid)
int pid;
int * child_pid;
{
/* This version of Unix doesn't support notification of fork events.
*/
return 0;
}
#endif
#if !defined(CHILD_HAS_VFORKED)
int
child_has_vforked (pid, child_pid)
int pid;
int * child_pid;
{
/* This version of Unix doesn't support notification of vfork events.
*/
return 0;
}
#endif
#if !defined(CHILD_CAN_FOLLOW_VFORK_PRIOR_TO_EXEC)
int
child_can_follow_vfork_prior_to_exec ()
{
/* This version of Unix doesn't support notification of vfork events.
However, if it did, it probably wouldn't allow vforks to be followed
before the following exec.
*/
return 0;
}
#endif
#if !defined(CHILD_POST_FOLLOW_VFORK)
void
child_post_follow_vfork (parent_pid, followed_parent, child_pid, followed_child)
int parent_pid;
int followed_parent;
int child_pid;
int followed_child;
{
/* This version of Unix doesn't require a meaningful "post follow vfork"
operation by a clone debugger.
*/
}
#endif
#if !defined(CHILD_INSERT_EXEC_CATCHPOINT)
int
child_insert_exec_catchpoint (pid)
int pid;
{
/* This version of Unix doesn't support notification of exec events.
*/
}
#endif
#if !defined(CHILD_REMOVE_EXEC_CATCHPOINT)
int
child_remove_exec_catchpoint (pid)
int pid;
{
/* This version of Unix doesn't support notification of exec events.
*/
}
#endif
#if !defined(CHILD_HAS_EXECD)
int
child_has_execd (pid, execd_pathname)
int pid;
char ** execd_pathname;
{
/* This version of Unix doesn't support notification of exec events.
*/
return 0;
}
#endif
#if !defined(CHILD_REPORTED_EXEC_EVENTS_PER_EXEC_CALL)
int
child_reported_exec_events_per_exec_call ()
{
/* This version of Unix doesn't support notification of exec events.
*/
return 1;
}
#endif
#if !defined(CHILD_HAS_SYSCALL_EVENT)
int
child_has_syscall_event (pid, kind, syscall_id)
int pid;
enum target_waitkind * kind;
int * syscall_id;
{
/* This version of Unix doesn't support notification of syscall events.
*/
return 0;
}
#endif
#if !defined(CHILD_HAS_EXITED)
int
child_has_exited (pid, wait_status, exit_status)
int pid;
int wait_status;
int * exit_status;
{
if (WIFEXITED (wait_status))
{
*exit_status = WEXITSTATUS (wait_status);
return 1;
}
if (WIFSIGNALED (wait_status))
{
*exit_status = 0; /* ?? Don't know what else to say here. */
return 1;
}
/* ?? Do we really need to consult the event state, too? Assume the
wait_state alone suffices.
*/
return 0;
}
#endif
static void static void
child_mourn_inferior () child_mourn_inferior ()
{ {
@ -353,6 +843,49 @@ child_stop ()
kill (-inferior_process_group, SIGINT); kill (-inferior_process_group, SIGINT);
} }
#if !defined(CHILD_ENABLE_EXCEPTION_CALLBACK)
struct symtab_and_line *
child_enable_exception_callback (kind, enable)
enum exception_event_kind kind;
int enable;
{
return (struct symtab_and_line *) NULL;
}
#endif
#if !defined(CHILD_GET_CURRENT_EXCEPTION_EVENT)
struct exception_event_record *
child_get_current_exception_event ()
{
return (struct exception_event_record *) NULL;
}
#endif
#if !defined(CHILD_PID_TO_EXEC_FILE)
char *
child_pid_to_exec_file (pid)
int pid;
{
/* This version of Unix doesn't support translation of a process ID
to the filename of the executable file.
*/
return NULL;
}
#endif
char *
child_core_file_to_sym_file (core)
char * core;
{
/* The target stratum for a running executable need not support
this operation.
*/
return NULL;
}
struct target_ops child_ops = { struct target_ops child_ops = {
"child", /* to_shortname */ "child", /* to_shortname */
@ -361,13 +894,13 @@ struct target_ops child_ops = {
child_open, /* to_open */ child_open, /* to_open */
0, /* to_close */ 0, /* to_close */
child_attach, /* to_attach */ child_attach, /* to_attach */
NULL, /* to_post_attach */ child_post_attach, /* to_post_attach */
NULL, /* to_require_attach */ child_require_attach, /* to_require_attach */
child_detach, /* to_detach */ child_detach, /* to_detach */
NULL, /* to_require_detach */ child_require_detach, /* to_require_detach */
child_resume, /* to_resume */ child_resume, /* to_resume */
child_wait, /* to_wait */ child_wait, /* to_wait */
NULL, /* to_post_wait */ child_post_wait, /* to_post_wait */
fetch_inferior_registers, /* to_fetch_registers */ fetch_inferior_registers, /* to_fetch_registers */
store_inferior_registers, /* to_store_registers */ store_inferior_registers, /* to_store_registers */
child_prepare_to_store, /* to_prepare_to_store */ child_prepare_to_store, /* to_prepare_to_store */
@ -384,33 +917,33 @@ struct target_ops child_ops = {
0, /* to_load */ 0, /* to_load */
0, /* to_lookup_symbol */ 0, /* to_lookup_symbol */
child_create_inferior, /* to_create_inferior */ child_create_inferior, /* to_create_inferior */
NULL, /* to_post_startup_inferior */ child_post_startup_inferior, /* to_post_startup_inferior */
NULL, /* to_acknowledge_created_inferior */ child_acknowledge_created_inferior, /* to_acknowledge_created_inferior */
NULL, /* to_clone_and_follow_inferior */ child_clone_and_follow_inferior, /* to_clone_and_follow_inferior */
NULL, /* to_post_follow_inferior_by_clone */ child_post_follow_inferior_by_clone, /* to_post_follow_inferior_by_clone */
NULL, /* to_insert_fork_catchpoint */ child_insert_fork_catchpoint, /* to_insert_fork_catchpoint */
NULL, /* to_remove_fork_catchpoint */ child_remove_fork_catchpoint, /* to_remove_fork_catchpoint */
NULL, /* to_insert_vfork_catchpoint */ child_insert_vfork_catchpoint, /* to_insert_vfork_catchpoint */
NULL, /* to_remove_vfork_catchpoint */ child_remove_vfork_catchpoint, /* to_remove_vfork_catchpoint */
NULL, /* to_has_forked */ child_has_forked, /* to_has_forked */
NULL, /* to_has_vforked */ child_has_vforked, /* to_has_vforked */
NULL, /* to_can_follow_vfork_prior_to_exec */ child_can_follow_vfork_prior_to_exec, /* to_can_follow_vfork_prior_to_exec */
NULL, /* to_post_follow_vfork */ child_post_follow_vfork, /* to_post_follow_vfork */
NULL, /* to_insert_exec_catchpoint */ child_insert_exec_catchpoint, /* to_insert_exec_catchpoint */
NULL, /* to_remove_exec_catchpoint */ child_remove_exec_catchpoint, /* to_remove_exec_catchpoint */
NULL, /* to_has_execd */ child_has_execd, /* to_has_execd */
NULL, /* to_reported_exec_events_per_exec_call */ child_reported_exec_events_per_exec_call, /* to_reported_exec_events_per_exec_call */
NULL, /* to_has_syscall_event */ child_has_syscall_event, /* to_has_syscall_event */
NULL, /* to_has_exited */ child_has_exited, /* to_has_exited */
child_mourn_inferior, /* to_mourn_inferior */ child_mourn_inferior, /* to_mourn_inferior */
child_can_run, /* to_can_run */ child_can_run, /* to_can_run */
0, /* to_notice_signals */ 0, /* to_notice_signals */
child_thread_alive, /* to_thread_alive */ child_thread_alive, /* to_thread_alive */
child_stop, /* to_stop */ child_stop, /* to_stop */
NULL, /* to_enable_exception_callback */ child_enable_exception_callback, /* to_enable_exception_callback */
NULL, /* to_get_current_exception_event */ child_get_current_exception_event, /* to_get_current_exception_event */
NULL, /* to_pid_to_exec_file */ child_pid_to_exec_file, /* to_pid_to_exec_file */
NULL, /* to_core_file_to_sym_file */ child_core_file_to_sym_file, /* to_core_file_to_sym_file */
process_stratum, /* to_stratum */ process_stratum, /* to_stratum */
0, /* to_next */ 0, /* to_next */
1, /* to_has_all_memory */ 1, /* to_has_all_memory */

5709
gdb/infttrace.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -846,7 +846,7 @@ symbol_add_stub (arg)
so -> objfile = symbol_file_add (so -> so_name, so -> from_tty, so -> objfile = symbol_file_add (so -> so_name, so -> from_tty,
text_addr, text_addr,
0, 0, 0); 0, 0, 0, 0, 0);
return (1); return (1);
} }

View file

@ -59,7 +59,13 @@ get_dynamics_objfile ()
{ {
if (dynamics_objfile == NULL) if (dynamics_objfile == NULL)
{ {
dynamics_objfile = allocate_objfile (NULL, 0);
/* CHECK WITH STU -- edie. Params 3 and 4 are USER_LOADED and IS_SOLIB.
USER_LOADED - used by run_command to remove old objfile entries which
are no longer valid
IS_SOLIB - 1 if the object file is a shared library */
dynamics_objfile = allocate_objfile (NULL, 0, 0, 0);
} }
return dynamics_objfile; return dynamics_objfile;
} }

View file

@ -3925,7 +3925,7 @@ m3_create_inferior (exec_file, allargs, env)
char *allargs; char *allargs;
char **env; char **env;
{ {
fork_inferior (exec_file, allargs, env, m3_trace_me, m3_trace_him, NULL); fork_inferior (exec_file, allargs, env, m3_trace_me, m3_trace_him, NULL, NULL);
/* We are at the first instruction we care about. */ /* We are at the first instruction we care about. */
/* Pedal to the metal... */ /* Pedal to the metal... */
proceed ((CORE_ADDR) -1, 0, 0); proceed ((CORE_ADDR) -1, 0, 0);

View file

@ -54,12 +54,18 @@ int display_time;
int display_space; int display_space;
/* Whether this is the command line version or not */
int tui_version = 0;
/* Whether xdb commands will be handled */ /* Whether xdb commands will be handled */
int xdb_commands = 0; int xdb_commands = 0;
/* Whether dbx commands will be handled */ /* Whether dbx commands will be handled */
int dbx_commands = 0; int dbx_commands = 0;
GDB_FILE *gdb_stdout;
GDB_FILE *gdb_stderr;
static void print_gdb_help PARAMS ((GDB_FILE *)); static void print_gdb_help PARAMS ((GDB_FILE *));
extern void gdb_init PARAMS ((char *)); extern void gdb_init PARAMS ((char *));
#ifdef __CYGWIN__ #ifdef __CYGWIN__
@ -108,6 +114,8 @@ main (argc, argv)
long time_at_startup = get_run_time (); long time_at_startup = get_run_time ();
int gdb_file_size;
START_PROGRESS (argv[0], 0); START_PROGRESS (argv[0], 0);
#ifdef MPW #ifdef MPW
@ -144,6 +152,20 @@ main (argc, argv)
getcwd (gdb_dirbuf, sizeof (gdb_dirbuf)); getcwd (gdb_dirbuf, sizeof (gdb_dirbuf));
current_directory = gdb_dirbuf; current_directory = gdb_dirbuf;
gdb_file_size = sizeof(GDB_FILE);
gdb_stdout = (GDB_FILE *)xmalloc (gdb_file_size);
gdb_stdout->ts_streamtype = afile;
gdb_stdout->ts_filestream = stdout;
gdb_stdout->ts_strbuf = NULL;
gdb_stdout->ts_buflen = 0;
gdb_stderr = (GDB_FILE *)xmalloc (gdb_file_size);
gdb_stderr->ts_streamtype = afile;
gdb_stderr->ts_filestream = stderr;
gdb_stderr->ts_strbuf = NULL;
gdb_stderr->ts_buflen = 0;
/* Parse arguments and options. */ /* Parse arguments and options. */
{ {
int c; int c;
@ -152,6 +174,11 @@ main (argc, argv)
with no equivalent). */ with no equivalent). */
static struct option long_options[] = static struct option long_options[] =
{ {
#if defined(TUI)
{"tui", no_argument, &tui_version, 1},
#endif
{"xdb", no_argument, &xdb_commands, 1},
{"dbx", no_argument, &dbx_commands, 1},
{"readnow", no_argument, &readnow_symbol_files, 1}, {"readnow", no_argument, &readnow_symbol_files, 1},
{"r", no_argument, &readnow_symbol_files, 1}, {"r", no_argument, &readnow_symbol_files, 1},
{"mapped", no_argument, &mapped_symbol_files, 1}, {"mapped", no_argument, &mapped_symbol_files, 1},
@ -340,7 +367,20 @@ main (argc, argv)
/* If --help or --version, disable window interface. */ /* If --help or --version, disable window interface. */
if (print_help || print_version) if (print_help || print_version)
{
use_windows = 0;
#ifdef TUI
/* Disable the TUI as well. */
tui_version = 0;
#endif
}
#ifdef TUI
/* An explicit --tui flag overrides the default UI, which is the
window system. */
if (tui_version)
use_windows = 0; use_windows = 0;
#endif
/* OK, that's all the options. The other arguments are filenames. */ /* OK, that's all the options. The other arguments are filenames. */
count = 0; count = 0;
@ -364,6 +404,10 @@ main (argc, argv)
quiet = 1; quiet = 1;
} }
#if defined(TUI)
if (tui_version)
init_ui_hook = tuiInit;
#endif
gdb_init (argv[0]); gdb_init (argv[0]);
/* Do these (and anything which might call wrap_here or *_filtered) /* Do these (and anything which might call wrap_here or *_filtered)
@ -496,10 +540,12 @@ main (argc, argv)
warning_pre_print = "\nwarning: "; warning_pre_print = "\nwarning: ";
if (corearg != NULL) if (corearg != NULL)
if (!SET_TOP_LEVEL ()) {
core_file_command (corearg, !batch); if (!SET_TOP_LEVEL ())
else if (isdigit (corearg[0]) && !SET_TOP_LEVEL ()) core_file_command (corearg, !batch);
attach_command (corearg, !batch); else if (isdigit (corearg[0]) && !SET_TOP_LEVEL ())
attach_command (corearg, !batch);
}
do_cleanups (ALL_CLEANUPS); do_cleanups (ALL_CLEANUPS);
if (ttyarg != NULL) if (ttyarg != NULL)
@ -626,6 +672,7 @@ Options:\n\n\
--core=COREFILE Analyze the core dump COREFILE.\n\ --core=COREFILE Analyze the core dump COREFILE.\n\
", stream); ", stream);
fputs_unfiltered ("\ fputs_unfiltered ("\
--dbx DBX compatibility mode.\n\
--directory=DIR Search for source files in DIR.\n\ --directory=DIR Search for source files in DIR.\n\
--epoch Output information used by epoch emacs-GDB interface.\n\ --epoch Output information used by epoch emacs-GDB interface.\n\
--exec=EXECFILE Use EXECFILE as the executable.\n\ --exec=EXECFILE Use EXECFILE as the executable.\n\
@ -643,7 +690,15 @@ Options:\n\n\
--se=FILE Use FILE as symbol file and executable file.\n\ --se=FILE Use FILE as symbol file and executable file.\n\
--symbols=SYMFILE Read symbols from SYMFILE.\n\ --symbols=SYMFILE Read symbols from SYMFILE.\n\
--tty=TTY Use TTY for input/output by the program being debugged.\n\ --tty=TTY Use TTY for input/output by the program being debugged.\n\
", stream);
#if defined(TUI)
fputs_unfiltered ("\
--tui Use a terminal user interface.\n\
", stream);
#endif
fputs_unfiltered ("\
--version Print version information and then exit.\n\ --version Print version information and then exit.\n\
--xdb XDB compatibility mode.\n\
", stream); ", stream);
#ifdef ADDITIONAL_OPTION_HELP #ifdef ADDITIONAL_OPTION_HELP
fputs_unfiltered (ADDITIONAL_OPTION_HELP, stream); fputs_unfiltered (ADDITIONAL_OPTION_HELP, stream);
@ -676,12 +731,57 @@ proc_remove_foreign (pid)
void void
fputs_unfiltered (linebuffer, stream) fputs_unfiltered (linebuffer, stream)
const char *linebuffer; const char *linebuffer;
FILE *stream; GDB_FILE *stream;
{ {
#if defined(TUI)
extern int tui_owns_terminal;
#endif
/* If anything (GUI, TUI) wants to capture GDB output, this is
* the place... the way to do it is to set up
* fputs_unfiltered_hook.
* Our TUI ("gdb -tui") used to hook output, but in the
* new (XDB style) scheme, we do not do that anymore... - RT
*/
if (fputs_unfiltered_hook if (fputs_unfiltered_hook
&& (stream == gdb_stdout && (stream == gdb_stdout
|| stream == gdb_stderr)) || stream == gdb_stderr))
fputs_unfiltered_hook (linebuffer, stream); fputs_unfiltered_hook (linebuffer, stream);
else else
fputs (linebuffer, stream); {
#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) {
gdb_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) {
gdb_file_adjust_strbuf(strlen(linebuffer), stream);
strcat(stream->ts_strbuf, linebuffer);
} else fputs (linebuffer, stream->ts_filestream);
}
#else
if (stream->ts_streamtype == astring) {
gdb_file_adjust_strbuf(strlen(linebuffer), stream);
strcat(stream->ts_strbuf, linebuffer);
} else fputs (linebuffer, stream->ts_filestream);
#endif
}
} }

View file

@ -123,12 +123,21 @@ build_objfile_section_table (objfile)
/* Given a pointer to an initialized bfd (ABFD) and a flag that indicates /* Given a pointer to an initialized bfd (ABFD) and a flag that indicates
whether or not an objfile is to be mapped (MAPPED), allocate a new objfile whether or not an objfile is to be mapped (MAPPED), allocate a new objfile
struct, fill it in as best we can, link it into the list of all known struct, fill it in as best we can, link it into the list of all known
objfiles, and return a pointer to the new objfile struct. */ objfiles, and return a pointer to the new objfile struct.
USER_LOADED is simply recorded in the objfile. This record offers a way for
run_command to remove old objfile entries which are no longer valid (i.e.,
are associated with an old inferior), but to preserve ones that the user
explicitly loaded via the add-symbol-file command.
IS_SOLIB is also simply recorded in the objfile. */
struct objfile * struct objfile *
allocate_objfile (abfd, mapped) allocate_objfile (abfd, mapped, user_loaded, is_solib)
bfd *abfd; bfd *abfd;
int mapped; int mapped;
int user_loaded;
int is_solib;
{ {
struct objfile *objfile = NULL; struct objfile *objfile = NULL;
struct objfile *last_one = NULL; struct objfile *last_one = NULL;
@ -287,6 +296,15 @@ allocate_objfile (abfd, mapped)
last_one = last_one -> next); last_one = last_one -> next);
last_one -> next = objfile; last_one -> next = objfile;
} }
/* Record whether this objfile was created because the user explicitly
caused it (e.g., used the add-symbol-file command).
*/
objfile -> user_loaded = user_loaded;
/* Record whether this objfile definitely represents a solib. */
objfile -> is_solib = is_solib;
return (objfile); return (objfile);
} }
@ -541,7 +559,8 @@ objfile_relocate (objfile, new_offsets)
But I'm leaving out that test, on the theory that But I'm leaving out that test, on the theory that
they can't possibly pass the tests below. */ they can't possibly pass the tests below. */
if ((SYMBOL_CLASS (sym) == LOC_LABEL if ((SYMBOL_CLASS (sym) == LOC_LABEL
|| SYMBOL_CLASS (sym) == LOC_STATIC) || SYMBOL_CLASS (sym) == LOC_STATIC
|| SYMBOL_CLASS (sym) == LOC_INDIRECT)
&& SYMBOL_SECTION (sym) >= 0) && SYMBOL_SECTION (sym) >= 0)
{ {
SYMBOL_VALUE_ADDRESS (sym) += SYMBOL_VALUE_ADDRESS (sym) +=
@ -699,6 +718,28 @@ have_full_symbols ()
return 0; return 0;
} }
/* This operations deletes all objfile entries that represent solibs that
weren't explicitly loaded by the user, via e.g., the add-symbol-file
command.
*/
void
objfile_purge_solibs ()
{
struct objfile * objf;
struct objfile * temp;
ALL_OBJFILES_SAFE (objf, temp)
{
/* We assume that the solib package has been purged already, or will
be soon.
*/
if (! objf->user_loaded && objf->is_solib)
free_objfile (objf);
}
}
/* Many places in gdb want to test just to see if we have any minimal /* Many places in gdb want to test just to see if we have any minimal
symbols available. This function returns zero if none are currently symbols available. This function returns zero if none are currently
available, nonzero otherwise. */ available, nonzero otherwise. */
@ -903,8 +944,13 @@ find_pc_sect_section (pc, section)
ALL_OBJFILES (objfile) ALL_OBJFILES (objfile)
for (s = objfile->sections; s < objfile->sections_end; ++s) for (s = objfile->sections; s < objfile->sections_end; ++s)
#if defined(HPUXHPPA)
if ((section == 0 || section == s->the_bfd_section) &&
s->addr <= pc && pc <= s->endaddr)
#else
if ((section == 0 || section == s->the_bfd_section) && if ((section == 0 || section == s->the_bfd_section) &&
s->addr <= pc && pc < s->endaddr) s->addr <= pc && pc < s->endaddr)
#endif
return(s); return(s);
return(NULL); return(NULL);

View file

@ -159,6 +159,24 @@ struct obj_section {
int ovly_mapped; int ovly_mapped;
}; };
/* An import entry contains information about a symbol that
is used in this objfile but not defined in it, and so needs
to be imported from some other objfile */
/* Currently we just store the name; no attributes. 1997-08-05 */
typedef char * ImportEntry;
/* An export entry contains information about a symbol that
is defined in this objfile and available for use in other
objfiles */
typedef struct {
char * name; /* name of exported symbol */
int address; /* offset subject to relocation */
/* Currently no other attributes 1997-08-05 */
} ExportEntry;
/* The "objstats" structure provides a place for gdb to record some /* The "objstats" structure provides a place for gdb to record some
interesting information about its internal state at runtime, on a interesting information about its internal state at runtime, on a
per objfile basis, such as information about the number of symbols per objfile basis, such as information about the number of symbols
@ -219,6 +237,22 @@ struct objfile
char *name; char *name;
/* TRUE if this objfile was created because the user explicitly caused
it (e.g., used the add-symbol-file command).
*/
int user_loaded;
/* TRUE if this objfile was explicitly created to represent a solib.
(If FALSE, the objfile may actually be a solib. This can happen if
the user created the objfile by using the add-symbol-file command.
GDB doesn't in that situation actually check whether the file is a
solib. Rather, the target's implementation of the solib interface
is responsible for setting this flag when noticing solibs used by
an inferior.)
*/
int is_solib;
/* Some flag bits for this objfile. */ /* Some flag bits for this objfile. */
unsigned short flags; unsigned short flags;
@ -358,6 +392,14 @@ struct objfile
/* two auxiliary fields, used to hold the fp of separate symbol files */ /* two auxiliary fields, used to hold the fp of separate symbol files */
FILE *auxf1, *auxf2; FILE *auxf1, *auxf2;
/* Imported symbols */
ImportEntry * import_list;
int import_list_size;
/* Exported symbols */
ExportEntry * export_list;
int export_list_size;
/* Place to stash various statistics about this objfile */ /* Place to stash various statistics about this objfile */
OBJSTATS; OBJSTATS;
}; };
@ -428,7 +470,7 @@ extern struct objfile *object_files;
/* Declarations for functions defined in objfiles.c */ /* Declarations for functions defined in objfiles.c */
extern struct objfile * extern struct objfile *
allocate_objfile PARAMS ((bfd *, int)); allocate_objfile PARAMS ((bfd *, int, int, int));
extern int extern int
build_objfile_section_table PARAMS ((struct objfile *)); build_objfile_section_table PARAMS ((struct objfile *));
@ -453,6 +495,13 @@ have_partial_symbols PARAMS ((void));
extern int extern int
have_full_symbols PARAMS ((void)); have_full_symbols PARAMS ((void));
/* This operation deletes all objfile entries that represent solibs that
weren't explicitly loaded by the user, via e.g., the add-symbol-file
command.
*/
extern void
objfile_purge_solibs PARAMS ((void));
/* Functions for dealing with the minimal symbol table, really a misc /* Functions for dealing with the minimal symbol table, really a misc
address<->symbol mapping for things we don't have debug symbols for. */ address<->symbol mapping for things we don't have debug symbols for. */

View file

@ -592,7 +592,7 @@ symbol_add_stub (arg)
so -> objfile = symbol_file_add (so -> so_name, so -> from_tty, so -> objfile = symbol_file_add (so -> so_name, so -> from_tty,
text_addr, text_addr,
0, 0, 0); 0, 0, 0, 0, 1);
return (1); return (1);
} }

View file

@ -59,6 +59,8 @@ int comma_terminates;
static int expressiondebug = 0; static int expressiondebug = 0;
#endif #endif
extern int hp_som_som_object_present;
static void static void
free_funcalls PARAMS ((void)); free_funcalls PARAMS ((void));
@ -477,6 +479,9 @@ write_dollar_variable (str)
/* Handle the tokens $digits; also $ (short for $0) and $$ (short for $$1) /* Handle the tokens $digits; also $ (short for $0) and $$ (short for $$1)
and $$digits (equivalent to $<-digits> if you could type that). */ and $$digits (equivalent to $<-digits> if you could type that). */
struct symbol * sym = NULL;
struct minimal_symbol * msym = NULL;
int negate = 0; int negate = 0;
int i = 1; int i = 1;
/* Double dollar means negate the number and add -1 as well. /* Double dollar means negate the number and add -1 as well.
@ -510,6 +515,29 @@ write_dollar_variable (str)
if( i >= 0 ) if( i >= 0 )
goto handle_register; goto handle_register;
/* On HP-UX, certain system routines (millicode) have names beginning
with $ or $$, e.g. $$dyncall, which handles inter-space procedure
calls on PA-RISC. Check for those, first. */
sym = lookup_symbol (copy_name (str), (struct block *) NULL,
VAR_NAMESPACE, (int *) NULL, (struct symtab **) NULL);
if (sym)
{
write_exp_elt_opcode (OP_VAR_VALUE);
write_exp_elt_block (block_found); /* set by lookup_symbol */
write_exp_elt_sym (sym);
write_exp_elt_opcode (OP_VAR_VALUE);
return;
}
msym = lookup_minimal_symbol (copy_name (str), NULL, NULL);
if (msym)
{
write_exp_msymbol (msym,
lookup_function_type (builtin_type_int),
builtin_type_int);
return;
}
/* Any other names starting in $ are debugger internal variables. */ /* Any other names starting in $ are debugger internal variables. */
write_exp_elt_opcode (OP_INTERNALVAR); write_exp_elt_opcode (OP_INTERNALVAR);
@ -527,6 +555,257 @@ write_dollar_variable (str)
write_exp_elt_opcode (OP_REGISTER); write_exp_elt_opcode (OP_REGISTER);
return; return;
} }
/* Parse a string that is possibly a namespace / nested class
specification, i.e., something of the form A::B::C::x. Input
(NAME) is the entire string; LEN is the current valid length; the
output is a string, TOKEN, which points to the largest recognized
prefix which is a series of namespaces or classes. CLASS_PREFIX is
another output, which records whether a nested class spec was
recognized (= 1) or a fully qualified variable name was found (=
0). ARGPTR is side-effected (if non-NULL) to point to beyond the
string recognized and consumed by this routine.
The return value is a pointer to the symbol for the base class or
variable if found, or NULL if not found. Callers must check this
first -- if NULL, the outputs may not be correct.
This function is used c-exp.y. This is used specifically to get
around HP aCC (and possibly other compilers), which insists on
generating names with embedded colons for namespace or nested class
members.
(Argument LEN is currently unused. 1997-08-27)
Callers must free memory allocated for the output string TOKEN. */
static const char coloncolon[2] = {':',':'};
struct symbol *
parse_nested_classes_for_hpacc (name, len, token, class_prefix, argptr)
char * name;
int len;
char ** token;
int * class_prefix;
char ** argptr;
{
/* Comment below comes from decode_line_1 which has very similar
code, which is called for "break" command parsing. */
/* We have what looks like a class or namespace
scope specification (A::B), possibly with many
levels of namespaces or classes (A::B::C::D).
Some versions of the HP ANSI C++ compiler (as also possibly
other compilers) generate class/function/member names with
embedded double-colons if they are inside namespaces. To
handle this, we loop a few times, considering larger and
larger prefixes of the string as though they were single
symbols. So, if the initially supplied string is
A::B::C::D::foo, we have to look up "A", then "A::B",
then "A::B::C", then "A::B::C::D", and finally
"A::B::C::D::foo" as single, monolithic symbols, because
A, B, C or D may be namespaces.
Note that namespaces can nest only inside other
namespaces, and not inside classes. So we need only
consider *prefixes* of the string; there is no need to look up
"B::C" separately as a symbol in the previous example. */
register char * p;
char * start, * end;
char * prefix = NULL;
char * tmp;
struct symbol * sym_class = NULL;
struct symbol * sym_var = NULL;
struct type * t;
register int i;
int colons_found = 0;
int prefix_len = 0;
int done = 0;
char * q;
/* Check for HP-compiled executable -- in other cases
return NULL, and caller must default to standard GDB
behaviour. */
if (!hp_som_som_object_present)
return (struct symbol *) NULL;
p = name;
/* Skip over whitespace and possible global "::" */
while (*p && (*p == ' ' || *p == '\t')) p++;
if (p[0] == ':' && p[1] == ':')
p += 2;
while (*p && (*p == ' ' || *p == '\t')) p++;
while (1)
{
/* Get to the end of the next namespace or class spec. */
/* If we're looking at some non-token, fail immediately */
start = p;
if (!(isalpha (*p) || *p == '$' || *p == '_'))
return (struct symbol *) NULL;
p++;
while (*p && (isalnum (*p) || *p == '$' || *p == '_')) p++;
if (*p == '<')
{
/* If we have the start of a template specification,
scan right ahead to its end */
q = find_template_name_end (p);
if (q)
p = q;
}
end = p;
/* Skip over "::" and whitespace for next time around */
while (*p && (*p == ' ' || *p == '\t')) p++;
if (p[0] == ':' && p[1] == ':')
p += 2;
while (*p && (*p == ' ' || *p == '\t')) p++;
/* Done with tokens? */
if (!*p || !(isalpha (*p) || *p == '$' || *p == '_'))
done = 1;
tmp = (char *) alloca (prefix_len + end - start + 3);
if (prefix)
{
memcpy (tmp, prefix, prefix_len);
memcpy (tmp + prefix_len, coloncolon, 2);
memcpy (tmp + prefix_len + 2, start, end - start);
tmp[prefix_len + 2 + end - start] = '\000';
}
else
{
memcpy (tmp, start, end - start);
tmp[end - start] = '\000';
}
prefix = tmp;
prefix_len = strlen (prefix);
#if 0 /* DEBUGGING */
printf ("Searching for nested class spec: Prefix is %s\n", prefix);
#endif
/* See if the prefix we have now is something we know about */
if (!done)
{
/* More tokens to process, so this must be a class/namespace */
sym_class = lookup_symbol (prefix, 0, STRUCT_NAMESPACE,
0, (struct symtab **) NULL);
}
else
{
/* No more tokens, so try as a variable first */
sym_var = lookup_symbol (prefix, 0, VAR_NAMESPACE,
0, (struct symtab **) NULL);
/* If failed, try as class/namespace */
if (!sym_var)
sym_class = lookup_symbol (prefix, 0, STRUCT_NAMESPACE,
0, (struct symtab **) NULL);
}
if (sym_var ||
(sym_class &&
(t = check_typedef (SYMBOL_TYPE (sym_class)),
(TYPE_CODE (t) == TYPE_CODE_STRUCT
|| TYPE_CODE (t) == TYPE_CODE_UNION))))
{
/* We found a valid token */
*token = (char *) xmalloc (prefix_len + 1 );
memcpy (*token, prefix, prefix_len);
(*token)[prefix_len] = '\000';
break;
}
/* No variable or class/namespace found, no more tokens */
if (done)
return (struct symbol *) NULL;
}
/* Out of loop, so we must have found a valid token */
if (sym_var)
*class_prefix = 0;
else
*class_prefix = 1;
if (argptr)
*argptr = done ? p : end;
#if 0 /* DEBUGGING */
printf ("Searching for nested class spec: Token is %s, class_prefix %d\n", *token, *class_prefix);
#endif
return sym_var ? sym_var : sym_class; /* found */
}
char *
find_template_name_end (p)
char * p;
{
int depth = 1;
int just_seen_right = 0;
int just_seen_colon = 0;
int just_seen_space = 0;
if (!p || (*p != '<'))
return 0;
while (*++p)
{
switch (*p)
{
case '\'': case '\"':
case '{': case '}':
/* In future, may want to allow these?? */
return 0;
case '<':
depth++; /* start nested template */
if (just_seen_colon || just_seen_right || just_seen_space)
return 0; /* but not after : or :: or > or space */
break;
case '>':
if (just_seen_colon || just_seen_right)
return 0; /* end a (nested?) template */
just_seen_right = 1; /* but not after : or :: */
if (--depth == 0) /* also disallow >>, insist on > > */
return ++p; /* if outermost ended, return */
break;
case ':':
if (just_seen_space || (just_seen_colon > 1))
return 0; /* nested class spec coming up */
just_seen_colon++; /* we allow :: but not :::: */
break;
case ' ':
break;
default:
if (!((*p >= 'a' && *p <= 'z') || /* allow token chars */
(*p >= 'A' && *p <= 'Z') ||
(*p >= '0' && *p <= '9') ||
(*p == '_') || (*p == ',') || /* commas for template args */
(*p == '&') || (*p == '*') || /* pointer and ref types */
(*p == '(') || (*p == ')') || /* function types */
(*p == '[') || (*p == ']') )) /* array types */
return 0;
}
if (*p != ' ')
just_seen_space = 0;
if (*p != ':')
just_seen_colon = 0;
if (*p != '>')
just_seen_right = 0;
}
return 0;
}
/* Return a null-terminated temporary copy of the name /* Return a null-terminated temporary copy of the name
of a string token. */ of a string token. */

View file

@ -534,7 +534,7 @@ static void procfs_attach PARAMS ((char *, int));
static void proc_set_exec_trap PARAMS ((void)); static void proc_set_exec_trap PARAMS ((void));
static int procfs_init_inferior PARAMS ((int)); static void procfs_init_inferior PARAMS ((int));
static struct procinfo *create_procinfo PARAMS ((int)); static struct procinfo *create_procinfo PARAMS ((int));
@ -2519,7 +2519,7 @@ LOCAL FUNCTION
SYNOPSIS SYNOPSIS
int procfs_init_inferior (int pid) void procfs_init_inferior (int pid)
DESCRIPTION DESCRIPTION
@ -2537,7 +2537,7 @@ NOTES
*/ */
static int static void
procfs_init_inferior (pid) procfs_init_inferior (pid)
int pid; int pid;
{ {
@ -2563,7 +2563,6 @@ procfs_init_inferior (pid)
/* One trap to exec the shell, one to exec the program being debugged. */ /* One trap to exec the shell, one to exec the program being debugged. */
startup_inferior (2); startup_inferior (2);
#endif #endif
return (pid);
} }
/* /*
@ -5574,7 +5573,7 @@ procfs_create_inferior (exec_file, allargs, env)
} }
fork_inferior (exec_file, allargs, env, fork_inferior (exec_file, allargs, env,
proc_set_exec_trap, procfs_init_inferior, shell_file); proc_set_exec_trap, procfs_init_inferior, NULL, shell_file);
/* We are at the first instruction we care about. */ /* We are at the first instruction we care about. */
/* Pedal to the metal... */ /* Pedal to the metal... */

View file

@ -70,9 +70,9 @@ pyr_do_registers_info (regnum, fpregs)
if (i == regnum) { if (i == regnum) {
long val = raw_regs[i]; long val = raw_regs[i];
fputs_filtered (REGISTER_NAME (i), stdout); fputs_filtered (REGISTER_NAME (i), gdb_stdout);
printf_filtered(":"); printf_filtered(":");
print_spaces_filtered (6 - strlen (REGISTER_NAME (i)), stdout); print_spaces_filtered (6 - strlen (REGISTER_NAME (i)), gdb_stdout);
if (val == 0) if (val == 0)
printf_filtered ("0"); printf_filtered ("0");
else else
@ -89,7 +89,7 @@ CORE_ADDR frame_locals_address (frame)
register int addr = find_saved_register (frame,CFP_REGNUM); register int addr = find_saved_register (frame,CFP_REGNUM);
register int result = read_memory_integer (addr, 4); register int result = read_memory_integer (addr, 4);
#ifdef PYRAMID_CONTROL_FRAME_DEBUGGING #ifdef PYRAMID_CONTROL_FRAME_DEBUGGING
fprintf_unfiltered (stderr, fprintf_unfiltered (gdb_stderr,
"\t[[..frame_locals:%8x, %s= %x @%x fcfp= %x foo= %x\n\t gr13=%x pr13=%x tr13=%x @%x]]\n", "\t[[..frame_locals:%8x, %s= %x @%x fcfp= %x foo= %x\n\t gr13=%x pr13=%x tr13=%x @%x]]\n",
frame->frame, frame->frame,
REGISTER_NAME (CFP_REGNUM), REGISTER_NAME (CFP_REGNUM),
@ -115,7 +115,7 @@ CORE_ADDR frame_args_addr (frame)
register int result = read_memory_integer (addr, 4); register int result = read_memory_integer (addr, 4);
#ifdef PYRAMID_CONTROL_FRAME_DEBUGGING #ifdef PYRAMID_CONTROL_FRAME_DEBUGGING
fprintf_unfiltered (stderr, fprintf_unfiltered (gdb_stderr,
"\t[[..frame_args:%8x, %s= %x @%x fcfp= %x r_r= %x\n\t gr13=%x pr13=%x tr13=%x @%x]]\n", "\t[[..frame_args:%8x, %s= %x @%x fcfp= %x r_r= %x\n\t gr13=%x pr13=%x tr13=%x @%x]]\n",
frame->frame, frame->frame,
REGISTER_NAME (CFP_REGNUM), REGISTER_NAME (CFP_REGNUM),
@ -184,7 +184,7 @@ CORE_ADDR pyr_saved_pc(frame)
int int
pyr_print_insn (memaddr, stream) pyr_print_insn (memaddr, stream)
CORE_ADDR memaddr; CORE_ADDR memaddr;
FILE *stream; GDB_FILE *stream;
{ {
unsigned char buffer[MAXLEN]; unsigned char buffer[MAXLEN];
register int i, nargs, insn_size =4; register int i, nargs, insn_size =4;

View file

@ -115,7 +115,7 @@ fetch_inferior_registers (regno)
supply_register(CSP_REGNUM, reg_buf+CSP_REGNUM); supply_register(CSP_REGNUM, reg_buf+CSP_REGNUM);
#ifdef PYRAMID_CONTROL_FRAME_DEBUGGING #ifdef PYRAMID_CONTROL_FRAME_DEBUGGING
if (skipped_frames) { if (skipped_frames) {
fprintf_unfiltered (stderr, fprintf_unfiltered (gdb_stderr,
"skipped %d frames from %x to %x; cfp was %x, now %x\n", "skipped %d frames from %x to %x; cfp was %x, now %x\n",
skipped_frames, reg_buf[CSP_REGNUM]); skipped_frames, reg_buf[CSP_REGNUM]);
} }

View file

@ -1299,7 +1299,7 @@ udi_load (args, from_tty)
/* As a convenience, pick up any symbol info that is in the program /* As a convenience, pick up any symbol info that is in the program
being loaded. Note that we assume that the program is the``mainline''; being loaded. Note that we assume that the program is the``mainline'';
if this is not always true, then this code will need to be augmented. */ if this is not always true, then this code will need to be augmented. */
symbol_file_add (strtok (args, " \t"), from_tty, 0, 1, 0, 0); symbol_file_add (strtok (args, " \t"), from_tty, 0, 1, 0, 0, 0, 0);
/* Getting new symbols may change our opinion about what is /* Getting new symbols may change our opinion about what is
frameless. */ frameless. */

View file

@ -691,7 +691,7 @@ vx_add_symbols (name, from_tty, text_addr, data_addr, bss_addr)
/* It might be nice to suppress the breakpoint_re_set which happens here /* It might be nice to suppress the breakpoint_re_set which happens here
because we are going to do one again after the objfile_relocate. */ because we are going to do one again after the objfile_relocate. */
objfile = symbol_file_add (name, from_tty, 0, 0, 0, 0); objfile = symbol_file_add (name, from_tty, 0, 0, 0, 0, 0, 0);
/* This is a (slightly cheesy) way of superceding the old symbols. A less /* This is a (slightly cheesy) way of superceding the old symbols. A less
cheesy way would be to find the objfile with the same name and cheesy way would be to find the objfile with the same name and

View file

@ -39,10 +39,10 @@ static serial_t scb_base;
suitable for playback by gdbserver. */ suitable for playback by gdbserver. */
static char *serial_logfile = NULL; static char *serial_logfile = NULL;
static FILE *serial_logfp = NULL; static GDB_FILE *serial_logfp = NULL;
static struct serial_ops *serial_interface_lookup PARAMS ((char *)); static struct serial_ops *serial_interface_lookup PARAMS ((char *));
static void serial_logchar PARAMS ((int chtype, int ch, int timeout)); static void serial_logchar PARAMS ((int, int, int));
static char logbase_hex[] = "hex"; static char logbase_hex[] = "hex";
static char logbase_octal[] = "octal"; static char logbase_octal[] = "octal";
static char logbase_ascii[] = "ascii"; static char logbase_ascii[] = "ascii";
@ -59,15 +59,15 @@ static int serial_current_type = 0;
#define SERIAL_BREAK 1235 #define SERIAL_BREAK 1235
static void static void
serial_logchar (chtype, ch, timeout) serial_logchar (ch_type, ch, timeout)
int chtype; int ch_type;
int ch; int ch;
int timeout; int timeout;
{ {
if (chtype != serial_current_type) if (ch_type != serial_current_type)
{ {
fprintf_unfiltered (serial_logfp, "\n%c ", chtype); fprintf_unfiltered (serial_logfp, "\n%c ", ch_type);
serial_current_type = chtype; serial_current_type = ch_type;
} }
if (serial_logbase != logbase_ascii) if (serial_logbase != logbase_ascii)
@ -308,7 +308,8 @@ serial_close (scb, really_close)
fputs_unfiltered ("\nEnd of log\n", serial_logfp); fputs_unfiltered ("\nEnd of log\n", serial_logfp);
serial_current_type = 0; serial_current_type = 0;
fclose (serial_logfp); /* XXX - What if serial_logfp == stdout or stderr? */ /* XXX - What if serial_logfp == gdb_stdout or gdb_stderr? */
gdb_fclose (serial_logfp);
serial_logfp = NULL; serial_logfp = NULL;
} }

View file

@ -207,6 +207,8 @@ solib_add_common_symbols PARAMS ((struct rtc_symb *));
#endif #endif
void _initialize_solib PARAMS ((void));
/* If non-zero, this is a prefix that will be added to the front of the name /* If non-zero, this is a prefix that will be added to the front of the name
shared libraries with an absolute filename for loading. */ shared libraries with an absolute filename for loading. */
static char *solib_absolute_prefix = NULL; static char *solib_absolute_prefix = NULL;
@ -412,7 +414,7 @@ solib_add_common_symbols (rtc_symp)
} }
init_minimal_symbol_collection (); init_minimal_symbol_collection ();
make_cleanup (discard_minimal_symbols, 0); make_cleanup ((make_cleanup_func) discard_minimal_symbols, 0);
while (rtc_symp) while (rtc_symp)
{ {
@ -583,7 +585,7 @@ look_for_base (fd, baseaddr)
if (fd == -1 if (fd == -1
|| (exec_bfd != NULL || (exec_bfd != NULL
&& fdmatch (fileno ((GDB_FILE *)(exec_bfd -> iostream)), fd))) && fdmatch (fileno ((FILE *)(exec_bfd -> iostream)), fd)))
{ {
return (0); return (0);
} }
@ -969,7 +971,7 @@ find_solib (so_list_ptr)
if (! solib_cleanup_queued) if (! solib_cleanup_queued)
{ {
make_run_cleanup (do_clear_solib); make_run_cleanup (do_clear_solib, NULL);
solib_cleanup_queued = 1; solib_cleanup_queued = 1;
} }
@ -1040,7 +1042,7 @@ symbol_add_stub (arg)
so -> objfile = so -> objfile =
symbol_file_add (so -> so_name, so -> from_tty, symbol_file_add (so -> so_name, so -> from_tty,
text_addr, text_addr,
0, 0, 0); 0, 0, 0, 0, 1);
return (1); return (1);
} }
@ -1119,7 +1121,7 @@ solib_add (arg_string, from_tty, target)
here, otherwise we dereference a potential dangling pointer here, otherwise we dereference a potential dangling pointer
for each call to target_read/write_memory within this routine. */ for each call to target_read/write_memory within this routine. */
update_coreops = core_ops.to_sections == target->to_sections; update_coreops = core_ops.to_sections == target->to_sections;
/* Reallocate the target's section table including the new size. */ /* Reallocate the target's section table including the new size. */
if (target -> to_sections) if (target -> to_sections)
{ {

View file

@ -44,9 +44,140 @@ solib_add PARAMS ((char *, int, struct target_ops *));
#define SOLIB_CREATE_INFERIOR_HOOK(PID) solib_create_inferior_hook() #define SOLIB_CREATE_INFERIOR_HOOK(PID) solib_create_inferior_hook()
/* Function to be called to remove the connection between debugger and
dynamic linker that was established by SOLIB_CREATE_INFERIOR_HOOK.
(This operation does not remove shared library information from
the debugger, as CLEAR_SOLIB does.)
This functionality is presently not implemented for this target.
*/
#define SOLIB_REMOVE_INFERIOR_HOOK(PID) (0)
extern void extern void
solib_create_inferior_hook PARAMS((void)); /* solib.c */ solib_create_inferior_hook PARAMS((void)); /* solib.c */
/* This function is called by the "catch load" command. It allows
the debugger to be notified by the dynamic linker when a specified
library file (or any library file, if filename is NULL) is loaded.
Presently, this functionality is not implemented.
*/
#define SOLIB_CREATE_CATCH_LOAD_HOOK(pid,tempflag,filename,cond_string) \
error("catch of library loads/unloads not yet implemented on this platform")
/* This function is called by the "catch unload" command. It allows
the debugger to be notified by the dynamic linker when a specified
library file (or any library file, if filename is NULL) is unloaded.
Presently, this functionality is not implemented.
*/
#define SOLIB_CREATE_CATCH_UNLOAD_HOOK(pid,tempflag,filename,cond_string) \
error("catch of library loads/unloads not yet implemented on this platform")
/* This function returns TRUE if the dynamic linker has just reported
a load of a library.
This function must be used only when the inferior has stopped in
the dynamic linker hook, or undefined results are guaranteed.
Presently, this functionality is not implemented.
*/
/*
#define SOLIB_HAVE_LOAD_EVENT(pid) \
error("catch of library loads/unloads not yet implemented on this platform")
*/
#define SOLIB_HAVE_LOAD_EVENT(pid) \
(0)
/* This function returns a pointer to the string representation of the
pathname of the dynamically-linked library that has just been loaded.
This function must be used only when SOLIB_HAVE_LOAD_EVENT is TRUE,
or undefined results are guaranteed.
This string's contents are only valid immediately after the inferior
has stopped in the dynamic linker hook, and becomes invalid as soon
as the inferior is continued. Clients should make a copy of this
string if they wish to continue the inferior and then access the string.
Presently, this functionality is not implemented.
*/
/*
#define SOLIB_LOADED_LIBRARY_PATHNAME(pid) \
error("catch of library loads/unloads not yet implemented on this platform")
*/
#define SOLIB_LOADED_LIBRARY_PATHNAME(pid) \
(0)
/* This function returns TRUE if the dynamic linker has just reported
an unload of a library.
This function must be used only when the inferior has stopped in
the dynamic linker hook, or undefined results are guaranteed.
Presently, this functionality is not implemented.
*/
/*
#define SOLIB_HAVE_UNLOAD_EVENT(pid) \
error("catch of library loads/unloads not yet implemented on this platform")
*/
#define SOLIB_HAVE_UNLOAD_EVENT(pid) \
(0)
/* This function returns a pointer to the string representation of the
pathname of the dynamically-linked library that has just been unloaded.
This function must be used only when SOLIB_HAVE_UNLOAD_EVENT is TRUE,
or undefined results are guaranteed.
This string's contents are only valid immediately after the inferior
has stopped in the dynamic linker hook, and becomes invalid as soon
as the inferior is continued. Clients should make a copy of this
string if they wish to continue the inferior and then access the string.
Presently, this functionality is not implemented.
*/
/*
#define SOLIB_UNLOADED_LIBRARY_PATHNAME(pid) \
error("catch of library loads/unloads not yet implemented on this platform")
*/
#define SOLIB_UNLOADED_LIBRARY_PATHNAME(pid) \
(0)
/* This function returns TRUE if pc is the address of an instruction that
lies within the dynamic linker (such as the event hook, or the dld
itself).
This function must be used only when a dynamic linker event has been
caught, and the inferior is being stepped out of the hook, or undefined
results are guaranteed.
Presently, this functionality is not implemented.
*/
/*
#define SOLIB_IN_DYNAMIC_LINKER(pid,pc) \
error("catch of library loads/unloads not yet implemented on this platform")
*/
#define SOLIB_IN_DYNAMIC_LINKER(pid,pc) \
(0)
/* This function must be called when the inferior is killed, and the program
restarted. This is not the same as CLEAR_SOLIB, in that it doesn't discard
any symbol tables.
Presently, this functionality is not implemented.
*/
#define SOLIB_RESTART() \
(0)
/* If we can't set a breakpoint, and it's in a shared library, just /* If we can't set a breakpoint, and it's in a shared library, just
disable it. */ disable it. */

View file

@ -123,11 +123,19 @@ som_symtab_read (abfd, objfile, section_offsets)
There's nothing in the header which easily allows us to do There's nothing in the header which easily allows us to do
this. The only reliable way I know of is to check for the this. The only reliable way I know of is to check for the
existance of a $SHLIB_INFO$ section with a non-zero size. */ existance of a $SHLIB_INFO$ section with a non-zero size. */
shlib_info = bfd_get_section_by_name (objfile->obfd, "$SHLIB_INFO$"); /* The code below is not a reliable way to check whether an
if (shlib_info) * executable is dynamic, so I commented it out - RT
dynamic = (bfd_section_size (objfile->obfd, shlib_info) != 0); * shlib_info = bfd_get_section_by_name (objfile->obfd, "$SHLIB_INFO$");
else * if (shlib_info)
dynamic = 0; * dynamic = (bfd_section_size (objfile->obfd, shlib_info) != 0);
* else
* dynamic = 0;
*/
/* I replaced the code with a simple check for text offset not being
* zero. Still not 100% reliable, but a more reliable way of asking
* "is this a dynamic executable?" than the above. RT
*/
dynamic = (text_offset != 0);
endbufp = buf + number_of_symbols; endbufp = buf + number_of_symbols;
for (bufp = buf; bufp < endbufp; ++bufp) for (bufp = buf; bufp < endbufp; ++bufp)
@ -355,19 +363,43 @@ som_symfile_read (objfile, section_offsets, mainline)
init_minimal_symbol_collection (); init_minimal_symbol_collection ();
back_to = make_cleanup (discard_minimal_symbols, 0); back_to = make_cleanup (discard_minimal_symbols, 0);
/* Process the normal SOM symbol table first. */ /* Read in the import list and the export list. Currently
the export list isn't used; the import list is used in
hp-symtab-read.c to handle static vars declared in other
shared libraries. */
init_import_symbols (objfile);
#if 0 /* Export symbols not used today 1997-08-05 */
init_export_symbols (objfile);
#else
objfile->export_list = NULL;
objfile->export_list_size = 0;
#endif
/* Process the normal SOM symbol table first.
This reads in the DNTT and string table, but doesn't
actually scan the DNTT. It does scan the linker symbol
table and thus build up a "minimal symbol table". */
som_symtab_read (abfd, objfile, section_offsets); som_symtab_read (abfd, objfile, section_offsets);
/* Now read information from the stabs debug sections. */ /* Now read information from the stabs debug sections.
This is a no-op for SOM.
Perhaps it is intended for some kind of mixed STABS/SOM
situation? */
stabsect_build_psymtabs (objfile, section_offsets, mainline, stabsect_build_psymtabs (objfile, section_offsets, mainline,
"$GDB_SYMBOLS$", "$GDB_STRINGS$", "$TEXT$"); "$GDB_SYMBOLS$", "$GDB_STRINGS$", "$TEXT$");
/* Now read the native debug information. */ /* Now read the native debug information.
This builds the psymtab. This used to be done via a scan of
the DNTT, but is now done via the PXDB-built quick-lookup tables
together with a scan of the GNTT. See hp-psymtab-read.c. */
hpread_build_psymtabs (objfile, section_offsets, mainline); hpread_build_psymtabs (objfile, section_offsets, mainline);
/* Install any minimal symbols that have been collected as the current /* Install any minimal symbols that have been collected as the current
minimal symbols for this objfile. */ minimal symbols for this objfile.
Further symbol-reading is done incrementally, file-by-file,
in a step known as "psymtab-to-symtab" expansion. hp-symtab-read.c
contains the code to do the actual DNTT scanning and symtab building. */
install_minimal_symbols (objfile); install_minimal_symbols (objfile);
/* Force hppa-tdep.c to re-read the unwind descriptors. */ /* Force hppa-tdep.c to re-read the unwind descriptors. */
@ -444,6 +476,307 @@ som_symfile_offsets (objfile, addr)
return section_offsets; return section_offsets;
} }
/* Check if a given symbol NAME is in the import list
of OBJFILE.
1 => true, 0 => false
This is used in hp_symtab_read.c to deal with static variables
that are defined in a different shared library than the one
whose symbols are being processed. */
int is_in_import_list (name, objfile)
char * name;
struct objfile * objfile;
{
register int i;
if (!objfile ||
!name ||
!*name)
return 0;
for (i=0; i < objfile->import_list_size; i++)
if (objfile->import_list[i] && STREQ (name, objfile->import_list[i]))
return 1;
return 0;
}
/* Read in and initialize the SOM import list which is present
for all executables and shared libraries. The import list
consists of the symbols that are referenced in OBJFILE but
not defined there. (Variables that are imported are dealt
with as "loc_indirect" vars.)
Return value = number of import symbols read in. */
int
init_import_symbols (objfile)
struct objfile * objfile;
{
unsigned int import_list;
unsigned int import_list_size;
unsigned int string_table;
unsigned int string_table_size;
char * string_buffer;
register int i;
register int j;
register int k;
asection * text_section; /* section handle */
unsigned int dl_header[12]; /* SOM executable header */
/* A struct for an entry in the SOM import list */
typedef struct {
int name; /* index into the string table */
short dont_care1; /* we don't use this */
unsigned char type; /* 0 = NULL, 2 = Data, 3 = Code, 7 = Storage, 13 = Plabel */
unsigned int reserved2 : 8; /* not used */
} SomImportEntry;
/* We read 100 entries in at a time from the disk file. */
# define SOM_READ_IMPORTS_NUM 100
# define SOM_READ_IMPORTS_CHUNK_SIZE (sizeof (SomImportEntry) * SOM_READ_IMPORTS_NUM)
SomImportEntry buffer[SOM_READ_IMPORTS_NUM];
/* Initialize in case we error out */
objfile->import_list = NULL;
objfile->import_list_size = 0;
#if 0 /* DEBUGGING */
printf ("Processing import list for %s\n", objfile->name);
#endif
/* It doesn't work, for some reason, to read in space $TEXT$;
the subspace $SHLIB_INFO$ has to be used. Some BFD quirk? pai/1997-08-05 */
text_section = bfd_get_section_by_name (objfile->obfd, "$SHLIB_INFO$");
if (!text_section)
return 0;
/* Get the SOM executable header */
bfd_get_section_contents (objfile->obfd, text_section, dl_header, 0, 12 * sizeof (int));
/* Check header version number for 10.x HP-UX */
/* Currently we deal only with 10.x systems; on 9.x the version # is 89060912.
FIXME: Change for future HP-UX releases and mods to the SOM executable format */
if (dl_header[0] != 93092112)
return 0;
import_list = dl_header[4];
import_list_size = dl_header[5];
if (!import_list_size)
return 0;
string_table = dl_header[10];
string_table_size = dl_header[11];
if (!string_table_size)
return 0;
/* Suck in SOM string table */
string_buffer = (char *) xmalloc (string_table_size);
bfd_get_section_contents (objfile->obfd, text_section, string_buffer,
string_table, string_table_size);
/* Allocate import list in the psymbol obstack; this has nothing
to do with psymbols, just a matter of convenience. We want the
import list to be freed when the objfile is deallocated */
objfile->import_list
= (ImportEntry *) obstack_alloc (&objfile->psymbol_obstack,
import_list_size * sizeof (ImportEntry));
/* Read in the import entries, a bunch at a time */
for (j=0, k=0;
j < (import_list_size / SOM_READ_IMPORTS_NUM);
j++)
{
bfd_get_section_contents (objfile->obfd, text_section, buffer,
import_list + j * SOM_READ_IMPORTS_CHUNK_SIZE,
SOM_READ_IMPORTS_CHUNK_SIZE);
for (i=0; i < SOM_READ_IMPORTS_NUM; i++, k++)
{
if (buffer[i].type != (unsigned char) 0)
{
objfile->import_list[k]
= (char *) obstack_alloc (&objfile->psymbol_obstack, strlen (string_buffer + buffer[i].name) + 1);
strcpy (objfile->import_list[k], string_buffer + buffer[i].name);
/* Some day we might want to record the type and other information too */
}
else /* null type */
objfile->import_list[k] = NULL;
#if 0 /* DEBUGGING */
printf ("Import String %d:%d (%d), type %d is %s\n", j, i, k,
(int) buffer[i].type, objfile->import_list[k]);
#endif
}
}
/* Get the leftovers */
if (k < import_list_size)
bfd_get_section_contents (objfile->obfd, text_section, buffer,
import_list + k * sizeof (SomImportEntry),
(import_list_size - k) * sizeof (SomImportEntry));
for (i=0; k < import_list_size; i++, k++)
{
if (buffer[i].type != (unsigned char) 0)
{
objfile->import_list[k]
= (char *) obstack_alloc (&objfile->psymbol_obstack, strlen (string_buffer + buffer[i].name) + 1);
strcpy (objfile->import_list[k], string_buffer + buffer[i].name);
/* Some day we might want to record the type and other information too */
}
else
objfile->import_list[k] = NULL;
#if 0 /* DEBUGGING */
printf ("Import String F:%d (%d), type %d, is %s\n", i, k,
(int) buffer[i].type, objfile->import_list[k]);
#endif
}
objfile->import_list_size = import_list_size;
free (string_buffer);
return import_list_size;
}
/* Read in and initialize the SOM export list which is present
for all executables and shared libraries. The import list
consists of the symbols that are referenced in OBJFILE but
not defined there. (Variables that are imported are dealt
with as "loc_indirect" vars.)
Return value = number of import symbols read in. */
int
init_export_symbols (objfile)
struct objfile * objfile;
{
unsigned int export_list;
unsigned int export_list_size;
unsigned int string_table;
unsigned int string_table_size;
char * string_buffer;
register int i;
register int j;
register int k;
asection * text_section; /* section handle */
unsigned int dl_header[12]; /* SOM executable header */
/* A struct for an entry in the SOM export list */
typedef struct {
int next; /* for hash table use -- we don't use this */
int name; /* index into string table */
int value; /* offset or plabel */
int dont_care1; /* not used */
unsigned char type; /* 0 = NULL, 2 = Data, 3 = Code, 7 = Storage, 13 = Plabel */
char dont_care2; /* not used */
short dont_care3; /* not used */
} SomExportEntry;
/* We read 100 entries in at a time from the disk file. */
# define SOM_READ_EXPORTS_NUM 100
# define SOM_READ_EXPORTS_CHUNK_SIZE (sizeof (SomExportEntry) * SOM_READ_EXPORTS_NUM)
SomExportEntry buffer[SOM_READ_EXPORTS_NUM];
/* Initialize in case we error out */
objfile->export_list = NULL;
objfile->export_list_size = 0;
#if 0 /* DEBUGGING */
printf ("Processing export list for %s\n", objfile->name);
#endif
/* It doesn't work, for some reason, to read in space $TEXT$;
the subspace $SHLIB_INFO$ has to be used. Some BFD quirk? pai/1997-08-05 */
text_section = bfd_get_section_by_name (objfile->obfd, "$SHLIB_INFO$");
if (!text_section)
return 0;
/* Get the SOM executable header */
bfd_get_section_contents (objfile->obfd, text_section, dl_header, 0, 12 * sizeof (int));
/* Check header version number for 10.x HP-UX */
/* Currently we deal only with 10.x systems; on 9.x the version # is 89060912.
FIXME: Change for future HP-UX releases and mods to the SOM executable format */
if (dl_header[0] != 93092112)
return 0;
export_list = dl_header[8];
export_list_size = dl_header[9];
if (!export_list_size)
return 0;
string_table = dl_header[10];
string_table_size = dl_header[11];
if (!string_table_size)
return 0;
/* Suck in SOM string table */
string_buffer = (char *) xmalloc (string_table_size);
bfd_get_section_contents (objfile->obfd, text_section, string_buffer,
string_table, string_table_size);
/* Allocate export list in the psymbol obstack; this has nothing
to do with psymbols, just a matter of convenience. We want the
export list to be freed when the objfile is deallocated */
objfile->export_list
= (ExportEntry *) obstack_alloc (&objfile->psymbol_obstack,
export_list_size * sizeof (ExportEntry));
/* Read in the export entries, a bunch at a time */
for (j=0, k=0;
j < (export_list_size / SOM_READ_EXPORTS_NUM);
j++)
{
bfd_get_section_contents (objfile->obfd, text_section, buffer,
export_list + j * SOM_READ_EXPORTS_CHUNK_SIZE,
SOM_READ_EXPORTS_CHUNK_SIZE);
for (i=0; i < SOM_READ_EXPORTS_NUM; i++, k++)
{
if (buffer[i].type != (unsigned char) 0)
{
objfile->export_list[k].name
= (char *) obstack_alloc (&objfile->psymbol_obstack, strlen (string_buffer + buffer[i].name) + 1);
strcpy (objfile->export_list[k].name, string_buffer + buffer[i].name);
objfile->export_list[k].address = buffer[i].value;
/* Some day we might want to record the type and other information too */
}
else /* null type */
{
objfile->export_list[k].name = NULL;
objfile->export_list[k].address = 0;
}
#if 0 /* DEBUGGING */
printf ("Export String %d:%d (%d), type %d is %s\n", j, i, k,
(int) buffer[i].type, objfile->export_list[k].name);
#endif
}
}
/* Get the leftovers */
if (k < export_list_size)
bfd_get_section_contents (objfile->obfd, text_section, buffer,
export_list + k * sizeof (SomExportEntry),
(export_list_size - k) * sizeof (SomExportEntry));
for (i=0; k < export_list_size; i++, k++)
{
if (buffer[i].type != (unsigned char) 0)
{
objfile->export_list[k].name
= (char *) obstack_alloc (&objfile->psymbol_obstack, strlen (string_buffer + buffer[i].name) + 1);
strcpy (objfile->export_list[k].name, string_buffer + buffer[i].name);
/* Some day we might want to record the type and other information too */
objfile->export_list[k].address = buffer[i].value;
}
else
{
objfile->export_list[k].name = NULL;
objfile->export_list[k].address = 0;
}
#if 0 /* DEBUGGING */
printf ("Export String F:%d (%d), type %d, value %x is %s\n", i, k,
(int) buffer[i].type, buffer[i].value, objfile->export_list[k].name);
#endif
}
objfile->export_list_size = export_list_size;
free (string_buffer);
return export_list_size;
}
/* Register that we are able to handle SOM object file formats. */ /* Register that we are able to handle SOM object file formats. */

File diff suppressed because it is too large Load diff

View file

@ -49,3 +49,129 @@ som_solib_section_offsets PARAMS ((struct objfile *, struct section_offsets *));
extern void extern void
som_solib_create_inferior_hook PARAMS((void)); som_solib_create_inferior_hook PARAMS((void));
/* Function to be called to remove the connection between debugger and
dynamic linker that was established by SOLIB_CREATE_INFERIOR_HOOK.
(This operation does not remove shared library information from
the debugger, as CLEAR_SOLIB does.)
*/
#define SOLIB_REMOVE_INFERIOR_HOOK(PID) som_solib_remove_inferior_hook(PID)
extern void
som_solib_remove_inferior_hook PARAMS((int));
/* This function is called by the "catch load" command. It allows
the debugger to be notified by the dynamic linker when a specified
library file (or any library file, if filename is NULL) is loaded.
*/
#define SOLIB_CREATE_CATCH_LOAD_HOOK(pid,tempflag, filename,cond_string) \
som_solib_create_catch_load_hook (pid, tempflag, filename, cond_string)
extern void
som_solib_create_catch_load_hook PARAMS((int, int, char *, char *));
/* This function is called by the "catch unload" command. It allows
the debugger to be notified by the dynamic linker when a specified
library file (or any library file, if filename is NULL) is unloaded.
*/
#define SOLIB_CREATE_CATCH_UNLOAD_HOOK(pid,tempflag,filename, cond_string) \
som_solib_create_catch_unload_hook (pid, tempflag, filename, cond_string)
extern void
som_solib_create_catch_unload_hook PARAMS((int, int, char *, char *));
/* This function returns TRUE if the dynamic linker has just reported
a load of a library.
This function must be used only when the inferior has stopped in
the dynamic linker hook, or undefined results are guaranteed.
*/
#define SOLIB_HAVE_LOAD_EVENT(pid) \
som_solib_have_load_event (pid)
extern int
som_solib_have_load_event PARAMS((int));
/* This function returns a pointer to the string representation of the
pathname of the dynamically-linked library that has just been loaded.
This function must be used only when SOLIB_HAVE_LOAD_EVENT is TRUE,
or undefined results are guaranteed.
This string's contents are only valid immediately after the inferior
has stopped in the dynamic linker hook, and becomes invalid as soon
as the inferior is continued. Clients should make a copy of this
string if they wish to continue the inferior and then access the string.
*/
#define SOLIB_LOADED_LIBRARY_PATHNAME(pid) \
som_solib_loaded_library_pathname (pid)
extern char *
som_solib_loaded_library_pathname PARAMS((int));
/* This function returns TRUE if the dynamic linker has just reported
an unload of a library.
This function must be used only when the inferior has stopped in
the dynamic linker hook, or undefined results are guaranteed.
*/
#define SOLIB_HAVE_UNLOAD_EVENT(pid) \
som_solib_have_unload_event (pid)
extern int
som_solib_have_unload_event PARAMS((int));
/* This function returns a pointer to the string representation of the
pathname of the dynamically-linked library that has just been unloaded.
This function must be used only when SOLIB_HAVE_UNLOAD_EVENT is TRUE,
or undefined results are guaranteed.
This string's contents are only valid immediately after the inferior
has stopped in the dynamic linker hook, and becomes invalid as soon
as the inferior is continued. Clients should make a copy of this
string if they wish to continue the inferior and then access the string.
*/
#define SOLIB_UNLOADED_LIBRARY_PATHNAME(pid) \
som_solib_unloaded_library_pathname (pid)
extern char *
som_solib_unloaded_library_pathname PARAMS((int));
/* This function returns TRUE if pc is the address of an instruction that
lies within the dynamic linker (such as the event hook, or the dld
itself).
This function must be used only when a dynamic linker event has been
caught, and the inferior is being stepped out of the hook, or undefined
results are guaranteed.
*/
#define SOLIB_IN_DYNAMIC_LINKER(pid,pc) \
som_solib_in_dynamic_linker (pid, pc)
extern int
som_solib_in_dynamic_linker PARAMS((int, CORE_ADDR));
/* This function must be called when the inferior is killed, and the program
restarted. This is not the same as CLEAR_SOLIB, in that it doesn't discard
any symbol tables.
Presently, this functionality is not implemented.
*/
#define SOLIB_RESTART() \
som_solib_restart ()
extern void
som_solib_restart PARAMS((void));
/* If we can't set a breakpoint, and it's in a shared library, just
disable it. */
#define DISABLE_UNSETTABLE_BREAK(addr) (som_solib_address(addr) != NULL)
extern char *
som_solib_address PARAMS ((CORE_ADDR)); /* somsolib.c */
/* If ADDR lies in a shared library, return its name. */
#define PC_SOLIB(addr) som_solib_address (addr)

View file

@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include <ctype.h>
#include "defs.h" #include "defs.h"
#include "gdb_string.h" #include "gdb_string.h"
#include "value.h" #include "value.h"
@ -53,13 +53,17 @@ static void return_command PARAMS ((char *, int));
static void down_command PARAMS ((char *, int)); static void down_command PARAMS ((char *, int));
static void down_silently_base PARAMS ((char *));
static void down_silently_command PARAMS ((char *, int)); static void down_silently_command PARAMS ((char *, int));
static void up_command PARAMS ((char *, int)); static void up_command PARAMS ((char *, int));
static void up_silently_base PARAMS ((char *));
static void up_silently_command PARAMS ((char *, int)); static void up_silently_command PARAMS ((char *, int));
static void frame_command PARAMS ((char *, int)); void frame_command PARAMS ((char *, int));
static void select_frame_command PARAMS ((char *, int)); static void select_frame_command PARAMS ((char *, int));
@ -67,21 +71,31 @@ static void print_frame_arg_vars PARAMS ((struct frame_info *, GDB_FILE *));
static void catch_info PARAMS ((char *, int)); static void catch_info PARAMS ((char *, int));
static void print_frame_label_vars PARAMS ((struct frame_info *, int, static void args_plus_locals_info PARAMS ((char *, int));
static void print_frame_label_vars PARAMS ((struct frame_info *,
int,
GDB_FILE *)); GDB_FILE *));
static void print_frame_local_vars PARAMS ((struct frame_info *, GDB_FILE *)); static void print_frame_local_vars PARAMS ((struct frame_info *,
int,
GDB_FILE *));
static int print_block_frame_labels PARAMS ((struct block *, int *, static int print_block_frame_labels PARAMS ((struct block *, int *,
GDB_FILE *)); GDB_FILE *));
static int print_block_frame_locals PARAMS ((struct block *, static int print_block_frame_locals PARAMS ((struct block *,
struct frame_info *, struct frame_info *,
int,
GDB_FILE *)); GDB_FILE *));
static void print_frame_info_base PARAMS ((struct frame_info *, int, int, int));
static void print_stack_frame_base PARAMS ((struct frame_info *, int, int));
static void backtrace_command PARAMS ((char *, int)); static void backtrace_command PARAMS ((char *, int));
static struct frame_info *parse_frame_specification PARAMS ((char *)); struct frame_info *parse_frame_specification PARAMS ((char *));
static void frame_info PARAMS ((char *, int)); static void frame_info PARAMS ((char *, int));
@ -116,21 +130,122 @@ struct print_stack_frame_args {
int args; int args;
}; };
static int print_stack_frame_stub PARAMS ((char *)); static int print_stack_frame_base_stub PARAMS ((char *));
/* Pass the args the way catch_errors wants them. */ /* Show and print the frame arguments.
Pass the args the way catch_errors wants them. */
static int
show_and_print_stack_frame_stub (args)
char *args;
{
struct print_stack_frame_args *p = (struct print_stack_frame_args *)args;
/* Reversed order of these so tuiDo() doesn't occur
* in the middle of "Breakpoint 1 ... [location]" printing = RT
*/
if (tui_version)
print_frame_info_base (p->fi, p->level, p->source, p->args);
print_frame_info (p->fi, p->level, p->source, p->args);
return 0;
}
/* Show or print the frame arguments.
Pass the args the way catch_errors wants them. */
static int static int
print_stack_frame_stub (args) print_stack_frame_stub (args)
char *args; char *args;
{ {
struct print_stack_frame_args *p = (struct print_stack_frame_args *)args; struct print_stack_frame_args *p = (struct print_stack_frame_args *)args;
print_frame_info (p->fi, p->level, p->source, p->args); if (tui_version)
print_frame_info (p->fi, p->level, p->source, p->args);
else
print_frame_info_base (p->fi, p->level, p->source, p->args);
return 0; return 0;
} }
/* Print a stack frame briefly. FRAME_INFI should be the frame info /* Print a stack frame briefly. FRAME_INFI should be the frame info
and LEVEL should be its level in the stack (or -1 for level not defined). and LEVEL should be its level in the stack (or -1 for level not defined).
/* Pass the args the way catch_errors wants them. */
static int
print_stack_frame_base_stub (args)
char *args;
{
struct print_stack_frame_args *p = (struct print_stack_frame_args *)args;
print_frame_info_base (p->fi, p->level, p->source, p->args);
return 0;
}
/* print the frame arguments to the terminal.
Pass the args the way catch_errors wants them. */
static int
print_only_stack_frame_stub (args)
char *args;
{
struct print_stack_frame_args *p = (struct print_stack_frame_args *)args;
print_frame_info_base (p->fi, p->level, p->source, p->args);
return 0;
}
/* Print a stack frame briefly. FRAME_INFI should be the frame info
and LEVEL should be its level in the stack (or -1 for level not defined).
This prints the level, the function executing, the arguments,
and the file name and line number.
If the pc is not at the beginning of the source line,
the actual pc is printed at the beginning.
If SOURCE is 1, print the source line as well.
If SOURCE is -1, print ONLY the source line. */
static void
print_stack_frame_base (fi, level, source)
struct frame_info *fi;
int level;
int source;
{
struct print_stack_frame_args args;
args.fi = fi;
args.level = level;
args.source = source;
args.args = 1;
catch_errors (print_stack_frame_stub, (char *)&args, "", RETURN_MASK_ALL);
}
/* Show and print a stack frame briefly. FRAME_INFI should be the frame info
and LEVEL should be its level in the stack (or -1 for level not defined).
This prints the level, the function executing, the arguments,
and the file name and line number.
If the pc is not at the beginning of the source line,
the actual pc is printed at the beginning.
If SOURCE is 1, print the source line as well.
If SOURCE is -1, print ONLY the source line. */
void
show_and_print_stack_frame (fi, level, source)
struct frame_info *fi;
int level;
int source;
{
struct print_stack_frame_args args;
args.fi = fi;
args.level = level;
args.source = source;
args.args = 1;
catch_errors (show_and_print_stack_frame_stub, (char *)&args, "", RETURN_MASK_ALL);
}
/* Show or print a stack frame briefly. FRAME_INFI should be the frame info
and LEVEL should be its level in the stack (or -1 for level not defined).
This prints the level, the function executing, the arguments, This prints the level, the function executing, the arguments,
and the file name and line number. and the file name and line number.
If the pc is not at the beginning of the source line, If the pc is not at the beginning of the source line,
@ -155,6 +270,33 @@ print_stack_frame (fi, level, source)
catch_errors (print_stack_frame_stub, (char *)&args, "", RETURN_MASK_ALL); catch_errors (print_stack_frame_stub, (char *)&args, "", RETURN_MASK_ALL);
} }
/* Print a stack frame briefly. FRAME_INFI should be the frame info
and LEVEL should be its level in the stack (or -1 for level not defined).
This prints the level, the function executing, the arguments,
and the file name and line number.
If the pc is not at the beginning of the source line,
the actual pc is printed at the beginning.
If SOURCE is 1, print the source line as well.
If SOURCE is -1, print ONLY the source line. */
void
print_only_stack_frame (fi, level, source)
struct frame_info *fi;
int level;
int source;
{
struct print_stack_frame_args args;
args.fi = fi;
args.level = level;
args.source = source;
args.args = 1;
catch_errors (print_only_stack_frame_stub,
(char *)&args, "", RETURN_MASK_ALL);
}
struct print_args_args { struct print_args_args {
struct symbol *func; struct symbol *func;
struct frame_info *fi; struct frame_info *fi;
@ -176,13 +318,20 @@ print_args_stub (args)
return 0; return 0;
} }
/* LEVEL is the level of the frame, or -1 if it is the innermost frame /* Print information about a frame for frame "fi" at level "level".
but we don't want to print the level. */ * Used in "where" output, also used to emit breakpoint or step messages.
* LEVEL is the level of the frame, or -1 if it is the innermost frame
* but we don't want to print the level.
* The meaning of the SOURCE argument is:
* -1: Print only source line
* 0: Print only location
* 1: Print location and source line
*/
void static void
print_frame_info (fi, level, source, args) print_frame_info_base (fi, level, source, args)
struct frame_info *fi; struct frame_info *fi;
register int level; int level;
int source; int source;
int args; int args;
{ {
@ -288,8 +437,31 @@ print_frame_info (fi, level, source, args)
} }
else else
{ {
/* I'd like to use SYMBOL_SOURCE_NAME() here, to display
* the demangled name that we already have stored in
* the symbol table, but we stored a version with
* DMGL_PARAMS turned on, and here we don't want
* to display parameters. So call the demangler again,
* with DMGL_ANSI only. RT
* (Yes, I know that printf_symbol_filtered() will
* again try to demangle the name on the fly, but
* the issue is that if cplus_demangle() fails here,
* it'll fail there too. So we want to catch the failure
* ("demangled==NULL" case below) here, while we still
* have our hands on the function symbol.)
*/
char * demangled;
funname = SYMBOL_NAME (func); funname = SYMBOL_NAME (func);
funlang = SYMBOL_LANGUAGE (func); funlang = SYMBOL_LANGUAGE (func);
if (funlang == language_cplus) {
demangled = cplus_demangle (funname, DMGL_ANSI);
if (demangled == NULL)
/* If the demangler fails, try the demangled name
* from the symbol table. This'll have parameters,
* but that's preferable to diplaying a mangled name.
*/
funname = SYMBOL_SOURCE_NAME (func);
}
} }
} }
else else
@ -357,7 +529,7 @@ print_frame_info (fi, level, source, args)
} }
#endif #endif
#ifdef PC_SOLIB #ifdef PC_SOLIB
if (!funname) if (!funname || (!sal.symtab || !sal.symtab->filename))
{ {
char *lib = PC_SOLIB (fi->pc); char *lib = PC_SOLIB (fi->pc);
if (lib) if (lib)
@ -380,14 +552,14 @@ print_frame_info (fi, level, source, args)
fi->pc); fi->pc);
if (!done) if (!done)
{ {
if (addressprint && mid_statement) if (addressprint && mid_statement && !tui_version)
{ {
print_address_numeric (fi->pc, 1, gdb_stdout); print_address_numeric (fi->pc, 1, gdb_stdout);
printf_filtered ("\t"); printf_filtered ("\t");
} }
if (print_frame_info_listing_hook) if (print_frame_info_listing_hook)
print_frame_info_listing_hook (sal.symtab, sal.line, sal.line + 1, 0); print_frame_info_listing_hook (sal.symtab, sal.line, sal.line + 1, 0);
else else if (!tui_version)
print_source_lines (sal.symtab, sal.line, sal.line + 1, 0); print_source_lines (sal.symtab, sal.line, sal.line + 1, 0);
} }
current_source_line = max (sal.line - lines_to_list/2, 1); current_source_line = max (sal.line - lines_to_list/2, 1);
@ -399,12 +571,53 @@ print_frame_info (fi, level, source, args)
gdb_flush (gdb_stdout); gdb_flush (gdb_stdout);
} }
void
stack_publish_stopped_with_no_frame()
{
TUIDO(((TuiOpaqueFuncPtr)tuiUpdateOnEnd));
return;
}
/* Show or print the frame info. If this is the tui, it will be shown in
the source display */
void
print_frame_info(fi, level, source, args)
struct frame_info *fi;
register int level;
int source;
int args;
{
if (!tui_version)
print_frame_info_base(fi, level, source, args);
else
{
if (fi && (frame_in_dummy(fi) || fi->signal_handler_caller))
print_frame_info_base(fi, level, source, args);
else
{
TUIDO(((TuiOpaqueFuncPtr)tui_vShowFrameInfo, fi));
}
}
}
/* Show the frame info. If this is the tui, it will be shown in
the source display otherwise, nothing is done */
void
show_stack_frame(fi)
struct frame_info *fi;
{
TUIDO(((TuiOpaqueFuncPtr)tui_vShowFrameInfo, fi));
}
/* Read a frame specification in whatever the appropriate format is. /* Read a frame specification in whatever the appropriate format is.
Call error() if the specification is in any way invalid (i.e. Call error() if the specification is in any way invalid (i.e.
this function never returns NULL). */ this function never returns NULL). */
static struct frame_info * struct frame_info *
parse_frame_specification (frame_exp) parse_frame_specification (frame_exp)
char *frame_exp; char *frame_exp;
{ {
@ -525,7 +738,6 @@ frame_info (addr_exp, from_tty)
int from_tty; int from_tty;
{ {
struct frame_info *fi; struct frame_info *fi;
struct frame_saved_regs fsr;
struct symtab_and_line sal; struct symtab_and_line sal;
struct symbol *func; struct symbol *func;
struct symtab *s; struct symtab *s;
@ -549,8 +761,32 @@ frame_info (addr_exp, from_tty)
s = find_pc_symtab(fi->pc); s = find_pc_symtab(fi->pc);
if (func) if (func)
{ {
funname = SYMBOL_NAME (func); /* I'd like to use SYMBOL_SOURCE_NAME() here, to display
funlang = SYMBOL_LANGUAGE (func); * the demangled name that we already have stored in
* the symbol table, but we stored a version with
* DMGL_PARAMS turned on, and here we don't want
* to display parameters. So call the demangler again,
* with DMGL_ANSI only. RT
* (Yes, I know that printf_symbol_filtered() will
* again try to demangle the name on the fly, but
* the issue is that if cplus_demangle() fails here,
* it'll fail there too. So we want to catch the failure
* ("demangled==NULL" case below) here, while we still
* have our hands on the function symbol.)
*/
char * demangled;
funname = SYMBOL_NAME (func);
funlang = SYMBOL_LANGUAGE (func);
if (funlang == language_cplus)
{
demangled = cplus_demangle (funname, DMGL_ANSI);
/* If the demangler fails, try the demangled name
* from the symbol table. This'll have parameters,
* but that's preferable to diplaying a mangled name.
*/
if (demangled == NULL)
funname = SYMBOL_SOURCE_NAME (func);
}
} }
else else
{ {
@ -666,36 +902,39 @@ frame_info (addr_exp, from_tty)
} }
} }
#if defined (FRAME_FIND_SAVED_REGS) FRAME_INIT_SAVED_REGS (fi);
get_frame_saved_regs (fi, &fsr); if (fi->saved_regs != NULL)
/* The sp is special; what's returned isn't the save address, but {
actually the value of the previous frame's sp. */ /* The sp is special; what's returned isn't the save address, but
printf_filtered (" Previous frame's sp is "); actually the value of the previous frame's sp. */
print_address_numeric (fsr.regs[SP_REGNUM], 1, gdb_stdout); printf_filtered (" Previous frame's sp is ");
printf_filtered ("\n"); print_address_numeric (fi->saved_regs[SP_REGNUM], 1, gdb_stdout);
count = 0; printf_filtered ("\n");
numregs = ARCH_NUM_REGS; count = 0;
for (i = 0; i < numregs; i++) numregs = ARCH_NUM_REGS;
if (fsr.regs[i] && i != SP_REGNUM) for (i = 0; i < numregs; i++)
{ if (fi->saved_regs[i] && i != SP_REGNUM)
if (count == 0) {
puts_filtered (" Saved registers:\n "); if (count == 0)
else puts_filtered (" Saved registers:\n ");
puts_filtered (","); else
wrap_here (" "); puts_filtered (",");
printf_filtered (" %s at ", REGISTER_NAME (i)); wrap_here (" ");
print_address_numeric (fsr.regs[i], 1, gdb_stdout); printf_filtered (" %s at ", REGISTER_NAME (i));
count++; print_address_numeric (fi->saved_regs[i], 1, gdb_stdout);
} count++;
if (count) }
puts_filtered ("\n"); if (count)
#else /* Have FRAME_FIND_SAVED_REGS. */ puts_filtered ("\n");
/* We could get some information about saved registers by calling }
get_saved_register on each register. Which info goes with which frame else
is necessarily lost, however, and I suspect that the users don't care {
whether they get the info. */ /* We could get some information about saved registers by
puts_filtered ("\n"); calling get_saved_register on each register. Which info goes
#endif /* Have FRAME_FIND_SAVED_REGS. */ with which frame is necessarily lost, however, and I suspect
that the users don't care whether they get the info. */
puts_filtered ("\n");
}
} }
#if 0 #if 0
@ -732,8 +971,9 @@ backtrace_limit_info (arg, from_tty)
/* Print briefly all stack frames or just the innermost COUNT frames. */ /* Print briefly all stack frames or just the innermost COUNT frames. */
static void static void
backtrace_command (count_exp, from_tty) backtrace_command_1 (count_exp, show_locals, from_tty)
char *count_exp; char *count_exp;
int show_locals;
int from_tty; int from_tty;
{ {
struct frame_info *fi; struct frame_info *fi;
@ -814,25 +1054,104 @@ backtrace_command (count_exp, from_tty)
means further attempts to backtrace would fail (on the other means further attempts to backtrace would fail (on the other
hand, perhaps the code does or could be fixed to make sure hand, perhaps the code does or could be fixed to make sure
the frame->prev field gets set to NULL in that case). */ the frame->prev field gets set to NULL in that case). */
print_frame_info (fi, trailing_level + i, 0, 1); print_frame_info_base (fi, trailing_level + i, 0, 1);
if (show_locals)
print_frame_local_vars(fi, 1, gdb_stdout);
} }
/* If we've stopped before the end, mention that. */ /* If we've stopped before the end, mention that. */
if (fi && from_tty) if (fi && from_tty)
printf_filtered ("(More stack frames follow...)\n"); printf_filtered ("(More stack frames follow...)\n");
} }
static void
backtrace_command (arg, from_tty)
char *arg;
int from_tty;
{
struct cleanup *old_chain = (struct cleanup *)NULL;
char **argv = (char **)NULL;
int argIndicatingFullTrace = (-1), totArgLen = 0, argc = 0;
char *argPtr = arg;
if (arg != (char *)NULL)
{
int i;
argv = buildargv(arg);
old_chain = make_cleanup(freeargv, (char *)argv);
argc = 0;
for (i = 0; (argv[i] != (char *)NULL); i++)
{
int j;
for (j = 0; (j < strlen(argv[i])); j++)
argv[i][j] = tolower(argv[i][j]);
if (argIndicatingFullTrace < 0 && subsetCompare(argv[i], "full"))
argIndicatingFullTrace = argc;
else
{
argc++;
totArgLen += strlen(argv[i]);
}
}
totArgLen += argc;
if (argIndicatingFullTrace >= 0)
{
if (totArgLen > 0)
{
argPtr = (char *)xmalloc(totArgLen + 1);
if (!argPtr)
nomem(0);
else
{
memset(argPtr, 0, totArgLen + 1);
for (i = 0; (i < (argc + 1)); i++)
{
if (i != argIndicatingFullTrace)
{
strcat(argPtr, argv[i]);
strcat(argPtr, " ");
}
}
}
}
else
argPtr = (char *)NULL;
}
}
backtrace_command_1 (argPtr, (argIndicatingFullTrace >= 0), from_tty);
if (argIndicatingFullTrace >= 0 && totArgLen > 0)
free(argPtr);
if (old_chain)
do_cleanups(old_chain);
}
static void
backtrace_full_command (arg, from_tty)
char *arg;
int from_tty;
{
backtrace_command_1 (arg, 1, from_tty);
}
/* Print the local variables of a block B active in FRAME. /* Print the local variables of a block B active in FRAME.
Return 1 if any variables were printed; 0 otherwise. */ Return 1 if any variables were printed; 0 otherwise. */
static int static int
print_block_frame_locals (b, fi, stream) print_block_frame_locals (b, fi, num_tabs, stream)
struct block *b; struct block *b;
register struct frame_info *fi; register struct frame_info *fi;
int num_tabs;
register GDB_FILE *stream; register GDB_FILE *stream;
{ {
int nsyms; int nsyms;
register int i; register int i, j;
register struct symbol *sym; register struct symbol *sym;
register int values_printed = 0; register int values_printed = 0;
@ -848,6 +1167,8 @@ print_block_frame_locals (b, fi, stream)
case LOC_STATIC: case LOC_STATIC:
case LOC_BASEREG: case LOC_BASEREG:
values_printed = 1; values_printed = 1;
for (j = 0; j < num_tabs; j++)
fputs_filtered("\t", stream);
fputs_filtered (SYMBOL_SOURCE_NAME (sym), stream); fputs_filtered (SYMBOL_SOURCE_NAME (sym), stream);
fputs_filtered (" = ", stream); fputs_filtered (" = ", stream);
print_variable_value (sym, fi, stream); print_variable_value (sym, fi, stream);
@ -913,8 +1234,9 @@ print_block_frame_labels (b, have_default, stream)
on the function running in FRAME. */ on the function running in FRAME. */
static void static void
print_frame_local_vars (fi, stream) print_frame_local_vars (fi, num_tabs, stream)
register struct frame_info *fi; register struct frame_info *fi;
register int num_tabs;
register GDB_FILE *stream; register GDB_FILE *stream;
{ {
register struct block *block = get_frame_block (fi); register struct block *block = get_frame_block (fi);
@ -928,7 +1250,7 @@ print_frame_local_vars (fi, stream)
while (block != 0) while (block != 0)
{ {
if (print_block_frame_locals (block, fi, stream)) if (print_block_frame_locals (block, fi, num_tabs, stream))
values_printed = 1; values_printed = 1;
/* After handling the function's top-level block, stop. /* After handling the function's top-level block, stop.
Don't continue to its superblock, the block of Don't continue to its superblock, the block of
@ -1024,7 +1346,7 @@ locals_info (args, from_tty)
{ {
if (!selected_frame) if (!selected_frame)
error ("No frame selected."); error ("No frame selected.");
print_frame_local_vars (selected_frame, gdb_stdout); print_frame_local_vars (selected_frame, 0, gdb_stdout);
} }
static void static void
@ -1032,9 +1354,29 @@ catch_info (ignore, from_tty)
char *ignore; char *ignore;
int from_tty; int from_tty;
{ {
struct symtab_and_line * sal;
/* Check for target support for exception handling */
sal = target_enable_exception_callback (EX_EVENT_CATCH, 1);
if (sal)
{
/* Currently not handling this */
/* Ideally, here we should interact with the C++ runtime
system to find the list of active handlers, etc. */
fprintf_filtered (gdb_stdout, "Info catch not supported with this target/compiler combination.\n");
#if 0
if (!selected_frame) if (!selected_frame)
error ("No frame selected."); error ("No frame selected.");
print_frame_label_vars (selected_frame, 0, gdb_stdout); #endif
}
else
{
/* Assume g++ compiled code -- old v 4.16 behaviour */
if (!selected_frame)
error ("No frame selected.");
print_frame_label_vars (selected_frame, 0, gdb_stdout);
}
} }
static void static void
@ -1112,6 +1454,16 @@ args_info (ignore, from_tty)
print_frame_arg_vars (selected_frame, gdb_stdout); print_frame_arg_vars (selected_frame, gdb_stdout);
} }
static void
args_plus_locals_info(ignore, from_tty)
char *ignore;
int from_tty;
{
args_info(ignore, from_tty);
locals_info(ignore, from_tty);
}
/* Select frame FI, and note that its stack level is LEVEL. /* Select frame FI, and note that its stack level is LEVEL.
LEVEL may be -1 if an actual level number is not known. */ LEVEL may be -1 if an actual level number is not known. */
@ -1139,9 +1491,48 @@ select_frame (fi, level)
&& language_mode == language_mode_auto) { && language_mode == language_mode_auto) {
set_language(s->language); set_language(s->language);
} }
/* elz: this if here fixes the problem with the pc not being displayed
in the tui asm layout, with no debug symbols. The value of s
would be 0 here, and select_source_symtab would abort the
command by calling the 'error' function*/
if (s)
{
TUIDO(((TuiOpaqueFuncPtr)tui_vSelectSourceSymtab, s));
}
} }
} }
/* Select frame FI, noting that its stack level is LEVEL. Also print
the stack frame and show the source if this is the tui version. */
void
select_and_print_frame(fi, level)
struct frame_info *fi;
int level;
{
select_frame(fi, level);
if (fi)
{
print_stack_frame(fi, level, 1);
TUIDO(((TuiOpaqueFuncPtr)tui_vCheckDataValues, fi));
}
}
/* Select frame FI, noting that its stack level is LEVEL. Be silent if
not the TUI */
void
select_and_maybe_print_frame(fi, level)
struct frame_info *fi;
int level;
{
if (!tui_version)
select_frame(fi, level);
else
select_and_print_frame(fi, level);
}
/* Store the selected frame and its level into *FRAMEP and *LEVELP. /* Store the selected frame and its level into *FRAMEP and *LEVELP.
If there is no selected frame, *FRAMEP is set to NULL. */ If there is no selected frame, *FRAMEP is set to NULL. */
@ -1249,23 +1640,34 @@ select_frame_command (level_exp, from_tty)
With arg, behaves like select_frame and then prints the selected With arg, behaves like select_frame and then prints the selected
frame. */ frame. */
static void void
frame_command (level_exp, from_tty) frame_command (level_exp, from_tty)
char *level_exp; char *level_exp;
int from_tty; int from_tty;
{ {
select_frame_command (level_exp, from_tty); select_frame_command (level_exp, from_tty);
print_stack_frame (selected_frame, selected_frame_level, 1); show_and_print_stack_frame (selected_frame, selected_frame_level, 1);
} }
/* The XDB Compatibility command to print the current frame. */
void
current_frame_command (level_exp, from_tty)
char *level_exp;
int from_tty;
{
if (target_has_stack == 0 || selected_frame == 0)
error ("No stack.");
print_only_stack_frame (selected_frame, selected_frame_level, 1);
}
/* Select the frame up one or COUNT stack levels /* Select the frame up one or COUNT stack levels
from the previously selected frame, and print it briefly. */ from the previously selected frame, and print it briefly. */
/* ARGSUSED */ /* ARGSUSED */
static void static void
up_silently_command (count_exp, from_tty) up_silently_base (count_exp)
char *count_exp; char *count_exp;
int from_tty;
{ {
register struct frame_info *fi; register struct frame_info *fi;
int count = 1, count1; int count = 1, count1;
@ -1282,13 +1684,23 @@ up_silently_command (count_exp, from_tty)
select_frame (fi, selected_frame_level + count - count1); select_frame (fi, selected_frame_level + count - count1);
} }
static void
up_silently_command (count_exp, from_tty)
char *count_exp;
int from_tty;
{
up_silently_base(count_exp);
if (tui_version)
print_stack_frame (selected_frame, selected_frame_level, 1);
}
static void static void
up_command (count_exp, from_tty) up_command (count_exp, from_tty)
char *count_exp; char *count_exp;
int from_tty; int from_tty;
{ {
up_silently_command (count_exp, from_tty); up_silently_base (count_exp);
print_stack_frame (selected_frame, selected_frame_level, 1); show_and_print_stack_frame (selected_frame, selected_frame_level, 1);
} }
/* Select the frame down one or COUNT stack levels /* Select the frame down one or COUNT stack levels
@ -1296,9 +1708,8 @@ up_command (count_exp, from_tty)
/* ARGSUSED */ /* ARGSUSED */
static void static void
down_silently_command (count_exp, from_tty) down_silently_base (count_exp)
char *count_exp; char *count_exp;
int from_tty;
{ {
register struct frame_info *frame; register struct frame_info *frame;
int count = -1, count1; int count = -1, count1;
@ -1324,14 +1735,24 @@ down_silently_command (count_exp, from_tty)
select_frame (frame, selected_frame_level + count - count1); select_frame (frame, selected_frame_level + count - count1);
} }
/* ARGSUSED */
static void
down_silently_command (count_exp, from_tty)
char *count_exp;
int from_tty;
{
down_silently_base (count_exp);
if (tui_version)
print_stack_frame (selected_frame, selected_frame_level, 1);
}
static void static void
down_command (count_exp, from_tty) down_command (count_exp, from_tty)
char *count_exp; char *count_exp;
int from_tty; int from_tty;
{ {
down_silently_command (count_exp, from_tty); down_silently_base (count_exp);
print_stack_frame (selected_frame, selected_frame_level, 1); show_and_print_stack_frame (selected_frame, selected_frame_level, 1);
} }
static void static void
@ -1416,6 +1837,66 @@ return_command (retval_exp, from_tty)
select_frame_command ("0", 0); select_frame_command ("0", 0);
} }
/* Sets the scope to input function name, provided that the
function is within the current stack frame */
typedef struct function_bounds
{
CORE_ADDR low, high;
};
static void
func_command (arg, from_tty)
char *arg;
int from_tty;
{
if (arg != (char *)NULL)
{
struct frame_info *fp;
int found = 0;
struct symtabs_and_lines sals;
int i;
int level = 1;
struct function_bounds *funcBounds = (struct function_bounds *)NULL;
fp = parse_frame_specification("0");
sals = decode_line_spec(arg, 1);
funcBounds = (struct function_bounds *)xmalloc(
sizeof(struct function_bounds) * sals.nelts);
for (i = 0; (i < sals.nelts && !found); i++)
{
if (sals.sals[i].pc == (CORE_ADDR)0 ||
find_pc_partial_function(sals.sals[i].pc,
(char **)NULL,
&funcBounds[i].low,
&funcBounds[i].high) == 0)
{
funcBounds[i].low =
funcBounds[i].high = (CORE_ADDR)NULL;
}
}
do
{
for (i = 0; (i < sals.nelts && !found); i++)
found = (fp->pc >= funcBounds[i].low &&
fp->pc < funcBounds[i].high);
if (!found)
{
level = 1;
fp = find_relative_frame(fp, &level);
}
} while (!found && level == 0);
if (funcBounds)
free(funcBounds);
if (!found)
printf_filtered("'%s' not within current stack frame.\n", arg);
else if (fp != selected_frame) /* set the stack frame here! */
select_and_print_frame(fp);
}
}
/* Gets the language of the current frame. */ /* Gets the language of the current frame. */
enum language enum language
@ -1477,6 +1958,12 @@ a command file or a user-defined command.");
add_com_alias ("f", "frame", class_stack, 1); add_com_alias ("f", "frame", class_stack, 1);
if (xdb_commands)
{
add_com("L", class_stack, current_frame_command,
"Print the current stack frame.\n");
add_com_alias ("V", "frame", class_stack, 1);
}
add_com ("select-frame", class_stack, select_frame_command, add_com ("select-frame", class_stack, select_frame_command,
"Select a stack frame without printing anything.\n\ "Select a stack frame without printing anything.\n\
An argument specifies the frame to select.\n\ An argument specifies the frame to select.\n\
@ -1484,8 +1971,19 @@ It can be a stack frame number or the address of the frame.\n");
add_com ("backtrace", class_stack, backtrace_command, add_com ("backtrace", class_stack, backtrace_command,
"Print backtrace of all stack frames, or innermost COUNT frames.\n\ "Print backtrace of all stack frames, or innermost COUNT frames.\n\
With a negative argument, print outermost -COUNT frames."); With a negative argument, print outermost -COUNT frames.\n\
Use of the 'full' qualifier also prints the values of the local variables.\n");
add_com_alias ("bt", "backtrace", class_stack, 0); add_com_alias ("bt", "backtrace", class_stack, 0);
if (xdb_commands)
{
add_com_alias ("t", "backtrace", class_stack, 0);
add_com ("T", class_stack, backtrace_full_command,
"Print backtrace of all stack frames, or innermost COUNT frames \n\
and the values of the local variables.\n\
With a negative argument, print outermost -COUNT frames.\n\
Usage: T <count>\n");
}
add_com_alias ("where", "backtrace", class_alias, 0); add_com_alias ("where", "backtrace", class_alias, 0);
add_info ("stack", backtrace_command, add_info ("stack", backtrace_command,
"Backtrace of the stack, or innermost COUNT frames."); "Backtrace of the stack, or innermost COUNT frames.");
@ -1497,6 +1995,14 @@ With a negative argument, print outermost -COUNT frames.");
"Local variables of current stack frame."); "Local variables of current stack frame.");
add_info ("args", args_info, add_info ("args", args_info,
"Argument variables of current stack frame."); "Argument variables of current stack frame.");
if (xdb_commands)
add_com("l", class_info, args_plus_locals_info,
"Argument and local variables of current stack frame.");
if (dbx_commands)
add_com("func", class_stack, func_command,
"Select the stack frame that contains <func>.\nUsage: func <name>\n");
add_info ("catch", catch_info, add_info ("catch", catch_info,
"Exceptions that can be caught in the current stack frame."); "Exceptions that can be caught in the current stack frame.");

View file

@ -1,5 +1,5 @@
/* Generic symbol file reading for the GNU debugger, GDB. /* Generic symbol file reading for the GNU debugger, GDB.
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996 Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998
Free Software Foundation, Inc. Free Software Foundation, Inc.
Contributed by Cygnus Support, using pieces from other GDB modules. Contributed by Cygnus Support, using pieces from other GDB modules.
@ -52,6 +52,20 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#define O_BINARY 0 #define O_BINARY 0
#endif #endif
#ifdef HPUXHPPA
extern int hpread_pxdb_check PARAMS ((bfd *, char *));
/* Some HP-UX related globals to clear when a new "main"
symbol file is loaded. HP-specific. */
extern int hp_som_som_object_present;
extern int hp_cxx_exception_support_initialized;
#define RESET_HP_UX_GLOBALS() do {\
hp_som_som_object_present = 0; /* indicates HP-compiled code */ \
hp_cxx_exception_support_initialized = 0; /* must reinitialize exception stuff */ \
} while (0)
#endif
int (*ui_load_progress_hook) PARAMS ((char *, unsigned long)); int (*ui_load_progress_hook) PARAMS ((char *, unsigned long));
void (*pre_add_symbol_hook) PARAMS ((char *)); void (*pre_add_symbol_hook) PARAMS ((char *));
void (*post_add_symbol_hook) PARAMS ((void)); void (*post_add_symbol_hook) PARAMS ((void));
@ -95,12 +109,42 @@ static int compare_psymbols PARAMS ((const void *, const void *));
static int compare_symbols PARAMS ((const void *, const void *)); static int compare_symbols PARAMS ((const void *, const void *));
static bfd *symfile_bfd_open PARAMS ((char *)); bfd *symfile_bfd_open PARAMS ((char *));
static void find_sym_fns PARAMS ((struct objfile *)); static void find_sym_fns PARAMS ((struct objfile *));
static void decrement_reading_symtab PARAMS ((void *)); static void decrement_reading_symtab PARAMS ((void *));
static void overlay_invalidate_all PARAMS ((void));
static int overlay_is_mapped PARAMS ((struct obj_section *));
void list_overlays_command PARAMS ((char *, int));
void map_overlay_command PARAMS ((char *, int));
void unmap_overlay_command PARAMS ((char *, int));
static void overlay_auto_command PARAMS ((char *, int));
static void overlay_manual_command PARAMS ((char *, int));
static void overlay_off_command PARAMS ((char *, int));
static void overlay_load_command PARAMS ((char *, int));
static void overlay_command PARAMS ((char *, int));
static void simple_free_overlay_table PARAMS ((void));
static void read_target_long_array PARAMS ((CORE_ADDR, unsigned int *, int));
static int simple_read_overlay_table PARAMS ((void));
static int simple_overlay_update_1 PARAMS ((struct obj_section *));
void _initialize_symfile PARAMS ((void));
/* List of all available sym_fns. On gdb startup, each object file reader /* List of all available sym_fns. On gdb startup, each object file reader
calls add_symtab_fns() to register information on each format it is calls add_symtab_fns() to register information on each format it is
prepared to read. */ prepared to read. */
@ -116,15 +160,25 @@ int symbol_reloading = SYMBOL_RELOADING_DEFAULT;
int symbol_reloading = 0; int symbol_reloading = 0;
#endif #endif
/* If true, then shared library symbols will be added automatically /* If non-zero, then on HP-UX (i.e., platforms that use somsolib.c),
when the inferior is created, new libraries are loaded, or when this variable is interpreted as a threshhold. If adding a new
attaching to the inferior. This is almost always what users library's symbol table to those already known to the debugger would
exceed this threshhold, then the shlib's symbols are not added.
If non-zero on other platforms, shared library symbols will be added
automatically when the inferior is created, new libraries are loaded,
or when attaching to the inferior. This is almost always what users
will want to have happen; but for very large programs, the startup will want to have happen; but for very large programs, the startup
time will be excessive, and so if this is a problem, the user can time will be excessive, and so if this is a problem, the user can
clear this flag and then add the shared library symbols as needed. clear this flag and then add the shared library symbols as needed.
Note that there is a potential for confusion, since if the shared Note that there is a potential for confusion, since if the shared
library symbols are not loaded, commands like "info fun" will *not* library symbols are not loaded, commands like "info fun" will *not*
report all the functions that are actually present. */ report all the functions that are actually present.
Note that HP-UX interprets this variable to mean, "threshhold size
in megabytes, where zero means never add". Other platforms interpret
this variable to mean, "always add if non-zero, never add if zero."
*/
int auto_solib_add = 1; int auto_solib_add = 1;
@ -186,7 +240,19 @@ compare_psymbols (s1p, s2p)
} }
else else
{ {
return (STRCMP (st1 + 2, st2 + 2)); /* Note: I replaced the STRCMP line (commented out below)
* with a simpler "strcmp()" which compares the 2 strings
* from the beginning. (STRCMP is a macro which first compares
* the initial characters, then falls back on strcmp).
* The reason is that the STRCMP line was tickling a C compiler
* bug on HP-UX 10.30, which is avoided with the simpler
* code. The performance gain from the more complicated code
* is negligible, given that we have already checked the
* initial 2 characters above. I reported the compiler bug,
* and once it is fixed the original line can be put back. RT
*/
/* return ( STRCMP (st1 + 2, st2 + 2)); */
return ( strcmp (st1, st2));
} }
} }
@ -431,13 +497,13 @@ syms_from_objfile (objfile, addr, mainline, verbo)
/* Make sure that partially constructed symbol tables will be cleaned up /* Make sure that partially constructed symbol tables will be cleaned up
if an error occurs during symbol reading. */ if an error occurs during symbol reading. */
old_chain = make_cleanup (free_objfile, objfile); old_chain = make_cleanup ((make_cleanup_func) free_objfile, objfile);
if (mainline) if (mainline)
{ {
/* We will modify the main symbol table, make sure that all its users /* We will modify the main symbol table, make sure that all its users
will be cleaned up if an error occurs during symbol reading. */ will be cleaned up if an error occurs during symbol reading. */
make_cleanup (clear_symtab_users, 0); make_cleanup ((make_cleanup_func) clear_symtab_users, 0);
/* Since no error yet, throw away the old symbol table. */ /* Since no error yet, throw away the old symbol table. */
@ -604,17 +670,25 @@ new_symfile_objfile (objfile, mainline, verbo)
as dynamically loaded code. If !mainline, ADDR is the address as dynamically loaded code. If !mainline, ADDR is the address
where the text segment was loaded. where the text segment was loaded.
USER_LOADED is TRUE if the add-symbol-file command was how this
symbol file came to be processed.
IS_SOLIB is TRUE if this symbol file represents a solib, as discovered
by the target's implementation of the solib package.
Upon success, returns a pointer to the objfile that was added. Upon success, returns a pointer to the objfile that was added.
Upon failure, jumps back to command level (never returns). */ Upon failure, jumps back to command level (never returns). */
struct objfile * struct objfile *
symbol_file_add (name, from_tty, addr, mainline, mapped, readnow) symbol_file_add (name, from_tty, addr, mainline, mapped, readnow, user_loaded, is_solib)
char *name; char *name;
int from_tty; int from_tty;
CORE_ADDR addr; CORE_ADDR addr;
int mainline; int mainline;
int mapped; int mapped;
int readnow; int readnow;
int user_loaded;
int is_solib;
{ {
struct objfile *objfile; struct objfile *objfile;
struct partial_symtab *psymtab; struct partial_symtab *psymtab;
@ -625,13 +699,59 @@ symbol_file_add (name, from_tty, addr, mainline, mapped, readnow)
abfd = symfile_bfd_open (name); abfd = symfile_bfd_open (name);
#if 0
#ifdef GDB_TARGET_IS_HPPA
{
/********* TARGET SPECIFIC CODE (HACK!) **********
*
* The following code is HP-specific. The "right" way of
* doing this is unknown, but we bet would involve a target-
* specific pre-file-load check using a generic mechanism.
*/
/* elz: I moved this code from inside the symfile_bfd_open function
this way we don't have to worry about recursion.
I also have taken out the call to pxdb from within the check
for pxdb processing. Seemed two logically unrelated things,
and I needed a pure checking later on anyway.
*/
if( hpread_pxdb_needed( abfd ))
{
/*
* This file has not been pre-processed.
* Preprocess now
*/
if (hpread_call_pxdb(name))
{
/* The
* call above has used "system" to pre-process
* the on-disk file, so we now need to close
* and re-open the file.
*/
bfd_close (abfd); /* This also closes 'desc', */
/* hence the recursion. */
abfd = symfile_bfd_open( name );
}
else /* we fail miserably without pxdb!!!*/
/* the warning to the user has already been given
from within the call_pxdb function
*/
error("Command ignored.\n");
}
}
/*************** END HACK ********************/
#endif
#endif /* 0 */
if ((have_full_symbols () || have_partial_symbols ()) if ((have_full_symbols () || have_partial_symbols ())
&& mainline && mainline
&& from_tty && from_tty
&& !query ("Load new symbol table from \"%s\"? ", name)) && !query ("Load new symbol table from \"%s\"? ", name))
error ("Not confirmed."); error ("Not confirmed.");
objfile = allocate_objfile (abfd, mapped); objfile = allocate_objfile (abfd, mapped, user_loaded, is_solib);
/* If the objfile uses a mapped symbol file, and we have a psymtab for /* If the objfile uses a mapped symbol file, and we have a psymtab for
it, then skip reading any symbols at this time. */ it, then skip reading any symbols at this time. */
@ -658,17 +778,17 @@ symbol_file_add (name, from_tty, addr, mainline, mapped, readnow)
performed, or need to read an unmapped symbol table. */ performed, or need to read an unmapped symbol table. */
if (from_tty || info_verbose) if (from_tty || info_verbose)
{ {
if (pre_add_symbol_hook) if (pre_add_symbol_hook)
pre_add_symbol_hook (name); pre_add_symbol_hook (name);
else else
{ {
printf_filtered ("Reading symbols from %s...", name); printf_filtered ("Reading symbols from %s...", name);
wrap_here (""); wrap_here ("");
gdb_flush (gdb_stdout); gdb_flush (gdb_stdout);
} }
} }
syms_from_objfile (objfile, addr, mainline, from_tty); syms_from_objfile (objfile, addr, mainline, from_tty);
} }
/* We now have at least a partial symbol table. Check to see if the /* We now have at least a partial symbol table. Check to see if the
user requested that all symbols be read on initial access via either user requested that all symbols be read on initial access via either
@ -742,11 +862,23 @@ symbol_file_command (args, from_tty)
symfile_objfile -> name)) symfile_objfile -> name))
error ("Not confirmed."); error ("Not confirmed.");
free_all_objfiles (); free_all_objfiles ();
/* solib descriptors may have handles to objfiles. Since their
storage has just been released, we'd better wipe the solib
descriptors as well.
*/
#if defined(SOLIB_RESTART)
SOLIB_RESTART ();
#endif
symfile_objfile = NULL; symfile_objfile = NULL;
if (from_tty) if (from_tty)
{ {
printf_unfiltered ("No symbol file now.\n"); printf_unfiltered ("No symbol file now.\n");
} }
#ifdef HPUXHPPA
RESET_HP_UX_GLOBALS ();
#endif
} }
else else
{ {
@ -754,7 +886,7 @@ symbol_file_command (args, from_tty)
{ {
nomem (0); nomem (0);
} }
cleanups = make_cleanup (freeargv, (char *) argv); cleanups = make_cleanup ((make_cleanup_func) freeargv, (char *) argv);
while (*argv != NULL) while (*argv != NULL)
{ {
if (STREQ (*argv, "-mapped")) if (STREQ (*argv, "-mapped"))
@ -786,11 +918,16 @@ symbol_file_command (args, from_tty)
if (text_relocation == (CORE_ADDR)0) if (text_relocation == (CORE_ADDR)0)
return; return;
else if (text_relocation == (CORE_ADDR)-1) else if (text_relocation == (CORE_ADDR)-1)
symbol_file_add (name, from_tty, (CORE_ADDR)0, 1, mapped, {
readnow); symbol_file_add (name, from_tty, (CORE_ADDR)0,
1, mapped, readnow, 1, 0);
#ifdef HPUXHPPA
RESET_HP_UX_GLOBALS ();
#endif
}
else else
symbol_file_add (name, from_tty, (CORE_ADDR)text_relocation, symbol_file_add (name, from_tty, (CORE_ADDR)text_relocation,
0, mapped, readnow); 0, mapped, readnow, 1, 0);
/* Getting new symbols may change our opinion about what is /* Getting new symbols may change our opinion about what is
frameless. */ frameless. */
@ -805,6 +942,7 @@ symbol_file_command (args, from_tty)
{ {
error ("no symbol file name was specified"); error ("no symbol file name was specified");
} }
TUIDO(((TuiOpaqueFuncPtr)tuiDisplayMainFunction));
do_cleanups (cleanups); do_cleanups (cleanups);
} }
} }
@ -847,7 +985,7 @@ set_initial_language ()
malloc'd` copy of NAME (tilde-expanded and made absolute). malloc'd` copy of NAME (tilde-expanded and made absolute).
In case of trouble, error() is called. */ In case of trouble, error() is called. */
static bfd * bfd *
symfile_bfd_open (name) symfile_bfd_open (name)
char *name; char *name;
{ {
@ -855,6 +993,8 @@ symfile_bfd_open (name)
int desc; int desc;
char *absolute_name; char *absolute_name;
name = tilde_expand (name); /* Returns 1st new malloc'd copy */ name = tilde_expand (name); /* Returns 1st new malloc'd copy */
/* Look down path for it, allocate 2nd new malloc'd copy. */ /* Look down path for it, allocate 2nd new malloc'd copy. */
@ -898,6 +1038,42 @@ symfile_bfd_open (name)
bfd_errmsg (bfd_get_error ())); bfd_errmsg (bfd_get_error ()));
} }
#ifdef HPUXHPPA
{
/********* TARGET SPECIFIC CODE (HACK!) **********
*
* The following code is HP-specific. The "right" way of
* doing this is unknown, but we bet would involve a target-
* specific pre-file-load check using a generic mechanism.
*/
static prevent_recursion = 0; /* Needed for hack below! HP-specific */
if( prevent_recursion == 0 ) {
if( hpread_pxdb_needed (sym_bfd, name)) {
/*
* This file has not been pre-processed.
* Preprocess now
*/
if (hpread_call_pxdb(name))
{
/* The
* call above has used "system" to pre-process
* the on-disk file, so we now need to close
* and re-open the file.
*/
bfd_close (sym_bfd); /* This also closes 'desc', */
/* hence the recursion. */
prevent_recursion++;
sym_bfd = symfile_bfd_open( name );
prevent_recursion--;
}
}
}
}
/*************** END HACK ********************/
#endif
return (sym_bfd); return (sym_bfd);
} }
@ -1004,7 +1180,7 @@ generic_load (filename, from_tty)
/* FIXME: should be checking for errors from bfd_close (for one thing, /* FIXME: should be checking for errors from bfd_close (for one thing,
on error it does not free all the storage associated with the on error it does not free all the storage associated with the
bfd). */ bfd). */
old_cleanups = make_cleanup (bfd_close, loadfile_bfd); old_cleanups = make_cleanup ((make_cleanup_func) bfd_close, loadfile_bfd);
if (!bfd_check_format (loadfile_bfd, bfd_object)) if (!bfd_check_format (loadfile_bfd, bfd_object))
{ {
@ -1210,7 +1386,9 @@ add_symbol_file_command (args, from_tty)
name, local_hex_string ((unsigned long)text_addr)))) name, local_hex_string ((unsigned long)text_addr))))
error ("Not confirmed."); error ("Not confirmed.");
symbol_file_add (name, from_tty, text_addr, 0, mapped, readnow); symbol_file_add (name, from_tty, text_addr, 0, mapped, readnow,
1, /* user_loaded */
0); /* We'll guess it's ! is_solib */
/* Getting new symbols may change our opinion about what is /* Getting new symbols may change our opinion about what is
frameless. */ frameless. */
@ -1284,9 +1462,10 @@ reread_symbols ()
/* If we get an error, blow away this objfile (not sure if /* If we get an error, blow away this objfile (not sure if
that is the correct response for things like shared that is the correct response for things like shared
libraries). */ libraries). */
old_cleanups = make_cleanup (free_objfile, objfile); old_cleanups = make_cleanup ((make_cleanup_func) free_objfile,
objfile);
/* We need to do this whenever any symbols go away. */ /* We need to do this whenever any symbols go away. */
make_cleanup (clear_symtab_users, 0); make_cleanup ((make_cleanup_func) clear_symtab_users, 0);
/* Clean up any state BFD has sitting around. We don't need /* Clean up any state BFD has sitting around. We don't need
to close the descriptor but BFD lacks a way of closing the to close the descriptor but BFD lacks a way of closing the
@ -1375,7 +1554,12 @@ reread_symbols ()
distinguishing between the main file and additional files distinguishing between the main file and additional files
in this way seems rather dubious. */ in this way seems rather dubious. */
if (objfile == symfile_objfile) if (objfile == symfile_objfile)
(*objfile->sf->sym_new_init) (objfile); {
(*objfile->sf->sym_new_init) (objfile);
#ifdef HPUXHPPA
RESET_HP_UX_GLOBALS ();
#endif
}
(*objfile->sf->sym_init) (objfile); (*objfile->sf->sym_init) (objfile);
clear_complaints (1, 1); clear_complaints (1, 1);
@ -1423,35 +1607,152 @@ reread_symbols ()
} }
typedef struct {
char *ext;
enum language lang;
} filename_language;
static filename_language * filename_language_table;
static int fl_table_size, fl_table_next;
static void
add_filename_language (ext, lang)
char *ext;
enum language lang;
{
if (fl_table_next >= fl_table_size)
{
fl_table_size += 10;
filename_language_table = realloc (filename_language_table,
fl_table_size);
}
filename_language_table[fl_table_next].ext = strsave (ext);
filename_language_table[fl_table_next].lang = lang;
fl_table_next++;
}
static char *ext_args;
static void
set_ext_lang_command (args, from_tty)
char *args;
int from_tty;
{
int i;
char *cp = ext_args;
enum language lang;
/* First arg is filename extension, starting with '.' */
if (*cp != '.')
error ("'%s': Filename extension must begin with '.'", ext_args);
/* Find end of first arg. */
while (*cp && !isspace (*cp))
cp++;
if (*cp == '\0')
error ("'%s': two arguments required -- filename extension and language",
ext_args);
/* Null-terminate first arg */
*cp++ = '\0';
/* Find beginning of second arg, which should be a source language. */
while (*cp && isspace (*cp))
cp++;
if (*cp == '\0')
error ("'%s': two arguments required -- filename extension and language",
ext_args);
/* Lookup the language from among those we know. */
lang = language_enum (cp);
/* Now lookup the filename extension: do we already know it? */
for (i = 0; i < fl_table_next; i++)
if (0 == strcmp (ext_args, filename_language_table[i].ext))
break;
if (i >= fl_table_next)
{
/* new file extension */
add_filename_language (ext_args, lang);
}
else
{
/* redefining a previously known filename extension */
/* if (from_tty) */
/* query ("Really make files of type %s '%s'?", */
/* ext_args, language_str (lang)); */
free (filename_language_table[i].ext);
filename_language_table[i].ext = strsave (ext_args);
filename_language_table[i].lang = lang;
}
}
static void
info_ext_lang_command (args, from_tty)
char *args;
int from_tty;
{
int i;
printf_filtered ("Filename extensions and the languages they represent:");
printf_filtered ("\n\n");
for (i = 0; i < fl_table_next; i++)
printf_filtered ("\t%s\t- %s\n",
filename_language_table[i].ext,
language_str (filename_language_table[i].lang));
}
static void
init_filename_language_table ()
{
if (fl_table_size == 0) /* protect against repetition */
{
fl_table_size = 20;
fl_table_next = 0;
filename_language_table =
xmalloc (fl_table_size * sizeof (*filename_language_table));
add_filename_language (".c", language_c);
add_filename_language (".C", language_cplus);
add_filename_language (".cc", language_cplus);
add_filename_language (".cp", language_cplus);
add_filename_language (".cpp", language_cplus);
add_filename_language (".cxx", language_cplus);
add_filename_language (".c++", language_cplus);
/* start-sanitize-java */
add_filename_language (".java", language_java);
add_filename_language (".class", language_java);
/* end-sanitize-java */
add_filename_language (".ch", language_chill);
add_filename_language (".c186", language_chill);
add_filename_language (".c286", language_chill);
add_filename_language (".f", language_fortran);
add_filename_language (".F", language_fortran);
add_filename_language (".s", language_asm);
add_filename_language (".S", language_asm);
}
}
enum language enum language
deduce_language_from_filename (filename) deduce_language_from_filename (filename)
char *filename; char *filename;
{ {
char *c; int i;
char *cp;
if (0 == filename)
; /* Get default */
else if (0 == (c = strrchr (filename, '.')))
; /* Get default. */
else if (STREQ (c, ".c"))
return language_c;
else if (STREQ (c, ".cc") || STREQ (c, ".C") || STREQ (c, ".cxx")
|| STREQ (c, ".cpp") || STREQ (c, ".cp") || STREQ (c, ".c++"))
return language_cplus;
/* start-sanitize-java */
else if (STREQ (c, ".java") || STREQ (c, ".class"))
return language_java;
/* end-sanitize-java */
else if (STREQ (c, ".ch") || STREQ (c, ".c186") || STREQ (c, ".c286"))
return language_chill;
else if (STREQ (c, ".f") || STREQ (c, ".F"))
return language_fortran;
else if (STREQ (c, ".mod"))
return language_m2;
else if (STREQ (c, ".s") || STREQ (c, ".S"))
return language_asm;
return language_unknown; /* default */ if (filename != NULL)
if ((cp = strrchr (filename, '.')) != NULL)
for (i = 0; i < fl_table_next; i++)
if (strcmp (cp, filename_language_table[i].ext) == 0)
return filename_language_table[i].lang;
return language_unknown;
} }
/* allocate_symtab: /* allocate_symtab:
@ -1874,6 +2175,83 @@ add_psymbol_to_list (name, namelength, namespace, class, list, val, coreaddr,
OBJSTAT (objfile, n_psyms++); OBJSTAT (objfile, n_psyms++);
} }
/* Add a symbol with a long value to a psymtab. This differs from
* add_psymbol_to_list above in taking both a mangled and a demangled
* name. */
void
add_psymbol_with_dem_name_to_list (name, namelength, dem_name, dem_namelength,
namespace, class, list, val, coreaddr, language, objfile)
char *name;
int namelength;
char *dem_name;
int dem_namelength;
namespace_enum namespace;
enum address_class class;
struct psymbol_allocation_list *list;
long val; /* Value as a long */
CORE_ADDR coreaddr; /* Value as a CORE_ADDR */
enum language language;
struct objfile *objfile;
{
register struct partial_symbol *psym;
char *buf = alloca (namelength + 1);
/* psymbol is static so that there will be no uninitialized gaps in the
structure which might contain random data, causing cache misses in
bcache. */
static struct partial_symbol psymbol;
/* Create local copy of the partial symbol */
memcpy (buf, name, namelength);
buf[namelength] = '\0';
SYMBOL_NAME (&psymbol) = bcache (buf, namelength + 1, &objfile->psymbol_cache);
buf = alloca (dem_namelength + 1);
memcpy (buf, dem_name, dem_namelength);
buf[dem_namelength] = '\0';
switch (language)
{
case language_c:
case language_cplus:
SYMBOL_CPLUS_DEMANGLED_NAME (&psymbol) =
bcache (buf, dem_namelength + 1, &objfile->psymbol_cache);
break;
case language_chill:
SYMBOL_CHILL_DEMANGLED_NAME (&psymbol) =
bcache (buf, dem_namelength + 1, &objfile->psymbol_cache);
/* FIXME What should be done for the default case? Ignoring for now. */
}
/* val and coreaddr are mutually exclusive, one of them *will* be zero */
if (val != 0)
{
SYMBOL_VALUE (&psymbol) = val;
}
else
{
SYMBOL_VALUE_ADDRESS (&psymbol) = coreaddr;
}
SYMBOL_SECTION (&psymbol) = 0;
SYMBOL_LANGUAGE (&psymbol) = language;
PSYMBOL_NAMESPACE (&psymbol) = namespace;
PSYMBOL_CLASS (&psymbol) = class;
SYMBOL_INIT_LANGUAGE_SPECIFIC (&psymbol, language);
/* Stash the partial symbol away in the cache */
psym = bcache (&psymbol, sizeof (struct partial_symbol), &objfile->psymbol_cache);
/* Save pointer to partial symbol in psymtab, growing symtab if needed. */
if (list->next >= list->list + list->size)
{
extend_psymbol_list (list, objfile);
}
*list->next++ = psym;
OBJSTAT (objfile, n_psyms++);
}
/* Initialize storage for partial symbols. */ /* Initialize storage for partial symbols. */
void void
@ -2240,10 +2618,17 @@ list_overlays_command (args, from_tty)
lma = bfd_section_lma (objfile->obfd, osect->the_bfd_section); lma = bfd_section_lma (objfile->obfd, osect->the_bfd_section);
size = bfd_get_section_size_before_reloc (osect->the_bfd_section); size = bfd_get_section_size_before_reloc (osect->the_bfd_section);
name = bfd_section_name (objfile->obfd, osect->the_bfd_section); name = bfd_section_name (objfile->obfd, osect->the_bfd_section);
printf_filtered ("Section %s, loaded at %08x - %08x, ",
name, lma, lma + size); printf_filtered ("Section %s, loaded at ", name);
printf_filtered ("mapped at %08x - %08x\n", print_address_numeric (lma, 1, stdout);
vma, vma + size); puts_filtered (" - ");
print_address_numeric (lma + size, 1, stdout);
printf_filtered (", mapped at ");
print_address_numeric (vma, 1, stdout);
puts_filtered (" - ");
print_address_numeric (vma + size, 1, stdout);
puts_filtered ("\n");
nmapped ++; nmapped ++;
} }
if (nmapped == 0) if (nmapped == 0)
@ -2367,7 +2752,7 @@ overlay_off_command (args, from_tty)
char *args; char *args;
int from_tty; int from_tty;
{ {
overlay_debugging = 0; overlay_debugging = 0;
if (info_verbose) if (info_verbose)
printf_filtered ("Overlay debugging disabled."); printf_filtered ("Overlay debugging disabled.");
} }
@ -2707,4 +3092,16 @@ for access from GDB.", &cmdlist);
"Enable automatic overlay debugging.", &overlaylist); "Enable automatic overlay debugging.", &overlaylist);
add_cmd ("load-target", class_support, overlay_load_command, add_cmd ("load-target", class_support, overlay_load_command,
"Read the overlay mapping state from the target.", &overlaylist); "Read the overlay mapping state from the target.", &overlaylist);
/* Filename extension to source language lookup table: */
init_filename_language_table ();
c = add_set_cmd ("extension-language", class_files, var_string_noescape,
(char *) &ext_args,
"Set mapping between filename extension and source language.\n\
Usage: set extension-language .foo bar",
&setlist);
c->function.cfunc = set_ext_lang_command;
add_info ("extensions", info_ext_lang_command,
"All filename extensions associated with a source language.");
} }

View file

@ -1,5 +1,5 @@
/* Do various things to symbol tables (other than lookup), for GDB. /* Do various things to symbol tables (other than lookup), for GDB.
Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996 Copyright 1986, 87, 89, 91, 92, 93, 94, 95, 96, 1998
Free Software Foundation, Inc. Free Software Foundation, Inc.
This file is part of GDB. This file is part of GDB.
@ -48,23 +48,26 @@ FILE *std_err;
/* Prototypes for local functions */ /* Prototypes for local functions */
static void static void dump_symtab PARAMS ((struct objfile *, struct symtab *,
dump_symtab PARAMS ((struct objfile *, struct symtab *, GDB_FILE *)); GDB_FILE *));
static void static void dump_psymtab PARAMS ((struct objfile *, struct partial_symtab *,
dump_psymtab PARAMS ((struct objfile *, struct partial_symtab *, GDB_FILE *)); GDB_FILE *));
static void static void dump_msymbols PARAMS ((struct objfile *, GDB_FILE *));
dump_msymbols PARAMS ((struct objfile *, GDB_FILE *));
static void static void dump_objfile PARAMS ((struct objfile *));
dump_objfile PARAMS ((struct objfile *));
static int static int block_depth PARAMS ((struct block *));
block_depth PARAMS ((struct block *));
static void static void print_partial_symbols PARAMS ((struct partial_symbol **, int,
print_partial_symbols PARAMS ((struct partial_symbol **, int, char *, GDB_FILE *)); char *, GDB_FILE *));
static int print_symbol PARAMS ((char *));
static void free_symtab_block PARAMS ((struct objfile *, struct block *));
void _initialize_symmisc PARAMS ((void));
struct print_symbol_args { struct print_symbol_args {
struct symbol *symbol; struct symbol *symbol;
@ -148,6 +151,8 @@ free_symtab (s)
mfree (s -> objfile -> md, (PTR) s -> line_charpos); mfree (s -> objfile -> md, (PTR) s -> line_charpos);
if (s -> fullname != NULL) if (s -> fullname != NULL)
mfree (s -> objfile -> md, s -> fullname); mfree (s -> objfile -> md, s -> fullname);
if (s -> debugformat != NULL)
mfree (s -> objfile -> md, s -> debugformat);
mfree (s -> objfile -> md, (PTR) s); mfree (s -> objfile -> md, (PTR) s);
} }
@ -180,22 +185,24 @@ print_objfile_statistics ()
printf_filtered (" Number of \"stab\" symbols read: %d\n", printf_filtered (" Number of \"stab\" symbols read: %d\n",
OBJSTAT (objfile, n_stabs)); OBJSTAT (objfile, n_stabs));
if (OBJSTAT (objfile, n_minsyms) > 0) if (OBJSTAT (objfile, n_minsyms) > 0)
printf_filtered (" Number of \"minimal symbols read: %d\n", printf_filtered (" Number of \"minimal\" symbols read: %d\n",
OBJSTAT (objfile, n_minsyms)); OBJSTAT (objfile, n_minsyms));
if (OBJSTAT (objfile, n_psyms) > 0) if (OBJSTAT (objfile, n_psyms) > 0)
printf_filtered (" Number of \"partial symbols read: %d\n", printf_filtered (" Number of \"partial\" symbols read: %d\n",
OBJSTAT (objfile, n_psyms)); OBJSTAT (objfile, n_psyms));
if (OBJSTAT (objfile, n_syms) > 0) if (OBJSTAT (objfile, n_syms) > 0)
printf_filtered (" Number of \"full symbols read: %d\n", printf_filtered (" Number of \"full\" symbols read: %d\n",
OBJSTAT (objfile, n_syms)); OBJSTAT (objfile, n_syms));
if (OBJSTAT (objfile, n_types) > 0) if (OBJSTAT (objfile, n_types) > 0)
printf_filtered (" Number of \"types defined: %d\n", printf_filtered (" Number of \"types\" defined: %d\n",
OBJSTAT (objfile, n_types)); OBJSTAT (objfile, n_types));
if (OBJSTAT (objfile, sz_strtab) > 0) if (OBJSTAT (objfile, sz_strtab) > 0)
printf_filtered (" Space used by a.out string tables: %d\n", printf_filtered (" Space used by a.out string tables: %d\n",
OBJSTAT (objfile, sz_strtab)); OBJSTAT (objfile, sz_strtab));
printf_filtered (" Total memory used for psymbol obstack: %d\n", printf_filtered (" Total memory used for psymbol obstack: %d\n",
obstack_memory_used (&objfile -> psymbol_obstack)); obstack_memory_used (&objfile -> psymbol_obstack));
printf_filtered (" Total memory used for psymbol cache: %d\n",
obstack_memory_used (&objfile -> psymbol_cache.cache));
printf_filtered (" Total memory used for symbol obstack: %d\n", printf_filtered (" Total memory used for symbol obstack: %d\n",
obstack_memory_used (&objfile -> symbol_obstack)); obstack_memory_used (&objfile -> symbol_obstack));
printf_filtered (" Total memory used for type obstack: %d\n", printf_filtered (" Total memory used for type obstack: %d\n",
@ -312,8 +319,13 @@ dump_msymbols (objfile, outfile)
ms_type = '?'; ms_type = '?';
break; break;
} }
fprintf_filtered (outfile, "[%2d] %c %#10lx %s", index, ms_type, fprintf_filtered (outfile, "[%2d] %c ", index, ms_type);
SYMBOL_VALUE_ADDRESS (msymbol), SYMBOL_NAME (msymbol)); print_address_numeric (SYMBOL_VALUE_ADDRESS (msymbol), 1, outfile);
fprintf_filtered (outfile, " %s", SYMBOL_NAME (msymbol));
if (SYMBOL_BFD_SECTION (msymbol))
fprintf_filtered (outfile, " section %s",
bfd_section_name (objfile->obfd,
SYMBOL_BFD_SECTION (msymbol)));
if (SYMBOL_DEMANGLED_NAME (msymbol) != NULL) if (SYMBOL_DEMANGLED_NAME (msymbol) != NULL)
{ {
fprintf_filtered (outfile, " %s", SYMBOL_DEMANGLED_NAME (msymbol)); fprintf_filtered (outfile, " %s", SYMBOL_DEMANGLED_NAME (msymbol));
@ -415,10 +427,13 @@ dump_symtab (objfile, symtab, outfile)
int depth; int depth;
fprintf_filtered (outfile, "\nSymtab for file %s\n", symtab->filename); fprintf_filtered (outfile, "\nSymtab for file %s\n", symtab->filename);
if (symtab->dirname)
fprintf_filtered (outfile, "Compilation directory is %s\n",
symtab->dirname);
fprintf_filtered (outfile, "Read from object file %s (", objfile->name); fprintf_filtered (outfile, "Read from object file %s (", objfile->name);
gdb_print_address (objfile, outfile); gdb_print_address (objfile, outfile);
fprintf_filtered (outfile, ")\n"); fprintf_filtered (outfile, ")\n");
fprintf_filtered (outfile, "Language: %s\n", language_str (symtab -> language)); fprintf_filtered (outfile, "Language: %s\n", language_str (symtab->language));
/* First print the line table. */ /* First print the line table. */
l = LINETABLE (symtab); l = LINETABLE (symtab);
@ -433,53 +448,59 @@ dump_symtab (objfile, symtab, outfile)
fprintf_filtered (outfile, "\n"); fprintf_filtered (outfile, "\n");
} }
} }
/* Now print the block info. */ /* Now print the block info, but only for primary symtabs since we will
fprintf_filtered (outfile, "\nBlockvector:\n\n"); print lots of duplicate info otherwise. */
bv = BLOCKVECTOR (symtab); if (symtab -> primary)
len = BLOCKVECTOR_NBLOCKS (bv);
for (i = 0; i < len; i++)
{ {
b = BLOCKVECTOR_BLOCK (bv, i); fprintf_filtered (outfile, "\nBlockvector:\n\n");
depth = block_depth (b) * 2; bv = BLOCKVECTOR (symtab);
print_spaces (depth, outfile); len = BLOCKVECTOR_NBLOCKS (bv);
fprintf_filtered (outfile, "block #%03d (object ", i); for (i = 0; i < len; i++)
gdb_print_address (b, outfile);
fprintf_filtered (outfile, ") ");
fprintf_filtered (outfile, "[");
print_address_numeric (BLOCK_START (b), 1, outfile);
fprintf_filtered (outfile, "..");
print_address_numeric (BLOCK_END (b), 1, outfile);
fprintf_filtered (outfile, "]");
if (BLOCK_SUPERBLOCK (b))
{ {
fprintf_filtered (outfile, " (under "); b = BLOCKVECTOR_BLOCK (bv, i);
gdb_print_address (BLOCK_SUPERBLOCK (b), outfile); depth = block_depth (b) * 2;
fprintf_filtered (outfile, ")"); print_spaces (depth, outfile);
} fprintf_filtered (outfile, "block #%03d, object at ", i);
if (BLOCK_FUNCTION (b)) gdb_print_address (b, outfile);
{ if (BLOCK_SUPERBLOCK (b))
fprintf_filtered (outfile, " %s", SYMBOL_NAME (BLOCK_FUNCTION (b)));
if (SYMBOL_DEMANGLED_NAME (BLOCK_FUNCTION (b)) != NULL)
{ {
fprintf_filtered (outfile, " %s", fprintf_filtered (outfile, " under ");
SYMBOL_DEMANGLED_NAME (BLOCK_FUNCTION (b))); gdb_print_address (BLOCK_SUPERBLOCK (b), outfile);
}
blen = BLOCK_NSYMS (b);
fprintf_filtered (outfile, ", %d syms in ", blen);
print_address_numeric (BLOCK_START (b), 1, outfile);
fprintf_filtered (outfile, "..");
print_address_numeric (BLOCK_END (b), 1, outfile);
if (BLOCK_FUNCTION (b))
{
fprintf_filtered (outfile, ", function %s", SYMBOL_NAME (BLOCK_FUNCTION (b)));
if (SYMBOL_DEMANGLED_NAME (BLOCK_FUNCTION (b)) != NULL)
{
fprintf_filtered (outfile, ", %s",
SYMBOL_DEMANGLED_NAME (BLOCK_FUNCTION (b)));
}
}
if (BLOCK_GCC_COMPILED(b))
fprintf_filtered (outfile, ", compiled with gcc%d", BLOCK_GCC_COMPILED(b));
fprintf_filtered (outfile, "\n");
/* Now print each symbol in this block */
for (j = 0; j < blen; j++)
{
struct print_symbol_args s;
s.symbol = BLOCK_SYM (b, j);
s.depth = depth + 1;
s.outfile = outfile;
catch_errors (print_symbol, &s, "Error printing symbol:\n",
RETURN_MASK_ALL);
} }
} }
if (BLOCK_GCC_COMPILED(b))
fprintf_filtered (outfile, " gcc%d compiled", BLOCK_GCC_COMPILED(b));
fprintf_filtered (outfile, "\n"); fprintf_filtered (outfile, "\n");
blen = BLOCK_NSYMS (b);
for (j = 0; j < blen; j++)
{
struct print_symbol_args s;
s.symbol = BLOCK_SYM (b, j);
s.depth = depth + 1;
s.outfile = outfile;
catch_errors (print_symbol, &s, "Error printing symbol:\n",
RETURN_MASK_ALL);
}
} }
fprintf_filtered (outfile, "\n"); else
{
fprintf_filtered (outfile, "\nBlockvector same as previous symtab\n\n");
}
} }
void void
@ -506,7 +527,7 @@ Arguments missing: an output file name and an optional symbol file name");
{ {
nomem (0); nomem (0);
} }
cleanups = make_cleanup (freeargv, (char *) argv); cleanups = make_cleanup ((make_cleanup_func) freeargv, (char *) argv);
if (argv[0] != NULL) if (argv[0] != NULL)
{ {
@ -524,7 +545,7 @@ Arguments missing: an output file name and an optional symbol file name");
outfile = gdb_fopen (filename, FOPEN_WT); outfile = gdb_fopen (filename, FOPEN_WT);
if (outfile == 0) if (outfile == 0)
perror_with_name (filename); perror_with_name (filename);
make_cleanup (fclose, (char *) outfile); make_cleanup ((make_cleanup_func) gdb_fclose, (char *) &outfile);
immediate_quit++; immediate_quit++;
ALL_SYMTABS (objfile, s) ALL_SYMTABS (objfile, s)
@ -552,7 +573,12 @@ print_symbol (args)
{ {
fprintf_filtered (outfile, "label %s at ", SYMBOL_SOURCE_NAME (symbol)); fprintf_filtered (outfile, "label %s at ", SYMBOL_SOURCE_NAME (symbol));
print_address_numeric (SYMBOL_VALUE_ADDRESS (symbol), 1, outfile); print_address_numeric (SYMBOL_VALUE_ADDRESS (symbol), 1, outfile);
fprintf_filtered (outfile, "\n"); if (SYMBOL_BFD_SECTION (symbol))
fprintf_filtered (outfile, " section %s\n",
bfd_section_name (SYMBOL_BFD_SECTION (symbol)->owner,
SYMBOL_BFD_SECTION (symbol)));
else
fprintf_filtered (outfile, "\n");
return 1; return 1;
} }
if (SYMBOL_NAMESPACE (symbol) == STRUCT_NAMESPACE) if (SYMBOL_NAMESPACE (symbol) == STRUCT_NAMESPACE)
@ -592,7 +618,7 @@ print_symbol (args)
switch (SYMBOL_CLASS (symbol)) switch (SYMBOL_CLASS (symbol))
{ {
case LOC_CONST: case LOC_CONST:
fprintf_filtered (outfile, "const %ld (0x%lx),", fprintf_filtered (outfile, "const %ld (0x%lx)",
SYMBOL_VALUE (symbol), SYMBOL_VALUE (symbol),
SYMBOL_VALUE (symbol)); SYMBOL_VALUE (symbol));
break; break;
@ -606,44 +632,53 @@ print_symbol (args)
for (i = 0; i < TYPE_LENGTH (type); i++) for (i = 0; i < TYPE_LENGTH (type); i++)
fprintf_filtered (outfile, " %02x", fprintf_filtered (outfile, " %02x",
(unsigned)SYMBOL_VALUE_BYTES (symbol) [i]); (unsigned)SYMBOL_VALUE_BYTES (symbol) [i]);
fprintf_filtered (outfile, ",");
} }
break; break;
case LOC_STATIC: case LOC_STATIC:
fprintf_filtered (outfile, "static at "); fprintf_filtered (outfile, "static at ");
print_address_numeric (SYMBOL_VALUE_ADDRESS (symbol), 1,outfile); print_address_numeric (SYMBOL_VALUE_ADDRESS (symbol), 1,outfile);
fprintf_filtered (outfile, ","); if (SYMBOL_BFD_SECTION (symbol))
fprintf_filtered (outfile, " section %s",
bfd_section_name
(SYMBOL_BFD_SECTION (symbol)->owner,
SYMBOL_BFD_SECTION (symbol)));
break;
case LOC_INDIRECT:
fprintf_filtered (outfile, "extern global at *(");
print_address_numeric (SYMBOL_VALUE_ADDRESS (symbol), 1,outfile);
fprintf_filtered (outfile, "),");
break; break;
case LOC_REGISTER: case LOC_REGISTER:
fprintf_filtered (outfile, "register %ld,", SYMBOL_VALUE (symbol)); fprintf_filtered (outfile, "register %ld", SYMBOL_VALUE (symbol));
break; break;
case LOC_ARG: case LOC_ARG:
fprintf_filtered (outfile, "arg at offset 0x%lx,", fprintf_filtered (outfile, "arg at offset 0x%lx",
SYMBOL_VALUE (symbol)); SYMBOL_VALUE (symbol));
break; break;
case LOC_LOCAL_ARG: case LOC_LOCAL_ARG:
fprintf_filtered (outfile, "arg at offset 0x%lx from fp,", fprintf_filtered (outfile, "arg at offset 0x%lx from fp",
SYMBOL_VALUE (symbol)); SYMBOL_VALUE (symbol));
break; break;
case LOC_REF_ARG: case LOC_REF_ARG:
fprintf_filtered (outfile, "reference arg at 0x%lx,", SYMBOL_VALUE (symbol)); fprintf_filtered (outfile, "reference arg at 0x%lx", SYMBOL_VALUE (symbol));
break; break;
case LOC_REGPARM: case LOC_REGPARM:
fprintf_filtered (outfile, "parameter register %ld,", SYMBOL_VALUE (symbol)); fprintf_filtered (outfile, "parameter register %ld", SYMBOL_VALUE (symbol));
break; break;
case LOC_REGPARM_ADDR: case LOC_REGPARM_ADDR:
fprintf_filtered (outfile, "address parameter register %ld,", SYMBOL_VALUE (symbol)); fprintf_filtered (outfile, "address parameter register %ld", SYMBOL_VALUE (symbol));
break; break;
case LOC_LOCAL: case LOC_LOCAL:
fprintf_filtered (outfile, "local at offset 0x%lx,", fprintf_filtered (outfile, "local at offset 0x%lx",
SYMBOL_VALUE (symbol)); SYMBOL_VALUE (symbol));
break; break;
@ -653,7 +688,7 @@ print_symbol (args)
break; break;
case LOC_BASEREG_ARG: case LOC_BASEREG_ARG:
fprintf_filtered (outfile, "arg at 0x%lx from register %d,", fprintf_filtered (outfile, "arg at 0x%lx from register %d",
SYMBOL_VALUE (symbol), SYMBOL_BASEREG (symbol)); SYMBOL_VALUE (symbol), SYMBOL_BASEREG (symbol));
break; break;
@ -663,16 +698,29 @@ print_symbol (args)
case LOC_LABEL: case LOC_LABEL:
fprintf_filtered (outfile, "label at "); fprintf_filtered (outfile, "label at ");
print_address_numeric (SYMBOL_VALUE_ADDRESS (symbol), 1, outfile); print_address_numeric (SYMBOL_VALUE_ADDRESS (symbol), 1, outfile);
if (SYMBOL_BFD_SECTION (symbol))
fprintf_filtered (outfile, " section %s",
bfd_section_name
(SYMBOL_BFD_SECTION (symbol)->owner,
SYMBOL_BFD_SECTION (symbol)));
break; break;
case LOC_BLOCK: case LOC_BLOCK:
fprintf_filtered (outfile, "block (object "); fprintf_filtered (outfile, "block object ");
gdb_print_address (SYMBOL_BLOCK_VALUE (symbol), outfile); gdb_print_address (SYMBOL_BLOCK_VALUE (symbol), outfile);
fprintf_filtered (outfile, ") starting at "); fprintf_filtered (outfile, ", ");
print_address_numeric (BLOCK_START (SYMBOL_BLOCK_VALUE (symbol)), print_address_numeric (BLOCK_START (SYMBOL_BLOCK_VALUE (symbol)),
1, 1,
outfile); outfile);
fprintf_filtered (outfile, ","); fprintf_filtered (outfile, "..");
print_address_numeric (BLOCK_END (SYMBOL_BLOCK_VALUE (symbol)),
1,
outfile);
if (SYMBOL_BFD_SECTION (symbol))
fprintf_filtered (outfile, " section %s",
bfd_section_name
(SYMBOL_BFD_SECTION (symbol)->owner,
SYMBOL_BFD_SECTION (symbol)));
break; break;
case LOC_UNRESOLVED: case LOC_UNRESOLVED:
@ -699,7 +747,7 @@ maintenance_print_psymbols (args, from_tty)
int from_tty; int from_tty;
{ {
char **argv; char **argv;
GDB_FILE *outfile; GDB_FILE *outfile;
struct cleanup *cleanups; struct cleanup *cleanups;
char *symname = NULL; char *symname = NULL;
char *filename = DEV_TTY; char *filename = DEV_TTY;
@ -716,7 +764,7 @@ maintenance_print_psymbols (args, from_tty)
{ {
nomem (0); nomem (0);
} }
cleanups = make_cleanup (freeargv, (char *) argv); cleanups = make_cleanup ((make_cleanup_func) freeargv, (char *) argv);
if (argv[0] != NULL) if (argv[0] != NULL)
{ {
@ -734,7 +782,7 @@ maintenance_print_psymbols (args, from_tty)
outfile = gdb_fopen (filename, FOPEN_WT); outfile = gdb_fopen (filename, FOPEN_WT);
if (outfile == 0) if (outfile == 0)
perror_with_name (filename); perror_with_name (filename);
make_cleanup (fclose, outfile); make_cleanup ((make_cleanup_func) gdb_fclose, &outfile);
immediate_quit++; immediate_quit++;
ALL_PSYMTABS (objfile, ps) ALL_PSYMTABS (objfile, ps)
@ -789,6 +837,9 @@ print_partial_symbols (p, count, what, outfile)
case LOC_STATIC: case LOC_STATIC:
fputs_filtered ("static", outfile); fputs_filtered ("static", outfile);
break; break;
case LOC_INDIRECT:
fputs_filtered ("extern global", outfile);
break;
case LOC_REGISTER: case LOC_REGISTER:
fputs_filtered ("register", outfile); fputs_filtered ("register", outfile);
break; break;
@ -833,10 +884,8 @@ print_partial_symbols (p, count, what, outfile)
break; break;
} }
fputs_filtered (", ", outfile); fputs_filtered (", ", outfile);
/* FIXME-32x64: Need to use SYMBOL_VALUE_ADDRESS, etc.; this print_address_numeric (SYMBOL_VALUE_ADDRESS (*p), 1, outfile);
could be 32 bits when some of the other fields in the union fprintf_filtered (outfile, "\n");
are 64. */
fprintf_filtered (outfile, "0x%lx\n", SYMBOL_VALUE (*p));
p++; p++;
} }
} }
@ -863,7 +912,7 @@ maintenance_print_msymbols (args, from_tty)
{ {
nomem (0); nomem (0);
} }
cleanups = make_cleanup (freeargv, argv); cleanups = make_cleanup ((make_cleanup_func) freeargv, argv);
if (argv[0] != NULL) if (argv[0] != NULL)
{ {
@ -881,7 +930,7 @@ maintenance_print_msymbols (args, from_tty)
outfile = gdb_fopen (filename, FOPEN_WT); outfile = gdb_fopen (filename, FOPEN_WT);
if (outfile == 0) if (outfile == 0)
perror_with_name (filename); perror_with_name (filename);
make_cleanup (fclose, outfile); make_cleanup ((make_cleanup_func) gdb_fclose, &outfile);
immediate_quit++; immediate_quit++;
ALL_OBJFILES (objfile) ALL_OBJFILES (objfile)

View file

@ -1196,7 +1196,7 @@ generic_mourn_inferior ()
inferior_pid = 0; inferior_pid = 0;
attach_flag = 0; attach_flag = 0;
breakpoint_init_inferior (); breakpoint_init_inferior (inf_exited);
registers_changed (); registers_changed ();
#ifdef CLEAR_DEFERRED_STORES #ifdef CLEAR_DEFERRED_STORES

View file

@ -53,10 +53,26 @@ struct thread_info
int trap_expected; int trap_expected;
int handling_longjmp; int handling_longjmp;
int another_trap; int another_trap;
/* This is set TRUE when a catchpoint of a shared library event
triggers. Since we don't wish to leave the inferior in the
solib hook when we report the event, we step the inferior
back to user code before stopping and reporting the event.
*/
int stepping_through_solib_after_catch;
/* When stepping_through_solib_after_catch is TRUE, this is a
list of the catchpoints that should be reported as triggering
when we finally do stop stepping.
*/
bpstat stepping_through_solib_catchpoints;
/* This is set to TRUE when this thread is in a signal handler
trampoline and we're single-stepping through it */
int stepping_through_sigtramp;
}; };
static struct target_thread_vector *target_thread_functions; static struct target_thread_vector *target_thread_functions;
int int
@ -104,6 +120,7 @@ bind_target_thread_vector (vec)
{ {
target_thread_functions = vec; target_thread_functions = vec;
} }
/* Prototypes for exported functions. */ /* Prototypes for exported functions. */
struct target_thread_vector * struct target_thread_vector *
@ -203,6 +220,9 @@ add_thread (pid)
tp->handling_longjmp = 0; tp->handling_longjmp = 0;
tp->trap_expected = 0; tp->trap_expected = 0;
tp->another_trap = 0; tp->another_trap = 0;
tp->stepping_through_solib_after_catch = 0;
tp->stepping_through_solib_catchpoints = NULL;
tp->stepping_through_sigtramp = 0;
tp->next = thread_list; tp->next = thread_list;
thread_list = tp; thread_list = tp;
} }
@ -301,7 +321,10 @@ void load_infrun_state (pid, prev_pc, prev_func_start, prev_func_name,
trap_expected, step_resume_breakpoint, trap_expected, step_resume_breakpoint,
through_sigtramp_breakpoint, step_range_start, through_sigtramp_breakpoint, step_range_start,
step_range_end, step_frame_address, step_range_end, step_frame_address,
handling_longjmp, another_trap) handling_longjmp, another_trap,
stepping_through_solib_after_catch,
stepping_through_solib_catchpoints,
stepping_through_sigtramp)
int pid; int pid;
CORE_ADDR *prev_pc; CORE_ADDR *prev_pc;
CORE_ADDR *prev_func_start; CORE_ADDR *prev_func_start;
@ -314,6 +337,9 @@ void load_infrun_state (pid, prev_pc, prev_func_start, prev_func_name,
CORE_ADDR *step_frame_address; CORE_ADDR *step_frame_address;
int *handling_longjmp; int *handling_longjmp;
int *another_trap; int *another_trap;
int * stepping_through_solib_after_catch;
bpstat * stepping_through_solib_catchpoints;
int * stepping_through_sigtramp;
{ {
struct thread_info *tp; struct thread_info *tp;
@ -334,6 +360,9 @@ void load_infrun_state (pid, prev_pc, prev_func_start, prev_func_name,
*handling_longjmp = tp->handling_longjmp; *handling_longjmp = tp->handling_longjmp;
*trap_expected = tp->trap_expected; *trap_expected = tp->trap_expected;
*another_trap = tp->another_trap; *another_trap = tp->another_trap;
*stepping_through_solib_after_catch = tp->stepping_through_solib_after_catch;
*stepping_through_solib_catchpoints = tp->stepping_through_solib_catchpoints;
*stepping_through_sigtramp = tp->stepping_through_sigtramp;
} }
/* Save infrun state for the thread PID. */ /* Save infrun state for the thread PID. */
@ -342,7 +371,10 @@ void save_infrun_state (pid, prev_pc, prev_func_start, prev_func_name,
trap_expected, step_resume_breakpoint, trap_expected, step_resume_breakpoint,
through_sigtramp_breakpoint, step_range_start, through_sigtramp_breakpoint, step_range_start,
step_range_end, step_frame_address, step_range_end, step_frame_address,
handling_longjmp, another_trap) handling_longjmp, another_trap,
stepping_through_solib_after_catch,
stepping_through_solib_catchpoints,
stepping_through_sigtramp)
int pid; int pid;
CORE_ADDR prev_pc; CORE_ADDR prev_pc;
CORE_ADDR prev_func_start; CORE_ADDR prev_func_start;
@ -355,6 +387,9 @@ void save_infrun_state (pid, prev_pc, prev_func_start, prev_func_name,
CORE_ADDR step_frame_address; CORE_ADDR step_frame_address;
int handling_longjmp; int handling_longjmp;
int another_trap; int another_trap;
int stepping_through_solib_after_catch;
bpstat stepping_through_solib_catchpoints;
int stepping_through_sigtramp;
{ {
struct thread_info *tp; struct thread_info *tp;
@ -375,6 +410,9 @@ void save_infrun_state (pid, prev_pc, prev_func_start, prev_func_name,
tp->handling_longjmp = handling_longjmp; tp->handling_longjmp = handling_longjmp;
tp->trap_expected = trap_expected; tp->trap_expected = trap_expected;
tp->another_trap = another_trap; tp->another_trap = another_trap;
tp->stepping_through_solib_after_catch = stepping_through_solib_after_catch;
tp->stepping_through_solib_catchpoints = stepping_through_solib_catchpoints;
tp->stepping_through_sigtramp = stepping_through_sigtramp;
} }
/* Return true if TP is an active thread. */ /* Return true if TP is an active thread. */
@ -414,7 +452,12 @@ prune_threads ()
} }
} }
/* Print information about currently known threads */ /* Print information about currently known threads
*
* Note: this has the drawback that it _really_ switches
* threads, which frees the frame cache. A no-side
* effects info-threads command would be nicer.
*/
static void static void
info_threads_command (arg, from_tty) info_threads_command (arg, from_tty)
@ -423,6 +466,9 @@ info_threads_command (arg, from_tty)
{ {
struct thread_info *tp; struct thread_info *tp;
int current_pid = inferior_pid; int current_pid = inferior_pid;
struct frame_info *cur_frame;
int saved_frame_level = selected_frame_level;
int counter;
/* Avoid coredumps which would happen if we tried to access a NULL /* Avoid coredumps which would happen if we tried to access a NULL
selected_frame. */ selected_frame. */
@ -440,16 +486,39 @@ info_threads_command (arg, from_tty)
else else
printf_filtered (" "); printf_filtered (" ");
#ifdef HPUXHPPA
printf_filtered ("%d %s ", tp->num, target_tid_to_str (tp->pid));
#else
printf_filtered ("%d %s ", tp->num, target_pid_to_str (tp->pid)); printf_filtered ("%d %s ", tp->num, target_pid_to_str (tp->pid));
#endif
switch_to_thread (tp->pid); switch_to_thread (tp->pid);
if (selected_frame) if (selected_frame)
print_stack_frame (selected_frame, -1, 0); print_only_stack_frame (selected_frame, -1, 0);
else else
printf_filtered ("[No stack.]\n"); printf_filtered ("[No stack.]\n");
} }
switch_to_thread (current_pid); switch_to_thread (current_pid);
/* Code below copied from "up_silently_base" in "stack.c".
* It restores the frame set by the user before the "info threads"
* command. We have finished the info-threads display by switching
* back to the current thread. That switch has put us at the top
* of the stack (leaf frame).
*/
counter = saved_frame_level;
cur_frame = find_relative_frame(selected_frame, &counter);
if (counter != 0) {
/* Ooops, can't restore, tell user where we are. */
warning ("Couldn't restore frame in current thread, at frame 0");
print_stack_frame (selected_frame, -1, 0);
}
else {
select_frame(cur_frame, saved_frame_level);
}
/* re-show current frame. */
show_stack_frame(cur_frame);
} }
/* Switch from one thread to another. */ /* Switch from one thread to another. */
@ -472,8 +541,10 @@ static void
restore_current_thread (pid) restore_current_thread (pid)
int pid; int pid;
{ {
if (pid != inferior_pid) if (pid != inferior_pid) {
switch_to_thread (pid); switch_to_thread (pid);
print_stack_frame( get_current_frame(), 0, -1);
}
} }
/* Apply a GDB command to a list of threads. List syntax is a whitespace /* Apply a GDB command to a list of threads. List syntax is a whitespace
@ -503,8 +574,14 @@ thread_apply_all_command (cmd, from_tty)
if (thread_alive (tp)) if (thread_alive (tp))
{ {
switch_to_thread (tp->pid); switch_to_thread (tp->pid);
#ifdef HPUXHPPA
printf_filtered ("\nThread %d (%s):\n",
tp->num,
target_tid_to_str (inferior_pid));
#else
printf_filtered ("\nThread %d (%s):\n", tp->num, printf_filtered ("\nThread %d (%s):\n", tp->num,
target_pid_to_str (inferior_pid)); target_pid_to_str (inferior_pid));
#endif
execute_command (cmd, from_tty); execute_command (cmd, from_tty);
} }
} }
@ -567,8 +644,13 @@ thread_apply_command (tidlist, from_tty)
else else
{ {
switch_to_thread (tp->pid); switch_to_thread (tp->pid);
#ifdef HPUXHPPA
printf_filtered ("\nThread %d (%s):\n", tp->num,
target_tid_to_str (inferior_pid));
#else
printf_filtered ("\nThread %d (%s):\n", tp->num, printf_filtered ("\nThread %d (%s):\n", tp->num,
target_pid_to_str (inferior_pid)); target_pid_to_str (inferior_pid));
#endif
execute_command (cmd, from_tty); execute_command (cmd, from_tty);
} }
} }
@ -587,9 +669,21 @@ thread_command (tidstr, from_tty)
struct thread_info *tp; struct thread_info *tp;
if (!tidstr) if (!tidstr)
error ("Please specify a thread ID. Use the \"info threads\" command to\n\ {
see the IDs of currently known threads."); /* Don't generate an error, just say which thread is current. */
if (target_has_stack)
printf_filtered ("[Current thread is %d (%s)]\n",
pid_to_thread_id(inferior_pid),
#if defined(HPUXHPPA)
target_tid_to_str(inferior_pid)
#else
target_pid_to_str(inferior_pid)
#endif
);
else
error ("No stack.");
return;
}
num = atoi (tidstr); num = atoi (tidstr);
tp = find_thread_id (num); tp = find_thread_id (num);
@ -602,9 +696,18 @@ see the IDs of currently known threads.", num);
error ("Thread ID %d has terminated.\n", num); error ("Thread ID %d has terminated.\n", num);
switch_to_thread (tp->pid); switch_to_thread (tp->pid);
if (context_hook) if (context_hook)
context_hook (num); context_hook (num);
printf_filtered ("[Switching to %s]\n", target_pid_to_str (inferior_pid));
printf_filtered ("[Switching to thread %d (%s)]\n",
pid_to_thread_id (inferior_pid),
#if defined(HPUXHPPA)
target_tid_to_str (inferior_pid)
#else
target_pid_to_str (inferior_pid)
#endif
);
print_stack_frame (selected_frame, selected_frame_level, 1); print_stack_frame (selected_frame, selected_frame_level, 1);
} }
@ -633,5 +736,6 @@ The new thread ID must be currently known.", &thread_cmd_list, "thread ", 1,
"Apply a command to all threads.", "Apply a command to all threads.",
&thread_apply_list); &thread_apply_list);
add_com_alias ("t", "thread", class_run, 1); if (!xdb_commands)
add_com_alias ("t", "thread", class_run, 1);
} }

View file

@ -203,6 +203,14 @@ struct cmd_list_element *enablelist;
struct cmd_list_element *disablelist; struct cmd_list_element *disablelist;
/* Chain containing all defined toggle subcommands. */
struct cmd_list_element *togglelist;
/* Chain containing all defined stop subcommands. */
struct cmd_list_element *stoplist;
/* Chain containing all defined delete subcommands. */ /* Chain containing all defined delete subcommands. */
struct cmd_list_element *deletelist; struct cmd_list_element *deletelist;
@ -371,7 +379,7 @@ void (*command_loop_hook) PARAMS ((void));
/* Called instead of fputs for all output. */ /* Called instead of fputs for all output. */
void (*fputs_unfiltered_hook) PARAMS ((const char *linebuffer, FILE *stream)); void (*fputs_unfiltered_hook) PARAMS ((const char *linebuffer, GDB_FILE *stream));
/* Called when the target says something to the host, which may /* Called when the target says something to the host, which may
want to appear in a different window. */ want to appear in a different window. */
@ -392,7 +400,7 @@ void (*warning_hook) PARAMS ((const char *, va_list));
/* Called from gdb_flush to flush output. */ /* Called from gdb_flush to flush output. */
void (*flush_hook) PARAMS ((FILE *stream)); void (*flush_hook) PARAMS ((GDB_FILE *stream));
/* These three functions support getting lines of text from the user. They /* These three functions support getting lines of text from the user. They
are used in sequence. First readline_begin_hook is called with a text are used in sequence. First readline_begin_hook is called with a text
@ -1301,13 +1309,16 @@ command_loop ()
int stdin_is_tty = ISATTY (stdin); int stdin_is_tty = ISATTY (stdin);
long time_at_cmd_start; long time_at_cmd_start;
#ifdef HAVE_SBRK #ifdef HAVE_SBRK
long space_at_cmd_start; long space_at_cmd_start = 0;
#endif #endif
extern int display_time; extern int display_time;
extern int display_space; extern int display_space;
while (instream && !feof (instream)) while (instream && !feof (instream))
{ {
#if defined(TUI)
extern int insert_mode;
#endif
if (window_hook && instream == stdin) if (window_hook && instream == stdin)
(*window_hook) (instream, prompt); (*window_hook) (instream, prompt);
@ -1315,8 +1326,22 @@ command_loop ()
if (instream == stdin && stdin_is_tty) if (instream == stdin && stdin_is_tty)
reinitialize_more_filter (); reinitialize_more_filter ();
old_chain = make_cleanup ((make_cleanup_func) command_loop_marker, 0); old_chain = make_cleanup ((make_cleanup_func) command_loop_marker, 0);
#if defined(TUI)
/* A bit of paranoia: I want to make sure the "insert_mode" global
* is clear except when it is being used for command-line editing
* (see tuiIO.c, utils.c); otherwise normal output will
* get messed up in the TUI. So clear it before/after
* the command-line-input call. - RT
*/
insert_mode = 0;
#endif
/* Get a command-line. This calls the readline package. */
command = command_line_input (instream == stdin ? prompt : (char *) NULL, command = command_line_input (instream == stdin ? prompt : (char *) NULL,
instream == stdin, "prompt"); instream == stdin, "prompt");
#if defined(TUI)
insert_mode = 0;
#endif
if (command == 0) if (command == 0)
return; return;
@ -2803,6 +2828,7 @@ document_command (comname, from_tty)
free_command_lines (&doclines); free_command_lines (&doclines);
} }
/* Print the GDB banner. */
void void
print_gdb_version (stream) print_gdb_version (stream)
GDB_FILE *stream; GDB_FILE *stream;
@ -2871,6 +2897,19 @@ get_prompt ()
{ {
return prompt; return prompt;
} }
void
set_prompt (s)
char *s;
{
/* ??rehrauer: I don't know why this fails, since it looks as though
assignments to prompt are wrapped in calls to savestring...
if (prompt != NULL)
free (prompt);
*/
prompt = savestring (s, strlen (s));
}
/* If necessary, make the user confirm that we should quit. Return /* If necessary, make the user confirm that we should quit. Return
non-zero if we should quit, zero if we shouldn't. */ non-zero if we should quit, zero if we shouldn't. */
@ -2934,6 +2973,16 @@ quit_force (args, from_tty)
do_final_cleanups(ALL_CLEANUPS); /* Do any final cleanups before exiting */ do_final_cleanups(ALL_CLEANUPS); /* Do any final cleanups before exiting */
#if defined(TUI)
/* tuiDo((TuiOpaqueFuncPtr)tuiCleanUp); */
/* The above does not need to be inside a tuiDo(), since
* it is not manipulating the curses screen, but rather,
* it is tearing it down.
*/
if (tui_version)
tuiCleanUp();
#endif
exit (exit_code); exit (exit_code);
} }
@ -3341,6 +3390,8 @@ init_cmd_lists ()
infolist = NULL; infolist = NULL;
enablelist = NULL; enablelist = NULL;
disablelist = NULL; disablelist = NULL;
togglelist = NULL;
stoplist = NULL;
deletelist = NULL; deletelist = NULL;
enablebreaklist = NULL; enablebreaklist = NULL;
setlist = NULL; setlist = NULL;
@ -3428,7 +3479,8 @@ well documented as user commands.",
The commands in this class are those defined by the user.\n\ The commands in this class are those defined by the user.\n\
Use the \"define\" command to define a command.", &cmdlist); Use the \"define\" command to define a command.", &cmdlist);
add_cmd ("support", class_support, NO_FUNCTION, "Support facilities.", &cmdlist); add_cmd ("support", class_support, NO_FUNCTION, "Support facilities.", &cmdlist);
add_cmd ("status", class_info, NO_FUNCTION, "Status inquiries.", &cmdlist); if (!dbx_commands)
add_cmd ("status", class_info, NO_FUNCTION, "Status inquiries.", &cmdlist);
add_cmd ("files", class_files, NO_FUNCTION, "Specifying and examining files.", &cmdlist); add_cmd ("files", class_files, NO_FUNCTION, "Specifying and examining files.", &cmdlist);
add_cmd ("breakpoints", class_breakpoint, NO_FUNCTION, "Making program stop at certain points.", &cmdlist); add_cmd ("breakpoints", class_breakpoint, NO_FUNCTION, "Making program stop at certain points.", &cmdlist);
add_cmd ("data", class_vars, NO_FUNCTION, "Examining data.", &cmdlist); add_cmd ("data", class_vars, NO_FUNCTION, "Examining data.", &cmdlist);

View file

@ -34,6 +34,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "gdb_string.h" #include "gdb_string.h"
#include <errno.h> #include <errno.h>
/* For real-type printing in whatis_exp() */
extern int objectprint; /* Controls looking up an object's derived type
using what we find in its vtables. */
static void static void
ptype_command PARAMS ((char *, int)); ptype_command PARAMS ((char *, int));
@ -74,6 +78,10 @@ whatis_exp (exp, show)
struct expression *expr; struct expression *expr;
register value_ptr val; register value_ptr val;
register struct cleanup *old_chain = NULL; register struct cleanup *old_chain = NULL;
struct type * real_type = NULL;
int full = 0;
int top = -1;
int using_enc = 0;
if (exp) if (exp)
{ {
@ -85,7 +93,16 @@ whatis_exp (exp, show)
else else
val = access_value_history (0); val = access_value_history (0);
real_type = value_rtti_type (val, &full, &top, &using_enc);
printf_filtered ("type = "); printf_filtered ("type = ");
if (real_type && objectprint)
printf_filtered ("/* real type = %s%s */\n",
TYPE_NAME (real_type),
full ? "" : " (incomplete object)");
/* FIXME: maybe better to use type_print (real_type, "", gdb_stdout, -1); */
type_print (VALUE_TYPE (val), "", gdb_stdout, show); type_print (VALUE_TYPE (val), "", gdb_stdout, show);
printf_filtered ("\n"); printf_filtered ("\n");

View file

@ -53,9 +53,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Prototypes for local functions */ /* Prototypes for local functions */
static void vfprintf_maybe_filtered PARAMS ((FILE *, const char *, va_list, int)); static void vfprintf_maybe_filtered PARAMS ((GDB_FILE *, const char *,
va_list, int));
static void fputs_maybe_filtered PARAMS ((const char *, FILE *, int)); static void fputs_maybe_filtered PARAMS ((const char *, GDB_FILE *, int));
#if defined (USE_MMALLOC) && !defined (NO_MMCHECK) #if defined (USE_MMALLOC) && !defined (NO_MMCHECK)
static void malloc_botch PARAMS ((void)); static void malloc_botch PARAMS ((void));
@ -70,12 +71,19 @@ prompt_for_continue PARAMS ((void));
static void static void
set_width_command PARAMS ((char *, int, struct cmd_list_element *)); set_width_command PARAMS ((char *, int, struct cmd_list_element *));
static void
set_width PARAMS ((void));
/* If this definition isn't overridden by the header files, assume /* If this definition isn't overridden by the header files, assume
that isatty and fileno exist on this system. */ that isatty and fileno exist on this system. */
#ifndef ISATTY #ifndef ISATTY
#define ISATTY(FP) (isatty (fileno (FP))) #define ISATTY(FP) (isatty (fileno (FP)))
#endif #endif
#ifndef GDB_FILE_ISATTY
#define GDB_FILE_ISATTY(GDB_FILE_PTR) (gdb_file_isatty(GDB_FILE_PTR))
#endif
/* Chain of cleanup actions established with make_cleanup, /* Chain of cleanup actions established with make_cleanup,
to be executed if an error happens. */ to be executed if an error happens. */
@ -132,6 +140,9 @@ char *quit_pre_print;
/* String to be printed before warning messages, if any. */ /* String to be printed before warning messages, if any. */
char *warning_pre_print = "\nwarning: "; char *warning_pre_print = "\nwarning: ";
int pagination_enabled = 1;
/* Add a new cleanup to the cleanup_chain, /* Add a new cleanup to the cleanup_chain,
and return the previous chain pointer and return the previous chain pointer
@ -969,10 +980,16 @@ mstrsave (md, ptr)
void void
print_spaces (n, file) print_spaces (n, file)
register int n; register int n;
register FILE *file; register GDB_FILE *file;
{ {
while (n-- > 0) if (file->ts_streamtype == astring) {
fputc (' ', file); gdb_file_adjust_strbuf (n, file);
while (n-- > 0)
strcat(file->ts_strbuf, ' ');
} else {
while (n-- > 0)
fputc (' ', file->ts_filestream);
}
} }
/* Print a host address. */ /* Print a host address. */
@ -1052,21 +1069,43 @@ query (va_alist)
fputs_unfiltered ("\n", gdb_stdout); fputs_unfiltered ("\n", gdb_stdout);
#endif /* MPW */ #endif /* MPW */
wrap_here("");
gdb_flush (gdb_stdout); gdb_flush (gdb_stdout);
answer = fgetc (stdin);
#if defined(TUI)
if (!tui_version || cmdWin == tuiWinWithFocus())
#endif
answer = fgetc (stdin);
#if defined(TUI)
else
answer = (unsigned char)tuiBufferGetc();
#endif
clearerr (stdin); /* in case of C-d */ clearerr (stdin); /* in case of C-d */
if (answer == EOF) /* C-d */ if (answer == EOF) /* C-d */
{ {
retval = 1; retval = 1;
break; break;
} }
if (answer != '\n') /* Eat rest of input line, to EOF or newline */ /* Eat rest of input line, to EOF or newline */
if ((answer != '\n') || (tui_version && answer != '\r'))
do do
{ {
ans2 = fgetc (stdin); #if defined(TUI)
if (!tui_version || cmdWin == tuiWinWithFocus())
#endif
ans2 = fgetc (stdin);
#if defined(TUI)
else
ans2 = (unsigned char)tuiBufferGetc();
#endif
clearerr (stdin); clearerr (stdin);
} }
while (ans2 != EOF && ans2 != '\n'); while (ans2 != EOF && ans2 != '\n' && ans2 != '\r');
TUIDO(((TuiOpaqueFuncPtr)tui_vStartNewLines, 1));
if (answer >= 'a') if (answer >= 'a')
answer -= 040; answer -= 040;
if (answer == 'Y') if (answer == 'Y')
@ -1178,7 +1217,7 @@ parse_escape (string_ptr)
void void
gdb_printchar (c, stream, quoter) gdb_printchar (c, stream, quoter)
register int c; register int c;
FILE *stream; GDB_FILE *stream;
int quoter; int quoter;
{ {
@ -1283,13 +1322,87 @@ static char *wrap_indent;
is not in effect. */ is not in effect. */
static int wrap_column; static int wrap_column;
/* ARGSUSED */
static void /* Inialize the lines and chars per page */
set_width_command (args, from_tty, c) void
char *args; init_page_info()
int from_tty;
struct cmd_list_element *c;
{ {
#if defined(TUI)
if (tui_version && m_winPtrNotNull(cmdWin))
{
lines_per_page = cmdWin->generic.height;
chars_per_line = cmdWin->generic.width;
}
else
#endif
{
/* These defaults will be used if we are unable to get the correct
values from termcap. */
#if defined(__GO32__)
lines_per_page = ScreenRows();
chars_per_line = ScreenCols();
#else
lines_per_page = 24;
chars_per_line = 80;
#if !defined (MPW) && !defined (_WIN32)
/* No termcap under MPW, although might be cool to do something
by looking at worksheet or console window sizes. */
/* Initialize the screen height and width from termcap. */
{
char *termtype = getenv ("TERM");
/* Positive means success, nonpositive means failure. */
int status;
/* 2048 is large enough for all known terminals, according to the
GNU termcap manual. */
char term_buffer[2048];
if (termtype)
{
status = tgetent (term_buffer, termtype);
if (status > 0)
{
int val;
val = tgetnum ("li");
if (val >= 0)
lines_per_page = val;
else
/* The number of lines per page is not mentioned
in the terminal description. This probably means
that paging is not useful (e.g. emacs shell window),
so disable paging. */
lines_per_page = UINT_MAX;
val = tgetnum ("co");
if (val >= 0)
chars_per_line = val;
}
}
}
#endif /* MPW */
#if defined(SIGWINCH) && defined(SIGWINCH_HANDLER)
/* If there is a better way to determine the window size, use it. */
SIGWINCH_HANDLER (SIGWINCH);
#endif
#endif
/* If the output is not a terminal, don't paginate it. */
if (!GDB_FILE_ISATTY (gdb_stdout))
lines_per_page = UINT_MAX;
} /* the command_line_version */
set_width();
}
static void
set_width()
{
if (chars_per_line == 0)
init_page_info();
if (!wrap_buffer) if (!wrap_buffer)
{ {
wrap_buffer = (char *) xmalloc (chars_per_line + 2); wrap_buffer = (char *) xmalloc (chars_per_line + 2);
@ -1297,7 +1410,17 @@ set_width_command (args, from_tty, c)
} }
else else
wrap_buffer = (char *) xrealloc (wrap_buffer, chars_per_line + 2); wrap_buffer = (char *) xrealloc (wrap_buffer, chars_per_line + 2);
wrap_pointer = wrap_buffer; /* Start it at the beginning */ wrap_pointer = wrap_buffer; /* Start it at the beginning */
}
/* ARGSUSED */
static void
set_width_command (args, from_tty, c)
char *args;
int from_tty;
struct cmd_list_element *c;
{
set_width ();
} }
/* Wait, so the user can read what's on the screen. Prompt the user /* Wait, so the user can read what's on the screen. Prompt the user
@ -1436,18 +1559,100 @@ begin_line ()
} }
} }
int
gdb_file_isatty (stream)
GDB_FILE *stream;
{
if (stream->ts_streamtype == afile)
return (isatty(fileno(stream->ts_filestream)));
else return 0;
}
GDB_FILE *
gdb_file_init_astring (n)
int n;
{
GDB_FILE *tmpstream;
tmpstream = xmalloc (sizeof(GDB_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
tmpstream->ts_strbuf = NULL;
tmpstream->ts_buflen = n;
return tmpstream;
}
void
gdb_file_deallocate (streamptr)
GDB_FILE **streamptr;
{
GDB_FILE *tmpstream;
tmpstream = *streamptr;
if ((tmpstream->ts_streamtype == astring) &&
(tmpstream->ts_strbuf != NULL))
{
free (tmpstream->ts_strbuf);
}
free (tmpstream);
*streamptr = NULL;
}
char *
gdb_file_get_strbuf (stream)
GDB_FILE *stream;
{
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
gdb_file_adjust_strbuf (n, stream)
int n;
GDB_FILE *stream;
{
int non_null_chars;
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);
}
}
GDB_FILE * GDB_FILE *
gdb_fopen (name, mode) gdb_fopen (name, mode)
char * name; char * name;
char * mode; char * mode;
{ {
return fopen (name, mode); int gdb_file_size;
GDB_FILE *tmp;
gdb_file_size = sizeof(GDB_FILE);
tmp = (GDB_FILE *) xmalloc (gdb_file_size);
tmp->ts_streamtype = afile;
tmp->ts_filestream = fopen (name, mode);
tmp->ts_strbuf = NULL;
tmp->ts_buflen = 0;
return tmp;
} }
void void
gdb_flush (stream) gdb_flush (stream)
FILE *stream; GDB_FILE *stream;
{ {
if (flush_hook if (flush_hook
&& (stream == gdb_stdout && (stream == gdb_stdout
@ -1457,7 +1662,18 @@ gdb_flush (stream)
return; return;
} }
fflush (stream); fflush (stream->ts_filestream);
}
void
gdb_fclose(streamptr)
GDB_FILE **streamptr;
{
GDB_FILE *tmpstream;
tmpstream = *streamptr;
fclose (tmpstream->ts_filestream);
gdb_file_deallocate (streamptr);
} }
/* Like fputs but if FILTER is true, pause after every screenful. /* Like fputs but if FILTER is true, pause after every screenful.
@ -1476,7 +1692,7 @@ gdb_flush (stream)
static void static void
fputs_maybe_filtered (linebuffer, stream, filter) fputs_maybe_filtered (linebuffer, stream, filter)
const char *linebuffer; const char *linebuffer;
FILE *stream; GDB_FILE *stream;
int filter; int filter;
{ {
const char *lineptr; const char *lineptr;
@ -1580,7 +1796,7 @@ fputs_maybe_filtered (linebuffer, stream, filter)
void void
fputs_filtered (linebuffer, stream) fputs_filtered (linebuffer, stream)
const char *linebuffer; const char *linebuffer;
FILE *stream; GDB_FILE *stream;
{ {
fputs_maybe_filtered (linebuffer, stream, 1); fputs_maybe_filtered (linebuffer, stream, 1);
} }
@ -1600,7 +1816,7 @@ putchar_unfiltered (c)
int int
fputc_unfiltered (c, stream) fputc_unfiltered (c, stream)
int c; int c;
FILE * stream; GDB_FILE * stream;
{ {
char buf[2]; char buf[2];
@ -1613,7 +1829,7 @@ fputc_unfiltered (c, stream)
int int
fputc_filtered (c, stream) fputc_filtered (c, stream)
int c; int c;
FILE * stream; GDB_FILE * stream;
{ {
char buf[2]; char buf[2];
@ -1713,7 +1929,7 @@ puts_debug (prefix, string, suffix)
static void static void
vfprintf_maybe_filtered (stream, format, args, filter) vfprintf_maybe_filtered (stream, format, args, filter)
FILE *stream; GDB_FILE *stream;
const char *format; const char *format;
va_list args; va_list args;
int filter; int filter;
@ -1735,7 +1951,7 @@ vfprintf_maybe_filtered (stream, format, args, filter)
void void
vfprintf_filtered (stream, format, args) vfprintf_filtered (stream, format, args)
FILE *stream; GDB_FILE *stream;
const char *format; const char *format;
va_list args; va_list args;
{ {
@ -1744,7 +1960,7 @@ vfprintf_filtered (stream, format, args)
void void
vfprintf_unfiltered (stream, format, args) vfprintf_unfiltered (stream, format, args)
FILE *stream; GDB_FILE *stream;
const char *format; const char *format;
va_list args; va_list args;
{ {
@ -1781,7 +1997,7 @@ vprintf_unfiltered (format, args)
/* VARARGS */ /* VARARGS */
void void
#ifdef ANSI_PROTOTYPES #ifdef ANSI_PROTOTYPES
fprintf_filtered (FILE *stream, const char *format, ...) fprintf_filtered (GDB_FILE *stream, const char *format, ...)
#else #else
fprintf_filtered (va_alist) fprintf_filtered (va_alist)
va_dcl va_dcl
@ -1791,11 +2007,11 @@ fprintf_filtered (va_alist)
#ifdef ANSI_PROTOTYPES #ifdef ANSI_PROTOTYPES
va_start (args, format); va_start (args, format);
#else #else
FILE *stream; GDB_FILE *stream;
char *format; char *format;
va_start (args); va_start (args);
stream = va_arg (args, FILE *); stream = va_arg (args, GDB_FILE *);
format = va_arg (args, char *); format = va_arg (args, char *);
#endif #endif
vfprintf_filtered (stream, format, args); vfprintf_filtered (stream, format, args);
@ -1805,7 +2021,7 @@ fprintf_filtered (va_alist)
/* VARARGS */ /* VARARGS */
void void
#ifdef ANSI_PROTOTYPES #ifdef ANSI_PROTOTYPES
fprintf_unfiltered (FILE *stream, const char *format, ...) fprintf_unfiltered (GDB_FILE *stream, const char *format, ...)
#else #else
fprintf_unfiltered (va_alist) fprintf_unfiltered (va_alist)
va_dcl va_dcl
@ -1815,11 +2031,11 @@ fprintf_unfiltered (va_alist)
#ifdef ANSI_PROTOTYPES #ifdef ANSI_PROTOTYPES
va_start (args, format); va_start (args, format);
#else #else
FILE *stream; GDB_FILE *stream;
char *format; char *format;
va_start (args); va_start (args);
stream = va_arg (args, FILE *); stream = va_arg (args, GDB_FILE *);
format = va_arg (args, char *); format = va_arg (args, char *);
#endif #endif
vfprintf_unfiltered (stream, format, args); vfprintf_unfiltered (stream, format, args);
@ -1832,7 +2048,7 @@ fprintf_unfiltered (va_alist)
/* VARARGS */ /* VARARGS */
void void
#ifdef ANSI_PROTOTYPES #ifdef ANSI_PROTOTYPES
fprintfi_filtered (int spaces, FILE *stream, const char *format, ...) fprintfi_filtered (int spaces, GDB_FILE *stream, const char *format, ...)
#else #else
fprintfi_filtered (va_alist) fprintfi_filtered (va_alist)
va_dcl va_dcl
@ -1843,12 +2059,12 @@ fprintfi_filtered (va_alist)
va_start (args, format); va_start (args, format);
#else #else
int spaces; int spaces;
FILE *stream; GDB_FILE *stream;
char *format; char *format;
va_start (args); va_start (args);
spaces = va_arg (args, int); spaces = va_arg (args, int);
stream = va_arg (args, FILE *); stream = va_arg (args, GDB_FILE *);
format = va_arg (args, char *); format = va_arg (args, char *);
#endif #endif
print_spaces_filtered (spaces, stream); print_spaces_filtered (spaces, stream);
@ -1978,7 +2194,7 @@ n_spaces (n)
void void
print_spaces_filtered (n, stream) print_spaces_filtered (n, stream)
int n; int n;
FILE *stream; GDB_FILE *stream;
{ {
fputs_filtered (n_spaces (n), stream); fputs_filtered (n_spaces (n), stream);
} }
@ -1992,7 +2208,7 @@ print_spaces_filtered (n, stream)
void void
fprintf_symbol_filtered (stream, name, lang, arg_mode) fprintf_symbol_filtered (stream, name, lang, arg_mode)
FILE *stream; GDB_FILE *stream;
char *name; char *name;
enum language lang; enum language lang;
int arg_mode; int arg_mode;
@ -2071,6 +2287,50 @@ strcmp_iw (string1, string2)
return (*string1 != '\0' && *string1 != '(') || (*string2 != '\0'); return (*string1 != '\0' && *string1 != '(') || (*string2 != '\0');
} }
/*
** subsetCompare()
** Answer whether stringToCompare is a full or partial match to
** templateString. The partial match must be in sequence starting
** at index 0.
*/
int
#ifdef _STDC__
subsetCompare(
char *stringToCompare,
char *templateString)
#else
subsetCompare(stringToCompare, templateString)
char *stringToCompare;
char *templateString;
#endif
{
int match = 0;
if (templateString != (char *)NULL && stringToCompare != (char *)NULL &&
strlen(stringToCompare) <= strlen(templateString))
match = (strncmp(templateString,
stringToCompare,
strlen(stringToCompare)) == 0);
return match;
} /* subsetCompare */
void pagination_on_command(arg, from_tty)
char *arg;
int from_tty;
{
pagination_enabled = 1;
}
void pagination_off_command(arg, from_tty)
char *arg;
int from_tty;
{
pagination_enabled = 0;
}
void void
initialize_utils () initialize_utils ()
@ -2090,62 +2350,10 @@ initialize_utils ()
"Set number of lines gdb thinks are in a page.", &setlist), "Set number of lines gdb thinks are in a page.", &setlist),
&showlist); &showlist);
/* These defaults will be used if we are unable to get the correct init_page_info ();
values from termcap. */
#if defined(__GO32__)
lines_per_page = ScreenRows();
chars_per_line = ScreenCols();
#else
lines_per_page = 24;
chars_per_line = 80;
#if !defined (MPW) && !defined (_WIN32)
/* No termcap under MPW, although might be cool to do something
by looking at worksheet or console window sizes. */
/* Initialize the screen height and width from termcap. */
{
char *termtype = getenv ("TERM");
/* Positive means success, nonpositive means failure. */
int status;
/* 2048 is large enough for all known terminals, according to the
GNU termcap manual. */
char term_buffer[2048];
if (termtype)
{
status = tgetent (term_buffer, termtype);
if (status > 0)
{
int val;
val = tgetnum ("li");
if (val >= 0)
lines_per_page = val;
else
/* The number of lines per page is not mentioned
in the terminal description. This probably means
that paging is not useful (e.g. emacs shell window),
so disable paging. */
lines_per_page = UINT_MAX;
val = tgetnum ("co");
if (val >= 0)
chars_per_line = val;
}
}
}
#endif /* MPW */
#if defined(SIGWINCH) && defined(SIGWINCH_HANDLER)
/* If there is a better way to determine the window size, use it. */
SIGWINCH_HANDLER (SIGWINCH);
#endif
#endif
/* If the output is not a terminal, don't paginate it. */ /* If the output is not a terminal, don't paginate it. */
if (!ISATTY (gdb_stdout)) if (!GDB_FILE_ISATTY (gdb_stdout))
lines_per_page = UINT_MAX; lines_per_page = UINT_MAX;
set_width_command ((char *)NULL, 0, c); set_width_command ((char *)NULL, 0, c);
@ -2157,6 +2365,19 @@ initialize_utils ()
&setprintlist), &setprintlist),
&showprintlist); &showprintlist);
add_show_from_set
(add_set_cmd ("pagination", class_support,
var_boolean, (char *)&pagination_enabled,
"Set state of pagination.", &setlist),
&showlist);
if (xdb_commands)
{
add_com("am", class_support, pagination_on_command,
"Enable pagination");
add_com("sm", class_support, pagination_off_command,
"Disable pagination");
}
add_show_from_set add_show_from_set
(add_set_cmd ("sevenbit-strings", class_support, var_boolean, (add_set_cmd ("sevenbit-strings", class_support, var_boolean,
(char *)&sevenbit_strings, (char *)&sevenbit_strings,

View file

@ -424,7 +424,7 @@ handle_load_dll (char *dummy)
FIXME: Is this the real reason that we need the 0x1000 ? */ FIXME: Is this the real reason that we need the 0x1000 ? */
printf_unfiltered ("%x:%s", event->lpBaseOfDll, dll_name); printf_unfiltered ("%x:%s", event->lpBaseOfDll, dll_name);
symbol_file_add (dll_name, 0, (int) event->lpBaseOfDll + 0x1000, 0, 0, 0); symbol_file_add (dll_name, 0, (int) event->lpBaseOfDll + 0x1000, 0, 0, 0, 0, 1);
printf_unfiltered ("\n"); printf_unfiltered ("\n");
out: out: