all remaining *.c *.h files from hp merge.
This commit is contained in:
parent
c450a7fe3f
commit
65b07ddca8
62 changed files with 27574 additions and 1386 deletions
|
@ -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
|
||||||
|
|
2818
gdb/ChangeLog
2818
gdb/ChangeLog
File diff suppressed because it is too large
Load diff
|
@ -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
|
||||||
|
|
3100
gdb/breakpoint.c
3100
gdb/breakpoint.c
File diff suppressed because it is too large
Load diff
189
gdb/breakpoint.h
189
gdb/breakpoint.h
|
@ -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) */
|
||||||
|
|
|
@ -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
|
||||||
|
|
38
gdb/c-lang.c
38
gdb/c-lang.c
|
@ -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,
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
{
|
{
|
||||||
|
|
|
@ -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.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
83
gdb/defs.h
83
gdb/defs.h
|
@ -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));
|
||||||
|
|
|
@ -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}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
{
|
{
|
||||||
|
|
355
gdb/fork-child.c
355
gdb/fork-child.c
|
@ -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 */
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
13
gdb/gdbtk.c
13
gdb/gdbtk.c
|
@ -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("");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
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
3988
gdb/hp-symtab-read.c
Normal file
File diff suppressed because it is too large
Load diff
1794
gdb/hppa-tdep.c
1794
gdb/hppa-tdep.c
File diff suppressed because it is too large
Load diff
899
gdb/hppah-nat.c
899
gdb/hppah-nat.c
|
@ -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 */
|
||||||
|
|
|
@ -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
150
gdb/hpread.h
Normal 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 */
|
139
gdb/infcmd.c
139
gdb/infcmd.c
|
@ -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, ¤t_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.");
|
||||||
|
|
113
gdb/inferior.h
113
gdb/inferior.h
|
@ -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) */
|
||||||
|
|
||||||
|
|
1530
gdb/infrun.c
1530
gdb/infrun.c
File diff suppressed because it is too large
Load diff
705
gdb/inftarg.c
705
gdb/inftarg.c
|
@ -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
5709
gdb/infttrace.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
112
gdb/main.c
112
gdb/main.c
|
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
279
gdb/parse.c
279
gdb/parse.c
|
@ -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. */
|
||||||
|
|
|
@ -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... */
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
|
@ -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
|
||||||
|
|
17
gdb/serial.c
17
gdb/serial.c
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
12
gdb/solib.c
12
gdb/solib.c
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
131
gdb/solib.h
131
gdb/solib.h
|
@ -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. */
|
||||||
|
|
||||||
|
|
351
gdb/somread.c
351
gdb/somread.c
|
@ -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. */
|
||||||
|
|
||||||
|
|
1146
gdb/somsolib.c
1146
gdb/somsolib.c
File diff suppressed because it is too large
Load diff
126
gdb/somsolib.h
126
gdb/somsolib.h
|
@ -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)
|
||||||
|
|
644
gdb/stack.c
644
gdb/stack.c
|
@ -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.");
|
||||||
|
|
||||||
|
|
515
gdb/symfile.c
515
gdb/symfile.c
|
@ -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.");
|
||||||
}
|
}
|
||||||
|
|
221
gdb/symmisc.c
221
gdb/symmisc.c
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
130
gdb/thread.c
130
gdb/thread.c
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
60
gdb/top.c
60
gdb/top.c
|
@ -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);
|
||||||
|
|
|
@ -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");
|
||||||
|
|
||||||
|
|
405
gdb/utils.c
405
gdb/utils.c
|
@ -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,
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue