summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Jacobowitz <dan@debian.org>2006-04-12 18:11:43 +0000
committerDaniel Jacobowitz <dan@debian.org>2006-04-12 18:11:43 +0000
commit973afa5c31fe8ce1e73258db8abc828dcb731e7d (patch)
tree26de7afb6c2e9946ef955de726e41a54b87df939
parent27d51c4b017f5fc2ce7bc680a9c811e45c0ad517 (diff)
downloadgdb-973afa5c31fe8ce1e73258db8abc828dcb731e7d.tar.gz
Add experimental support for SymbianOS-related protocol features.
-rw-r--r--ChangeLog.csl128
-rw-r--r--gdb/Makefile.in6
-rw-r--r--gdb/arm-tdep.c82
-rw-r--r--gdb/cli/cli-setshow.c78
-rw-r--r--gdb/config/arm/symbian.mt6
-rw-r--r--gdb/configure.tgt1
-rw-r--r--gdb/doc/gdb.texinfo18
-rw-r--r--gdb/gdbserver/linux-low.c18
-rw-r--r--gdb/gdbserver/remote-utils.c6
-rw-r--r--gdb/gdbserver/server.c471
-rw-r--r--gdb/infcmd.c10
-rw-r--r--gdb/inflow.c5
-rw-r--r--gdb/infrun.c87
-rw-r--r--gdb/remote.c681
-rw-r--r--gdb/solib-som.c3
-rw-r--r--gdb/solib-target.c270
-rw-r--r--gdb/solib.c47
-rw-r--r--gdb/solib.h4
-rw-r--r--gdb/solist.h12
-rw-r--r--gdb/symbian-tdep.c32
-rw-r--r--gdb/symfile.c241
-rw-r--r--gdb/symfile.h9
-rw-r--r--gdb/target.c56
-rw-r--r--gdb/target.h22
-rw-r--r--gdb/testsuite/gdb.base/define.exp4
-rw-r--r--readline/emacs_keymap.c4
-rw-r--r--readline/readline.c17
27 files changed, 2019 insertions, 299 deletions
diff --git a/ChangeLog.csl b/ChangeLog.csl
index 3a2bda55019..3dfc1b32735 100644
--- a/ChangeLog.csl
+++ b/ChangeLog.csl
@@ -1,5 +1,133 @@
2006-04-12 Daniel Jacobowitz <dan@codesourcery.com>
+ * gdb/Makefile.in (ALLDEPFILES): Add solib-target.c.
+ (remote.o): Update dependencies.
+ (solib-target.o, symbian-tdep.o): New rules.
+ * gdb/arm-tdep.c (arm_mode_strings, arm_fallback_mode_string)
+ (arm_force_mode_string): New.
+ (arm_pc_is_thumb): Use them.
+ (thumb_scan_prologue): Abort scan when symbols are missing.
+ (arm_show_fallback_mode, arm_show_force_mode): New.
+ (_initialize_arm_tdep): Register fallback-mode and force-mode.
+ * gdb/configure.tgt: Add arm*-*-symbian*.
+ * gdb/infcmd.c (_initialize_infcmd): Make "set args" a string
+ variable.
+ * gdb/inflow.c (kill_command): Assume that a target with stack
+ can have a frame.
+ * gdb/infrun.c (init_wait_for_inferior): Clear
+ target_last_wait_ptid.
+ (insert_step_resume_breakpoint_at_frame): Add use_previous argument.
+ Use get_prev_frame if requested.
+ (handle_inferior_event): Update TARGET_WAITKIND_LOADED support.
+ Update calls to insert_step_resume_breakpoint_at_frame.
+ * gdb/remote.c: Include "solist.h".
+ (remote_exec_file): New variable.
+ (PACKET_vAttach, PACKET_vRun, PACKET_qfDllInfo): New enums.
+ (remote_mark_running, remote_mark_killed): New functions.
+ (extended_remote_restart): Don't send a query.
+ (get_offsets): Handle TextSeg and DataSeg response.
+ (parse_load_response, remote_get_shared_libraries): New functions.
+ (remote_start_remote): Take a target as the second argument for
+ extended mode. Check whether the target is running. Reset
+ inferior_ptid here.
+ (remote_open_1): Assume the target is running. Don't reset
+ inferior_ptid here. Pass the target to remote_start_remote
+ in extended mode. Only do some setup if the target is running.
+ (remote_detach_1): New function, renamed from remote_detach.
+ Don't say we are disconnecting if we aren't.
+ (remote_detach): Call remote_detach_1.
+ (extended_remote_detach): New function.
+ (remote_disconnect): Take a target_ops argument. Correct the
+ error message. Call remote_mourn_1 directly.
+ (extended_remote_attach_1, extended_remote_attach)
+ (extended_async_remote_attach): New functions.
+ (remote_wait): Handle load and unload events.
+ (extended_remote_mourn_1): New function.
+ (extended_remote_mourn): Replace with a call to
+ extended_remote_mourn_1.
+ (extended_async_remote_mourn): New function.
+ (extended_remote_run): New function.
+ (extended_remote_create_inferior_1): New function, from
+ extended_remote_create_inferior. Call get_offsets.
+ (extended_remote_create_inferior)
+ (extended_remote_async_create_inferior): Use it.
+ (remote_stopped_by_watchpoint, crc32_table)
+ (compare_sections_command): Whitespace tweaks.
+ (init_remote_ops, init_extended_remote_ops): Update.
+ (init_remote_async_ops): Whitespace tweaks and update.
+ (init_extended_async_remote_ops): Update.
+ (_initialize_remote): Add new configurable packets. Add
+ "set remote exec-file".
+ * gdb/solib-som.c (som_current_sos): Set addr_low and addr_high.
+ * gdb/solib-target.c: New file.
+ * gdb/solib.c (solib_symbols_extension): New variable.
+ (solib_open): Use it.
+ (solib_map_sections): Set addr_low and addr_high instead of
+ textsection.
+ (info_sharedlibrary_command): Use addr_low and addr_high.
+ * gdb/solib.h (solib_symbols_extension): New declaration.
+ * gdb/solist.h (struct so_list): Replace textsection
+ with addr_low and addr_high.
+ (struct target_so_ops): Add add_one_solib and remove_one_solib.
+ * gdb/symbian-tdep.c: New file.
+ * gdb/symfile.c (init_objfile_sect_indices): Use
+ symfile_find_segment_sections to find the text section.
+ (symfile_find_segments, symfile_find_segment_sections)
+ (symfile_map_offsets_to_segments, symfile_find_segment_lengths)
+ (symfile_section_offset_from_segment): New functions.
+ * gdb/symfile.h (symfile_map_offsets_to_segments)
+ (symfile_section_offset_from_segment)
+ (symfile_find_segment_lengths): New prototypes.
+ * gdb/target.c (debug_to_disconnect): Delete.
+ (update_current_target): Make global. Do not inherit to_disconnect.
+ Mention to_get_shared_libraries.
+ (target_disconnect): Search for to_disconnect.
+ (target_get_shared_libraries): New.
+ (setup_target_debug): Update.
+ * gdb/target.h (struct target_ops): Update to_disconnect prototype.
+ Add to_get_shared_libraries.
+ (target_has_execution): Update comment.
+ (target_get_shared_libraries, update_current_target): New
+ prototypes.
+ * gdb/cli/cli-setshow.c (do_setshow_command): Revise string variable
+ handling.
+ * gdb/config/arm/symbian.mt: New file.
+ * gdb/doc/gdb.texinfo (ARM): Document set/show arm fallback-mode
+ and set/show arm force-mode.
+
+ * gdb/testsuite/gdb.base/define.exp: Don't use backslashes in the
+ prompt.
+
+ * readline/emacs_keymap.c: Add a MINGW32 hack.
+ * readline/readline.c: Use _rl_bind_if_unbound to avoid macro bugs.
+
+ * gdb/gdbserver/linux-low.c (linux_kill): Reset inferior thread and
+ process lists.
+ (linux_detach): Likewise.
+ (linux_wait_for_process): Discard unexpected exits.
+ * gdb/gdbserver/remote-utils.c (unblock_async_io): Ignore if we are
+ restarting.
+ * gdb/gdbserver/server.c (exit_requested, restarting_program)
+ (program_argv): New variables.
+ (attached): Move higher.
+ (start_inferior): Clear attached. Use restarting_program to avoid
+ troubles with the 'R' packet.
+ (attach_inferior): Set attached.
+ (handle_query): Implement "monitor exit".
+ (handle_query_non_running): New function.
+ (handle_v_cont): Report errors.
+ (handle_v_attach, handle_v_run): New.
+ (handle_v_requests): Handle vAttach and vRun.
+ (handle_v_requests_non_running, non_running): New.
+ (debug_threads): Add declaration.
+ (main): Handle --debug. Don't adjust attached here.
+ Save the argv. Keep track of requested exits. Use
+ non_running when the target is dead. Do not always exit
+ after detach. Fix up Hc support. Do not automatically
+ restart the inferior in extended mode.
+
+2006-04-12 Daniel Jacobowitz <dan@codesourcery.com>
+
Backport:
2006-04-12 Daniel Jacobowitz <dan@codesourcery.com>
* remote.c (extended_remote_restart): Pass the correct length
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index d955c09dc4e..cd0834cb983 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -1474,6 +1474,7 @@ ALLDEPFILES = \
mips64obsd-nat.c mips64obsd-tdep.c \
nbsd-tdep.c obsd-tdep.c \
solib-osf.c \
+ solib-target.c \
somread.c solib-som.c $(HPREAD_SOURCE) \
posix-hdep.c \
ppc-sysv-tdep.c ppc-linux-nat.c ppc-linux-tdep.c \
@@ -2510,7 +2511,7 @@ remote.o: remote.c $(defs_h) $(gdb_string_h) $(inferior_h) $(bfd_h) \
$(gdb_stabs_h) $(gdbthread_h) $(remote_h) $(regcache_h) $(value_h) \
$(gdb_assert_h) $(event_loop_h) $(event_top_h) $(inf_loop_h) \
$(serial_h) $(gdbcore_h) $(remote_fileio_h) $(solib_h) $(observer_h) \
- $(cli_decode_h) $(cli_setshow_h) $(available_h)
+ $(cli_decode_h) $(cli_setshow_h) $(available_h) $(solist_h)
remote-e7000.o: remote-e7000.c $(defs_h) $(gdbcore_h) $(gdbarch_h) \
$(inferior_h) $(target_h) $(value_h) $(command_h) $(gdb_string_h) \
$(exceptions_h) $(gdbcmd_h) $(serial_h) $(remote_utils_h) \
@@ -2645,6 +2646,8 @@ solib-svr4.o: solib-svr4.c $(defs_h) $(elf_external_h) $(elf_common_h) \
$(elf_mips_h) $(symtab_h) $(bfd_h) $(symfile_h) $(objfiles_h) \
$(gdbcore_h) $(target_h) $(inferior_h) $(gdb_assert_h) \
$(solist_h) $(solib_h) $(solib_svr4_h) $(bfd_target_h) $(exec_h)
+solib-target.o: solib-target.c $(defs_h) $(solist_h) $(symtab_h) \
+ $(symfile_h) $(target_h) $(gdb_string_h)
sol-thread.o: sol-thread.c $(defs_h) $(gdbthread_h) $(target_h) \
$(inferior_h) $(gdb_stat_h) $(gdbcmd_h) $(gdbcore_h) $(regcache_h) \
$(solib_h) $(symfile_h) $(gdb_string_h) $(gregset_h)
@@ -2733,6 +2736,7 @@ stack.o: stack.c $(defs_h) $(value_h) $(symtab_h) $(gdbtypes_h) \
std-regs.o: std-regs.c $(defs_h) $(user_regs_h) $(frame_h) $(gdbtypes_h) \
$(value_h) $(gdb_string_h)
stop-gdb.o: stop-gdb.c $(defs_h)
+symbian-tdep.o: symbian-tdep.c $(defs_h) $(solib_h)
symfile.o: symfile.c $(defs_h) $(bfdlink_h) $(symtab_h) $(gdbtypes_h) \
$(gdbcore_h) $(frame_h) $(target_h) $(value_h) $(symfile_h) \
$(objfiles_h) $(source_h) $(gdbcmd_h) $(breakpoint_h) $(language_h) \
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index 6142feb15a1..064ba882358 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -102,6 +102,17 @@ static const char *arm_abi_strings[] =
static enum arm_abi_kind arm_abi_global = ARM_ABI_AUTO;
static const char *arm_abi_string = "auto";
+/* The execution mode to assume. */
+static const char *arm_mode_strings[] =
+ {
+ "auto",
+ "arm",
+ "thumb"
+ };
+
+static const char *arm_fallback_mode_string = "auto";
+static const char *arm_force_mode_string = "auto";
+
/* Number of different reg name sets (options). */
static int num_disassembly_options;
@@ -191,16 +202,30 @@ arm_pc_is_thumb (CORE_ADDR memaddr)
if (IS_THUMB_ADDR (memaddr))
return 1;
+ /* If the user wants to override the symbol table, let him. */
+ if (strcmp (arm_force_mode_string, "arm") == 0)
+ return 0;
+ if (strcmp (arm_force_mode_string, "thumb") == 0)
+ return 1;
+
/* Thumb functions have a "special" bit set in minimal symbols. */
sym = lookup_minimal_symbol_by_pc (memaddr);
if (sym)
- {
- return (MSYMBOL_IS_SPECIAL (sym));
- }
- else
- {
- return 0;
- }
+ return (MSYMBOL_IS_SPECIAL (sym));
+
+ /* If the user wants to override the fallback mode, let them. */
+ if (strcmp (arm_fallback_mode_string, "arm") == 0)
+ return 0;
+ if (strcmp (arm_fallback_mode_string, "thumb") == 0)
+ return 1;
+
+ /* If we couldn't find any symbol, but we're talking to a running
+ target, then trust the current value of $cpsr. */
+ if (target_has_registers)
+ return (read_register (ARM_PS_REGNUM) & 0x20) != 0;
+
+ /* Otherwise we're out of luck; we assume ARM. */
+ return 0;
#else
/* ARMV7M processors are always in Thumb mode. */
return 1;
@@ -548,9 +573,9 @@ thumb_scan_prologue (CORE_ADDR prev_pc, struct arm_prologue_cache *cache)
prologue_end = sal.end; /* (probably means no prologue) */
}
else
- /* We're in the boondocks: allow for
- 16 pushes, an add, and "mv fp,sp". */
- prologue_end = prologue_start + 40;
+ /* We're in the boondocks: we have no idea where the start of the
+ function is. */
+ return;
prologue_end = min (prologue_end, prev_pc);
@@ -2510,6 +2535,28 @@ The current ARM ABI is \"auto\" (currently \"%s\").\n"),
arm_abi_string);
}
+static void
+arm_show_fallback_mode (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+
+ fprintf_filtered (file, _("\
+The current execution mode assumed (when symbols are unavailable) is \"%s\".\n"),
+ arm_fallback_mode_string);
+}
+
+static void
+arm_show_force_mode (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+
+ fprintf_filtered (file, _("\
+The current execution mode assumed (even when symbols are available) is \"%s\".\n"),
+ arm_force_mode_string);
+}
+
/* If the user changes the register disassembly style used for info
register and other commands, we have to also switch the style used
in opcodes for disassembly output. This function is run in the "set
@@ -3200,6 +3247,21 @@ vfp - VFP co-processor."),
NULL, arm_set_abi, arm_show_abi,
&setarmcmdlist, &showarmcmdlist);
+ /* Add two commands to allow the user to force the assumed
+ execution mode. */
+ add_setshow_enum_cmd ("fallback-mode", class_support,
+ arm_mode_strings, &arm_fallback_mode_string,
+ _("Set the mode assumed when symbols are unavailable."),
+ _("Show the mode assumed when symbols are unavailable."),
+ NULL, NULL, arm_show_fallback_mode,
+ &setarmcmdlist, &showarmcmdlist);
+ add_setshow_enum_cmd ("force-mode", class_support,
+ arm_mode_strings, &arm_force_mode_string,
+ _("Set the mode assumed even when symbols are available."),
+ _("Show the mode assumed even when symbols are available."),
+ NULL, NULL, arm_show_force_mode,
+ &setarmcmdlist, &showarmcmdlist);
+
/* Debugging flag. */
add_setshow_boolean_cmd ("arm", class_maintenance, &arm_debug,
_("Set ARM debugging."),
diff --git a/gdb/cli/cli-setshow.c b/gdb/cli/cli-setshow.c
index ac8bdb7ad94..453196103a7 100644
--- a/gdb/cli/cli-setshow.c
+++ b/gdb/cli/cli-setshow.c
@@ -124,63 +124,36 @@ deprecated_show_value_hack (struct ui_file *ignore_file,
void
do_setshow_command (char *arg, int from_tty, struct cmd_list_element *c)
{
+ struct cleanup *back_to = make_cleanup (null_cleanup, NULL);
+
if (c->type == set_cmd)
{
+ char **argv;
+
switch (c->var_type)
{
- case var_string:
- {
- char *new;
- char *p;
- char *q;
- int ch;
+ /* case var_string: */
+ case var_string_noescape:
+ case var_filename:
+ case var_optional_filename:
+ if (arg != NULL)
+ {
+ argv = buildargv (arg);
+ if (argv == NULL)
+ nomem (0);
+ if (argv[0] == NULL || argv[1] != NULL)
+ error (_("A single argument is required (missing quotes?)."));
+ make_cleanup_freeargv (argv);
+ arg = argv[0];
+ }
+ }
- if (arg == NULL)
- arg = "";
- new = (char *) xmalloc (strlen (arg) + 2);
- p = arg;
- q = new;
- while ((ch = *p++) != '\000')
- {
- if (ch == '\\')
- {
- /* \ at end of argument is used after spaces
- so they won't be lost. */
- /* This is obsolete now that we no longer strip
- trailing whitespace and actually, the backslash
- didn't get here in my test, readline or
- something did something funky with a backslash
- right before a newline. */
- if (*p == 0)
- break;
- ch = parse_escape (&p);
- if (ch == 0)
- break; /* C loses */
- else if (ch > 0)
- *q++ = ch;
- }
- else
- *q++ = ch;
- }
-#if 0
- if (*(p - 1) != '\\')
- *q++ = ' ';
-#endif
- *q++ = '\0';
- new = (char *) xrealloc (new, q - new);
- if (*(char **) c->var != NULL)
- xfree (*(char **) c->var);
- *(char **) c->var = new;
- }
- break;
+ switch (c->var_type)
+ {
+ case var_string:
case var_string_noescape:
- if (arg == NULL)
- arg = "";
- if (*(char **) c->var != NULL)
- xfree (*(char **) c->var);
- *(char **) c->var = savestring (arg, strlen (arg));
- break;
case var_optional_filename:
+ /* Should the var_optional_filename case call tilde_expand? */
if (arg == NULL)
arg = "";
if (*(char **) c->var != NULL)
@@ -301,9 +274,12 @@ do_setshow_command (char *arg, int from_tty, struct cmd_list_element *c)
switch (c->var_type)
{
case var_string:
+ /* FALLTHROUGH */
+#if 0
if (*(char **) c->var)
fputstr_filtered (*(char **) c->var, '"', stb->stream);
break;
+#endif
case var_string_noescape:
case var_optional_filename:
case var_filename:
@@ -380,6 +356,8 @@ do_setshow_command (char *arg, int from_tty, struct cmd_list_element *c)
c->func (c, NULL, from_tty);
if (c->type == set_cmd && deprecated_set_hook)
deprecated_set_hook (c);
+
+ do_cleanups (back_to);
}
/* Show all the settings in a list of show commands. */
diff --git a/gdb/config/arm/symbian.mt b/gdb/config/arm/symbian.mt
new file mode 100644
index 00000000000..0d6761929fe
--- /dev/null
+++ b/gdb/config/arm/symbian.mt
@@ -0,0 +1,6 @@
+# Target: ARM embedded system
+TDEPFILES= arm-tdep.o prologue-value.o solib-target.o symbian-tdep.o
+DEPRECATED_TM_FILE= tm-embed.h
+
+SIM_OBS = remote-sim.o
+SIM = ../sim/arm/libsim.a
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index 4e0f6f2c968..aca93b9d71e 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -59,6 +59,7 @@ arm*-*-netbsd* | arm*-*-knetbsd*-gnu)
gdb_target=nbsd ;;
arm-*-nto*) gdb_target=nto ;;
arm*-*-openbsd*) gdb_target=nbsd ;;
+arm*-*-symbian*) gdb_target=symbian ;;
arm*-stellaris-*) gdb_target=armv7m ;;
arm*-*-* | thumb*-*-* | strongarm*-*-*)
gdb_target=embed
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index d79933a1511..221a95a2fa9 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -14012,6 +14012,24 @@ This command forces @value{GDBN} to use the specified ABI.
@item show arm abi
Show the currently used ABI.
+@item set arm fallback-mode
+This command sets the mode (ARM versus Thumb) which @value{GDBN} will
+assume for code without a symbol table. The default is @samp{auto},
+which causes @value{GDBN} to use the mode associated with the current
+CPSR.
+
+@item show arm fallback-mode
+Show the current fallback execution mode.
+
+@item set arm force-mode
+This command sets the mode (ARM versus Thumb) which @value{GDBN} will
+assume for all code, even when a symbol table is present. The default
+is @samp{auto}, which causes @value{GDBN} to use the symbol table
+and fall back to the value of @samp{set arm fallback-mode}.
+
+@item show arm force-mode
+Show the currently forced execution mode.
+
@item set debug arm
Toggle whether to display ARM-specific debugging messages from the ARM
target support subsystem.
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 08f1d89466d..d677870caaa 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -263,6 +263,10 @@ linux_kill (void)
/* Make sure it died. The loop is most likely unnecessary. */
wstat = linux_wait_for_event (thread);
} while (WIFSTOPPED (wstat));
+
+ clear_inferiors ();
+ free (all_processes.head);
+ all_processes.head = all_processes.tail = NULL;
}
static void
@@ -278,6 +282,10 @@ static void
linux_detach (void)
{
for_each_inferior (&all_threads, linux_detach_one_process);
+
+ clear_inferiors ();
+ free (all_processes.head);
+ all_processes.head = all_processes.tail = NULL;
}
/* Return nonzero if the given thread is still alive. */
@@ -416,6 +424,16 @@ linux_wait_for_process (struct process_info **childp, int *wstatp)
if (to_wait_for == -1)
*childp = (struct process_info *) find_inferior_id (&all_processes, ret);
+ /* If we see an event for a process we don't know about, one of two things
+ could be happening: it could be a new thread, e.g. via CLONE_PTRACE,
+ or it could be a detached process exiting. We do not yet support
+ CLONE_PTRACE, so we should disregard extraneous events. */
+ if (*childp == NULL)
+ {
+ linux_wait_for_process (childp, wstatp);
+ return;
+ }
+
(*childp)->stopped = 1;
(*childp)->pending_is_breakpoint = 0;
diff --git a/gdb/gdbserver/remote-utils.c b/gdb/gdbserver/remote-utils.c
index c36570239f8..f0e0d4b7195 100644
--- a/gdb/gdbserver/remote-utils.c
+++ b/gdb/gdbserver/remote-utils.c
@@ -396,6 +396,12 @@ void
unblock_async_io (void)
{
sigset_t sigio_set;
+
+ /* HACK */
+ extern int restarting_program;
+ if (restarting_program)
+ return;
+
sigemptyset (&sigio_set);
sigaddset (&sigio_set, SIGIO);
sigprocmask (SIG_UNBLOCK, &sigio_set, NULL);
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index 51b87642a83..b9de99a5982 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -33,9 +33,12 @@ unsigned long thread_from_wait;
unsigned long old_thread_from_wait;
int extended_protocol;
int server_waiting;
+int exit_requested;
jmp_buf toplevel;
+static int attached;
+
/* The PID of the originally created or attached inferior. Used to
send signals to the process when GDB sends us an asynchronous interrupt
(user hitting Control-C in the client), and to wait for the child to exit
@@ -43,9 +46,17 @@ jmp_buf toplevel;
unsigned long signal_pid;
+int restarting_program;
+
+char **program_argv;
+
static int
start_inferior (char *argv[], char *statusptr)
{
+ int sig;
+
+ attached = 0;
+
signal (SIGTTOU, SIG_DFL);
signal (SIGTTIN, SIG_DFL);
@@ -59,7 +70,11 @@ start_inferior (char *argv[], char *statusptr)
tcsetpgrp (fileno (stderr), signal_pid);
/* Wait till we are at 1st instruction in program, return signal number. */
- return mywait (statusptr, 0);
+ restarting_program = 1;
+ block_async_io ();
+ sig = mywait (statusptr, 0);
+ restarting_program = 0;
+ return sig;
}
static int
@@ -71,6 +86,8 @@ attach_inferior (int pid, char *statusptr, int *sigptr)
if (myattach (pid) != 0)
return -1;
+ attached = 1;
+
fprintf (stderr, "Attached; pid = %d\n", pid);
/* FIXME - It may be that we should get the SIGNAL_PID from the
@@ -163,6 +180,67 @@ handle_query (char *own_buf)
return;
}
+ if (strncmp ("qRcmd,", own_buf, 6) == 0)
+ {
+ if (strcmp (own_buf + 6, "65786974") == 0)
+ {
+ /* "exit". */
+ write_ok (own_buf);
+ exit_requested = 1;
+ return;
+ }
+ else
+ {
+ write_enn (own_buf);
+ return;
+ }
+ }
+
+ /* Otherwise we didn't know what packet it was. Say we didn't
+ understand it. */
+ own_buf[0] = 0;
+}
+
+void
+handle_query_non_running (char *own_buf)
+{
+ if (strcmp ("qSymbol::", own_buf) == 0)
+ {
+ /* No symbols to look up when the target is not running. */
+ write_ok (own_buf);
+ return;
+ }
+
+ if (strcmp ("qfThreadInfo", own_buf) == 0
+ || strcmp ("qsThreadInfo", own_buf) == 0)
+ {
+ write_enn (own_buf);
+ return;
+ }
+
+ if (the_target->read_auxv != NULL
+ && strncmp ("qPart:auxv:read::", own_buf, 17) == 0)
+ {
+ write_enn (own_buf);
+ return;
+ }
+
+ if (strncmp ("qRcmd,", own_buf, 6) == 0)
+ {
+ if (strcmp (own_buf + 6, "65786974") == 0)
+ {
+ /* "exit". */
+ write_ok (own_buf);
+ exit_requested = 1;
+ return;
+ }
+ else
+ {
+ write_enn (own_buf);
+ return;
+ }
+ }
+
/* Otherwise we didn't know what packet it was. Say we didn't
understand it. */
own_buf[0] = 0;
@@ -275,12 +353,106 @@ handle_v_cont (char *own_buf, char *status, int *signal)
return;
err:
- /* No other way to report an error... */
- strcpy (own_buf, "");
+ write_enn (own_buf);
free (resume_info);
return;
}
+/* Attach to a new program. Return 1 if successful, 0 if failure. */
+int
+handle_v_attach (char *own_buf, char *status, int *signal)
+{
+ int pid;
+
+ /* FIXME: attach_inferior failures may return -1, or may call error().
+ gdbserver use of error() is totally busted; the protocol conversation
+ gets out of sync. */
+
+ pid = strtol (own_buf + 8, NULL, 16);
+ if (pid != 0 && attach_inferior (pid, status, signal) == 0)
+ {
+ prepare_resume_reply (own_buf, *status, *signal);
+ putpkt (own_buf);
+ return 1;
+ }
+ else
+ {
+ write_enn (own_buf);
+ return 0;
+ }
+}
+
+/* Run a new program. Return 1 if successful, 0 if failure. */
+static int
+handle_v_run (char *own_buf, char *status, int *signal)
+{
+ char *p, **pp, *next_p, **new_argv;
+ int i, new_argc;
+
+ new_argc = 0;
+ for (p = own_buf + strlen ("vRun;"); p && *p; p = strchr (p, ';'))
+ {
+ p++;
+ new_argc++;
+ }
+
+ new_argv = malloc ((new_argc + 2) * sizeof (char *));
+ i = 0;
+ for (p = own_buf + strlen ("vRun;"); *p; p = next_p)
+ {
+ next_p = strchr (p, ';');
+ if (next_p == NULL)
+ next_p = p + strlen (p);
+
+ if (i == 0 && p == next_p)
+ new_argv[i] = NULL;
+ else
+ {
+ new_argv[i] = malloc (1 + (next_p - p) / 2);
+ unhexify (new_argv[i], p, (next_p - p) / 2);
+ new_argv[i][(next_p - p) / 2] = '\0';
+ }
+
+ if (*next_p)
+ next_p++;
+ i++;
+ }
+ new_argv[i] = NULL;
+
+ if (new_argv[0] == NULL)
+ {
+ if (program_argv == NULL)
+ {
+ write_enn (own_buf);
+ return 0;
+ }
+
+ new_argv[0] = strdup (program_argv[0]);
+ }
+
+ /* Free the old argv. */
+ if (program_argv)
+ {
+ for (pp = program_argv; *pp != NULL; pp++)
+ free (*pp);
+ free (program_argv);
+ }
+ program_argv = new_argv;
+
+ *signal = start_inferior (program_argv, status);
+ if (*status == 'T')
+ {
+ prepare_resume_reply (own_buf, *status, *signal);
+ putpkt (own_buf);
+ return 1;
+ }
+ else
+ {
+ write_enn (own_buf);
+ return 0;
+ }
+}
+
/* Handle all of the extended 'v' packets. */
void
handle_v_requests (char *own_buf, char *status, int *signal)
@@ -297,12 +469,58 @@ handle_v_requests (char *own_buf, char *status, int *signal)
return;
}
+ if (strncmp (own_buf, "vAttach;", 8) == 0)
+ {
+ fprintf (stderr, "Killing inferior\n");
+ kill_inferior ();
+ handle_v_attach (own_buf, status, signal);
+ return;
+ }
+
+ if (strncmp (own_buf, "vRun;", 5) == 0)
+ {
+ fprintf (stderr, "Killing inferior\n");
+ kill_inferior ();
+ handle_v_run (own_buf, status, signal);
+ return;
+ }
+
/* Otherwise we didn't know what packet it was. Say we didn't
understand it. */
own_buf[0] = 0;
return;
}
+/* Handle all of the extended 'v' packets. Return 1 if there is now
+ an inferior. */
+int
+handle_v_requests_non_running (char *own_buf, char *status, int *signal)
+{
+ if (strncmp (own_buf, "vCont;", 6) == 0)
+ {
+ /* Can't do this when not running. */
+ write_enn (own_buf);
+ return 0;
+ }
+
+ if (strncmp (own_buf, "vCont?", 6) == 0)
+ {
+ strcpy (own_buf, "vCont;c;C;s;S");
+ return 0;
+ }
+
+ if (strncmp (own_buf, "vAttach;", 8) == 0)
+ return handle_v_attach (own_buf, status, signal);
+
+ if (strncmp (own_buf, "vRun;", 5) == 0)
+ return handle_v_run (own_buf, status, signal);
+
+ /* Otherwise we didn't know what packet it was. Say we didn't
+ understand it. */
+ own_buf[0] = 0;
+ return 0;
+}
+
void
myresume (int step, int sig)
{
@@ -326,8 +544,6 @@ myresume (int step, int sig)
(*the_target->resume) (resume_info);
}
-static int attached;
-
static void
gdbserver_version (void)
{
@@ -348,6 +564,97 @@ gdbserver_usage (void)
"HOST:PORT to listen for a TCP connection.\n");
}
+/* FIXME declare here, give sensible name, give values? */
+extern int debug_threads;
+
+/* Handle a single packet. Return 1 if the program is now running, 0
+ if it is not. */
+
+int
+non_running (char *own_buf, char *status, int *signal)
+{
+ char ch;
+ int i = 0;
+
+ ch = own_buf[i++];
+ switch (ch)
+ {
+ case 'q':
+ handle_query_non_running (own_buf);
+ break;
+ case 'd':
+ remote_debug = !remote_debug;
+ break;
+ case 'D':
+ /* Can not detach with nothing running. */
+ write_enn (own_buf);
+ break;
+ case '!':
+ /* Already in extended mode. */
+ write_ok (own_buf);
+ break;
+ case '?':
+ prepare_resume_reply (own_buf, *status, *signal);
+ break;
+ case 'H':
+ if (own_buf[1] == 'c' || own_buf[1] == 'g' || own_buf[1] == 's')
+ write_enn (own_buf);
+ else
+ own_buf[0] = 0;
+ break;
+ case 'g':
+ case 'G':
+ case 'm':
+ case 'M':
+ case 'C':
+ case 'S':
+ case 'c':
+ case 's':
+ /* Commands which do not make sense without a program to debug. */
+ write_enn (own_buf);
+ break;
+
+ case 'k':
+ /* This is special. It doesn't make sense - but we can't reply
+ to it, either. */
+ return 2;
+
+ case 'Z':
+ case 'z':
+ /* If we return an error, the client will assume we support this
+ particular breakpoint packet. But maybe we do, and maybe we
+ don't. However, we don't worry about it - it's a bug in the
+ client to insert breakpoints when there is no inferior. */
+ write_enn (own_buf);
+ break;
+
+ case 'T':
+ /* Obviously the thread is not alive. */
+ write_enn (own_buf);
+ break;
+
+ case 'R':
+ /* Restart request. */
+ fprintf (stderr, "GDBserver restarting\n");
+
+ /* Wait till we are at 1st instruction in prog. */
+ *signal = start_inferior (program_argv, status);
+ return 1;
+
+ case 'v':
+ /* Extended (long) request. */
+ return handle_v_requests_non_running (own_buf, status, signal);
+
+ default:
+ /* It is a request we don't understand. Respond with an
+ empty packet so that gdb knows that we don't support this
+ request. */
+ own_buf[0] = '\0';
+ break;
+ }
+ return 0;
+}
+
int
main (int argc, char *argv[])
{
@@ -360,6 +667,7 @@ main (int argc, char *argv[])
int bad_attach;
int pid;
char *arg_end;
+ int running;
if (argc >= 2 && strcmp (argv[1], "--version") == 0)
{
@@ -379,9 +687,15 @@ main (int argc, char *argv[])
exit (1);
}
+ if (argc >= 2 && strcmp (argv[1], "--debug") == 0)
+ {
+ argc--;
+ argv++;
+ debug_threads = 1;
+ }
+
bad_attach = 0;
pid = 0;
- attached = 0;
if (argc >= 3 && strcmp (argv[2], "--attach") == 0)
{
if (argc == 4
@@ -408,23 +722,25 @@ main (int argc, char *argv[])
if (pid == 0)
{
+ int i;
+ program_argv = malloc (sizeof (char *) * (argc + 1));
+ for (i = 0; 2 + i < argc; i++)
+ program_argv[i] = strdup (argv[2 + i]);
+ program_argv[argc] = NULL;
+
/* Wait till we are at first instruction in program. */
- signal = start_inferior (&argv[2], &status);
+ signal = start_inferior (program_argv, &status);
/* We are now stopped at the first instruction of the target process */
}
else
{
- switch (attach_inferior (pid, &status, &signal))
- {
- case -1:
- error ("Attaching not supported on this target");
- break;
- default:
- attached = 1;
- break;
- }
+ if (attach_inferior (pid, &status, &signal) == -1)
+ error ("Attaching not supported on this target");
+
+ /* Otherwise succeeded. */
}
+ running = 1;
while (1)
{
@@ -432,9 +748,27 @@ main (int argc, char *argv[])
restart:
setjmp (toplevel);
- while (getpkt (own_buf) > 0)
+ while (!exit_requested && getpkt (own_buf) > 0)
{
unsigned char sig;
+
+ if (running == 0)
+ {
+ int ret = non_running (own_buf, &status, &signal);
+ if (ret == 1)
+ {
+ /* Go back to the top. We do not call putpkt; the 'R'
+ packet does not expect a response for historical
+ reasons. */
+ running = 1;
+ goto restart;
+ }
+ if (ret == 2)
+ /* A packet which should not be responded to. */
+ goto restart;
+ goto done_packet;
+ }
+
i = 0;
ch = own_buf[i++];
switch (ch)
@@ -449,24 +783,36 @@ main (int argc, char *argv[])
fprintf (stderr, "Detaching from inferior\n");
detach_inferior ();
write_ok (own_buf);
- putpkt (own_buf);
- remote_close ();
- /* If we are attached, then we can exit. Otherwise, we need to
- hang around doing nothing, until the child is gone. */
- if (!attached)
+ if (extended_protocol)
{
- int status, ret;
-
- do {
- ret = waitpid (signal_pid, &status, 0);
- if (WIFEXITED (status) || WIFSIGNALED (status))
- break;
- } while (ret != -1 || errno != ECHILD);
+ /* Treat this like a normal program exit. */
+ signal = 0;
+ status = 'W';
+ running = 0;
}
+ else
+ {
+ putpkt (own_buf);
+ remote_close ();
- exit (0);
+ /* If we are attached, then we can exit. Otherwise,
+ we need to hang around doing nothing, until the
+ child is gone. */
+ if (!attached)
+ {
+ int status, ret;
+
+ do {
+ ret = waitpid (signal_pid, &status, 0);
+ if (WIFEXITED (status) || WIFSIGNALED (status))
+ break;
+ } while (ret != -1 || errno != ECHILD);
+ }
+ exit (0);
+ }
+ break;
case '!':
if (attached == 0)
{
@@ -490,11 +836,16 @@ main (int argc, char *argv[])
unsigned long gdb_id, thread_id;
gdb_id = strtoul (&own_buf[2], NULL, 16);
- thread_id = gdb_id_to_thread_id (gdb_id);
- if (thread_id == 0)
+ if (gdb_id == 0 || gdb_id == -1)
+ thread_id = gdb_id;
+ else
{
- write_enn (own_buf);
- break;
+ thread_id = gdb_id_to_thread_id (gdb_id);
+ if (thread_id == 0)
+ {
+ write_enn (own_buf);
+ break;
+ }
}
if (own_buf[1] == 'g')
@@ -642,10 +993,17 @@ main (int argc, char *argv[])
if (extended_protocol)
{
write_ok (own_buf);
+ status = 'X';
+ signal = SIGKILL;
+#if 0
fprintf (stderr, "GDBserver restarting\n");
/* Wait till we are at 1st instruction in prog. */
- signal = start_inferior (&argv[2], &status);
+ signal = start_inferior (program_argv, &status);
+#else
+ fprintf (stderr, "GDBserver killing inferior\n");
+ running = 0;
+#endif
goto restart;
break;
}
@@ -682,7 +1040,7 @@ main (int argc, char *argv[])
fprintf (stderr, "GDBserver restarting\n");
/* Wait till we are at 1st instruction in prog. */
- signal = start_inferior (&argv[2], &status);
+ signal = start_inferior (program_argv, &status);
goto restart;
break;
}
@@ -706,27 +1064,22 @@ main (int argc, char *argv[])
break;
}
+done_packet:
putpkt (own_buf);
- if (status == 'W')
- fprintf (stderr,
- "\nChild exited with status %d\n", signal);
- if (status == 'X')
- fprintf (stderr, "\nChild terminated with signal = 0x%x\n",
- signal);
- if (status == 'W' || status == 'X')
+ if (running && (status == 'W' || status == 'X'))
{
+ if (status == 'W')
+ fprintf (stderr,
+ "\nChild exited with status %d\n", signal);
+ if (status == 'X')
+ fprintf (stderr, "\nChild terminated with signal = 0x%x\n",
+ signal);
+
if (extended_protocol)
{
- fprintf (stderr, "Killing inferior\n");
- kill_inferior ();
- write_ok (own_buf);
- fprintf (stderr, "GDBserver restarting\n");
-
- /* Wait till we are at 1st instruction in prog. */
- signal = start_inferior (&argv[2], &status);
+ running = 0;
goto restart;
- break;
}
else
{
@@ -736,16 +1089,18 @@ main (int argc, char *argv[])
}
}
- /* We come here when getpkt fails.
-
- For the extended remote protocol we exit (and this is the only
- way we gracefully exit!).
+ /* If an exit was requested (using the "monitor exit" command),
+ terminate now. The only other way to get here is for
+ getpkt to fail; close the connection and reopen it at the
+ top of the loop. */
- For the traditional remote protocol close the connection,
- and re-open it at the top of the loop. */
- if (extended_protocol)
+ if (exit_requested)
{
remote_close ();
+ if (attached && running)
+ detach_inferior ();
+ else if (running)
+ kill_inferior ();
exit (0);
}
else
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 3d18298a1c6..1095a792afb 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -2068,14 +2068,14 @@ Show terminal for future runs of program being debugged."), _("\
Usage: set inferior-tty /dev/pts/1"), NULL, NULL, &setlist, &showlist);
add_com_alias ("tty", "set inferior-tty", class_alias, 0);
- add_setshow_optional_filename_cmd ("args", class_run,
- &inferior_args, _("\
+ add_setshow_string_cmd ("args", class_run,
+ &inferior_args, _("\
Set argument list to give program being debugged when it is started."), _("\
Show argument list to give program being debugged when it is started."), _("\
Follow this command with any number of args, to be passed to the program."),
- notice_args_set,
- notice_args_read,
- &setlist, &showlist);
+ notice_args_set,
+ notice_args_read,
+ &setlist, &showlist);
c = add_cmd ("environment", no_class, environment_info, _("\
The environment to give the program, or one variable's value.\n\
diff --git a/gdb/inflow.c b/gdb/inflow.c
index 1b15d2c3958..04f70ed02e2 100644
--- a/gdb/inflow.c
+++ b/gdb/inflow.c
@@ -588,10 +588,7 @@ kill_command (char *arg, int from_tty)
if (target_has_stack)
{
printf_filtered (_("In %s,\n"), target_longname);
- if (deprecated_safe_get_selected_frame () == NULL)
- fputs_filtered ("No selected stack frame.\n", gdb_stdout);
- else
- print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC);
+ print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC);
}
bfd_cache_close_all ();
}
diff --git a/gdb/infrun.c b/gdb/infrun.c
index d4bf88940bb..ae0d2cdffc3 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -877,6 +877,8 @@ init_wait_for_inferior (void)
clear_proceed_status ();
stepping_past_singlestep_breakpoint = 0;
+
+ target_last_wait_ptid = minus_one_ptid;
}
/* This enum encodes possible reasons for doing a target_wait, so that
@@ -942,7 +944,7 @@ void init_execution_control_state (struct execution_control_state *ecs);
void handle_inferior_event (struct execution_control_state *ecs);
static void step_into_function (struct execution_control_state *ecs);
-static void insert_step_resume_breakpoint_at_frame (struct frame_info *step_frame);
+static void insert_step_resume_breakpoint_at_frame (struct frame_info *, int);
static void insert_step_resume_breakpoint_at_sal (struct symtab_and_line sr_sal,
struct frame_id sr_id);
static void stop_stepping (struct execution_control_state *ecs);
@@ -1314,13 +1316,16 @@ handle_inferior_event (struct execution_control_state *ecs)
/* Ignore gracefully during startup of the inferior, as it
might be the shell which has just loaded some objects,
otherwise add the symbols for the newly loaded objects. */
-#ifdef SOLIB_ADD
if (stop_soon == NO_STOP_QUIETLY)
{
+ int breakpoints_were_inserted;
+
/* Remove breakpoints, SOLIB_ADD might adjust
breakpoint addresses via breakpoint_re_set. */
+ breakpoints_were_inserted = breakpoints_inserted;
if (breakpoints_inserted)
remove_breakpoints ();
+ breakpoints_inserted = 0;
/* Check for any newly added shared libraries if we're
supposed to be adding them automatically. Switch
@@ -1342,17 +1347,52 @@ handle_inferior_event (struct execution_control_state *ecs)
exec/process stratum, instead relying on the target stack
to propagate relevant changes (stop, section table
changed, ...) up to other layers. */
+#ifdef SOLIB_ADD
SOLIB_ADD (NULL, 0, &current_target, auto_solib_add);
+#else
+ solib_add (NULL, 0, &current_target, auto_solib_add);
+#endif
target_terminal_inferior ();
+ /* Try to reenable shared library breakpoints, additional
+ code segments in shared libraries might be mapped in now. */
+ re_enable_breakpoints_in_shlibs ();
+
+ /* If requested, stop when the dynamic linker notifies
+ gdb of events. This allows the user to get control
+ and place breakpoints in initializer routines for
+ dynamically loaded objects (among other things). */
+ if (stop_on_solib_events || stop_stack_dummy)
+ {
+ stop_stepping (ecs);
+ return;
+ }
+
+ /* NOTE drow/2006-03-14: This might be a good place to check
+ for "catch load". */
+
/* Reinsert breakpoints and continue. */
- if (breakpoints_inserted)
- insert_breakpoints ();
+ if (breakpoints_were_inserted)
+ {
+ insert_breakpoints ();
+ breakpoints_inserted = 1;
+ }
}
-#endif
- resume (0, TARGET_SIGNAL_0);
- prepare_to_wait (ecs);
- return;
+
+ /* NOTE drow/2006-03-28: For the reason described before the
+ previous if statement, GDB used to automatically resume
+ here. But that's only true if a shell is running; if
+ we've just attached to a process, then that's a whole
+ different case - it might have been stopped at a load
+ event. */
+ if (inferior_ignoring_startup_exec_events || stop_soon == NO_STOP_QUIETLY)
+ {
+ resume (0, TARGET_SIGNAL_0);
+ prepare_to_wait (ecs);
+ return;
+ }
+ else
+ break;
case TARGET_WAITKIND_SPURIOUS:
if (debug_infrun)
@@ -1965,7 +2005,7 @@ process_event_stop_test:
code paths as single-step - set a breakpoint at the
signal return address and then, once hit, step off that
breakpoint. */
- insert_step_resume_breakpoint_at_frame (get_current_frame ());
+ insert_step_resume_breakpoint_at_frame (get_current_frame (), 0);
ecs->step_after_step_resume_breakpoint = 1;
keep_going (ecs);
return;
@@ -1987,7 +2027,7 @@ process_event_stop_test:
Note that this is only needed for a signal delivered
while in the single-step range. Nested signals aren't a
problem as they eventually all return. */
- insert_step_resume_breakpoint_at_frame (get_current_frame ());
+ insert_step_resume_breakpoint_at_frame (get_current_frame (), 0);
keep_going (ecs);
return;
}
@@ -2396,7 +2436,7 @@ process_event_stop_test:
/* We're doing a "next", set a breakpoint at callee's return
address (the address at which the caller will
resume). */
- insert_step_resume_breakpoint_at_frame (get_prev_frame (get_current_frame ()));
+ insert_step_resume_breakpoint_at_frame (get_current_frame (), 1);
keep_going (ecs);
return;
}
@@ -2459,7 +2499,7 @@ process_event_stop_test:
/* Set a breakpoint at callee's return address (the address at
which the caller will resume). */
- insert_step_resume_breakpoint_at_frame (get_prev_frame (get_current_frame ()));
+ insert_step_resume_breakpoint_at_frame (get_current_frame (), 1);
keep_going (ecs);
return;
}
@@ -2528,7 +2568,7 @@ process_event_stop_test:
{
/* Set a breakpoint at callee's return address (the address
at which the caller will resume). */
- insert_step_resume_breakpoint_at_frame (get_prev_frame (get_current_frame ()));
+ insert_step_resume_breakpoint_at_frame (get_current_frame (), 1);
keep_going (ecs);
return;
}
@@ -2741,22 +2781,33 @@ insert_step_resume_breakpoint_at_sal (struct symtab_and_line sr_sal,
that the function/signal handler being skipped eventually returns
to the breakpoint inserted at RETURN_FRAME.pc.
- For the skip-function case, the function may have been reached by
- either single stepping a call / return / signal-return instruction,
- or by hitting a breakpoint. In all cases, the RETURN_FRAME belongs
- to the skip-function's caller.
+ If USE_PREVIOUS is zero, RETURN_FRAME belongs to the function being
+ skipped. The function may have been reached by either single
+ stepping a call / return / signal-return instruction, or by hitting
+ a breakpoint.
For the signals case, this is called with the interrupted
function's frame. The signal handler, when it returns, will resume
the interrupted function at RETURN_FRAME.pc. */
static void
-insert_step_resume_breakpoint_at_frame (struct frame_info *return_frame)
+insert_step_resume_breakpoint_at_frame (struct frame_info *return_frame,
+ int use_previous)
{
struct symtab_and_line sr_sal;
init_sal (&sr_sal); /* initialize to zeros */
+ if (use_previous)
+ {
+ struct frame_info *caller_frame;
+ caller_frame = get_prev_frame (return_frame);
+ if (caller_frame == NULL)
+ error (_("Could not step out of the function at 0x%lx - unwinding failed"),
+ (long) get_frame_pc (return_frame));
+ return_frame = caller_frame;
+ }
+
sr_sal.pc = ADDR_BITS_REMOVE (get_frame_pc (return_frame));
sr_sal.section = find_pc_overlay (sr_sal.pc);
diff --git a/gdb/remote.c b/gdb/remote.c
index 9f14816b25b..a5a6f841911 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -43,6 +43,7 @@
#include "gdb_assert.h"
#include "observer.h"
#include "solib.h"
+#include "solist.h"
#include "cli/cli-decode.h"
#include "cli/cli-setshow.h"
#include "available.h"
@@ -439,6 +440,10 @@ static int remote_address_size;
static int remote_async_terminal_ours_p;
+/* The executable file to use for "run" on the remote side. */
+
+static char *remote_exec_file = "";
+
/* User configurable variables for the number of characters in a
memory read/write packet. MIN (rs->remote_packet_size,
@@ -818,6 +823,9 @@ enum {
PACKET_qPart_auxv,
PACKET_qPart_features,
PACKET_qGetTLSAddr,
+ PACKET_vAttach,
+ PACKET_vRun,
+ PACKET_qfDllInfo,
PACKET_MAX
};
@@ -1830,6 +1838,37 @@ remote_threads_extra_info (struct thread_info *tp)
}
+/* Mark OPS as a running target. This should restore the target to its
+ original state, undoing any effects of remote_mark_killed. */
+
+static void
+remote_mark_running (struct target_ops *ops)
+{
+ ops->to_has_execution = 1;
+ ops->to_has_all_memory = 1;
+ ops->to_has_memory = 1;
+ ops->to_has_stack = 1;
+ ops->to_has_registers = 1;
+
+ update_current_target ();
+}
+
+/* Mark OPS as a dead target, undoing any effects of remote_mark_running.
+ The target is still on the stack, and GDB is still connected to it,
+ but the process we were debugging has exited. */
+
+static void
+remote_mark_killed (struct target_ops *ops)
+{
+ ops->to_has_execution = 0;
+ ops->to_has_all_memory = 0;
+ ops->to_has_memory = 0;
+ ops->to_has_stack = 0;
+ ops->to_has_registers = 0;
+
+ update_current_target ();
+}
+
/* Restart the remote side; this is an extended protocol operation. */
static void
@@ -1842,10 +1881,8 @@ extended_remote_restart (void)
xsnprintf (rs->buf, rs->remote_packet_size, "R%x", 0);
putpkt (rs->buf);
- /* Now query for status so this looks just like we restarted
- gdbserver from scratch. */
- putpkt ("?");
- getpkt (&rs->buf, &rs->buf_size, 0);
+ /* We used to query for status here ("?"), but we just discarded the
+ result; there's no point to that. */
}
/* Clean up connection to a remote debugger. */
@@ -1866,7 +1903,7 @@ get_offsets (void)
struct remote_state *rs = get_remote_state ();
char *buf = rs->buf;
char *ptr;
- int lose;
+ int lose, seen_text_seg = 0;
CORE_ADDR text_addr, data_addr, bss_addr;
struct section_offsets *offs;
@@ -1902,24 +1939,41 @@ get_offsets (void)
/* Don't use strtol, could lose on big values. */
while (*ptr && *ptr != ';')
text_addr = (text_addr << 4) + fromhex (*ptr++);
- }
- else
- lose = 1;
- if (!lose && strncmp (ptr, ";Data=", 6) == 0)
- {
- ptr += 6;
- while (*ptr && *ptr != ';')
- data_addr = (data_addr << 4) + fromhex (*ptr++);
- }
- else
- lose = 1;
+ if (strncmp (ptr, ";Data=", 6) == 0)
+ {
+ ptr += 6;
+ while (*ptr && *ptr != ';')
+ data_addr = (data_addr << 4) + fromhex (*ptr++);
+ }
+ else
+ lose = 1;
- if (!lose && strncmp (ptr, ";Bss=", 5) == 0)
+ if (!lose && strncmp (ptr, ";Bss=", 5) == 0)
+ {
+ ptr += 5;
+ while (*ptr && *ptr != ';')
+ bss_addr = (bss_addr << 4) + fromhex (*ptr++);
+ }
+ else
+ lose = 1;
+ }
+ else if (strncmp (ptr, "TextSeg=", 8) == 0)
{
- ptr += 5;
+ ptr += 8;
+ /* Don't use strtol, could lose on big values. */
while (*ptr && *ptr != ';')
- bss_addr = (bss_addr << 4) + fromhex (*ptr++);
+ text_addr = (text_addr << 4) + fromhex (*ptr++);
+ seen_text_seg = 1;
+
+ if (strncmp (ptr, ";DataSeg=", 9) == 0)
+ {
+ ptr += 9;
+ while (*ptr && *ptr != ';')
+ data_addr = (data_addr << 4) + fromhex (*ptr++);
+ }
+ else
+ lose = 1;
}
else
lose = 1;
@@ -1935,18 +1989,182 @@ get_offsets (void)
memcpy (offs, symfile_objfile->section_offsets,
SIZEOF_N_SECTION_OFFSETS (symfile_objfile->num_sections));
- offs->offsets[SECT_OFF_TEXT (symfile_objfile)] = text_addr;
+ if (seen_text_seg)
+ {
+ if (! symfile_map_offsets_to_segments (symfile_objfile, offs,
+ text_addr, data_addr))
+ error (_("Can not handle qOffsets TextSeg response with this symbol file"));
+ }
+ else
+ {
+ offs->offsets[SECT_OFF_TEXT (symfile_objfile)] = text_addr;
- /* This is a temporary kludge to force data and bss to use the same offsets
- because that's what nlmconv does now. The real solution requires changes
- to the stub and remote.c that I don't have time to do right now. */
+ /* This is a temporary kludge to force data and bss to use the same offsets
+ because that's what nlmconv does now. The real solution requires changes
+ to the stub and remote.c that I don't have time to do right now. */
- offs->offsets[SECT_OFF_DATA (symfile_objfile)] = data_addr;
- offs->offsets[SECT_OFF_BSS (symfile_objfile)] = data_addr;
+ offs->offsets[SECT_OFF_DATA (symfile_objfile)] = data_addr;
+ offs->offsets[SECT_OFF_BSS (symfile_objfile)] = data_addr;
+ }
objfile_relocate (symfile_objfile, offs);
}
+/* Parse a load or unload message for a DLL. Loads are required to
+ have all fields, unloads must have at least one. P is not
+ necessarily NUL terminated, but it is always either NUL or semicolon
+ terminated (i.e. *P_END is either NUL or a semicolon) and the containing
+ string is NUL terminated. */
+
+int
+parse_load_response (const char *p, const char *p_end, int is_load)
+{
+ const char *name_start;
+ char *name;
+ CORE_ADDR text_addr, data_addr;
+ int i;
+
+ name = NULL;
+ text_addr = ~(CORE_ADDR) 0;
+ data_addr = ~(CORE_ADDR) 0;
+
+ if (p < p_end && strncmp (p, "Name=", 5) == 0)
+ {
+ p += 5;
+
+ name_start = p;
+ while (p < p_end && *p != ',')
+ p++;
+
+ if ((p - name_start) % 2 != 0)
+ return -1;
+
+ name = alloca ((p - name_start) / 2 + 1);
+ i = hex2bin (name_start, name, (p - name_start) / 2);
+ name[i] = '\0';
+
+ if (p < p_end)
+ p++;
+ }
+ else if (is_load)
+ return -1;
+
+ if (p < p_end && strncmp (p, "TextSeg=", 8) == 0)
+ {
+ p += 8;
+
+ text_addr = 0;
+ while (p < p_end && *p != ',')
+ text_addr = (text_addr << 4) + fromhex (*p++);
+
+ if (p < p_end)
+ p++;
+ }
+ else if (is_load)
+ return -1;
+
+ if (p < p_end && strncmp (p, "DataSeg=", 8) == 0)
+ {
+ p += 8;
+
+ data_addr = 0;
+ while (p < p_end && *p != ',')
+ data_addr = (data_addr << 4) + fromhex (*p++);
+
+ if (p < p_end)
+ p++;
+ }
+ else if (is_load)
+ return -1;
+
+ if (is_load)
+ current_target_so_ops->add_one_solib (name, text_addr, data_addr);
+ else
+ {
+ if (text_addr == ~(CORE_ADDR) 0
+ && data_addr == ~(CORE_ADDR) 0
+ && name == NULL)
+ return -1;
+
+ current_target_so_ops->remove_one_solib (name, text_addr, data_addr);
+ }
+
+ return 0;
+}
+
+/* Query the remote side for loaded solibs. */
+
+static void
+remote_get_shared_libraries (struct target_ops *ops)
+{
+ struct remote_state *rs = get_remote_state ();
+ int added = 0;
+
+ /* If this target doesn't support remote DLLs, nothing to do. */
+ if (current_target_so_ops->add_one_solib == NULL)
+ return;
+
+ /* If qfDllInfo is not available, nothing to do. */
+ if (remote_protocol_packets[PACKET_qfDllInfo].support == PACKET_DISABLE)
+ return;
+
+ putpkt ("qfDllInfo");
+ getpkt (&rs->buf, &rs->buf_size, 0);
+
+ if (packet_ok (rs->buf, &remote_protocol_packets[PACKET_qfDllInfo]) == PACKET_ERROR)
+ {
+ warning (_("Remote failure reply: %s"), rs->buf);
+ return;
+ }
+ else if (remote_protocol_packets[PACKET_qfDllInfo].support == PACKET_DISABLE)
+ /* It wasn't disabled before, but it is now. */
+ return;
+
+ while (rs->buf[0] == 'm')
+ {
+ char *p = rs->buf + 1;
+
+ while (1)
+ {
+ char *p_end = p;
+
+ while (*p_end && *p_end != ';')
+ p_end++;
+
+ if (parse_load_response (p, p_end, 1) != 0)
+ {
+ warning (_("Malformed response to DLL query, %s"), rs->buf);
+ return;
+ }
+
+ added = 1;
+
+ if (*p_end == ';')
+ p = p_end + 1;
+ else
+ break;
+ }
+
+ putpkt ("qsDllInfo");
+ getpkt (&rs->buf, &rs->buf_size, 0);
+ }
+
+ if (strcmp (rs->buf, "l") != 0)
+ {
+ warning (_("Malformed response to DLL query, %s"), rs->buf);
+ return;
+ }
+
+ if (added)
+ {
+#ifdef SOLIB_ADD
+ SOLIB_ADD (NULL, 0, &current_target, auto_solib_add);
+#else
+ solib_add (NULL, 0, &current_target, auto_solib_add);
+#endif
+ }
+}
+
/* Stub for catch_errors. */
static int
@@ -1959,16 +2177,50 @@ remote_start_remote_dummy (struct ui_out *uiout, void *dummy)
}
static void
-remote_start_remote (struct ui_out *uiout, void *dummy)
+remote_start_remote (struct ui_out *uiout, void *target_)
{
+ struct target_ops *target = target_;
+
immediate_quit++; /* Allow user to interrupt it. */
/* Ack any packet which the remote side has already sent. */
serial_write (remote_desc, "+", 1);
+ if (target)
+ {
+ struct remote_state *rs = get_remote_state ();
+ char *buf = alloca (rs->remote_packet_size);
+
+ /* In extended mode, check whether the target is running now. This
+ duplicates the ? request/response, which is a shame; a FIXME
+ is to cache the response for later. */
+ putpkt ("?");
+ getpkt (&buf, &rs->buf_size, 0);
+
+ if (buf[0] == 'W' || buf[0] == 'X')
+ {
+ remote_mark_killed (target);
+ /* FIXME: This bypasses start_remote; mostly this is OK,
+ but do we need to call init_wait_for_inferior somewhere? */
+ return;
+ }
+ else
+ remote_mark_running (target);
+ }
+
/* Let the stub know that we want it to return the thread. */
set_thread (-1, 0);
+ /* Without this, some commands which require an active target
+ (such as kill) won't work. This variable serves (at least)
+ double duty as both the pid of the target process (if it has
+ such), and as a flag indicating that a target is active.
+ These functions should be split out into seperate variables,
+ especially since GDB will someday have a notion of debugging
+ several processes. */
+ inferior_ptid = pid_to_ptid (MAGIC_NULL_PID);
+
+ /* Now, if we have thread information, update inferior_ptid. */
inferior_ptid = remote_current_thread (inferior_ptid);
get_offsets (); /* Get text, data & bss offsets. */
@@ -1976,7 +2228,7 @@ remote_start_remote (struct ui_out *uiout, void *dummy)
putpkt ("?"); /* Initiate a query from remote machine. */
immediate_quit--;
- remote_start_remote_dummy (uiout, dummy);
+ remote_start_remote_dummy (uiout, NULL);
}
/* Open a connection to a remote debugger.
@@ -2206,6 +2458,10 @@ remote_open_1 (char *name, int from_tty, struct target_ops *target,
unpush_target (target);
+ /* We're about to connect; assume that the target will be running
+ when we do so. */
+ remote_mark_running (target);
+
remote_desc = remote_serial_open (name);
if (!remote_desc)
perror_with_name (name);
@@ -2252,15 +2508,6 @@ remote_open_1 (char *name, int from_tty, struct target_ops *target,
which later probes to skip. */
remote_query_packet_info ();
- /* Without this, some commands which require an active target (such
- as kill) won't work. This variable serves (at least) double duty
- as both the pid of the target process (if it has such), and as a
- flag indicating that a target is active. These functions should
- be split out into seperate variables, especially since GDB will
- someday have a notion of debugging several processes. */
-
- inferior_ptid = pid_to_ptid (MAGIC_NULL_PID);
-
if (async_p)
{
/* With this target we start out by owning the terminal. */
@@ -2304,7 +2551,8 @@ remote_open_1 (char *name, int from_tty, struct target_ops *target,
function. See cli-dump.c. */
{
struct gdb_exception ex
- = catch_exception (uiout, remote_start_remote, NULL, RETURN_MASK_ALL);
+ = catch_exception (uiout, remote_start_remote,
+ extended_p ? target : NULL, RETURN_MASK_ALL);
if (ex.reason < 0)
{
pop_target ();
@@ -2324,10 +2572,14 @@ remote_open_1 (char *name, int from_tty, struct target_ops *target,
getpkt (&rs->buf, &rs->buf_size, 0);
}
- post_create_inferior (&current_target, from_tty);
+ /* If we connected to a live target, do some additional setup. */
+ if (target_has_execution)
+ {
+ post_create_inferior (&current_target, from_tty);
- if (exec_bfd) /* No use without an exec file. */
- remote_check_symbols (symfile_objfile);
+ if (exec_bfd) /* No use without an exec file. */
+ remote_check_symbols (symfile_objfile);
+ }
}
/* This takes a program previously attached to and detaches it. After
@@ -2336,13 +2588,16 @@ remote_open_1 (char *name, int from_tty, struct target_ops *target,
die when it hits one. */
static void
-remote_detach (char *args, int from_tty)
+remote_detach_1 (char *args, int from_tty, int extended)
{
struct remote_state *rs = get_remote_state ();
if (args)
error (_("Argument given to \"detach\" when remotely debugging."));
+ if (!target_has_execution)
+ error (_("No process to detach from."));
+
/* Tell the remote target to detach. */
strcpy (rs->buf, "D");
remote_send (&rs->buf, &rs->buf_size);
@@ -2352,27 +2607,108 @@ remote_detach (char *args, int from_tty)
serial_async (remote_desc, NULL, 0);
target_mourn_inferior ();
+
if (from_tty)
- puts_filtered ("Ending remote debugging.\n");
+ {
+ if (extended)
+ puts_filtered ("Detached from remote process.\n");
+ else
+ puts_filtered ("Ending remote debugging.\n");
+ }
+}
+
+static void
+remote_detach (char *args, int from_tty)
+{
+ remote_detach_1 (args, from_tty, 0);
+}
+
+static void
+extended_remote_detach (char *args, int from_tty)
+{
+ remote_detach_1 (args, from_tty, 1);
}
/* Same as remote_detach, but don't send the "D" packet; just disconnect. */
static void
-remote_disconnect (char *args, int from_tty)
+remote_disconnect (struct target_ops *target, char *args, int from_tty)
{
if (args)
- error (_("Argument given to \"detach\" when remotely debugging."));
+ error (_("Argument given to \"disconnect\" when remotely debugging."));
/* Unregister the file descriptor from the event loop. */
if (target_is_async_p ())
serial_async (remote_desc, NULL, 0);
- target_mourn_inferior ();
+ /* Make sure we unpush even the extended remote targets; mourn
+ won't do it. So call remote_mourn_1 directly instead of
+ target_mourn_inferior. */
+ remote_mourn_1 (target);
+
if (from_tty)
puts_filtered ("Ending remote debugging.\n");
}
+/* Attach to the process specified by ARGS. If FROM_TTY is non-zero,
+ be chatty about it. */
+
+static void
+extended_remote_attach_1 (struct target_ops *target, char *args, int from_tty)
+{
+ struct remote_state *rs = get_remote_state ();
+ pid_t pid;
+ char *dummy, *buf;
+
+ if (!args)
+ error_no_arg (_("process-id to attach"));
+
+ 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."), args);
+
+ if (remote_protocol_packets[PACKET_vAttach].support == PACKET_DISABLE)
+ error (_("This target does not support attaching to a process"));
+
+ buf = alloca (rs->remote_packet_size);
+ sprintf (buf, "vAttach;%x", pid);
+ putpkt (buf);
+ getpkt (&rs->buf, &rs->buf_size, 0);
+
+ if (packet_ok (buf, &remote_protocol_packets[PACKET_vAttach]) == PACKET_OK)
+ {
+ if (from_tty)
+ printf_unfiltered (_("Attached to %s\n"),
+ target_pid_to_str (pid_to_ptid (pid)));
+
+ /* We have a wait response. We could reuse it, which is a FIXME,
+ but for now just request the target to send it again. */
+ putpkt ("?");
+ }
+ else if (remote_protocol_packets[PACKET_vAttach].support == PACKET_DISABLE)
+ error (_("This target does not support attaching to a process"));
+ else
+ error (_("Attaching to %s failed"),
+ target_pid_to_str (pid_to_ptid (pid)));
+
+ remote_mark_running (target);
+ inferior_ptid = pid_to_ptid (pid);
+}
+
+static void
+extended_remote_attach (char *args, int from_tty)
+{
+ extended_remote_attach_1 (&extended_remote_ops, args, from_tty);
+}
+
+static void
+extended_async_remote_attach (char *args, int from_tty)
+{
+ extended_remote_attach_1 (&extended_async_remote_ops, args, from_tty);
+}
+
/* Convert hex digit A to a number. */
static int
@@ -2843,6 +3179,7 @@ remote_wait (ptid_t ptid, struct target_waitstatus *status)
char *buf = rs->buf;
ULONGEST thread_num = -1;
ULONGEST addr;
+ int solibs_changed = 0;
status->kind = TARGET_WAITKIND_EXITED;
status->value.integer = 0;
@@ -2926,6 +3263,30 @@ Packet: '%s'\n"),
p = unpack_varlen_hex (++p1, &addr);
remote_watch_data_address = (CORE_ADDR)addr;
}
+ else if (strncmp (p, "load", p1 - p) == 0)
+ {
+ p1++;
+ p_temp = p1;
+ while (*p_temp && *p_temp != ';')
+ p_temp++;
+
+ parse_load_response (p1, p_temp, 1);
+
+ solibs_changed = 1;
+ p = p_temp;
+ }
+ else if (strncmp (p, "unload", p1 - p) == 0)
+ {
+ p1++;
+ p_temp = p1;
+ while (*p_temp && *p_temp != ';')
+ p_temp++;
+
+ parse_load_response (p1, p_temp, 0);
+
+ solibs_changed = 1;
+ p = p_temp;
+ }
else
{
/* Silently skip unknown optional info. */
@@ -3017,6 +3378,9 @@ Packet: '%s'\n"),
}
}
got_status:
+ if (solibs_changed)
+ status->kind = TARGET_WAITKIND_LOADED;
+
if (thread_num != -1)
{
return pid_to_ptid (thread_num);
@@ -4485,19 +4849,6 @@ remote_async_mourn (void)
remote_mourn_1 (&remote_async_ops);
}
-static void
-extended_remote_mourn (void)
-{
- /* We do _not_ want to mourn the target like this; this will
- remove the extended remote target from the target stack,
- and the next time the user says "run" it'll fail.
-
- FIXME: What is the right thing to do here? */
-#if 0
- remote_mourn_1 (&extended_remote_ops);
-#endif
-}
-
/* Worker function for remote_mourn. */
static void
remote_mourn_1 (struct target_ops *target)
@@ -4506,55 +4857,167 @@ remote_mourn_1 (struct target_ops *target)
generic_mourn_inferior ();
}
-/* In the extended protocol we want to be able to do things like
- "run" and have them basically work as expected. So we need
- a special create_inferior function.
+static void
+extended_remote_mourn_1 (struct target_ops *target)
+{
+ struct remote_state *rs = get_remote_state ();
+ char *buf = alloca (rs->remote_packet_size);
- FIXME: One day add support for changing the exec file
- we're debugging, arguments and an environment. */
+ /* Unlike "target remote", we do not want to unpush the target; then
+ the next time the user says "run", we won't be connected. */
+
+ /* Call common code to mark the inferior as not running. */
+ generic_mourn_inferior ();
+
+ /* Check whether the target is running now - some remote stubs
+ automatically restart after kill. */
+ putpkt ("?");
+ getpkt (&rs->buf, &rs->buf_size, 0);
+
+ if (buf[0] == 'S' || buf[0] == 'T')
+ {
+ /* Assume that the target has been restarted. Set inferior_ptid
+ so that bits of core GDB realizes there's something here, e.g.,
+ so that the user can say "kill" again. */
+ inferior_ptid = pid_to_ptid (MAGIC_NULL_PID);
+ }
+ else
+ {
+ /* Mark this (still pushed) target as not executable until we
+ restart it. */
+ remote_mark_killed (target);
+ }
+}
static void
-extended_remote_create_inferior (char *exec_file, char *args,
- char **env, int from_tty)
+extended_remote_mourn (void)
{
- /* Rip out the breakpoints; we'll reinsert them after restarting
- the remote server. */
- remove_breakpoints ();
+ extended_remote_mourn_1 (&extended_remote_ops);
+}
- /* Now restart the remote server. */
- extended_remote_restart ();
+static void
+extended_async_remote_mourn (void)
+{
+ extended_remote_mourn_1 (&extended_async_remote_ops);
+}
+
+int
+extended_remote_run (char *args)
+{
+ struct remote_state *rs = get_remote_state ();
+ char *buf, *p;
+ int len;
- /* Now put the breakpoints back in. This way we're safe if the
- restart function works via a unix fork on the remote side. */
- insert_breakpoints ();
+ buf = alloca (rs->remote_packet_size);
- /* Clean up from the last time we were running. */
- clear_proceed_status ();
+ strcpy (buf, "vRun;");
+ len = strlen (buf);
+
+ if (strlen (remote_exec_file) * 2 + len >= rs->remote_packet_size)
+ error (_("Remote file name too long for run packet"));
+ len += 2 * bin2hex ((gdb_byte *) remote_exec_file, buf + len, 0);
+
+ if (*args)
+ {
+ struct cleanup *back_to;
+ int i;
+ char **argv;
+
+ argv = buildargv (args);
+ back_to = make_cleanup ((void (*) (void *)) freeargv, argv);
+ for (i = 0; argv[i] != NULL; i++)
+ {
+ if (strlen (argv[i]) * 2 + 1 + len >= rs->remote_packet_size)
+ error (_("Argument list too long for run packet"));
+ buf[len++] = ';';
+ len += 2 * bin2hex ((gdb_byte *) argv[i], buf + len, 0);
+ }
+ do_cleanups (back_to);
+ }
+
+ buf[len++] = '\0';
+
+ putpkt (buf);
+ getpkt (&rs->buf, &rs->buf_size, 0);
+
+ if (packet_ok (buf, &remote_protocol_packets[PACKET_vRun]) == PACKET_OK)
+ {
+ /* We have a wait response; we don't need it, though. All is well. */
+ return 0;
+ }
+ else if (remote_protocol_packets[PACKET_vRun].support == PACKET_DISABLE)
+ /* It wasn't disabled before, but it is now. */
+ return -1;
+ else
+ {
+ if (remote_exec_file == NULL)
+ error (_("Running the default executable on the remote target failed; "
+ "try \"set remote exec-file\"?"));
+ else
+ error (_("Running \"%s\" on the remote target failed"),
+ remote_exec_file);
+ }
}
-/* Async version of extended_remote_create_inferior. */
+/* In the extended protocol we want to be able to do things like
+ "run" and have them basically work as expected. So we need
+ a special create_inferior function.
+
+ FIXME: One day add support for an environment? */
+
static void
-extended_remote_async_create_inferior (char *exec_file, char *args,
- char **env, int from_tty)
+extended_remote_create_inferior_1 (char *exec_file, char *args,
+ char **env, int from_tty,
+ int async_p)
{
- /* Rip out the breakpoints; we'll reinsert them after restarting
- the remote server. */
- remove_breakpoints ();
-
/* If running asynchronously, register the target file descriptor
with the event loop. */
- if (target_can_async_p ())
+ if (async_p && target_can_async_p ())
target_async (inferior_event_handler, 0);
/* Now restart the remote server. */
- extended_remote_restart ();
+ if (remote_protocol_packets[PACKET_vRun].support == PACKET_DISABLE)
+ extended_remote_restart ();
+ else if (extended_remote_run (args) == -1)
+ {
+ /* vRun was not supported. Fail if we need it to do what the
+ user requested. */
+ if (remote_exec_file[0])
+ error (_("Remote target does not support \"set remote exec-file\""));
+ if (args[0])
+ error (_("Remote target does not support \"set args\" or run <ARGS>"));
+
+ /* Fall back to "R". */
+ extended_remote_restart ();
+ }
+
+ /* Now mark the inferior as running before we do anything else. */
+ inferior_ptid = pid_to_ptid (MAGIC_NULL_PID);
+ if (async_p)
+ remote_mark_running (&extended_async_remote_ops);
+ else
+ remote_mark_running (&extended_remote_ops);
- /* Now put the breakpoints back in. This way we're safe if the
- restart function works via a unix fork on the remote side. */
- insert_breakpoints ();
+ /* Get updated offsets, if the stub uses qOffsets. */
+ get_offsets ();
/* Clean up from the last time we were running. */
- clear_proceed_status ();
+ init_thread_list ();
+ init_wait_for_inferior ();
+}
+
+static void
+extended_remote_create_inferior (char *exec_file, char *args,
+ char **env, int from_tty)
+{
+ extended_remote_create_inferior_1 (exec_file, args, env, from_tty, 0);
+}
+
+static void
+extended_remote_async_create_inferior (char *exec_file, char *args,
+ char **env, int from_tty)
+{
+ extended_remote_create_inferior_1 (exec_file, args, env, from_tty, 1);
}
@@ -4803,7 +5266,7 @@ remote_check_watch_resources (int type, int cnt, int ot)
static int
remote_stopped_by_watchpoint (void)
{
- return remote_stopped_by_watchpoint_p;
+ return remote_stopped_by_watchpoint_p;
}
extern int stepped_after_stopped_by_watchpoint;
@@ -4921,7 +5384,7 @@ push_remote_target (char *name, int from_tty)
/* Table used by the crc32 function to calcuate the checksum. */
static unsigned long crc32_table[256] =
-{0, 0};
+ {0, 0};
static unsigned long
crc32 (unsigned char *buf, int len, unsigned int crc)
@@ -4950,10 +5413,10 @@ crc32 (unsigned char *buf, int len, unsigned int crc)
/* compare-sections command
- With no arguments, compares each loadable section in the exec bfd
- with the same memory range on the target, and reports mismatches.
- Useful for verifying the image on the target against the exec file.
- Depends on the target understanding the new "qCRC:" request. */
+With no arguments, compares each loadable section in the exec bfd
+with the same memory range on the target, and reports mismatches.
+Useful for verifying the image on the target against the exec file.
+Depends on the target understanding the new "qCRC:" request. */
/* FIXME: cagney/1999-10-26: This command should be broken down into a
target method (target verify memory) and generic version of the
@@ -5510,6 +5973,7 @@ Specify the serial device it is connected to\n\
remote_ops.to_xfer_partial = remote_xfer_partial;
remote_ops.to_rcmd = remote_rcmd;
remote_ops.to_get_thread_local_address = remote_get_thread_local_address;
+ remote_ops.to_get_shared_libraries = remote_get_shared_libraries;
remote_ops.to_available_features = available_features_from_target_object;
remote_ops.to_stratum = process_stratum;
remote_ops.to_has_all_memory = 1;
@@ -5538,6 +6002,8 @@ Specify the serial device it is connected to (e.g. /dev/ttya).",
extended_remote_ops.to_open = extended_remote_open;
extended_remote_ops.to_create_inferior = extended_remote_create_inferior;
extended_remote_ops.to_mourn_inferior = extended_remote_mourn;
+ extended_remote_ops.to_detach = extended_remote_detach;
+ extended_remote_ops.to_attach = extended_remote_attach;
}
static int
@@ -5591,9 +6057,9 @@ remote_async (void (*callback) (enum inferior_event_type event_type,
/* Target async and target extended-async.
- This are temporary targets, until it is all tested. Eventually
- async support will be incorporated int the usual 'remote'
- target. */
+This are temporary targets, until it is all tested. Eventually
+async support will be incorporated int the usual 'remote'
+target. */
static void
init_remote_async_ops (void)
@@ -5636,6 +6102,7 @@ Specify the serial device it is connected to (e.g. /dev/ttya).";
remote_async_ops.to_stop = remote_stop;
remote_async_ops.to_xfer_partial = remote_xfer_partial;
remote_async_ops.to_rcmd = remote_rcmd;
+ remote_async_ops.to_get_shared_libraries = remote_get_shared_libraries;
remote_async_ops.to_available_features
= available_features_from_target_object;
remote_async_ops.to_stratum = process_stratum;
@@ -5668,7 +6135,9 @@ init_extended_async_remote_ops (void)
Specify the serial device it is connected to (e.g. /dev/ttya).",
extended_async_remote_ops.to_open = extended_remote_async_open;
extended_async_remote_ops.to_create_inferior = extended_remote_async_create_inferior;
- extended_async_remote_ops.to_mourn_inferior = extended_remote_mourn;
+ extended_async_remote_ops.to_mourn_inferior = extended_async_remote_mourn;
+ extended_async_remote_ops.to_detach = extended_remote_detach;
+ extended_async_remote_ops.to_attach = extended_async_remote_attach;
}
static void
@@ -5890,6 +6359,15 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
"qGetTLSAddr", "get-thread-local-storage-address",
0, 0);
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_vAttach],
+ "vAttach", "attach", 0, 0);
+
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_vRun],
+ "vRun", "run", 0, 0);
+
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_qfDllInfo],
+ "qfDllInfo", "dll-info", 0, 0);
+
/* Keep the old ``set remote Z-packet ...'' working. Each individual
Z sub-packet has its own set and show commands, but users may
have sets to this variable in their .gdbinit files (or in their
@@ -5904,6 +6382,13 @@ packets."),
show_remote_protocol_Z_packet_cmd, /* FIXME: i18n: Use of remote protocol `Z' packets is %s. */
&remote_set_cmdlist, &remote_show_cmdlist);
+ remote_exec_file = xstrdup ("");
+ add_setshow_string_noescape_cmd ("exec-file", class_files,
+ &remote_exec_file, _("\
+Set the remote pathname for \"run\""), _("\
+Show the remote pathname for \"run\""), NULL, NULL, NULL,
+ &remote_set_cmdlist, &remote_show_cmdlist);
+
/* Eventually initialize fileio. See fileio.c */
initialize_remote_fileio (remote_set_cmdlist, remote_show_cmdlist);
}
diff --git a/gdb/solib-som.c b/gdb/solib-som.c
index 3d027ccf70c..8d1b943e905 100644
--- a/gdb/solib-som.c
+++ b/gdb/solib-som.c
@@ -623,6 +623,9 @@ som_current_sos (void)
paddr_nz (new->lm_info->tsd_start_addr));
#endif
+ new->addr_low = lmi->text_addr;
+ new->addr_high = lmi->text_end;
+
/* Link the new object onto the list. */
new->next = NULL;
*link_ptr = new;
diff --git a/gdb/solib-target.c b/gdb/solib-target.c
new file mode 100644
index 00000000000..8c60237d7df
--- /dev/null
+++ b/gdb/solib-target.c
@@ -0,0 +1,270 @@
+/* Definitions for targets which report shared library events.
+
+ Copyright (C) 2006
+ 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., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+#include "defs.h"
+#include "solist.h"
+#include "symtab.h"
+#include "symfile.h"
+#include "target.h"
+
+#include "gdb_string.h"
+
+struct lm_info
+{
+ CORE_ADDR textSeg, dataSeg;
+};
+
+static struct so_list *solib_start;
+static int solibs_fetched;
+
+static struct so_list *
+solib_target_current_sos (void)
+{
+ struct so_list *sop;
+ struct so_list *start = NULL;
+ struct so_list *last = NULL;
+
+ /* If we have not asked the target for the list of shared libraries
+ yet, do it now. */
+ if (!solibs_fetched)
+ {
+ solibs_fetched = 1;
+ target_get_shared_libraries ();
+ }
+
+ for (sop = solib_start; sop; sop = sop->next)
+ {
+ struct so_list *new;
+
+ /* Duplicate the recorded solib. */
+ new = XZALLOC (struct so_list);
+ strcpy (new->so_name, sop->so_name);
+ strcpy (new->so_original_name, sop->so_original_name);
+ new->lm_info = XMALLOC (struct lm_info);
+ *new->lm_info = *sop->lm_info;
+
+ /* Add it to the list. */
+ if (!start)
+ last = start = new;
+ else
+ {
+ last->next = new;
+ last = new;
+ }
+ }
+
+ return start;
+}
+
+static void
+solib_target_special_symbol_handling (void)
+{
+ /* Nothing needed. */
+}
+
+static void
+solib_target_solib_create_inferior_hook (void)
+{
+ /* Nothing needed. */
+}
+
+static void
+solib_target_clear_solib (void)
+{
+ struct so_list *sop, *next;
+
+ for (sop = solib_start; sop; sop = next)
+ {
+ next = sop->next;
+
+ free_so (sop);
+ }
+
+ solib_start = NULL;
+ solibs_fetched = 0;
+}
+
+static void
+solib_target_free_so (struct so_list *so)
+{
+ xfree (so->lm_info);
+}
+
+static void
+solib_target_relocate_section_addresses (struct so_list *so,
+ struct section_table *sec)
+{
+ int flags = bfd_get_section_flags (sec->bfd, sec->the_bfd_section);
+ CORE_ADDR offset;
+
+ offset = symfile_section_offset_from_segment (sec->bfd, sec->the_bfd_section,
+ so->lm_info->textSeg,
+ so->lm_info->dataSeg);
+
+ sec->addr += offset;
+ sec->endaddr += offset;
+
+ /* If we haven't set these yet, do so now. If this fails, we may waste some
+ cycles uselessly retrying it, but that is rare and harmless. */
+ if (so->addr_low == 0 && so->addr_high == 0)
+ {
+ CORE_ADDR text_len, data_len;
+
+ symfile_find_segment_lengths (sec->bfd, &text_len, &data_len);
+
+ if (text_len)
+ {
+ so->addr_low = so->lm_info->textSeg;
+ so->addr_high = so->addr_low + text_len;
+ }
+ else if (data_len)
+ {
+ so->addr_low = so->lm_info->dataSeg;
+ so->addr_high = so->addr_low + data_len;
+ }
+ }
+}
+
+static int
+solib_target_open_symbol_file_object (void *from_ttyp)
+{
+ /* We can't locate the main symbol file based on the target's
+ knowledge; the user has to specify it. */
+ return 0;
+}
+
+static int
+solib_target_in_dynsym_resolve_code (CORE_ADDR pc)
+{
+ /* Assume there isn't target dynsym resolution code. DLL targets
+ generally have only import stubs (which GDB treats as "PLT entries"),
+ and no runtime binding code. */
+ return 0;
+}
+
+static void
+solib_target_add_one_solib (char *soname, CORE_ADDR textSeg,
+ CORE_ADDR dataSeg)
+{
+ struct so_list *new_solib, *so;
+
+ /* We should already have queried the target for shared libraries
+ before this point. If we haven't, we may have just connected;
+ we'll be querying shortly. */
+ if (!solibs_fetched)
+ return;
+
+ /* Check for duplicates already on the list. This can happen, for
+ instance, if we are stopped at a DLL load event when we first
+ connect to a remote target: the DLL will already be in the
+ queried list, but also be reported by the initial wait. */
+ for (so = solib_start; so; so = so->next)
+ if (strcmp (so->so_name, soname) == 0
+ && so->lm_info->textSeg == textSeg
+ && so->lm_info->dataSeg == dataSeg)
+ return;
+
+ new_solib = XZALLOC (struct so_list);
+ strncpy (new_solib->so_name, soname, SO_NAME_MAX_PATH_SIZE - 1);
+ new_solib->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
+ strncpy (new_solib->so_original_name, soname, SO_NAME_MAX_PATH_SIZE - 1);
+ new_solib->so_original_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
+
+ new_solib->lm_info = XZALLOC (struct lm_info);
+ new_solib->lm_info->textSeg = textSeg;
+ new_solib->lm_info->dataSeg = dataSeg;
+
+ if (solib_start == NULL)
+ solib_start = new_solib;
+ else
+ {
+ so = solib_start;
+ while (so->next)
+ so = so->next;
+ so->next = new_solib;
+ }
+
+ /* We do not trigger symbol reading here; the target will do it,
+ after all load events have been processed. */
+}
+
+static void
+solib_target_remove_one_solib (char *soname, CORE_ADDR textSeg,
+ CORE_ADDR dataSeg)
+{
+ struct so_list **slot, *removed;
+
+ /* We should already have queried the target for shared libraries
+ before this point. If we haven't, we may have just connected;
+ we'll be querying shortly. */
+ if (!solibs_fetched)
+ return;
+
+ slot = &solib_start;
+ while (*slot)
+ {
+ if (textSeg != ~(CORE_ADDR) 0 && textSeg != (*slot)->lm_info->textSeg)
+ continue;
+ if (dataSeg != ~(CORE_ADDR) 0 && dataSeg != (*slot)->lm_info->dataSeg)
+ continue;
+ if (soname != NULL && strcmp (soname, (*slot)->so_name) != 0)
+ continue;
+ break;
+ }
+
+ if (*slot == NULL)
+ return;
+
+ removed = *slot;
+ *slot = removed->next;
+
+ free_so (removed);
+
+ /* We do not trigger symbol unloading here; the target will do it,
+ after all unload events have been processed. */
+}
+
+static struct target_so_ops solib_target_so_ops;
+
+extern initialize_file_ftype _initialize_solib_target; /* -Wmissing-prototypes */
+
+void
+_initialize_solib_target (void)
+{
+ solib_target_so_ops.relocate_section_addresses
+ = solib_target_relocate_section_addresses;
+ solib_target_so_ops.free_so = solib_target_free_so;
+ solib_target_so_ops.clear_solib = solib_target_clear_solib;
+ solib_target_so_ops.solib_create_inferior_hook
+ = solib_target_solib_create_inferior_hook;
+ solib_target_so_ops.special_symbol_handling
+ = solib_target_special_symbol_handling;
+ solib_target_so_ops.current_sos = solib_target_current_sos;
+ solib_target_so_ops.open_symbol_file_object
+ = solib_target_open_symbol_file_object;
+ solib_target_so_ops.in_dynsym_resolve_code
+ = solib_target_in_dynsym_resolve_code;
+ solib_target_so_ops.add_one_solib = solib_target_add_one_solib;
+ solib_target_so_ops.remove_one_solib = solib_target_remove_one_solib;
+
+ current_target_so_ops = &solib_target_so_ops;
+}
diff --git a/gdb/solib.c b/gdb/solib.c
index 1368227c638..d6a6f462660 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -85,6 +85,11 @@ static int solib_cleanup_queued = 0; /* make_run_cleanup called */
static void do_clear_solib (void *);
+/* If non-empty, this is a file extension that will be opened in place
+ of the file extension reported by the shared library list. */
+
+char *solib_symbols_extension;
+
/* 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. */
static char *solib_absolute_prefix = NULL;
@@ -145,7 +150,30 @@ solib_open (char *in_pathname, char **found_pathname)
struct target_so_ops *ops = solib_ops (current_gdbarch);
int found_file = -1;
char *temp_pathname = NULL;
- char *p = in_pathname;
+ char *p;
+
+ /* If solib-symbols-extension is set, replace the file's extension. */
+ if (solib_symbols_extension && *solib_symbols_extension)
+ {
+ p = in_pathname + strlen (in_pathname);
+ while (p > in_pathname && *p != '.')
+ p--;
+
+ if (*p == '.')
+ {
+ char *new_pathname;
+
+ new_pathname = alloca (p - in_pathname + 1
+ + strlen (solib_symbols_extension) + 1);
+ memcpy (new_pathname, in_pathname, p - in_pathname + 1);
+ strcpy (new_pathname + (p - in_pathname) + 1,
+ solib_symbols_extension);
+
+ in_pathname = new_pathname;
+ }
+ }
+
+ p = in_pathname;
while (*p && !IS_DIR_SEPARATOR (*p))
p++;
@@ -314,9 +342,14 @@ solib_map_sections (void *arg)
object's file by the base address to which the object was actually
mapped. */
ops->relocate_section_addresses (so, p);
- if (strcmp (p->the_bfd_section->name, ".text") == 0)
+
+ /* If the target didn't provide information about the address range
+ of the DLL, assume we want the location of the .text section. */
+ if (so->addr_low == 0 && so->addr_high == 0
+ && strcmp (p->the_bfd_section->name, ".text") == 0)
{
- so->textsection = p;
+ so->addr_low = p->addr;
+ so->addr_high = p->endaddr;
}
}
@@ -716,15 +749,15 @@ info_sharedlibrary_command (char *ignore, int from_tty)
}
printf_unfiltered ("%-*s", addr_width,
- so->textsection != NULL
+ so->addr_high != 0
? hex_string_custom (
- (LONGEST) so->textsection->addr,
+ (LONGEST) so->addr_low,
addr_width - 4)
: "");
printf_unfiltered ("%-*s", addr_width,
- so->textsection != NULL
+ so->addr_high != 0
? hex_string_custom (
- (LONGEST) so->textsection->endaddr,
+ (LONGEST) so->addr_high,
addr_width - 4)
: "");
printf_unfiltered ("%-12s", so->symbols_loaded ? "Yes" : "No");
diff --git a/gdb/solib.h b/gdb/solib.h
index 7469d125e7b..4ed69d354e0 100644
--- a/gdb/solib.h
+++ b/gdb/solib.h
@@ -27,6 +27,10 @@
struct so_list;
struct target_ops;
+/* An alternate extension for symbol files. */
+
+extern char *solib_symbols_extension;
+
/* Called when we free all symtabs, to free the shared library information
as well. */
diff --git a/gdb/solist.h b/gdb/solist.h
index 1ac306af7a5..79ec0a765ab 100644
--- a/gdb/solist.h
+++ b/gdb/solist.h
@@ -65,7 +65,11 @@ struct so_list
struct objfile *objfile; /* objfile for loaded lib */
struct section_table *sections;
struct section_table *sections_end;
- struct section_table *textsection;
+
+ /* Record the range of addresses belonging to this shared library.
+ There may not be just one (e.g. if two segments are relocated
+ differently); but this is only used for "info sharedlibrary". */
+ CORE_ADDR addr_low, addr_high;
};
struct target_so_ops
@@ -104,7 +108,11 @@ struct target_so_ops
Convenience function for remote debuggers finding host libs. */
int (*find_and_open_solib) (char *soname,
unsigned o_flags, char **temp_pathname);
-
+
+ void (*add_one_solib) (char *soname, CORE_ADDR textSeg,
+ CORE_ADDR dataSeg);
+ void (*remove_one_solib) (char *soname, CORE_ADDR textSeg,
+ CORE_ADDR dataSeg);
};
/* Free the memory associated with a (so_list *). */
diff --git a/gdb/symbian-tdep.c b/gdb/symbian-tdep.c
new file mode 100644
index 00000000000..9875430bfc1
--- /dev/null
+++ b/gdb/symbian-tdep.c
@@ -0,0 +1,32 @@
+/* SymbianOS specific target support.
+
+ Copyright (C) 2006
+ 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., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+#include "defs.h"
+#include "solib.h"
+
+void _initialize_symbian_tdep (void);
+
+void
+_initialize_symbian_tdep (void)
+{
+ solib_symbols_extension = xstrdup ("SYM");
+}
diff --git a/gdb/symfile.c b/gdb/symfile.c
index a4c883be12f..05c0c8f7236 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -145,6 +145,8 @@ static char *find_separate_debug_file (struct objfile *objfile);
static void init_filename_language_table (void);
+static void symfile_find_segment_sections (struct objfile *objfile);
+
void _initialize_symfile (void);
/* List of all available sym_fns. On gdb startup, each object file reader
@@ -429,12 +431,19 @@ init_objfile_sect_indices (struct objfile *objfile)
/* This is where things get really weird... We MUST have valid
indices for the various sect_index_* members or gdb will abort.
So if for example, there is no ".text" section, we have to
- accomodate that. Except when explicitly adding symbol files at
- some address, section_offsets contains nothing but zeros, so it
- doesn't matter which slot in section_offsets the individual
- sect_index_* members index into. So if they are all zero, it is
- safe to just point all the currently uninitialized indices to the
- first slot. */
+ accomodate that. First, check for a file with the standard
+ one or two segments. */
+
+ symfile_find_segment_sections (objfile);
+
+ /* Except when explicitly adding symbol files at some address,
+ section_offsets contains nothing but zeros, so it doesn't matter
+ which slot in section_offsets the individual sect_index_* members
+ index into. So if they are all zero, it is safe to just point
+ all the currently uninitialized indices to the first slot. But
+ beware: if this is the main executable, it may be relocated
+ later, e.g. by the remote qOffsets packet, and then this will
+ be wrong! That's why we try segments first. */
for (i = 0; i < objfile->num_sections; i++)
{
@@ -3723,6 +3732,226 @@ symfile_relocate_debug_section (bfd *abfd, asection *sectp, bfd_byte *buf)
return bfd_simple_get_relocated_section_contents (abfd, sectp, buf, NULL);
}
+/* FIXME: This should probably go through the symfile ops vector. */
+
+#include "elf/internal.h"
+#include "elf/common.h"
+
+static int
+symfile_find_segments (bfd *abfd, Elf_Internal_Phdr *text_segment,
+ Elf_Internal_Phdr *data_segment)
+{
+ Elf_Internal_Phdr *phdrs, *segments[2];
+ int num_phdrs, i, num_segments;
+ long phdrs_size;
+ asection *sect;
+ CORE_ADDR text_offset, data_offset;
+
+ phdrs_size = bfd_get_elf_phdr_upper_bound (abfd);
+ if (phdrs_size == -1)
+ return 0;
+
+ phdrs = alloca (phdrs_size);
+ num_phdrs = bfd_get_elf_phdrs (abfd, phdrs);
+ if (num_phdrs == -1)
+ return 0;
+
+ num_segments = 0;
+ for (i = 0; i < num_phdrs; i++)
+ if (phdrs[i].p_type == PT_LOAD)
+ {
+ if (num_segments == 2)
+ return 0;
+ segments[num_segments++] = &phdrs[i];
+ }
+
+ if (num_segments == 0)
+ return 0;
+
+ if (num_segments == 1)
+ {
+ if ((segments[0]->p_flags & PF_W) && !(segments[0]->p_flags & PF_X))
+ {
+ memset (text_segment, 0, sizeof (*text_segment));
+ *data_segment = *segments[0];
+ }
+ else
+ {
+ *text_segment = *segments[0];
+ memset (data_segment, 0, sizeof (*data_segment));
+ }
+ }
+ else
+ {
+ if ((segments[0]->p_flags & PF_X) && !(segments[1]->p_flags & PF_X))
+ {
+ *text_segment = *segments[0];
+ *data_segment = *segments[1];
+ }
+ else if ((segments[1]->p_flags & PF_X) && !(segments[0]->p_flags & PF_X))
+ {
+ *text_segment = *segments[1];
+ *data_segment = *segments[0];
+ }
+ else if ((segments[1]->p_flags & PF_W) && !(segments[0]->p_flags & PF_W))
+ {
+ *text_segment = *segments[0];
+ *data_segment = *segments[1];
+ }
+ else if ((segments[0]->p_flags & PF_W) && !(segments[1]->p_flags & PF_W))
+ {
+ *text_segment = *segments[1];
+ *data_segment = *segments[0];
+ }
+ else
+ return 0;
+ }
+
+ return 1;
+}
+
+int
+symfile_map_offsets_to_segments (struct objfile *objfile,
+ struct section_offsets *offsets,
+ CORE_ADDR text_addr, CORE_ADDR data_addr)
+{
+ Elf_Internal_Phdr text_segment, data_segment;
+ bfd *abfd = objfile->obfd;
+ int i;
+ asection *sect;
+ CORE_ADDR text_offset, data_offset;
+
+ if (symfile_find_segments (abfd, &text_segment, &data_segment) == 0)
+ return 0;
+
+ text_offset = text_addr - text_segment.p_vaddr;
+ data_offset = data_addr - data_segment.p_vaddr;
+
+ for (i = 0, sect = abfd->sections; sect != NULL; i++, sect = sect->next)
+ {
+ CORE_ADDR vma;
+
+ if ((bfd_get_section_flags (abfd, sect) & SEC_LOAD) == 0)
+ continue;
+
+ vma = bfd_get_section_vma (abfd, sect);
+
+ if (text_segment.p_memsz
+ && vma >= text_segment.p_vaddr
+ && vma < text_segment.p_vaddr + text_segment.p_memsz)
+ offsets->offsets[i] = text_offset;
+
+ else if (data_segment.p_memsz
+ && vma >= data_segment.p_vaddr
+ && vma < data_segment.p_vaddr + data_segment.p_memsz)
+ offsets->offsets[i] = data_offset;
+
+ else
+ warning (_("Loadable segment \"%s\" outside of ELF segments"),
+ bfd_section_name (abfd, sect));
+ }
+
+ return 1;
+}
+
+CORE_ADDR
+symfile_section_offset_from_segment (bfd *abfd, asection *sect,
+ CORE_ADDR text_addr, CORE_ADDR data_addr)
+{
+ Elf_Internal_Phdr text_segment, data_segment;
+ CORE_ADDR text_offset, data_offset, vma;
+
+ if (symfile_find_segments (abfd, &text_segment, &data_segment) == 0)
+ return 0;
+
+ text_offset = text_addr - text_segment.p_vaddr;
+ data_offset = data_addr - data_segment.p_vaddr;
+
+ if ((bfd_get_section_flags (abfd, sect) & SEC_LOAD) == 0)
+ return 0;
+
+ vma = bfd_get_section_vma (abfd, sect);
+
+ if (text_segment.p_memsz
+ && vma >= text_segment.p_vaddr
+ && vma < text_segment.p_vaddr + text_segment.p_memsz)
+ return text_offset;
+
+ else if (data_segment.p_memsz
+ && vma >= data_segment.p_vaddr
+ && vma < data_segment.p_vaddr + data_segment.p_memsz)
+ return data_offset;
+
+ else
+ {
+ warning (_("Loadable segment \"%s\" outside of ELF segments"),
+ bfd_section_name (abfd, sect));
+ return 0;
+ }
+}
+
+static void
+symfile_find_segment_sections (struct objfile *objfile)
+{
+ Elf_Internal_Phdr text_segment, data_segment;
+ bfd *abfd = objfile->obfd;
+ int i;
+ asection *sect;
+
+ if (symfile_find_segments (abfd, &text_segment, &data_segment) == 0)
+ return;
+
+ for (i = 0, sect = abfd->sections; sect != NULL; i++, sect = sect->next)
+ {
+ CORE_ADDR vma;
+
+ if ((bfd_get_section_flags (abfd, sect) & SEC_LOAD) == 0)
+ continue;
+
+ vma = bfd_get_section_vma (abfd, sect);
+
+ if (text_segment.p_memsz
+ && vma >= text_segment.p_vaddr
+ && vma < text_segment.p_vaddr + text_segment.p_memsz)
+ {
+ if (objfile->sect_index_text == -1)
+ objfile->sect_index_text = sect->index;
+
+ if (objfile->sect_index_rodata == -1)
+ objfile->sect_index_rodata = sect->index;
+ }
+
+ else if (data_segment.p_memsz
+ && vma >= data_segment.p_vaddr
+ && vma < data_segment.p_vaddr + data_segment.p_memsz)
+ {
+ if (objfile->sect_index_data == -1)
+ objfile->sect_index_data = sect->index;
+
+ if (objfile->sect_index_bss == -1)
+ objfile->sect_index_bss = sect->index;
+ }
+ }
+}
+
+void
+symfile_find_segment_lengths (bfd *abfd, CORE_ADDR *text_len,
+ CORE_ADDR *data_len)
+{
+ Elf_Internal_Phdr text_segment, data_segment;
+
+ if (symfile_find_segments (abfd, &text_segment, &data_segment) == 0)
+ {
+ *text_len = 0;
+ *data_len = 0;
+ }
+ else
+ {
+ *text_len = text_segment.p_memsz;
+ *data_len = data_segment.p_memsz;
+ }
+}
+
void
_initialize_symfile (void)
{
diff --git a/gdb/symfile.h b/gdb/symfile.h
index 10361e795d9..13dc4d7526a 100644
--- a/gdb/symfile.h
+++ b/gdb/symfile.h
@@ -319,6 +319,15 @@ extern void symbol_file_clear (int from_tty);
extern bfd_byte *symfile_relocate_debug_section (bfd *abfd, asection *sectp,
bfd_byte * buf);
+extern int symfile_map_offsets_to_segments (struct objfile *,
+ struct section_offsets *,
+ CORE_ADDR, CORE_ADDR);
+
+extern CORE_ADDR symfile_section_offset_from_segment (bfd *, asection *,
+ CORE_ADDR, CORE_ADDR);
+
+extern void symfile_find_segment_lengths (bfd *, CORE_ADDR *, CORE_ADDR *);
+
/* From dwarfread.c */
extern void dwarf_build_psymtabs (struct objfile *, int, file_ptr,
diff --git a/gdb/target.c b/gdb/target.c
index 4e0b997179f..d488c194825 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -97,8 +97,6 @@ static void debug_to_attach (char *, int);
static void debug_to_detach (char *, int);
-static void debug_to_disconnect (char *, int);
-
static void debug_to_resume (ptid_t, int, enum target_signal);
static ptid_t debug_to_wait (ptid_t, struct target_waitstatus *);
@@ -366,7 +364,7 @@ maybe_kill_then_create_inferior (char *exec, char *args, char **env,
locally search the target stack for the target that can handle the
request. */
-static void
+void
update_current_target (void)
{
struct target_ops *t;
@@ -388,7 +386,7 @@ update_current_target (void)
INHERIT (to_attach, t);
INHERIT (to_post_attach, t);
INHERIT (to_detach, t);
- INHERIT (to_disconnect, t);
+ /* Do not inherit to_disconnect. */
INHERIT (to_resume, t);
INHERIT (to_wait, t);
INHERIT (to_fetch_registers, t);
@@ -458,6 +456,7 @@ update_current_target (void)
INHERIT (to_make_corefile_notes, t);
INHERIT (to_get_thread_local_address, t);
/* Do not inherit to_available_features. */
+ /* Do not inherit to_get_shared_libraries. */
INHERIT (to_magic, t);
}
#undef INHERIT
@@ -484,9 +483,6 @@ update_current_target (void)
de_fault (to_detach,
(void (*) (char *, int))
target_ignore);
- de_fault (to_disconnect,
- (void (*) (char *, int))
- tcomplain);
de_fault (to_resume,
(void (*) (ptid_t, int, enum target_signal))
noprocess);
@@ -1535,7 +1531,19 @@ target_detach (char *args, int from_tty)
void
target_disconnect (char *args, int from_tty)
{
- (current_target.to_disconnect) (args, from_tty);
+ struct target_ops *t;
+
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
+ if (t->to_disconnect != NULL)
+ {
+ if (targetdebug)
+ fprintf_unfiltered (gdb_stdlog, "target_disconnect (%s, %d)\n",
+ args, from_tty);
+ t->to_disconnect (t, args, from_tty);
+ return;
+ }
+
+ tcomplain ();
}
int
@@ -1594,6 +1602,27 @@ target_available_features (struct target_ops *target, struct obstack *obstack)
}
/* Look through the list of possible targets for a target that can
+ fetch shared libraries. */
+
+void
+target_get_shared_libraries (void)
+{
+ struct target_ops *t;
+
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
+ {
+ if (t->to_get_shared_libraries != NULL)
+ {
+ t->to_get_shared_libraries (t);
+ break;
+ }
+ }
+
+ if (targetdebug)
+ fprintf_unfiltered (gdb_stdlog, "target_get_shared_libraries ()\n");
+}
+
+/* Look through the list of possible targets for a target that can
execute a run or attach command without any other data. This is
used to locate the default process stratum.
@@ -1974,15 +2003,6 @@ debug_to_detach (char *args, int from_tty)
}
static void
-debug_to_disconnect (char *args, int from_tty)
-{
- debug_target.to_disconnect (args, from_tty);
-
- fprintf_unfiltered (gdb_stdlog, "target_disconnect (%s, %d)\n",
- args, from_tty);
-}
-
-static void
debug_to_resume (ptid_t ptid, int step, enum target_signal siggnal)
{
debug_target.to_resume (ptid, step, siggnal);
@@ -2588,7 +2608,6 @@ setup_target_debug (void)
current_target.to_attach = debug_to_attach;
current_target.to_post_attach = debug_to_post_attach;
current_target.to_detach = debug_to_detach;
- current_target.to_disconnect = debug_to_disconnect;
current_target.to_resume = debug_to_resume;
current_target.to_wait = debug_to_wait;
current_target.to_fetch_registers = debug_to_fetch_registers;
@@ -2636,7 +2655,6 @@ setup_target_debug (void)
current_target.to_enable_exception_callback = debug_to_enable_exception_callback;
current_target.to_get_current_exception_event = debug_to_get_current_exception_event;
current_target.to_pid_to_exec_file = debug_to_pid_to_exec_file;
-
}
diff --git a/gdb/target.h b/gdb/target.h
index f7203abbbf4..86a34a89cc3 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -328,7 +328,7 @@ struct target_ops
void (*to_attach) (char *, int);
void (*to_post_attach) (int);
void (*to_detach) (char *, int);
- void (*to_disconnect) (char *, int);
+ void (*to_disconnect) (struct target_ops *, char *, int);
void (*to_resume) (ptid_t, int, enum target_signal);
ptid_t (*to_wait) (ptid_t, struct target_waitstatus *);
void (*to_fetch_registers) (int);
@@ -456,6 +456,9 @@ struct target_ops
struct gdb_feature_set *(*to_available_features) (struct target_ops *ops,
struct obstack *obstack);
+ /* Refresh the list of shared libraries. */
+ void (*to_get_shared_libraries) (struct target_ops *ops);
+
int to_magic;
/* Need sub-structure for target machine related rather than comm related?
*/
@@ -897,11 +900,9 @@ int target_follow_fork (int follow_child);
(current_target.to_has_registers)
/* Does the target have execution? Can we make it jump (through
- hoops), or pop its stack a few times? FIXME: If this is to work that
- way, it needs to check whether an inferior actually exists.
- remote-udi.c and probably other targets can be the current target
- when the inferior doesn't actually exist at the moment. Right now
- this just tells us whether this target is *capable* of execution. */
+ hoops), or pop its stack a few times? This used to mean the target
+ was capable of execution; now it means that a program is actually
+ running. */
#define target_has_execution \
(current_target.to_has_execution)
@@ -1133,6 +1134,10 @@ extern struct gdb_feature_set *target_available_features (struct target_ops *,
#define RESUME_EXECD_VFORKING_CHILD_TO_GET_PARENT_VFORK() (0)
#endif
+/* Refresh the list of shared libraries from the target. */
+
+extern void target_get_shared_libraries (void);
+
/* Routines for maintenance of the target structures...
add_target: Add a target to the list of all possible targets.
@@ -1158,6 +1163,11 @@ extern void target_preopen (int);
extern void pop_target (void);
+/* Update current_target after some target on the current stack has
+ changed state. */
+
+extern void update_current_target (void);
+
/* Struct section_table maps address ranges to file sections. It is
mostly used with BFD files, but can be used without (e.g. for handling
raw disks, or files not in formats handled by BFD). */
diff --git a/gdb/testsuite/gdb.base/define.exp b/gdb/testsuite/gdb.base/define.exp
index a13d886e9f1..b3c811043e1 100644
--- a/gdb/testsuite/gdb.base/define.exp
+++ b/gdb/testsuite/gdb.base/define.exp
@@ -324,7 +324,7 @@ gdb_expect {
# This is a quasi-define command: Verify that the user can redefine
# GDB's gdb_prompt.
#
-send_gdb "set prompt \\(blah\\) \n"
+send_gdb "set prompt (blah) \n"
gdb_expect {
-re "\\(blah\\) $"\
{pass "set gdb_prompt"}
@@ -333,7 +333,7 @@ gdb_expect {
timeout {fail "(timeout) set gdb_prompt"}
}
-send_gdb "set prompt \\(gdb\\) \n"
+send_gdb "set prompt (gdb) \n"
gdb_expect {
-re "$gdb_prompt $"\
{pass "reset gdb_prompt"}
diff --git a/readline/emacs_keymap.c b/readline/emacs_keymap.c
index ca9d1343b65..cbacb0309af 100644
--- a/readline/emacs_keymap.c
+++ b/readline/emacs_keymap.c
@@ -278,7 +278,11 @@ KEYMAP_ENTRY_ARRAY emacs_standard_keymap = {
{ ISFUNC, rl_insert }, /* Latin capital letter Y with acute */
{ ISFUNC, rl_insert }, /* Latin capital letter thorn (Icelandic) */
{ ISFUNC, rl_insert }, /* Latin small letter sharp s (German) */
+#ifndef __MINGW32__
{ ISFUNC, rl_insert }, /* Latin small letter a with grave */
+#else
+ { ISFUNC, 0 }, /* Must leave this unbound for the arrow keys to work. */
+#endif
{ ISFUNC, rl_insert }, /* Latin small letter a with acute */
{ ISFUNC, rl_insert }, /* Latin small letter a with circumflex */
{ ISFUNC, rl_insert }, /* Latin small letter a with tilde */
diff --git a/readline/readline.c b/readline/readline.c
index 07fb58fd210..3ba5cf00cac 100644
--- a/readline/readline.c
+++ b/readline/readline.c
@@ -869,19 +869,10 @@ bind_arrow_keys_internal (map)
#endif
#ifdef __MINGW32__
- /* Under Windows, when an extend key (like an arrow key) is
- pressed, getch() will return 340 (octal) followed by a code for
- the extended key. We use macros to transform those into the
- normal ANSI terminal sequences for these keys. */
-
- /* Up arrow. */
- rl_macro_bind ("\340H", "\033[A", map);
- /* Left arrow. */
- rl_macro_bind ("\340K", "\033[D", map);
- /* Right arrow. */
- rl_macro_bind ("\340M", "\033[C", map);
- /* Down arrow. */
- rl_macro_bind ("\340P", "\033[B", map);
+ _rl_bind_if_unbound ("\340H", rl_get_previous_history);
+ _rl_bind_if_unbound ("\340P", rl_get_next_history);
+ _rl_bind_if_unbound ("\340M", rl_forward_char);
+ _rl_bind_if_unbound ("\340K", rl_backward_char);
#endif
_rl_bind_if_unbound ("\033[A", rl_get_previous_history);