displaced_step_closure is a type defined in multiple -tdep.c files.
Trying to xfree it from the common code (infrun.c) is a problem when we
try to poison xfree for non-POD types. Because there can be multiple of
these types in the same build, this patch makes a hierarchy of classes
with a virtual destructor. When the common code deletes the object
through a displaced_step_closure pointer, it will invoke the right
destructor.
The amd64 used a last-member array with a variable size. That doesn't
work with new, so I changed it for an std::vector. Other architectures
which used a simple byte buffer as a closure now use a shared
buf_displaced_step_closure, a closure type that only contains a
gdb::byte_vector.
Reg-tested on the buildbot.
gdb/ChangeLog:
* infrun.h: Include common/byte-vector.h.
(struct displaced_step_closure): New struct.
(struct buf_displaced_step_closure): New struct.
* infrun.c (displaced_step_closure::~displaced_step_closure):
Provide default implementation.
(displaced_step_clear): Deallocate step closure with delete.
* aarch64-tdep.c (displaced_step_closure): Rename to ...
(aarch64_displaced_step_closure): ... this, extend
displaced_step_closure.
(aarch64_displaced_step_data) <dsc>: Change type to
aarch64_displaced_step_closure.
(aarch64_displaced_step_copy_insn): Adjust to type change, use
unique_ptr.
(aarch64_displaced_step_fixup): Add cast for displaced step
closure.
* amd64-tdep.c (displaced_step_closure): Rename to ...
(amd64_displaced_step_closure): ... this, extend
displaced_step_closure.
<insn_buf>: Change type to std::vector<gdb_byte>.
<max_len>: Remove.
(fixup_riprel): Change type of DSC parameter, adjust to type
change of insn_buf.
(fixup_displaced_copy): Change type of DSC parameter.
(amd64_displaced_step_copy_insn): Instantiate
amd64_displaced_step_closure.
(amd64_displaced_step_fixup): Add cast for closure type, adjust
to type change of insn_buf.
* arm-linux-tdep.c (arm_linux_cleanup_svc): Change type of
parameter DSC.
(arm_linux_copy_svc): Likewise.
(cleanup_kernel_helper_return): Likewise.
(arm_catch_kernel_helper_return): Likewise.
(arm_linux_displaced_step_copy_insn): Instantiate
arm_displaced_step_closure.
* arm-tdep.c (arm_pc_is_thumb): Add cast for closure.
(displaced_read_reg): Change type of parameter DSC.
(branch_write_pc): Likewise.
(load_write_pc): Likewise.
(alu_write_pc): Likewise.
(displaced_write_reg): Likewise.
(arm_copy_unmodified): Likewise.
(thumb_copy_unmodified_32bit): Likewise.
(thumb_copy_unmodified_16bit): Likewise.
(cleanup_preload): Likewise.
(install_preload): Likewise.
(arm_copy_preload): Likewise.
(thumb2_copy_preload): Likewise.
(install_preload_reg): Likewise.
(arm_copy_preload_reg): Likewise.
(cleanup_copro_load_store): Likewise.
(install_copro_load_store): Likewise.
(arm_copy_copro_load_store) Likewise.
(thumb2_copy_copro_load_store): Likewise.
(cleanup_branch): Likewise.
(install_b_bl_blx): Likewise.
(arm_copy_b_bl_blx): Likewise.
(thumb2_copy_b_bl_blx): Likewise.
(thumb_copy_b): Likewise.
(install_bx_blx_reg): Likewise.
(arm_copy_bx_blx_reg): Likewise.
(thumb_copy_bx_blx_reg): Likewise.
(cleanup_alu_imm): Likewise.
(arm_copy_alu_imm): Likewise.
(thumb2_copy_alu_imm): Likewise.
(cleanup_alu_reg): Likewise.
(install_alu_reg): Likewise.
(arm_copy_alu_reg): Likewise.
(thumb_copy_alu_reg): Likewise.
(cleanup_alu_shifted_reg): Likewise.
(install_alu_shifted_reg): Likewise.
(arm_copy_alu_shifted_reg): Likewise.
(cleanup_load): Likewise.
(cleanup_store): Likewise.
(arm_copy_extra_ld_st): Likewise.
(install_load_store): Likewise.
(thumb2_copy_load_literal): Likewise.
(thumb2_copy_load_reg_imm): Likewise.
(arm_copy_ldr_str_ldrb_strb): Likewise.
(cleanup_block_load_all): Likewise.
(cleanup_block_store_pc): Likewise.
(cleanup_block_load_pc): Likewise.
(arm_copy_block_xfer): Likewise.
(thumb2_copy_block_xfer): Likewise.
(cleanup_svc): Likewise.
(install_svc): Likewise.
(arm_copy_svc): Likewise.
(thumb_copy_svc): Likewise.
(arm_copy_undef): Likewise.
(thumb_32bit_copy_undef): Likewise.
(arm_copy_unpred): Likewise.
(arm_decode_misc_memhint_neon): Likewise.
(arm_decode_unconditional): Likewise.
(arm_decode_miscellaneous): Likewise.
(arm_decode_dp_misc): Likewise.
(arm_decode_ld_st_word_ubyte): Likewise.
(arm_decode_media): Likewise.
(arm_decode_b_bl_ldmstm): Likewise.
(arm_decode_ext_reg_ld_st): Likewise.
(thumb2_decode_dp_shift_reg): Likewise.
(thumb2_decode_ext_reg_ld_st): Likewise.
(arm_decode_svc_copro): Likewise.
(thumb2_decode_svc_copro): Likewise.
(install_pc_relative): Likewise.
(thumb_copy_pc_relative_16bit): Likewise.
(thumb_decode_pc_relative_16bit): Likewise.
(thumb_copy_pc_relative_32bit): Likewise.
(thumb_copy_16bit_ldr_literal): Likewise.
(thumb_copy_cbnz_cbz): Likewise.
(thumb2_copy_table_branch): Likewise.
(cleanup_pop_pc_16bit_all): Likewise.
(thumb_copy_pop_pc_16bit): Likewise.
(thumb_process_displaced_16bit_insn): Likewise.
(decode_thumb_32bit_ld_mem_hints): Likewise.
(thumb_process_displaced_32bit_insn): Likewise.
(thumb_process_displaced_insn): Likewise.
(arm_process_displaced_insn): Likewise.
(arm_displaced_init_closure): Likewise.
(arm_displaced_step_fixup): Add cast for closure.
* arm-tdep.h: Include infrun.h.
(displaced_step_closure): Rename to ...
(arm_displaced_step_closure): ... this, extend
displaced_step_closure.
<u::svc::copy_svc_os>: Change type of parameter DSC.
<cleanup>: Likewise.
(arm_process_displaced_insn): Likewise.
(arm_displaced_init_closure): Likewise.
(displaced_read_reg): Likewise.
(displaced_write_reg): Likewise.
* i386-linux-tdep.c (i386_linux_displaced_step_copy_insn):
Adjust.
* i386-tdep.h: Include infrun.h.
(i386_displaced_step_closure): New typedef.
* i386-tdep.c (i386_displaced_step_copy_insn): Use
i386_displaced_step_closure.
(i386_displaced_step_fixup): Adjust.
* rs6000-tdep.c (ppc_displaced_step_closure): New typedef.
(ppc_displaced_step_copy_insn): Use ppc_displaced_step_closure
and unique_ptr.
(ppc_displaced_step_fixup): Adjust.
* s390-linux-tdep.c (s390_displaced_step_closure): New typedef.
(s390_displaced_step_copy_insn): Use s390_displaced_step_closure
and unique_ptr.
(s390_displaced_step_fixup): Adjust.
If you want to use catch_errors with a function with parameters, then
currently you have to manually write a "capture" struct wrapping the
arguments and marshall/unmarshall that.
https://sourceware.org/ml/gdb-patches/2017-09/msg00834.html proposed
adjusting catch_errors to use gdb::function_view, which would allow
passing lambdas with automatic captures. However, it seems like using
TRY/CATCH directly instead ends up producing clearer and easier to
debug code. This is what this commit does.
Note that removing catch_errors exposes further cleanup opportunities
around no longer having to follow catch_errors callback type, and also
removes a few cleanups.
I didn't do anything to save/restore current_uiout because I think
that should be the responsibility of the code that changes
current_uiout in the first place.
(Another approach could be to make catch_errors a variadic template
like:
template<typename Function, typename... Args>
int catch_errors (const char *errstring, return_mask mask,
Function &&func, Args... args);
and then with:
extern void function_with_args (int, int);
extern void function_with_no_args ();
calls to the above functions would be wrapped like this:
catch_errors ("some error happened", RETURN_MASK_ERROR,
function_with_args, arg1, arg2);
catch_errors ("some error happened", RETURN_MASK_ERROR,
function_with_no_args);
but I'm thinking that that doesn't improve much if at all either.)
gdb/ChangeLog
2017-10-10 Pedro Alves <palves@redhat.com>
Tom Tromey <tom@tromey.com>
* breakpoint.c (breakpoint_cond_eval): Change return type to bool
and reverse logic.
(WP_DELETED, WP_VALUE_CHANGED, WP_VALUE_NOT_CHANGED, WP_IGNORE):
No longer macros. Instead ...
(enum wp_check_result): They're now values of this new
enumeration.
(watchpoint_check): Change return type to wp_check_result and
parameter type to bpstat.
(bpstat_check_watchpoint): Use TRY/CATCH instead of catch_errors.
(bpstat_check_breakpoint_conditions): Use TRY/CATCH instead of
catch_errors. Reverse logic of watchpoint_check call.
(breakpoint_re_set_one): Now returns void and takes a breakpoint
pointer as parameter.
(breakpoint_re_set): Use TRY/CATCH instead of catch_errors.
* common/common-exceptions.c (throw_exception_sjlj): Update
comments to avoid mentioning catch_errors.
* exceptions.c (catch_errors): Delete.
* exceptions.h: Update comments to avoid mentioning catch_errors.
(catch_errors_ftype, catch_errors): Delete.
* infrun.c (normal_stop): Use TRY/CATCH instead of catch_errors.
(hook_stop_stub): Delete.
(restore_selected_frame): Change return type to void, and
parameter type to const frame_id &.
(restore_infcall_control_state): Use TRY/CATCH instead of
catch_errors.
* main.c (captured_command_loop): Return void and remove
parameter. Remove references to catch_errors.
(captured_main): Use TRY/CATCH instead of catch_errors.
* objc-lang.c (objc_submethod_helper_data)
(find_objc_msgcall_submethod_helper): Delete.
(find_objc_msgcall_submethod): Use TRY/CATCH instead of
catch_errors.
* record-full.c (record_full_message): Return void.
(record_full_message_args, record_full_message_wrapper): Delete.
(record_full_message_wrapper_safe): Return bool and use TRY/CATCH
instead of catch_errors.
* solib-aix.c (solib_aix_open_symbol_file_object): Change
parameter type to int.
* solib-darwin.c (open_symbol_file_object): Ditto.
* solib-dsbt.c (open_symbol_file_object): Ditto.
* solib-frv.c (open_symbol_file_object): Ditto.
* solib-svr4.c (open_symbol_file_object): Ditto.
* solib-target.c (solib_target_open_symbol_file_object): Ditto.
* solib.c (update_solib_list): Use TRY/CATCH instead of
catch_errors.
* solist.h (struct target_so_ops) <open_symbol_file_object>:
Change type.
* symmisc.c (struct print_symbol_args): Remove.
(dump_symtab_1): Use TRY/CATCH instead of catch_errors.
(print_symbol): Change type.
* windows-nat.c (handle_load_dll, handle_unload_dll): Return void
and remove parameters.
(catch_errors): New.
(get_windows_debug_event): Adjust.
gdb/testsuite/ChangeLog:
2017-10-10 Pedro Alves <palves@redhat.com>
* lib/selftest-support.exp (selftest_setup): Update for
captured_command_loop's prototype change.
As mentioned in commit bf93d7ba99 ("Add thread after updating
gdbarch when exec'ing"), we should avoid doing register reads after a
process does an exec and before we've updated that inferior's gdbarch.
Otherwise, we may interpret the registers using the wrong
architecture.
There's still (at least) one case where we still read registers
post-exec with the pre-exec architecture. That's when infrun decides
it needs to switch context to the exec'ing thread. I.e., if the exec
event is processed at a time when the current thread is not already
the exec'ing thread, then we get (with the test added by this commit):
continue
Continuing.
Truncated register 50 in remote 'g' packet
Truncated register 50 in remote 'g' packet
(gdb) FAIL: gdb.multi/multi-arch-exec.exp: selected_thread=2: follow_exec_mode=same: continue across exec that changes architecture
The fix is to avoid reading registers when switching context in this
case.
(I'd be nice to get rid of the constant stop_pc reading when switching
threads, but that'd be a deeper change.)
gdb/ChangeLog:
2017-10-09 Pedro Alves <palves@redhat.com>
* infrun.c (handle_inferior_event_1) <TARGET_WAITKIND_EXECD>: Skip
reading registers when switching context.
gdb/testsuite/ChangeLog:
2017-10-09 Pedro Alves <palves@redhat.com>
* gdb.multi/multi-arch-exec.c: Include <pthread.h> and <assert.h>.
(barrier): New.
(thread_start, all_started): New functions.
(main): Spawn new thread and wait until it is scheduled.
* gdb.multi/multi-arch-exec.exp: Build $srcfile1 with the pthreads
option.
(do_test): Add 'selected_thread' parameter. Run to all_started
instead of main. Explicitly set the breakpoint at main. Switch
to the SELECTED_THREAD thread.
(top level): Test handling the exec event with either the main
thread or the second thread selected.
This changes record_full_gdb_operation_disable_set to return a
scoped_restore rather than a cleanup, and fixes all the users.
ChangeLog
2017-10-03 Tom Tromey <tom@tromey.com>
* record-full.h (record_full_gdb_operation_disable_set): Return
scoped_restore_tmpl<int>.
* infrun.c (adjust_pc_after_break): Update.
(handle_signal_stop): Update.
* record-full.c (record_full_gdb_operation_disable_set): Return
scoped_restore_tmpl<int>.
(record_full_wait_1, record_full_insert_breakpoint)
(record_full_remove_breakpoint, record_full_save)
(record_full_goto_insn): Update.
This removes make_cleanup_defer_target_commit_resume in favor of using
scoped_restore.
gdb/ChangeLog
2017-09-29 Tom Tromey <tom@tromey.com>
* target.h (make_scoped_defer_target_commit_resume): Update.
* target.c (make_scoped_defer_target_commit_resume): Rename from
make_cleanup_defer_target_commit_resume. Return a
scoped_restore.
* infrun.c (proceed): Use make_scoped_defer_target_commit_resume.
As mentioned in the previous patch, we should avoid doing register reads
after a process does an exec and before we've updated that inferior's
gdbarch. Otherwise, we may interpret the registers using the wrong
architecture. When a process does an exec with "follow-exec-mode new",
a new inferior is added by follow_exec. The gdbarch of that new
inferior is at first set to some default value, probably specific to the
gdb build (I get "i386" here), which may not be the right one. It is
updated later by the call to target_find_description. Before that
point, if we try to read the inferior's registers, we may not interpret
them correctly. This has been exposed by a failure in
gdb.base/foll-exec-mode.exp after the previous patch, with:
Remote 'g' packet reply is too long (expected 312 bytes, got 816 bytes)
The call to "add_thread" done just after adding the inferior is
problematic, because it ends up reading the registers (because the ptid
is re-used, we end up doing a switch_to_thread to it, which tries to
update stop_pc). The registers returned by gdbserver are the x86-64
ones, while we try to interpret them using the "i386" gdbarch.
Postponing the call to add_thread to until the target
description/gdbarch has been updated seems to fix the issue.
As to why this issue was uncovered by the previous patch: what I think
happened before that patch is that since we were updating stop_pc before
switching to the new inferior, we were filling the regcache associated
to the ptid (this worked fine as long as the architectures of the
previous and new process images were the same). The call to
switch_to_thread then worked, because the register read hit the
regcache. Now, it triggers a register read, while the gdbarch is not
set correctly, leading to the "reply is too long" error. If this is
right, it sounds wrong that we delete and re-add a thread with the same
ptid, and are able to access the registers from the deleted thread.
When we delete a thread, should we clear the regcache associated to that
ptid, so that the new thread starts with a fresh/empty regcache?
gdb/ChangeLog:
* infrun.c (follow_exec): Call add_thread after
target_find_description.
When an inferior execs and changes architecture (e.g. 64 bits to 32
bits), the gdbarch associated to the inferior is updated by the
follow_exec call in handle_inferior_event_1. We should avoid doing any
register read before that point, because the registers sent by the
remote side will be those of the new architecture, but we would
interpret them using the old architecture. We do just that by setting
stop_pc during this window, which obviously requires reading the
registers. This results in gdb.multi/multi-arch-exec.exp failing, GDB
outputting the following error:
Truncated register 50 in remote 'g' packet
This patch fixes that by postponing the setting of stop_pc to after
we've updated the inferior gdbarch.
This bug was hiding another problem, and as such introduces some
failures in gdb.base/foll-exec-mode.exp. The following patch takes care
of that.
gdb/ChangeLog:
* infrun.c (handle_inferior_event_1): When exec'ing, read
stop_pc after follow_exec.
Instead, make symtab_and_line initialize its members itself. Many
symtab_and_line declarations are moved to where the object is
initialized at the same time both for clarity and to avoid double
initialization. A few functions, like e.g., find_frame_sal are
adjusted to return the sal using normal function return instead of an
output parameter likewise to avoid having to default-construct a sal
and then immediately have the object overwritten.
gdb/ChangeLog:
2017-09-04 Pedro Alves <palves@redhat.com>
* ada-lang.c (is_known_support_routine): Move sal declaration to
where it is initialized.
* breakpoint.c (create_internal_breakpoint, init_catchpoint)
(parse_breakpoint_sals, decode_static_tracepoint_spec)
(clear_command, update_static_tracepoint): Remove init_sal
references. Move declarations closer to initializations.
* cli/cli-cmds.c (list_command): Move sal declarations closer to
initializations.
* elfread.c (elf_gnu_ifunc_resolver_stop): Remove init_sal
references. Move sal declarations closer to initializations.
* frame.c (find_frame_sal): Return a symtab_and_line via function
return instead of output parameter. Remove init_sal references.
* frame.h (find_frame_sal): Return a symtab_and_line via function
return instead of output parameter.
* guile/scm-frame.c (gdbscm_frame_sal): Adjust.
* guile/scm-symtab.c (stscm_make_sal_smob): Use in-place new
instead of memset.
(gdbscm_find_pc_line): Remove init_sal reference.
* infcall.c (call_function_by_hand_dummy): Remove init_sal
references. Move declarations closer to initializations.
* infcmd.c (set_step_frame): Update. Move declarations closer to
initializations.
(finish_backward): Remove init_sal references. Move declarations
closer to initializations.
* infrun.c (process_event_stop_test, handle_step_into_function)
(insert_hp_step_resume_breakpoint_at_frame)
(insert_step_resume_breakpoint_at_caller): Likewise.
* linespec.c (create_sals_line_offset, decode_digits_ordinary)
(symbol_to_sal): Likewise.
* probe.c (parse_probes_in_pspace): Remove init_sal reference.
* python/py-frame.c (frapy_find_sal): Move sal declaration closer
to its initialization.
* reverse.c (save_bookmark_command): Use new/delete. Remove
init_sal references. Move declarations closer to initializations.
* source.c (get_current_source_symtab_and_line): Remove brace
initialization.
(set_current_source_symtab_and_line): Now takes the sal by const
reference. Remove brace initialization.
(line_info): Remove init_sal reference.
* source.h (set_current_source_symtab_and_line): Now takes a
symtab_and_line via const reference.
* stack.c (set_current_sal_from_frame): Adjust.
(print_frame_info): Adjust.
(get_last_displayed_sal): Return the sal via function return
instead of via output parameter. Simplify.
(frame_info): Adjust.
* stack.h (get_last_displayed_sal): Return the sal via function
return instead of via output parameter.
* symtab.c (init_sal): Delete.
(find_pc_sect_line): Remove init_sal references. Move
declarations closer to initializations.
(find_function_start_sal): Remove init_sal references. Move
declarations closer to initializations.
* symtab.h (struct symtab_and_line): In-class initialize all
fields.
* tracepoint.c (set_traceframe_context)
(print_one_static_tracepoint_marker): Remove init_sal references.
Move declarations closer to initializations.
* tui/tui-disasm.c (tui_show_disassem_and_update_source): Adjust.
* tui/tui-stack.c (tui_show_frame_info): Adjust. Move
declarations closer to initializations.
* tui/tui-winsource.c (tui_update_source_window_as_is): Remove
init_sal references. Adjust.
A quite straightforward change. It does "fix" leaks in record-btrace.c,
although since this is only used in debug printing code, it has no real
world impact.
gdb/ChangeLog:
* target/waitstatus.h (target_waitstatus_to_string): Change
return type to std::string.
* target/waitstatus.c (target_waitstatus_to_string): Return
std::string.
* target.h (target_waitstatus_to_string): Remove declaration.
* infrun.c (resume, clear_proceed_status_thread,
print_target_wait_results, do_target_wait, save_waitstatus,
stop_all_threads): Adjust.
* record-btrace.c (record_btrace_wait): Adjust.
* target-debug.h
(target_debug_print_struct_target_waitstatus_p): Adjust.
gdb/gdbserver/ChangeLog:
* linux-low.c (linux_wait_1): Adjust.
* server.c (queue_stop_reply_callback): Adjust.
This removes save_inferior_ptid, a cleanup function, in favor of
scoped_restore.
This also fixes a possible (it seems unlikely that it could happen in
practice) memory leak -- save_inferior_ptid should have used
make_cleanup_dtor, because it allocated memory.
I tested this on the buildbot. However, there are two caveats to
this. First, sometimes it seems I misread the results. Second, I
think this patch touches some platforms that can't be tested by the
buildbot. So, extra care seems warranted.
ChangeLog
2017-08-18 Tom Tromey <tom@tromey.com>
Pedro Alves <palves@redhat.com>
* spu-multiarch.c (parse_spufs_run): Use scoped_restore.
* sol-thread.c (sol_thread_resume, sol_thread_wait)
(sol_thread_xfer_partial, rw_common): Use scoped_restore.
* procfs.c (procfs_do_thread_registers): Use scoped_restore.
* proc-service.c (ps_xfer_memory): Use scoped_restore.
* linux-tdep.c (linux_corefile_thread): Remove a cleanup.
(linux_get_siginfo_data): Add "thread" argument. Use
scoped_restore.
* linux-nat.c (linux_child_follow_fork)
(check_stopped_by_watchpoint): Use scoped_restore.
* infrun.c (displaced_step_prepare_throw, write_memory_ptid)
(THREAD_STOPPED_BY, handle_signal_stop): Use scoped_restore.
(restore_inferior_ptid, save_inferior_ptid): Remove.
* btrace.c (btrace_fetch): Use scoped_restore.
* bsd-uthread.c (bsd_uthread_fetch_registers)
(bsd_uthread_store_registers): Use scoped_restore.
* breakpoint.c (reattach_breakpoints, detach_breakpoints): Use
scoped_restore.
* aix-thread.c (aix_thread_resume, aix_thread_wait)
(aix_thread_xfer_partial): Use scoped_restore.
* inferior.h (save_inferior_ptid): Remove.
- Make skiplist_entry a class with private data members.
- Move all construction logic to the ctor.
- Make skip_file_p etc be methods of skiplist_entry.
- Use std::list for the skip entries chain. Make the list own its
elements.
- Get rid of the ALL_SKIPLIST_ENTRIES/ALL_SKIPLIST_ENTRIES_SAFE
macros, use range-for / iterators instead.
- function_name_is_marked_for_skip 'function_sal' argument must be
non-NULL, so make it a reference instead.
All skiplist_entry invariants are now controlled by skiplist_entry
methods/internals. Some gdb_asserts disappear for being redundant.
gdb/ChangeLog:
2017-08-11 Pedro Alves <palves@redhat.com>
* infrun.c (process_event_stop_test): Adjust
function_name_is_marked_for_skip call.
* skip.c: Include <list>.
(skiplist_entry): Make it a class with private fields, and
getters/setters.
(skiplist_entry_chain): Delete.
(skiplist_entries): New.
(skiplist_entry_count): Delete.
(highest_skiplist_entry_num): New.
(ALL_SKIPLIST_ENTRIES, ALL_SKIPLIST_ENTRIES_SAFE): Delete.
(add_skiplist_entry): Delete.
(skiplist_entry::skiplist_entry): New.
(skiplist_entry::add_entry): New.
(skip_file_command, skip_function): Adjust.
(compile_skip_regexp): Delete.
(skip_command): Don't compile regexp here. Adjust to use
skiplist_entry::add_entry.
(skip_info): Adjust to use range-for and getters.
(skip_enable_command, skip_disable_command): Adjust to use
range-for and setters.
(skip_delete_command): Adjust to use std::list.
(add_skiplist_entry): Delete.
(skip_file_p): Delete, refactored as ...
(skiplist_entry::do_skip_file_p): ... this new method.
(skip_gfile_p): Delete, refactored as ...
(skiplist_entry::do_gskip_file_p): ... this new method.
(skip_function_p, skip_rfunction_p): Delete, refactored as ...
(skiplist_entry::skip_function_p): ... this new method.
(function_name_is_marked_for_skip): Now returns bool, and takes
the function sal by const reference. Adjust to use range-for and
skiplist_entry methods.
(_initialize_step_skip): Remove references to
skiplist_entry_chain, skiplist_entry_count.
* skip.h (function_name_is_marked_for_skip): Now returns bool, and
takes the function sal by const reference.
This introduces gdb_argv, a class wrapping an "argv" pointer; that is,
a pointer to a NULL-terminated array of char*, where both the array
and each non-NULL element in the array are xmalloc'd.
This patch then changes most users of gdb_buildargv to use gdb_argv
instead.
ChangeLog
2017-08-03 Tom Tromey <tom@tromey.com>
* utils.h (struct gdb_argv_deleter): New.
(gdb_argv): New class.
* utils.c (gdb_argv::reset): New method.
* tracepoint.c (delete_trace_variable_command): Use gdb_argv.
* tracefile.c (tsave_command): Use gdb_argv.
* top.c (new_ui_command): Use gdb_argv.
* symmisc.c (maintenance_print_symbols)
(maintenance_print_msymbols, maintenance_expand_symtabs): Use gdb_argv.
* symfile.c (symbol_file_command, generic_load)
(remove_symbol_file_command): Use gdb_argv.
* stack.c (backtrace_command): Use gdb_argv.
* source.c (add_path, show_substitute_path_command)
(unset_substitute_path_command, set_substitute_path_command):
Use gdb_argv.
* skip.c (skip_command): Use gdb_argv. Use gdb_buildargv.
* ser-mingw.c (pipe_windows_open): Use gdb_argv.
* remote.c (extended_remote_run, remote_put_command)
(remote_get_command, remote_delete_command): Use gdb_argv.
* remote-sim.c (gdbsim_load, gdbsim_create_inferior)
(gdbsim_open): Use gdb_argv.
* python/py-cmd.c (gdbpy_string_to_argv): Use gdb_argv.
* psymtab.c (maintenance_print_psymbols): Use gdb_argv.
* procfs.c (procfs_info_proc): Use gdb_argv.
* interps.c (interpreter_exec_cmd): Use gdb_argv.
* infrun.c (handle_command): Use gdb_argv.
* inferior.c (add_inferior_command, clone_inferior_command):
Use gdb_argv.
* guile/scm-string.c (gdbscm_string_to_argv): Use gdb_argv.
* exec.c (exec_file_command): Use gdb_argv.
* cli/cli-cmds.c (alias_command): Use gdb_argv.
* compile/compile.c (build_argc_argv): Use gdb_argv.
PR 21555 is caused by the exception during the prologue analysis when re-set
a breakpoint.
(gdb) bt
#0 memory_error_message (err=TARGET_XFER_E_IO, gdbarch=0x153db50, memaddr=93824992233232) at ../../binutils-gdb/gdb/corefile.c:192
#1 0x00000000005718ed in memory_error (err=TARGET_XFER_E_IO, memaddr=memaddr@entry=93824992233232) at ../../binutils-gdb/gdb/corefile.c:220
#2 0x00000000005719d6 in read_memory_object (object=object@entry=TARGET_OBJECT_CODE_MEMORY, memaddr=93824992233232, memaddr@entry=1, myaddr=myaddr@entry=0x7fffffffd0a0 "P\333S\001", len=len@entry=1) at ../../binutils-gdb/gdb/corefile.c:259
#3 0x0000000000571c6e in read_code (len=1, myaddr=0x7fffffffd0a0 "P\333S\001", memaddr=<optimized out>) at ../../binutils-gdb/gdb/corefile.c:287
#4 read_code_unsigned_integer (memaddr=memaddr@entry=93824992233232, len=len@entry=1, byte_order=byte_order@entry=BFD_ENDIAN_LITTLE) at ../../binutils-gdb/gdb/corefile.c:362
#5 0x000000000041d4a0 in amd64_analyze_prologue (gdbarch=gdbarch@entry=0x153db50, pc=pc@entry=93824992233232, current_pc=current_pc@entry=18446744073709551615, cache=cache@entry=0x7fffffffd1e0) at ../../binutils-gdb/gdb/amd64-tdep.c:2310
#6 0x000000000041e404 in amd64_skip_prologue (gdbarch=0x153db50, start_pc=93824992233232) at ../../binutils-gdb/gdb/amd64-tdep.c:2459
#7 0x000000000067bfb0 in skip_prologue_sal (sal=sal@entry=0x7fffffffd4e0) at ../../binutils-gdb/gdb/symtab.c:3628
#8 0x000000000067c4d8 in find_function_start_sal (sym=sym@entry=0x1549960, funfirstline=1) at ../../binutils-gdb/gdb/symtab.c:3501
#9 0x000000000060999d in symbol_to_sal (result=result@entry=0x7fffffffd5f0, funfirstline=<optimized out>, sym=sym@entry=0x1549960) at ../../binutils-gdb/gdb/linespec.c:3860
....
#16 0x000000000054b733 in location_to_sals (b=b@entry=0x15792d0, location=0x157c230, search_pspace=search_pspace@entry=0x1148120, found=found@entry=0x7fffffffdc64) at ../../binutils-gdb/gdb/breakpoint.c:14211
#17 0x000000000054c1f5 in breakpoint_re_set_default (b=0x15792d0) at ../../binutils-gdb/gdb/breakpoint.c:14301
#18 0x00000000005412a9 in breakpoint_re_set_one (bint=bint@entry=0x15792d0) at ../../binutils-gdb/gdb/breakpoint.c:14412
This problem can be fixed by
- either each prologue analyzer doesn't throw exception,
- or catch the exception thrown from gdbarch_skip_prologue,
I choose the latter because the former needs to fix *every* prologue
analyzer to not throw exception.
This error can be reproduced by changing reread.exp. The test reread.exp
has already test that breakpoint can be reset correctly after the
executable is re-read. This patch extends this test by compiling test c
file with and without -fPIE.
(gdb) run ^M
The program being debugged has been started already.^M
Start it from the beginning? (y or n) y^M
x86_64/gdb/testsuite/outputs/gdb.base/reread/reread' has changed; re-reading symbols.
Error in re-setting breakpoint 1: Cannot access memory at address 0x555555554790^M
Error in re-setting breakpoint 2: Cannot access memory at address 0x555555554790^M
Starting program: /scratch/yao/gdb/build-git/x86_64/gdb/testsuite/outputs/gdb.base/reread/reread ^M
This is foo^M
[Inferior 1 (process 27720) exited normally]^M
(gdb) FAIL: gdb.base/reread.exp: opts= "-fPIE" "ldflags=-pie" : run to foo() second time (the program exited)
This patch doesn't re-indent the code, to keep the patch simple.
gdb:
2017-07-25 Yao Qi <yao.qi@linaro.org>
PR gdb/21555
* arch-utils.c (gdbarch_skip_prologue_noexcept): New function.
* arch-utils.h (gdbarch_skip_prologue_noexcept): Declare.
* infrun.c: Include arch-utils.h
(handle_step_into_function): Call gdbarch_skip_prologue_noexcept.
(handle_step_into_function_backward): Likewise.
* symtab.c (skip_prologue_sal): Likewise.
gdb/testsuite:
2017-07-25 Yao Qi <yao.qi@linaro.org>
PR gdb/21555
* gdb.base/reread.exp: Wrap the whole test with two kinds of
compilation flags, with -fPIE and without -fPIE.
This patch reworks the whole completion machinery, and prepares it
for later enhancements.
Adds a new "completion_tracker" class that is meant to hold everything
about the state of the current completion operation.
This class now has the responsibility of tracking the list of
completion matches, and checking whether the max completions limit has
been reached. You can look at this as this patch starting out by
C++fying the existing "completion_tracker" in symtab.c (it's just an
htab_t typedef currently), moving it to completer.h/c, and then making
it a class/generalizing/enhancing it.
Unlike with the current tracking, completion_tracker now checks
whether the limit has been reached on each completion match list
insertion. This both simplifies the max-completions handling code
(maybe_add_completion_enum is gone, for example), and is a
prerequisite for follow up patches.
The current completion_tracker is only used for symbol completions,
and the symbol code gets at the current instance via globals. This
patch cleans that up by adding a completion_tracker reference to the
signature of the completion functions, and passing the tracker around
everywhere necessary.
Then, the patch changes how the completion match list is handed over
to readline. Currently, we're using the rl_completion_entry_function
readline entry point, and the patch switches to
rl_attempted_completion_function. A following patch will want to let
GDB itself decide the common completion prefix between all matches
(what readline calls the "lowest common denominator"), instead of
having readline compute it, and that's not possible with the
rl_completion_entry_function entry point. Also,
rl_attempted_completion_function lets GDB hand over the match list to
readline as an array in one go instead of passing down matches one by
one, so from that angle it's a nicer entry point anyway.
Lastly, the patch catches exceptions around the readline entry points,
because we can't let C++ exceptions cross readline. We handle that in
the readline input entry point, but the completion entry point isn't
guarded, so GDB can abort if completion throws. E.g., in current
master:
(gdb) b -function "fun<tab>
terminate called after throwing an instance of 'gdb_exception_RETURN_MASK_ERROR'
Aborted (core dumped)
This patch fixes that. This will be exercised in the new tests added
later on in the series.
gdb/ChangeLog:
2017-07-17 Pedro Alves <palves@redhat.com>
* ada-lang.c (symbol_completion_match): Adjust comments.
(symbol_completion_add): Replace vector parameter with
completion_tracker parameter. Use it.
(ada_make_symbol_completion_list): Rename to...
(ada_collect_symbol_completion_matches): ... this. Add
completion_tracker parameter and use it.
(ada_language_defn): Adjust.
* break-catch-syscall.c (catch_syscall_completer): Adjust
prototype and work with completion_tracker instead of VEC.
* breakpoint.c (condition_completer): Adjust prototype and work
with completion_tracker instead of VEC.
* c-lang.c (c_language_defn, cplus_language_defn)
(asm_language_defn, minimal_language_defn): Adjust to renames.
* cli/cli-cmds.c (complete_command): Rework using
completion_tracker. Catch exceptions when completing.
* cli/cli-decode.c (integer_unlimited_completer)
(complete_on_cmdlist, complete_on_enum): Adjust prototype and work
with completion_tracker instead of VEC.
* command.h (struct completion_tracker): Forward declare.
(completer_ftype, completer_handle_brkchars_ftype): Change
types.
(complete_on_cmdlist, complete_on_enum): Adjust.
* completer.c: Include <algorithm>.
(struct gdb_completer_state): New.
(current_completion): New global.
(readline_line_completion_function): Delete.
(noop_completer, filename_completer)
(filename_completer_handle_brkchars, complete_files_symbols)
(linespec_location_completer): Adjust to work with a
completion_tracker instead of a VEC.
(string_or_empty): New.
(collect_explicit_location_matches): Adjust to work with a
completion_tracker instead of a VEC.
(explicit_location_completer): Rename to ...
(complete_explicit_location): ... this and adjust to work with a
completion_tracker instead of a VEC.
(location_completer): Adjust to work with a completion_tracker
instead of a VEC.
(add_struct_fields): Adjust to work with a completion_list instead
of VEC.
(expression_completer): Rename to ...
(complete_expression): ... this and adjust to work with a
completion_tracker instead of a VEC. Use complete_files_symbols.
(expression_completer): Reimplement on top of complete_expression.
(symbol_completer): Adjust to work with a completion_tracker
instead of a VEC.
(enum complete_line_internal_reason): Add describing comments.
(complete_line_internal_normal_command): Adjust to work with a
completion_tracker instead of a VEC.
(complete_line_internal): Rename to ...
(complete_line_internal_1): ... this and adjust to work with a
completion_tracker instead of a VEC. Assert TEXT is NULL in the
handle_brkchars phase.
(new_completion_tracker): Delete.
(complete_line_internal): Reimplement as TRY/CATCH wrapper around
complete_line_internal_1.
(free_completion_tracker): Delete.
(INITIAL_COMPLETION_HTAB_SIZE): New.
(completion_tracker::completion_tracker)
(completion_tracker::~completion_tracker): New.
(maybe_add_completion): Delete.
(completion_tracker::maybe_add_completion)
(completion_tracker::add_completion)
(completion_tracker::add_completions): New.
(throw_max_completions_reached_error): Delete.
(complete_line): Adjust to work with a completion_tracker instead
of a VEC. Don't create a completion_tracker_t or check for max
completions here.
(command_completer, command_completer_handle_brkchars)
(signal_completer, reg_or_group_completer_1)
(reg_or_group_completer, default_completer_handle_brkchars):
Adjust to work with a completion_tracker.
(gdb_completion_word_break_characters_throw): New.
(gdb_completion_word_break_characters): Reimplement.
(line_completion_function): Delete.
(completion_tracker::recompute_lowest_common_denominator)
(expand_preserving_ws)
(completion_tracker::build_completion_result)
(completion_result::completion_result)
(completion_result::completion_result)
(completion_result::~completion_result)
(completion_result::completion_result)
(completion_result::release_match_list, compare_cstrings)
(completion_result::sort_match_list)
(completion_result::reset_match_list)
(gdb_rl_attempted_completion_function_throw)
(gdb_rl_attempted_completion_function): New.
* completer.h (completion_list, struct completion_result)
(class completion_tracker): New.
(complete_line): Add completion_tracker parameter.
(readline_line_completion_function): Delete.
(gdb_rl_attempted_completion_function): New.
(noop_completer, filename_completer, expression_completer)
(location_completer, symbol_completer, command_completer)
(signal_completer, reg_or_group_completer): Update prototypes.
(completion_tracker_t, new_completion_tracker)
(make_cleanup_free_completion_tracker): Delete.
(enum maybe_add_completion_enum): Delete.
(maybe_add_completion): Delete.
(throw_max_completions_reached_error): Delete.
* corefile.c (complete_set_gnutarget): Adjust to work with a
completion_tracker instead of a VEC.
* cp-abi.c (cp_abi_completer): Adjust to work with a
completion_tracker instead of a VEC.
* d-lang.c (d_language_defn): Adjust.
* disasm.c (disassembler_options_completer): Adjust to work with a
completion_tracker instead of a VEC.
* f-lang.c (f_make_symbol_completion_list): Rename to ...
(f_collect_symbol_completion_matches): ... this. Adjust to work
with a completion_tracker instead of a VEC.
(f_language_defn): Adjust.
* go-lang.c (go_language_defn): Adjust.
* guile/scm-cmd.c (cmdscm_add_completion, cmdscm_completer):
Adjust to work with a completion_tracker instead of a VEC.
* infrun.c (handle_completer): Likewise.
* interps.c (interpreter_completer): Likewise.
* interps.h (interpreter_completer): Likewise.
* language.c (unknown_language_defn, auto_language_defn)
(local_language_defn): Adjust.
* language.h (language_defn::la_make_symbol_completion_list):
Rename to ...
(language_defn::la_collect_symbol_completion_matches): ... this
and adjust to work with a completion_tracker instead of a VEC.
* m2-lang.c (m2_language_defn): Adjust.
* objc-lang.c (objc_language_defn): Adjust.
* opencl-lang.c (opencl_language_defn): Adjust.
* p-lang.c (pascal_language_defn): Adjust.
* python/py-cmd.c (cmdpy_completer_helper): Handle NULL word.
(cmdpy_completer_handle_brkchars, cmdpy_completer): Adjust to work
with a completion_tracker.
* rust-lang.c (rust_language_defn): Adjust.
* symtab.c (free_completion_list, do_free_completion_list)
(return_val, completion_tracker): Delete.
(completion_list_add_name, completion_list_add_symbol)
(completion_list_add_msymbol, completion_list_objc_symbol)
(completion_list_add_fields, add_symtab_completions): Add
completion_tracker parameter and use it.
(default_make_symbol_completion_list_break_on_1): Rename to...
(default_collect_symbol_completion_matches_break_on): ... this.
Add completion_tracker parameter and use it instead of allocating
a completion tracker here.
(default_make_symbol_completion_list_break_on): Delete old
implementation.
(default_make_symbol_completion_list): Delete.
(default_collect_symbol_completion_matches): New.
(make_symbol_completion_list): Delete.
(collect_symbol_completion_matches): New.
(make_symbol_completion_type): Rename to ...
(collect_symbol_completion_matches_type): ... this. Add
completion_tracker parameter and use it instead of VEC.
(make_file_symbol_completion_list_1): Rename to...
(collect_file_symbol_completion_matches): ... this. Add
completion_tracker parameter and use it instead of VEC.
(make_file_symbol_completion_list): Delete.
(add_filename_to_list): Use completion_list instead of a VEC.
(add_partial_filename_data::list): Now a completion_list.
(make_source_files_completion_list): Work with a completion_list
instead of a VEC.
* symtab.h: Include "completer.h".
(default_make_symbol_completion_list_break_on)
(default_make_symbol_completion_list, make_symbol_completion_list)
(make_symbol_completion_type, make_file_symbol_completion_list)
(make_source_files_completion_list): Delete.
(default_collect_symbol_completion_matches_break_on)
(default_collect_symbol_completion_matches)
(collect_symbol_completion_matches)
(collect_symbol_completion_matches_type)
(collect_file_symbol_completion_matches)
(make_source_files_completion_list): New.
* top.c (init_main): Don't install a rl_completion_entry_function
hook. Install a rl_attempted_completion_function hook instead.
* tui/tui-layout.c (layout_completer): Adjust to work with a
completion_tracker.
* tui/tui-regs.c (tui_reggroup_completer):
* tui/tui-win.c (window_name_completer, focus_completer)
(winheight_completer): Adjust to work with a completion_tracker.
* value.c: Include "completer.h".
(complete_internalvar): Adjust to work with a completion_tracker.
* value.h (complete_internalvar): Likewise.
The displaced_step_free_closure gdbarch hook allows architectures to
free data they might have allocated to complete a displaced step.
However, all architectures using that hook use the
simple_displaced_step_free_closure provided in arch-utils.{c,h}, which
does a simple xfree. We can remove it and do an xfree directly instead
of calling the hook.
gdb/ChangeLog:
* gdbarch.sh (displaced_step_free_closure): Remove.
* gdbarch.h, gdbarch.c: Re-generate.
* aarch64-linux-tdep.c (aarch64_linux_init_abi): Don't set
displaced_step_free_closure.
* amd64-linux-tdep.c (amd64_linux_init_abi_common): Likewise.
* arm-linux-tdep.c (arm_linux_init_abi): Likewise.
* i386-linux-tdep.c (i386_linux_init_abi): Likewise.
* rs6000-aix-tdep.c (rs6000_aix_init_osabi): Likewise.
* rs6000-tdep.c (rs6000_gdbarch_init): Likewise.
* s390-linux-tdep.c (s390_gdbarch_init): Likewise.
* arch-utils.h (simple_displaced_step_free_closure): Remove.
* arch-utils.c (simple_displaced_step_free_closure): Remove.
* infrun.c (displaced_step_clear): Call xfree instead of
gdbarch_displaced_step_free_closure.
After all the make_cleanup_restore_current_thread fixing, I thought
I'd convert that and its relatives (which are all cleanups) to RAII
classes.
scoped_restore_current_pspace_and_thread was put in a separate file to
avoid a circular dependency.
Tested on x86-64 Fedora 23, native and gdbserver.
gdb/ChangeLog:
2017-05-04 Pedro Alves <palves@redhat.com>
* Makefile.in (SFILES): Add progspace-and-thread.c.
(HFILES_NO_SRCDIR): Add progspace-and-thread.h.
(COMMON_OBS): Add progspace-and-thread.o.
* breakpoint.c: Include "progspace-and-thread.h".
(update_inserted_breakpoint_locations)
(insert_breakpoint_locations, create_longjmp_master_breakpoint):
Use scoped_restore_current_pspace_and_thread.
(create_std_terminate_master_breakpoint): Use
scoped_restore_current_program_space.
(remove_breakpoint): Use scoped_restore_current_pspace_and_thread.
(print_breakpoint_location): Use
scoped_restore_current_program_space.
(bp_loc_is_permanent): Use
scoped_restore_current_pspace_and_thread.
(resolve_sal_pc): Use scoped_restore_current_pspace_and_thread.
(download_tracepoint_locations): Use
scoped_restore_current_pspace_and_thread.
(breakpoint_re_set): Use scoped_restore_current_pspace_and_thread.
* exec.c (exec_close_1): Use scoped_restore_current_program_space.
(enum step_over_calls_kind): Moved from inferior.h.
(class scoped_restore_current_thread): New class.
* gdbthread.h (make_cleanup_restore_current_thread): Delete
declaration.
(scoped_restore_current_thread): New class.
* infcmd.c: Include "common/gdb_optional.h".
(continue_1, proceed_after_attach): Use
scoped_restore_current_thread.
(notice_new_inferior): Use scoped_restore_current_thread.
* inferior.c: Include "progspace-and-thread.h".
(restore_inferior, save_current_inferior): Delete.
(add_inferior_command, clone_inferior_command): Use
scoped_restore_current_pspace_and_thread.
* inferior.h (scoped_restore_current_inferior): New class.
* infrun.c: Include "progspace-and-thread.h" and
"common/gdb_optional.h".
(follow_fork_inferior): Use
scoped_restore_current_pspace_and_thread.
(scoped_restore_exited_inferior): New class.
(handle_vfork_child_exec_or_exit): Use
scoped_restore_exited_inferior,
scoped_restore_current_pspace_and_thread,
scoped_restore_current_thread and scoped_restore.
(fetch_inferior_event): Use scoped_restore_current_thread.
* linespec.c (decode_line_full, decode_line_1): Use
scoped_restore_current_program_space.
* mi/mi-main.c: Include "progspace-and-thread.h".
(exec_continue): Use scoped_restore_current_thread.
(mi_cmd_exec_run): Use scoped_restore_current_pspace_and_thread.
(mi_cmd_trace_frame_collected): Use scoped_restore_current_thread.
* proc-service.c (ps_pglobal_lookup): Use
scoped_restore_current_program_space.
* progspace-and-thread.c: New file.
* progspace-and-thread.h: New file.
* progspace.c (release_program_space, clone_program_space): Use
scoped_restore_current_program_space.
(restore_program_space, save_current_program_space)
(save_current_space_and_thread): Delete.
(switch_to_program_space_and_thread): Moved to
progspace-and-thread.c.
* progspace.h (save_current_program_space)
(save_current_space_and_thread): Delete declarations.
(scoped_restore_current_program_space): New class.
* remote.c (remote_btrace_maybe_reopen): Use
scoped_restore_current_thread.
* symtab.c: Include "progspace-and-thread.h".
(skip_prologue_sal): Use scoped_restore_current_pspace_and_thread.
* thread.c (print_thread_info_1): Use
scoped_restore_current_thread.
(struct current_thread_cleanup): Delete.
(do_restore_current_thread_cleanup)
(restore_current_thread_cleanup_dtor): Rename/convert both to ...
(scoped_restore_current_thread::~scoped_restore_current_thread):
... this new dtor.
(make_cleanup_restore_current_thread): Rename/convert to ...
(scoped_restore_current_thread::scoped_restore_current_thread):
... this new ctor.
(thread_apply_all_command): Use scoped_restore_current_thread.
(thread_apply_command): Use scoped_restore_current_thread.
* tracepoint.c (tdump_command): Use scoped_restore_current_thread.
* varobj.c (value_of_root_1): Use scoped_restore_current_thread.
I left making inferior::detaching a bool to a separate patch, because
doing that makes a make_cleanup_restore_integer call in
infrun.c:prepare_for_detach no longer compile (passing a 'bool *' when
an 'int *' is expected). Since we want to get rid of cleanups anyway,
I looked at converting that to a scoped_restore. However,
prepare_for_detach wants to discard the cleanup on success, and
scoped_restore doesn't have an equivalent for that. So I added one --
I called it "release()" because it seems like a natural fit in the way
standard components call similarly-spirited methods, and, it's also
what the proposal for a generic scope guard calls it too, AFAICS:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4189.pdf
I've added some scoped_guard unit tests, while at it.
gdb/ChangeLog:
2017-04-19 Pedro Alves <palves@redhat.com>
* Makefile.in (SUBDIR_UNITTESTS_SRCS): Add
unittests/scoped_restore-selftests.c.
(SUBDIR_UNITTESTS_OBS): Add scoped_restore-selftests.o.
* common/scoped_restore.h (scoped_restore_base): Make "class".
(scoped_restore_base::release): New public method.
(scoped_restore_base::scoped_restore_base): New protected ctor.
(scoped_restore_base::m_saved_var): New protected field.
(scoped_restore_tmpl::scoped_restore_tmpl(T*)): Initialize the
scoped_restore_base base class instead of m_saved_var directly.
(scoped_restore_tmpl::scoped_restore_tmpl(T*, T2)): Likewise.
(scoped_restore_tmpl::scoped_restore_tmpl(const
scoped_restore_tmpl<T>&)): Likewise.
(scoped_restore_tmpl::~scoped_restore_tmpl): Use the saved_var
method.
(scoped_restore_tmpl::saved_var): New method.
(scoped_restore_tmpl::m_saved_var): Delete.
* inferior.h (inferior::detaching): Now a bool.
* infrun.c (prepare_for_detach): Use a scoped_restore instead of a
cleanup.
* unittests/scoped_restore-selftests.c: New file.
A later patch in the series adds an assertion to switch_to_thread that
the resulting inferior_ptid always matches the "current_inferior()"
inferior. This exposed a latent bug in the follow-fork code, where
we're building the fork child inferior. We're switching
inferior_ptid, but not the current inferior object...
gdb/ChangeLog:
2017-04-13 Pedro Alves <palves@redhat.com>
* infrun.c (follow_fork_inferior): Also switch the current
inferior.
I build GDB with asan, and run test case hook-stop.exp, and threadapply.exp,
I got the following asan error,
=================================================================^M
^[[1m^[[31m==2291==ERROR: AddressSanitizer: heap-use-after-free on address 0x6160000999c4 at pc 0x000000826022 bp 0x7ffd28a8ff70 sp 0x7ffd28a8ff60^M
^[[1m^[[0m^[[1m^[[34mREAD of size 4 at 0x6160000999c4 thread T0^[[1m^[[0m^M
#0 0x826021 in release_stop_context_cleanup ../../binutils-gdb/gdb/infrun.c:8203^M
#1 0x72798a in do_my_cleanups ../../binutils-gdb/gdb/common/cleanups.c:154^M
#2 0x727a32 in do_cleanups(cleanup*) ../../binutils-gdb/gdb/common/cleanups.c:176^M
#3 0x826895 in normal_stop() ../../binutils-gdb/gdb/infrun.c:8381^M
#4 0x815208 in fetch_inferior_event(void*) ../../binutils-gdb/gdb/infrun.c:4011^M
#5 0x868aca in inferior_event_handler(inferior_event_type, void*) ../../binutils-gdb/gdb/inf-loop.c:44^M
....
^[[1m^[[32m0x6160000999c4 is located 68 bytes inside of 568-byte region [0x616000099980,0x616000099bb8)^M
^[[1m^[[0m^[[1m^[[35mfreed by thread T0 here:^[[1m^[[0m^M
#0 0x7fb0bc1312ca in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x982ca)^M
#1 0xb8c62f in xfree(void*) ../../binutils-gdb/gdb/common/common-utils.c:100^M
#2 0x83df67 in free_thread ../../binutils-gdb/gdb/thread.c:207^M
#3 0x83dfd2 in init_thread_list() ../../binutils-gdb/gdb/thread.c:223^M
#4 0x805494 in kill_command ../../binutils-gdb/gdb/infcmd.c:2595^M
....
Detaching from program: /home/yao.qi/SourceCode/gnu/build-with-asan/gdb/testsuite/outputs/gdb.threads/threadapply/threadapply, process 2399^M
=================================================================^M
^[[1m^[[31m==2387==ERROR: AddressSanitizer: heap-use-after-free on address 0x6160000a98c0 at pc 0x00000083fd28 bp 0x7ffd401c3110 sp 0x7ffd401c3100^M
^[[1m^[[0m^[[1m^[[34mREAD of size 4 at 0x6160000a98c0 thread T0^[[1m^[[0m^M
#0 0x83fd27 in thread_alive ../../binutils-gdb/gdb/thread.c:741^M
#1 0x844277 in thread_apply_all_command ../../binutils-gdb/gdb/thread.c:1804^M
....
^M
^[[1m^[[32m0x6160000a98c0 is located 64 bytes inside of 568-byte region [0x6160000a9880,0x6160000a9ab8)^M
^[[1m^[[0m^[[1m^[[35mfreed by thread T0 here:^[[1m^[[0m^M
#0 0x7f59a7e322ca in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x982ca)^M
#1 0xb8c62f in xfree(void*) ../../binutils-gdb/gdb/common/common-utils.c:100^M
#2 0x83df67 in free_thread ../../binutils-gdb/gdb/thread.c:207^M
#3 0x83dfd2 in init_thread_list() ../../binutils-gdb/gdb/thread.c:223^M
This patch fixes the issue by deleting thread_info object if it is
deletable, otherwise, mark it as exited (by set_thread_exited).
Function set_thread_exited is shared from delete_thread_1. This patch
also moves field "refcount" to private and methods incref and
decref. Additionally, we stop using "ptid_t" in
"struct current_thread_cleanup" to reference threads, instead we use
"thread_info" directly. Due to this change, we don't need
restore_current_thread_ptid_changed anymore.
gdb:
2017-04-10 Yao Qi <yao.qi@linaro.org>
PR gdb/19942
* gdbthread.h (thread_info::deletable): New method.
(thread_info::incref): New method.
(thread_info::decref): New method.
(thread_info::refcount): Move it to private.
* infrun.c (save_stop_context): Call inc_refcount.
(release_stop_context_cleanup): Likewise.
* thread.c (set_thread_exited): New function.
(init_thread_list): Delete "tp" only it is deletable, otherwise
call set_thread_exited.
(delete_thread_1): Call set_thread_exited.
(current_thread_cleanup) <inferior_pid>: Remove.
<thread>: New field.
(restore_current_thread_ptid_changed): Removed.
(do_restore_current_thread_cleanup): Adjust.
(restore_current_thread_cleanup_dtor): Don't call
find_thread_ptid.
(set_thread_refcount): Use dec_refcount.
(make_cleanup_restore_current_thread): Adjust.
(thread_apply_all_command): Call inc_refcount.
(_initialize_thread): Don't call
observer_attach_thread_ptid_changed.
If you do "interrupt -a" just while some thread is stepping over a
breakpoint, gdb trips on an internal error.
The test added by this patch manages to trigger this consistently by
spawning a few threads that are constantly tripping on a conditional
breakpoint whose condition always evaluates to false. With current
gdb, you get:
~~~
interrupt -a
.../src/gdb/inline-frame.c:343: internal-error: void skip_inline_frames(ptid_t): Assertion `find_inline_frame_state (ptid) == NULL' failed.
A problem internal to GDB has been detected,
further debugging may prove unreliable.
Quit this debugging session? (y or n) FAIL: gdb.threads/interrupt-while-step-over.exp: displaced-stepping=on: iter=0: interrupt -a (GDB internal error)
[...]
.../src/gdb/inline-frame.c:343: internal-error: void skip_inline_frames(ptid_t): Assertion `find_inline_frame_state (ptid) == NULL' failed.
A problem internal to GDB has been detected,
further debugging may prove unreliable.
Quit this debugging session? (y or n) FAIL: gdb.threads/interrupt-while-step-over.exp: displaced-stepping=off: iter=0: wait for stops (GDB internal error)
~~~
The assertion triggers because we're processing a stop for a thread
that had already stopped before and thus had already its inline-frame
state filled in.
Calling handle_inferior_event_1 directly within a
"thread_stop_requested" observer is something that I've wanted to get
rid of before, for being fragile. Nowadays, infrun is aware of
threads with pending events, so we can use that instead, and let the
normal fetch_inferior_event -> handle_inferior_event code path handle
the forced stop.
The change to finish_step_over is necessary because sometimes a thread
that was told to PTRACE_SINGLESTEP reports back a SIGSTOP instead of a
SIGTRAP (i.e., we tell it to single-step, and then interrupt it quick
enough that on the kernel side the thread dequeues the SIGTOP before
ever having had a chance of executing the instruction to be stepped).
SIGSTOP gets translated to a GDB_SIGNAL_0. And then finish_step_over
would miss calling clear_step_over_info, and thus miss restarting the
other threads (which in this case of threads with pending events,
means setting their "resumed" flag, so their pending events can be
consumed).
And now that we always restart threads in finish_step_over, we no
longer need to do that in handle_signal_stop.
Tested on x86_64 Fedora 23, native and gdbserver.
gdb/ChangeLog:
2017-03-08 Pedro Alves <palves@redhat.com>
PR gdb/18360
* infrun.c (start_step_over, do_target_resume, resume)
(restart_threads): Assert we're not resuming a thread that is
meant to be stopped.
(infrun_thread_stop_requested_callback): Delete.
(infrun_thread_stop_requested): If the thread is internally
stopped, queue a pending stop event and clear the thread's
inline-frame state.
(handle_stop_requested): New function.
(handle_syscall_event, handle_inferior_event_1): Use
handle_stop_requested.
(handle_stop_requested): New function.
(handle_signal_stop): Set the thread's stop_signal here instead of
at caller.
(finish_step_over): Clear step over info unconditionally.
(handle_signal_stop): If the user had interrupted the event
thread, consider the stop a random signal.
(handle_signal_stop) <signal arrived while stepping over
breakpoint>: Don't restart threads here.
(stop_waiting): Don't clear step-over info here.
gdb/testsuite/ChangeLog:
2017-03-08 Pedro Alves <palves@redhat.com>
PR gdb/18360
* gdb.threads/interrupt-while-step-over.c: New file.
* gdb.threads/interrupt-while-step-over.exp: New file.
This patch starts from the desire to eliminate
make_cleanup_ui_file_delete, but then goes beyond. It makes ui_file &
friends a real C++ class hierarchy, and switches temporary
ui_file-like objects to stack-based allocation.
- mem_fileopen -> string_file
mem_fileopen is replaced with a new string_file class that is treated
as a value class created on the stack. This alone eliminates most
make_cleanup_ui_file_delete calls, and, simplifies code a whole lot
(diffstat shows around 1k loc dropped.)
string_file's internal buffer is a std::string, thus the "string" in
the name. This simplifies the implementation much, compared to
mem_fileopen, which managed growing its internal buffer manually.
- ui_file_as_string, ui_file_strdup, ui_file_obsavestring all gone
The new string_file class has a string() method that provides direct
writable access to the internal std::string buffer. This replaced
ui_file_as_string, which forced a copy of the same data the stream had
inside. With direct access via a writable reference, we can instead
move the string out of the string_stream, avoiding deep string
copying.
Related, ui_file_xstrdup calls are replaced with xstrdup'ping the
stream's string, and ui_file_obsavestring is replaced by
obstack_copy0.
With all those out of the way, getting rid of the weird ui_file_put
mechanism was possible.
- New ui_file::printf, ui_file::puts, etc. methods
These simplify / clarify client code. I considered splitting
client-code changes, like these, e.g.:
- stb = mem_fileopen ();
- fprintf_unfiltered (stb, "%s%s%s",
- _("The valid values are:\n"),
- regdesc,
- _("The default is \"std\"."));
+ string_file stb;
+ stb.printf ("%s%s%s",
+ _("The valid values are:\n"),
+ regdesc,
+ _("The default is \"std\"."));
In two steps, with the first step leaving fprintf_unfiltered (etc.)
calls in place, and only afterwards do a pass to change all those to
call stb.printf etc.. I didn't do that split, because (when I tried),
it turned out to be pointless make-work: the first pass would have to
touch the fprintf_unfiltered line anyway, to replace "stb" with
"&stb".
- gdb_fopen replaced with stack-based objects
This avoids the need for cleanups or unique_ptr's. I.e., this:
struct ui_file *file = gdb_fopen (filename, "w");
if (filename == NULL)
perror_with_name (filename);
cleanups = make_cleanup_ui_file_delete (file);
// use file.
do_cleanups (cleanups);
is replaced with this:
stdio_file file;
if (!file.open (filename, "w"))
perror_with_name (filename);
// use file.
- odd contorsions in null_file_write / null_file_fputs around when to
call to_fputs / to_write eliminated.
- Global null_stream object
A few places that were allocating a ui_file in order to print to
"nowhere" are adjusted to instead refer to a new 'null_stream' global
stream.
- TUI's tui_sfileopen eliminated. TUI's ui_file much simplified
The TUI's ui_file was serving a dual purpose. It supported being used
as string buffer, and supported being backed by a stdio FILE. The
string buffer part is gone, replaced by using of string_file. The
'FILE *' support is now much simplified, by making the TUI's ui_file
inherit from stdio_file.
gdb/ChangeLog:
2017-02-02 Pedro Alves <palves@redhat.com>
* ada-lang.c (type_as_string): Use string_file.
* ada-valprint.c (ada_print_floating): Use string_file.
* ada-varobj.c (ada_varobj_scalar_image)
(ada_varobj_get_value_image): Use string_file.
* aix-thread.c (aix_thread_extra_thread_info): Use string_file.
* arm-tdep.c (_initialize_arm_tdep): Use string_printf.
* breakpoint.c (update_inserted_breakpoint_locations)
(insert_breakpoint_locations, reattach_breakpoints)
(print_breakpoint_location, print_one_detail_ranged_breakpoint)
(print_it_watchpoint): Use string_file.
(save_breakpoints): Use stdio_file.
* c-exp.y (oper): Use string_file.
* cli/cli-logging.c (set_logging_redirect): Use ui_file_up and
tee_file.
(pop_output_files): Use delete.
(handle_redirections): Use stdio_file and tee_file.
* cli/cli-setshow.c (do_show_command): Use string_file.
* compile/compile-c-support.c (c_compute_program): Use
string_file.
* compile/compile-c-symbols.c (generate_vla_size): Take a
'string_file &' instead of a 'ui_file *'.
(generate_c_for_for_one_variable): Take a 'string_file &' instead
of a 'ui_file *'. Use string_file.
(generate_c_for_variable_locations): Take a 'string_file &'
instead of a 'ui_file *'.
* compile/compile-internal.h (generate_c_for_for_one_variable):
Take a 'string_file &' instead of a 'ui_file *'.
* compile/compile-loc2c.c (push, pushf, unary, binary)
(print_label, pushf_register_address, pushf_register)
(do_compile_dwarf_expr_to_c): Take a 'string_file &' instead of a
'ui_file *'. Adjust.
* compile/compile.c (compile_to_object): Use string_file.
* compile/compile.h (compile_dwarf_expr_to_c)
(compile_dwarf_bounds_to_c): Take a 'string_file &' instead of a
'ui_file *'.
* cp-support.c (inspect_type): Use string_file and obstack_copy0.
(replace_typedefs_qualified_name): Use string_file and
obstack_copy0.
* disasm.c (gdb_pretty_print_insn): Use string_file.
(gdb_disassembly): Adjust reference the null_stream global.
(do_ui_file_delete): Delete.
(gdb_insn_length): Use null_stream.
* dummy-frame.c (maintenance_print_dummy_frames): Use stdio_file.
* dwarf2loc.c (dwarf2_compile_property_to_c)
(locexpr_generate_c_location, loclist_generate_c_location): Take a
'string_file &' instead of a 'ui_file *'.
* dwarf2loc.h (dwarf2_compile_property_to_c): Likewise.
* dwarf2read.c (do_ui_file_peek_last): Delete.
(dwarf2_compute_name): Use string_file.
* event-top.c (gdb_setup_readline): Use stdio_file.
* gdbarch.sh (verify_gdbarch): Use string_file.
* gdbtypes.c (safe_parse_type): Use null_stream.
* guile/scm-breakpoint.c (gdbscm_breakpoint_commands): Use
string_file.
* guile/scm-disasm.c (gdbscm_print_insn_from_port): Take a
'string_file *' instead of a 'ui_file *'.
(gdbscm_arch_disassemble): Use string_file.
* guile/scm-frame.c (frscm_print_frame_smob): Use string_file.
* guile/scm-ports.c (class ioscm_file_port): Now a class that
inherits from ui_file.
(ioscm_file_port_delete, ioscm_file_port_rewind)
(ioscm_file_port_put): Delete.
(ioscm_file_port_write): Rename to ...
(ioscm_file_port::write): ... this. Remove file_port_magic
checks.
(ioscm_file_port_new): Delete.
(ioscm_with_output_to_port_worker): Use ioscm_file_port and
ui_file_up.
* guile/scm-type.c (tyscm_type_name): Use string_file.
* guile/scm-value.c (vlscm_print_value_smob, gdbscm_value_print):
Use string_file.
* infcmd.c (print_return_value_1): Use string_file.
* infrun.c (print_target_wait_results): Use string_file.
* language.c (add_language): Use string_file.
* location.c (explicit_to_string_internal): Use string_file.
* main.c (captured_main_1): Use null_file.
* maint.c (maintenance_print_architecture): Use stdio_file.
* mi/mi-cmd-stack.c (list_arg_or_local): Use string_file.
* mi/mi-common.h (struct mi_interp) <out, err, log, targ,
event_channel>: Change type to mi_console_file pointer.
* mi/mi-console.c (mi_console_file_fputs, mi_console_file_flush)
(mi_console_file_delete): Delete.
(struct mi_console_file): Delete.
(mi_console_file_magic): Delete.
(mi_console_file_new): Delete.
(mi_console_file::mi_console_file): New.
(mi_console_file_delete): Delete.
(mi_console_file_fputs): Delete.
(mi_console_file::write): New.
(mi_console_raw_packet): Delete.
(mi_console_file::flush): New.
(mi_console_file_flush): Delete.
(mi_console_set_raw): Rename to ...
(mi_console_file::set_raw): ... this.
* mi/mi-console.h (class mi_console_file): New class.
(mi_console_file_new, mi_console_set_raw): Delete.
* mi/mi-interp.c (mi_interpreter_init): Use mi_console_file.
(mi_set_logging): Use delete and tee_file. Adjust.
* mi/mi-main.c (output_register): Use string_file.
(mi_cmd_data_evaluate_expression): Use string_file.
(mi_cmd_data_read_memory): Use string_file.
(mi_cmd_execute, print_variable_or_computed): Use string_file.
* mi/mi-out.c (mi_ui_out::main_stream): New.
(mi_ui_out::rewind): Use main_stream and
string_file.
(mi_ui_out::put): Use main_stream and string_file.
(mi_ui_out::mi_ui_out): Remove 'stream' parameter.
Allocate a 'string_file' instead.
(mi_out_new): Don't allocate a mem_fileopen stream here.
* mi/mi-out.h (mi_ui_out::mi_ui_out): Remove 'stream' parameter.
(mi_ui_out::main_stream): Declare method.
* printcmd.c (eval_command): Use string_file.
* psymtab.c (maintenance_print_psymbols): Use stdio_file.
* python/py-arch.c (archpy_disassemble): Use string_file.
* python/py-breakpoint.c (bppy_get_commands): Use string_file.
* python/py-frame.c (frapy_str): Use string_file.
* python/py-framefilter.c (py_print_type, py_print_single_arg):
Use string_file.
* python/py-type.c (typy_str): Use string_file.
* python/py-unwind.c (unwind_infopy_str): Use string_file.
* python/py-value.c (valpy_str): Use string_file.
* record-btrace.c (btrace_insn_history): Use string_file.
* regcache.c (regcache_print): Use stdio_file.
* reggroups.c (maintenance_print_reggroups): Use stdio_file.
* remote.c (escape_buffer): Use string_file.
* rust-lang.c (rust_get_disr_info): Use string_file.
* serial.c (serial_open_ops_1): Use stdio_file.
(do_serial_close): Use delete.
* stack.c (print_frame_arg): Use string_file.
(print_frame_args): Remove local mem_fileopen stream, not used.
(print_frame): Use string_file.
* symmisc.c (maintenance_print_symbols): Use stdio_file.
* symtab.h (struct symbol_computed_ops) <generate_c_location>:
Take a 'string_file *' instead of a 'ui_file *'.
* top.c (new_ui): Use stdio_file and stderr_file.
(free_ui): Use delete.
(execute_command_to_string): Use string_file.
(quit_confirm): Use string_file.
* tracepoint.c (collection_list::append_exp): Use string_file.
* tui/tui-disasm.c (tui_disassemble): Use string_file.
* tui/tui-file.c: Don't include "ui-file.h".
(enum streamtype, struct tui_stream): Delete.
(tui_file_new, tui_file_delete, tui_fileopen, tui_sfileopen)
(tui_file_isatty, tui_file_rewind, tui_file_put): Delete.
(tui_file::tui_file): New method.
(tui_file_fputs): Delete.
(tui_file_get_strbuf): Delete.
(tui_file::puts): New method.
(tui_file_adjust_strbuf): Delete.
(tui_file_flush): Delete.
(tui_file::flush): New method.
* tui/tui-file.h: Tweak intro comment.
Include ui-file.h.
(tui_fileopen, tui_sfileopen, tui_file_get_strbuf)
(tui_file_adjust_strbuf): Delete declarations.
(class tui_file): New class.
* tui/tui-io.c (tui_initialize_io): Use tui_file.
* tui/tui-regs.c (tui_restore_gdbout): Use delete.
(tui_register_format): Use string_stream.
* tui/tui-stack.c (tui_make_status_line): Use string_file.
(tui_get_function_from_frame): Use string_file.
* typeprint.c (type_to_string): Use string_file.
* ui-file.c (struct ui_file, ui_file_magic, ui_file_new): Delete.
(null_stream): New global.
(ui_file_delete): Delete.
(ui_file::ui_file): New.
(null_file_isatty): Delete.
(ui_file::~ui_file): New.
(null_file_rewind): Delete.
(ui_file::printf): New.
(null_file_put): Delete.
(null_file_flush): Delete.
(ui_file::putstr): New.
(null_file_write): Delete.
(ui_file::putstrn): New.
(null_file_read): Delete.
(ui_file::putc): New.
(null_file_fputs): Delete.
(null_file_write_async_safe): Delete.
(ui_file::vprintf): New.
(null_file_delete): Delete.
(null_file::write): New.
(null_file_fseek): Delete.
(null_file::puts): New.
(ui_file_data): Delete.
(null_file::write_async_safe): New.
(gdb_flush, ui_file_isatty): Adjust.
(ui_file_put, ui_file_rewind): Delete.
(ui_file_write): Adjust.
(ui_file_write_for_put): Delete.
(ui_file_write_async_safe, ui_file_read): Adjust.
(ui_file_fseek): Delete.
(fputs_unfiltered): Adjust.
(set_ui_file_flush, set_ui_file_isatty, set_ui_file_rewind)
(set_ui_file_put, set_ui_file_write, set_ui_file_write_async_safe)
(set_ui_file_read, set_ui_file_fputs, set_ui_file_fseek)
(set_ui_file_data): Delete.
(string_file::~string_file, string_file::write)
(struct accumulated_ui_file, do_ui_file_xstrdup, ui_file_xstrdup)
(do_ui_file_as_string, ui_file_as_string): Delete.
(do_ui_file_obsavestring, ui_file_obsavestring): Delete.
(struct mem_file): Delete.
(mem_file_new): Delete.
(stdio_file::stdio_file): New.
(mem_file_delete): Delete.
(stdio_file::stdio_file): New.
(mem_fileopen): Delete.
(stdio_file::~stdio_file): New.
(mem_file_rewind): Delete.
(stdio_file::set_stream): New.
(mem_file_put): Delete.
(stdio_file::open): New.
(mem_file_write): Delete.
(stdio_file_magic, struct stdio_file): Delete.
(stdio_file_new, stdio_file_delete, stdio_file_flush): Delete.
(stdio_file::flush): New.
(stdio_file_read): Rename to ...
(stdio_file::read): ... this. Adjust.
(stdio_file_write): Rename to ...
(stdio_file::write): ... this. Adjust.
(stdio_file_write_async_safe): Rename to ...
(stdio_file::write_async_safe) ... this. Adjust.
(stdio_file_fputs): Rename to ...
(stdio_file::puts) ... this. Adjust.
(stdio_file_isatty): Delete.
(stdio_file_fseek): Delete.
(stdio_file::isatty): New.
(stderr_file_write): Rename to ...
(stderr_file::write) ... this. Adjust.
(stderr_file_fputs): Rename to ...
(stderr_file::puts) ... this. Adjust.
(stderr_fileopen, stdio_fileopen, gdb_fopen): Delete.
(stderr_file::stderr_file): New.
(tee_file_magic): Delete.
(struct tee_file): Delete.
(tee_file::tee_file): New.
(tee_file_new): Delete.
(tee_file::~tee_file): New.
(tee_file_delete): Delete.
(tee_file_flush): Rename to ...
(tee_file::flush): ... this. Adjust.
(tee_file_write): Rename to ...
(tee_file::write): ... this. Adjust.
(tee_file::write_async_safe): New.
(tee_file_fputs): Rename to ...
(tee_file::puts): ... this. Adjust.
(tee_file_isatty): Rename to ...
(tee_file::isatty): ... this. Adjust.
* ui-file.h (struct obstack, struct ui_file): Don't
forward-declare.
(ui_file_new, ui_file_flush_ftype, set_ui_file_flush)
(ui_file_write_ftype)
(set_ui_file_write, ui_file_fputs_ftype, set_ui_file_fputs)
(ui_file_write_async_safe_ftype, set_ui_file_write_async_safe)
(ui_file_read_ftype, set_ui_file_read, ui_file_isatty_ftype)
(set_ui_file_isatty, ui_file_rewind_ftype, set_ui_file_rewind)
(ui_file_put_method_ftype, ui_file_put_ftype, set_ui_file_put)
(ui_file_delete_ftype, set_ui_file_data, ui_file_fseek_ftype)
(set_ui_file_fseek): Delete.
(ui_file_data, ui_file_delete, ui_file_rewind)
(struct ui_file): New.
(ui_file_up): New.
(class null_file): New.
(null_stream): Declare.
(ui_file_write_for_put, ui_file_put): Delete.
(ui_file_xstrdup, ui_file_as_string, ui_file_obsavestring):
Delete.
(ui_file_fseek, mem_fileopen, stdio_fileopen, stderr_fileopen)
(gdb_fopen, tee_file_new): Delete.
(struct string_file): New.
(struct stdio_file): New.
(stdio_file_up): New.
(struct stderr_file): New.
(class tee_file): New.
* ui-out.c (ui_out::field_stream): Take a 'string_file &' instead
of a 'ui_file *'. Adjust.
* ui-out.h (class ui_out) <field_stream>: Likewise.
* utils.c (do_ui_file_delete, make_cleanup_ui_file_delete)
(null_stream): Delete.
(error_stream): Take a 'string_file &' instead of a 'ui_file *'.
Adjust.
* utils.h (struct ui_file): Delete forward declaration..
(make_cleanup_ui_file_delete, null_stream): Delete declarations.
(error_stream): Take a 'string_file &' instead of a
'ui_file *'.
* varobj.c (varobj_value_get_print_value): Use string_file.
* xtensa-tdep.c (xtensa_verify_config): Use string_file.
* gdbarch.c: Regenerate.
This applies the second part of GDB's End of Year Procedure, which
updates the copyright year range in all of GDB's files.
gdb/ChangeLog:
Update copyright year range in all GDB files.
The following testcases make GDB crash whenever an invalid sysroot is
provided, when GDB is unable to find a valid path to the symbol file:
gdb.base/catch-syscall.exp
gdb.base/execl-update-breakpoints.exp
gdb.base/foll-exec-mode.exp
gdb.base/foll-exec.exp
gdb.base/foll-vfork.exp
gdb.base/pie-execl.exp
gdb.multi/bkpt-multi-exec.exp
gdb.python/py-finish-breakpoint.exp
gdb.threads/execl.exp
gdb.threads/non-ldr-exc-1.exp
gdb.threads/non-ldr-exc-2.exp
gdb.threads/non-ldr-exc-3.exp
gdb.threads/non-ldr-exc-4.exp
gdb.threads/thread-execl.exp
The immediate cause of the segv is that follow_exec is passing a NULL
argument (the result of exec_file_find) to strlen.
However, the problem is deeper than that: follow_exec simply isn't
prepared for the case where sysroot translation fails to locate the
new executable. Actually all callers of exec_file_find have bugs due
to confusion between host and target pathnames. This commit attempts
to fix all that.
In terms of the testcases that were formerly segv'ing, GDB now prints
a warning but continues execution of the new program, so that the
tests now mostly FAIL instead. You could argue the FAILs are due to a
legitimate problem with the test environment setting up the sysroot
translation incorrectly.
A new representative test is added which exercises the ne wwarning
code path even with native testing.
Tested on x86_64 Fedora 23, native and gdbserver.
gdb/ChangeLog:
2016-10-25 Sandra Loosemore <sandra@codesourcery.com>
Luis Machado <lgustavo@codesourcery.com>
Pedro Alves <palves@redhat.com>
PR gdb/20569
* exceptions.c (exception_print_same): Moved here from exec.c.
* exceptions.h (exception_print_same): Declare.
* exec.h: Include "symfile-add-flags.h".
(try_open_exec_file): New declaration.
* exec.c (exception_print_same): Moved to exceptions.c.
(try_open_exec_file): New function.
(exec_file_locate_attach): Rename exec_file and full_exec_path
variables to avoid confusion between target and host pathnames.
Move pathname processing logic to exec_file_find. Do not return
early if pathname lookup fails; Call try_open_exec_file.
* infrun.c (follow_exec): Split and rename execd_pathname variable
to avoid confusion between target and host pathnames. Warn if
pathname lookup fails. Pass target pathname to
target_follow_exec, not hostpathname. Call try_open_exec_file.
* main.c (symbol_file_add_main_adapter): New function.
(captured_main_1): Use it.
* solib-svr4.c (open_symbol_file_object): Adjust to pass
symfile_add_flags to symbol_file_add_main.
* solib.c (exec_file_find): Incorporate fallback logic for relative
pathnames formerly in exec_file_locate_attach.
* symfile.c (symbol_file_add_main, symbol_file_add_main_1):
Replace 'from_tty' parameter with a symfile_add_file.
(symbol_file_command): Adjust to pass symfile_add_flags to
symbol_file_add_main.
* symfile.h (symbol_file_add_main): Replace 'from_tty' parameter
with a symfile_add_file.
gdb/testsuite/ChangeLog:
2016-10-25 Luis Machado <lgustavo@codesourcery.com>
* gdb.base/exec-invalid-sysroot.exp: New file.
Currently, with "maint set target-non-stop on", that is, when gdb
connects with the non-stop/asynchronous variant of the remote
protocol, even with "set non-stop off", GDB always sends one vCont
packet per thread resumed. This patch makes GDB aggregate and
coalesce vCont packets, so we send vCont packets like "vCont;s:p1.1;c"
in non-stop mode too.
Basically, this is done by:
- Adding a new target method target_commit_resume that is called
after calling target_resume one or more times. When resuming a
batch of threads, we'll only call target_commit_resume once after
calling target_resume for all threads.
- Making the remote target defer sending the actual vCont packet to
target_commit_resume.
Special care must be taken to avoid sending a vCont action with a
"wildcard" thread-id (all threads of process / all threads) when that
would resume threads/processes that should not be resumed. See
remote_commit_resume comments for details.
Unlike all-stop's remote_resume implementation, this handles the case
of too many actions resulting in a too-big vCont packet, by flushing
the vCont packet and starting a new one.
E.g., imagining that the "c" action in:
vCont;s:1;c
overflows the packet buffer, we split the actions like:
vCont;s:1
vCont;c
Tested on x86_64 Fedora 20, with and without "maint set
target-non-stop on".
Also tested with a hack that makes remote_commit_resume flush the vCont
packet after every action appended (which caught a few bugs).
gdb/ChangeLog:
2016-10-26 Pedro Alves <palves@redhat.com>
* inferior.h (ALL_NON_EXITED_INFERIORS): New macro.
* infrun.c (do_target_resume): Call target_commit_resume.
(proceed): Defer target_commit_resume while looping over threads,
resuming them. Call target_commit_resume at the end.
* record-btrace.c (record_btrace_commit_resume): New function.
(init_record_btrace_ops): Install it as to_commit_resume method.
* record-full.c (record_full_commit_resume): New function.
(record_full_wait_1): Call the beneath target's to_commit_resume
method.
(init_record_full_ops): Install record_full_commit_resume as
to_commit_resume method.
* remote.c (struct private_thread_info) <last_resume_step,
last_resume_sig, vcont_resumed>: New fields.
(remote_add_thread): Set the new thread's vcont_resumed flag.
(demand_private_info): Delete.
(get_private_info_thread, get_private_info_ptid): New functions.
(remote_update_thread_list): Adjust.
(process_initial_stop_replies): Clear the thread's vcont_resumed
flag.
(remote_resume): If connected in non-stop mode, record the resume
request and return early.
(struct private_inferior): New.
(struct vcont_builder): New.
(vcont_builder_restart, vcont_builder_flush)
(vcont_builder_push_action): New functions.
(MAX_ACTION_SIZE): New macro.
(remote_commit_resume): New function.
(thread_pending_fork_status, is_pending_fork_parent_thread): New
functions.
(check_pending_event_prevents_wildcard_vcont_callback)
(check_pending_events_prevent_wildcard_vcont): New functions.
(process_stop_reply): Adjust. Clear the thread's vcont_resumed
flag.
(init_remote_ops): Install remote_commit_resume.
* target-delegates.c: Regenerate.
* target.c (defer_target_commit_resume): New global.
(target_commit_resume, make_cleanup_defer_target_commit_resume):
New functions.
* target.h (struct target_ops) <to_commit_resume>: New field.
(target_resume): Update comments.
(target_commit_resume): New declaration.
This removes make_cleanup_restore_current_uiout in favor of an
RAII-based class.
2016-10-21 Tom Tromey <tom@tromey.com>
* stack.c (print_stack_frame_to_uiout): Use scoped_restore.
* ui-out.c (make_cleanup_restore_current_uiout)
(restore_current_uiout_cleanup): Remove.
* infrun.c (print_stop_event): Use scoped_restore.
* ui-out.h (make_cleanup_restore_current_uiout): Don't declare.
This removes make_cleanup_restore_current_ui by converting the last
use. The last use was in a few functions used to iterate over all
UIs. This patch replaces these functions with a class, and arranges
for the class destructor to do the needed cleanup.
2016-10-21 Tom Tromey <tom@tromey.com>
* tui/tui-interp.c (tui_on_normal_stop, tui_on_signal_received)
(tui_on_end_stepping_range, tui_on_signal_exited, tui_on_exited)
(tui_on_no_history, tui_on_user_selected_context_changed):
Update.
* top.h (switch_thru_all_uis): New class.
(SWITCH_THRU_ALL_UIS): Rewrite.
(make_cleanup_restore_current_ui, switch_thru_all_uis_init)
(switch_thru_all_uis_cond, switch_thru_all_uis_next): Don't
declare.
* mi/mi-interp.c (mi_new_thread, mi_thread_exit)
(mi_record_changed, mi_inferior_added, mi_inferior_appeared)
(mi_inferior_exit, mi_inferior_removed, mi_on_signal_received)
(mi_on_end_stepping_range, mi_on_signal_exited, mi_on_exited)
(mi_on_no_history, mi_on_normal_stop, mi_traceframe_changed)
(mi_tsv_created, mi_tsv_deleted, mi_tsv_modified)
(mi_breakpoint_created, mi_breakpoint_deleted)
(mi_breakpoint_modified, mi_output_running_pid, mi_on_resume)
(mi_solib_loaded, mi_solib_unloaded, mi_command_param_changed)
(mi_memory_changed, mi_user_selected_context_changed): Update.
* infrun.c (all_uis_check_sync_execution_done)
(all_uis_on_sync_execution_starting, normal_stop): Update.
* event-top.c (restore_ui_cleanup)
(make_cleanup_restore_current_ui, switch_thru_all_uis_init)
(switch_thru_all_uis_cond, switch_thru_all_uis_next): Remove.
* cli/cli-interp.c (cli_on_normal_stop, cli_on_signal_received)
(cli_on_end_stepping_range, cli_on_signal_exited, cli_on_exited)
(cli_on_no_history, cli_on_user_selected_context_changed):
Update.
* breakpoint.c (watchpoint_check): Update.
This changes most uses of make_cleanup_restore_current_ui to use
scoped_restore. The use in switch_thru_all_uis_init still remains;
that is dealt with in a later patch by replacing this iterator with a
real class.
2016-10-21 Tom Tromey <tom@tromey.com>
* top.c (new_ui_command, wait_sync_command_done)
(gdb_readline_wrapper): Use scoped_restore.
* infrun.c (fetch_inferior_event): Use scoped_restore.
* infcall.c (call_thread_fsm_should_stop): Use scoped_restore.
This patch replaces many (but not all) uses of
make_cleanup_restore_integer with a simple RAII-based template class.
It also removes the similar restore_execution_direction cleanup in
favor of this new class. Subsequent patches will replace other
similar cleanups with this class.
The class is typically instantiated using make_scoped_restore. This
allows for template argument deduction.
2016-10-21 Tom Tromey <tom@tromey.com>
* common/scoped_restore.h: New file.
* utils.h: Include scoped_restore.h.
* top.c (execute_command_to_string): Use scoped_restore.
* python/python.c (python_interactive_command): Use
scoped_restore.
(python_command, execute_gdb_command): Likewise.
* printcmd.c (do_one_display): Use scoped_restore.
* mi/mi-main.c (exec_continue): Use scoped_restore.
* mi/mi-cmd-var.c (mi_cmd_var_assign): Use scoped_restore.
* linux-fork.c (checkpoint_command): Use scoped_restore.
* infrun.c (restore_execution_direction): Remove.
(fetch_inferior_event): Use scoped_restore.
* compile/compile.c (compile_file_command): Use
scoped_restore.
(compile_code_command, compile_print_command): Likewise.
* cli/cli-script.c (execute_user_command): Use
scoped_restore.
(while_command, if_command, script_from_file): Likewise.
* arm-tdep.c (arm_insert_single_step_breakpoint): Use
scoped_restore.
This patch consolidates the API of target_mourn_inferior between GDB
and gdbserver, in my continuing efforts to make sharing the
fork_inferior function possible between both.
GDB's version of the function did not care about the inferior's ptid
being mourned, but gdbserver's needed to know this information. Since
it actually makes sense to pass the ptid as an argument, instead of
depending on a global value directly (which GDB's version did), I
decided to make the generic API to accept it. I then went on and
extended all calls being made on GDB to include a ptid argument (which
ended up being inferior_ptid most of the times, anyway), and now we
have a more sane interface.
On GDB's side, after talking to Pedro a bit about it, we decided that
just an assertion to make sure that the ptid being passed is equal to
inferior_ptid would be enough for now, on the GDB side. We can remove
the assertion and perform more operations later if we ever pass
anything different than inferior_ptid.
Regression tested on our BuildBot, everything OK.
I'd appreciate a special look at gdb/windows-nat.c's modification
because I wasn't really sure what to do there. It seemed to me that
maybe I should build a ptid out of the process information there, but
then I am almost sure the assertion on GDB's side would trigger.
gdb/ChangeLog:
2016-09-19 Sergio Durigan Junior <sergiodj@redhat.com>
* darwin-nat.c (darwin_kill_inferior): Adjusting call to
target_mourn_inferior to include ptid_t argument.
* fork-child.c (startup_inferior): Likewise.
* gnu-nat.c (gnu_kill_inferior): Likewise.
* inf-ptrace.c (inf_ptrace_kill): Likewise.
* infrun.c (handle_inferior_event_1): Likewise.
* linux-nat.c (linux_nat_attach): Likewise.
(linux_nat_kill): Likewise.
* nto-procfs.c (interrupt_query): Likewise.
(procfs_interrupt): Likewise.
(procfs_kill_inferior): Likewise.
* procfs.c (procfs_kill_inferior): Likewise.
* record.c (record_mourn_inferior): Likewise.
* remote-sim.c (gdbsim_kill): Likewise.
* remote.c (remote_detach_1): Likewise.
(remote_kill): Likewise.
* target.c (target_mourn_inferior): Change declaration to accept
new ptid_t argument; use gdb_assert on it.
* target.h (target_mourn_inferior): Move function prototype from
here...
* target/target.h (target_mourn_inferior): ... to here. Adjust it
to accept new ptid_t argument.
* windows-nat.c (get_windows_debug_event): Adjusting call to
target_mourn_inferior to include ptid_t argument.
gdb/gdbserver/ChangeLog:
2016-09-19 Sergio Durigan Junior <sergiodj@redhat.com>
* server.c (start_inferior): Call target_mourn_inferior instead of
mourn_inferior; pass ptid_t argument to it.
(resume): Likewise.
(handle_target_event): Likewise.
* target.c (target_mourn_inferior): New function.
* target.h (mourn_inferior): Delete macro.
Make a globally available cleanup from a pre-existing one in infrun.c.
This is used in a following patch.
gdb/ChangeLog:
* infrun.c (restore_current_uiout_cleanup): Move to ui-out.c.
(print_stop_event): Use make_cleanup_restore_current_uiout.
* python/python.c (execute_gdb_command): Likewise.
* ui-out.c (restore_current_uiout_cleanup): Move from infrun.c.
(make_cleanup_restore_current_uiout): New function definition.
* ui-out.h (make_cleanup_restore_current_uiout): New function
declaration.
* utils.c (do_restore_ui_out): Remove.
(make_cleanup_restore_ui_out): Remove.
* utils.h (make_cleanup_restore_ui_out): Remove.
Just a tidy, no functional changes.
gdb/ChangeLog:
2016-09-06 Pedro Alves <palves@redhat.com>
* event-top.c (restore_ui_cleanup): Now static.
(make_cleanup_restore_current_ui): New function.
(switch_thru_all_uis_init): Use it.
* infcall.c (call_thread_fsm_should_stop): Use it.
* infrun.c (fetch_inferior_event): Use it.
* top.c (new_ui_command): Use it.
* top.h (restore_ui_cleanup): Delete declaration.
(make_cleanup_restore_current_ui): New declaration.
When executing commands on a secondary UI running the MI interpreter,
some commands that should be synchronous are not. MI incorrectly
continues processing input right after the synchronous command is
sent, before the target stops.
The problem happens when we emit MI async events (=library-loaded,
etc.), and we go about restoring the previous terminal state, we end
up calling target_terminal_ours, which incorrectly always installs the
current UI's input_fd in the event loop... That is, code like this:
old_chain = make_cleanup_restore_target_terminal ();
target_terminal_ours_for_output ();
fprintf_unfiltered (mi->event_channel, "library-loaded");
...
do_cleanups (old_chain);
The fix is to move the add_file_handler/delete_file_handler calls out
of target_terminal_$foo, making these completely no-ops unless called
with the main UI as current UI.
gdb/ChangeLog:
2016-08-09 Pedro Alves <palves@redhat.com>
PR gdb/20418
* event-top.c (ui_register_input_event_handler)
(ui_unregister_input_event_handler): New functions.
(async_enable_stdin): Register input in the event loop.
(async_disable_stdin): Unregister input from the event loop.
(gdb_setup_readline): Register input in the event loop.
* infrun.c (check_curr_ui_sync_execution_done): Register input in
the event loop.
* target.c (target_terminal_inferior): Don't unregister input from
the event loop.
(target_terminal_ours): Don't register input in the event loop.
* target.h (target_terminal_inferior)
(target_terminal_ours_for_output, target_terminal_ours): Update
comments.
* top.h (ui_register_input_event_handler)
(ui_unregister_input_event_handler): New declarations.
* utils.c (ui_unregister_input_event_handler_cleanup)
(prepare_to_handle_input): New functions.
(defaulted_query, prompt_for_continue): Use
prepare_to_handle_input.
gdb/testsuite/ChangeLog:
2016-08-09 Pedro Alves <palves@redhat.com>
Simon Marchi <simon.marchi@ericsson.com>
PR gdb/20418
* gdb.mi/new-ui-mi-sync.c, gdb.mi/new-ui-mi-sync.exp: New files.
* lib/mi-support.exp (mi_expect_interrupt): Remove anchors.
FreeBSD's librt uses SIGLIBRT as an internal signal to implement
SIGEV_THREAD sigevent notifications. Similar to SIGLWP or SIGCANCEL
this signal should be passed through to child processes by default.
include/ChangeLog:
* signals.def: Add GDB_SIGNAL_LIBRT.
gdb/ChangeLog:
* common/signals.c (gdb_signal_from_host): Handle SIGLIBRT.
(do_gdb_signal_to_host): Likewise.
* infrun.c (_initialize_infrun): Pass GDB_SIGNAL_LIBRT through to
programs.
* proc-events.c (signal_table): Add entry for SIGLIBRT.
I noticed that if we step into an inline function, step_1 never
reaches proceed, and thus nevers sets the thread's
tp->control.command_interp. Because of that,
should_print_stop_to_console fails to determine that is should print
stop output to the console.
The fix is to set the thread's command_interp earlier. However, I
realized that we can move that field to the thread_fsm, given that its
lifetime is exactly the same as thread_fsm. So the patch plumbs all
fsms constructors to take the command interp and store it in the
thread_fsm.
We can see the fix in action, with e.g., the gdb.opt/inline-cmds.exp
test, and issuing a step when stopped at line 67:
&"s\n"
^running
*running,thread-id="all"
(gdb)
~"67\t result = func2 ();\n"
*stopped,reason="end-stepping-range",frame={addr="0x00000000004004d0",func="main",args=[],file="/home/pedro/gdb/mygit/src/gdb/testsuite/gdb.opt/inline-cmds.c",fullname="/home/pedro/gdb/mygit/src/gdb/testsuite/gdb.opt/inline-cmds.c",line="67"},thread-id="1",stopped-threads="all",core="0"
(gdb)
s
&"s\n"
^running
*running,thread-id="all"
(gdb)
+ ~"func2 () at /home/pedro/gdb/mygit/src/gdb/testsuite/gdb.opt/inline-cmds.c:67\n"
+ ~"67\t result = func2 ();\n"
*stopped,reason="end-stepping-range",frame={addr="0x00000000004004d0",func="func2",args=[],file="/home/pedro/gdb/mygit/src/gdb/testsuite/gdb.opt/inline-cmds.c",fullname="/home/pedro/gdb/mygit/src/gdb/testsuite/gdb.opt/inline-cmds.c",line="67"},thread-id="1",stopped-threads="all",core="0"
(gdb)
(The inline-cmds.exp command is adjusted to exercise this.)
(Due to the follow_fork change, this also fixes "next N" across a fork
with "set follow-fork child" with "set detach-on-fork on". Commands
that rely on internal breakpoints, like "finish" will still require
more work to migrate breakpoints etc. to the child thread.)
gdb/ChangeLog:
2016-06-21 Pedro Alves <palves@redhat.com>
* breakpoint.c (new_until_break_fsm): Add 'cmd_interp' parameter.
(until_break_fsm_should_stop, until_break_fsm_clean_up): Add
thread parameter.
(until_break_command): Pass command interpreter to thread fsm
ctor.
* cli/cli-interp.c (should_print_stop_to_console): Adjust.
* gdbthread.h (struct thread_control_state) <command_interp>:
Delete field.
* infcall.c (new_call_thread_fsm): Add 'cmd_interp' parameter.
Pass it down.
(call_thread_fsm_should_stop): Add thread parameter.
(call_function_by_hand_dummy): Pass command interpreter to thread
fsm ctor. Pass thread pointer to fsm clean up method.
* infcmd.c: Include interps.h.
(struct step_command_fsm) <thread>: Delete field.
(new_step_command_fsm): Add 'cmd_interp' parameter. Pass it down.
(step_command_fsm_prepare): Remove references to fsm's thread
field.
(step_1): Pass command interpreter to thread
fsm ctor. Pass thread pointer to fsm clean up method.
(step_command_fsm_should_stop, step_command_fsm_clean_up): Add
thread parameter and use it.
(new_until_next_fsm): Add 'cmd_interp' parameter. Pass it down.
(until_next_fsm_should_stop, until_next_fsm_clean_up): Add thread
parameter and use it.
(until_next_command): Pass command interpreter to thread fsm ctor.
(struct finish_command_fsm) <thread>: Delete field.
(finish_command_fsm_ops): Add NULL slot for should_notify_stop.
(new_finish_command_fsm): Add 'cmd_interp' parameter and pass it
down. Remove thread parameter and adjust.
(finish_command_fsm_should_stop, finish_command_fsm_clean_up): Add
thread parameter and use it.
(finish_command): Pass command interpreter to thread fsm ctor.
Don't pass thread.
* infrun.c (follow_fork): Move thread fsm to child fork instead of
command interpreter, only.
(clear_proceed_status_thread): Remove reference to command_interp.
(proceed): Don't record the thread's command interpreter.
(clean_up_just_stopped_threads_fsms): Pass thread to fsm clean_up
method.
(fetch_inferior_event): Pass thread to fsm should_stop method.
* thread-fsm.c (thread_fsm_ctor): Add 'cmd_interp' parameter.
Store it.
(thread_fsm_clean_up, thread_fsm_should_stop): Add thread
parameter and pass it down.
* thread-fsm.h (struct thread_fsm) <command_interp>: New field.
(struct thread_fsm_ops) <clean_up, should_stop>: Add thread
parameter.
(thread_fsm_ctor): Add 'cmd_interp' parameter.
(thread_fsm_clean_up, thread_fsm_should_stop): Add thread
parameter.
* thread.c (thread_cancel_execution_command): Pass thread to
thread fsm clean_up method.
gdb/testsuite/ChangeLog:
2016-06-21 Pedro Alves <palves@redhat.com>
* gdb.opt/inline-cmds.c: Add "set mi break here" marker.
* gdb.opt/inline-cmds.exp: Add MI tests.
Running mi-break.exp with MI on a secondary UI reveals that MI emits
spurious prompts compared MI running as primary UI:
-exec-continue
^running
*running,thread-id="all"
(gdb)
=breakpoint-modified,bkpt={number="9",type="breakpoint",disp="keep",enabled="y",func="callee2",line="39",script={"set $i=0","while $i<10","print $i","set $i=$i+1","end","continue"}}
~"\n"
~"Breakpoint 9, callee2 (intarg=2, strarg=0x400730 \"A string argument.\") at ...src/gdb/testsuite/gdb.mi/basics.c:39\n"
~"39\t callee3 (strarg);\n"
*stopped,reason="breakpoint-hit",disp="keep",bkptno="9",frame={addr="0x00000000004005dd",func="callee2",...
*running,thread-id="all"
>> (gdb)
=breakpoint-modified,bkpt={number="9",...
~"\n"
~"Breakpoint 9, callee2 (intarg=2, strarg=0x400730 \"A string argument.\") at ...src/gdb/testsuite/gdb.mi/basics.c:39\n"
~"39\t callee3 (strarg);\n"
*stopped,reason="breakpoint-hit",disp="keep",bkptno="9",...
*running,thread-id="all"
~"[Inferior 1 (process 12639) exited normally]\n"
=thread-exited,id="1",group-id="i1"
=thread-group-exited,id="i1",exit-code="0"
*stopped,reason="exited-normally"
FAIL: gdb.mi/mi-break.exp: intermediate stop and continue
FAIL: gdb.mi/mi-break.exp: test hitting breakpoint with commands (timeout)
Note the line marked >> above.
The test sets a breakpoint that runs "continue", a foreground command.
When we get to run the "continue", we've already emitted the *stopped
event on the MI UI, and set its prompt state to PROMPT_NEEDED (this is
done from within normal_stop). Since inferior events are always
handled with the main UI as current UI, breakpoint commands always run
with the main UI as current UI too. This means that the "continue"
ends up always disabling the prompt on the main UI, instead of the UI
that had just been done with synchronous execution.
I think we'll want to extend this with a concept of "set of
threads/inferiors a UI/interpreter is blocked waiting on", but I'm
leaving that for a separate series.
gdb/ChangeLog:
2016-06-21 Pedro Alves <palves@redhat.com>
* infcmd.c (prepare_execution_command): Use
all_uis_on_sync_execution_starting.
* infrun.c (all_uis_on_sync_execution_starting): New function.
* infrun.h (all_uis_on_sync_execution_starting): Declare.
When sync_execution (a boolean) is true, it means we're running a
foreground command -- we hide the prompt stop listening to input, give
the inferior the terminal, then go to the event loop waiting for the
target to stop.
With multiple independent UIs, we need to track whether each UI is
synchronously blocked waiting for the target. IOW, if you do
"continue" in one console, that console stops accepting commands, but
you should still be free to type other commands in the others
consoles.
Just simply making sync_execution be per-UI alone not sufficient,
because of this in fetch_inferior_event:
/* If the inferior was in sync execution mode, and now isn't,
restore the prompt (a synchronous execution command has finished,
and we're ready for input). */
if (current_ui->async && was_sync && !sync_execution)
observer_notify_sync_execution_done ();
We'd have to record at entry the "was_sync" state for each UI, not
just of the current UI.
This patch instead replaces the sync_execution flag by a per-UI
tristate flag indicating the command line prompt state:
enum prompt_state
{
/* The command line is blocked simulating synchronous execution.
This is used to implement the foreground execution commands
('run', 'continue', etc.). We won't display the prompt and
accept further commands until the execution is actually over. */
PROMPT_BLOCKED,
/* The command finished; display the prompt before returning back to
the top level. */
PROMPT_NEEDED,
/* We've displayed the prompt already, ready for input. */
PROMPTED,
;
I think the end result is _much_ clearer than the current code, and,
it addresses the original motivation too.
gdb/ChangeLog:
2016-06-21 Pedro Alves <palves@redhat.com>
* annotate.c: Include top.h.
(async_background_execution_p): Delete.
(print_value_flags): Check the UI's prompt state rather then
async_background_execution_p.
* event-loop.c (start_event_loop): Set the prompt state to
PROMPT_NEEDED.
* event-top.c (display_gdb_prompt, async_enable_stdin)
(async_disable_stdin): Check the current UI's prompt state instead
of the sync_execution global.
(command_line_handler): Set the prompt state to PROMPT_NEEDED
before running a command, and display the prompt if still needed
afterwards.
* infcall.c (struct call_thread_fsm) <waiting_ui>: New field.
(new_call_thread_fsm): New parameter 'waiting_ui'. Store it.
(call_thread_fsm_should_stop): Set the prompt state to
PROMPT_NEEDED.
(run_inferior_call): Adjust to temporarily set the prompt state to
PROMPT_BLOCKED instead of using the sync_execution global.
(call_function_by_hand_dummy): Pass the current UI to
new_call_thread_fsm.
* infcmd.c: Include top.h.
(continue_1): Check the current UI's prompt state instead of the
sync_execution global.
(continue_command): Validate global execution state before calling
prepare_execution_command.
(step_1): Call all_uis_check_sync_execution_done.
(attach_post_wait): Don't call async_enable_stdin here. Remove
reference to sync_execution.
* infrun.c (sync_execution): Delete global.
(follow_fork_inferior)
(reinstall_readline_callback_handler_cleanup): Check the current
UI's prompt state instead of the sync_execution global.
(check_curr_ui_sync_execution_done)
(all_uis_check_sync_execution_done): New functions.
(fetch_inferior_event): Call all_uis_check_sync_execution_done
instead of trying to determine whether the global sync execution
changed.
(handle_no_resumed): Check the prompt state of all UIs.
(normal_stop): Emit the no unwait-for even to all PROMPT_BLOCKED
UIs. Emit the "Switching to" notification to all UIs. Enable
stdin in all UIs.
* infrun.h (sync_execution): Delete.
(all_uis_check_sync_execution_done): Declare.
* main.c (captured_command_loop): Don't call
interp_pre_command_loop if the prompt is blocked.
(catch_command_errors, catch_command_errors_const): Adjust.
(captured_main): Set the initial prompt state to PROMPT_NEEDED.
* mi/mi-interp.c (display_mi_prompt): Set the prompt state to
PROMPTED.
(mi_interpreter_resume): Don't clear sync_execution. Remove hack
comment.
(mi_execute_command_input_handler): Set the prompt state to
PROMPT_NEEDED before executing the command, and only display the
prompt if the prompt state is PROMPT_NEEDED afterwards.
(mi_on_resume_1): Adjust to check the prompt state.
* target.c (target_terminal_inferior): Adjust to check the prompt
state.
* top.c (wait_sync_command_done, maybe_wait_sync_command_done)
(execute_command): Check the current UI's prompt state instead of
sync_execution.
* top.h (enum prompt_state): New.
(struct ui) <prompt_state>: New field.
(ALL_UIS): New macro.
This makes target events always be always processed with the main UI
as current UI. This way, warnings, debug output, etc. are always
consistently sent to the main console.
gdb/ChangeLog:
2016-06-21 Pedro Alves <palves@redhat.com>
* event-top.c (restore_ui_cleanup): Make extern.
* infrun.c (fetch_inferior_event): Always switch to the main UI.
* top.h (restore_ui_cleanup): Declare.
Due to the way that readline's API works (based on globals), we can
only have one instance of readline in a process. So the goal of this
patch is to only allow editing in the main UI, and make sure that only
one UI calls into readline. Some MI paths touch readline variables
currently, which is bad as that is changing variables that matter for
the main console UI. This patch fixes those.
This actually fixes a nasty bug -- starting gdb in MI mode ("gdb
-i=mi"), and then doing "set editing on" crashes GDB, because MI is
not prepared to use readline:
set editing on
&"set editing on\n"
=cmd-param-changed,param="editing",value="on"
^done
(gdb)
p 1
readline: readline_callback_read_char() called with no handler!
Aborted (core dumped)
The fix for that was to add an interp_proc method to query the
interpreter whether it actually supports editing. New test included.
gdb/ChangeLog:
2016-06-21 Pedro Alves <palves@redhat.com>
PR mi/20034
* cli/cli-interp.c: Include cli-interp.h and event-top.h.
(cli_interpreter_resume): Pass 1 to gdb_setup_readline. Set the
UI's input_handler here.
(cli_interpreter_supports_command_editing): New function.
(cli_interp_procs): Install it.
* cli/cli-interp.h: New file.
* event-top.c (async_command_editing_p): Rename to ...
(set_editing_cmd_var): ... this.
(change_line_handler): Add parameter 'editing', and use it. Bail
early if the interpreter doesn't support editing. Don't touch
readline state if editing is off.
(gdb_rl_callback_handler_remove, gdb_rl_callback_handler_install)
(gdb_rl_callback_handler_reinstall): Assert the current UI is the
main UI.
(display_gdb_prompt): Don't call gdb_rl_callback_handler_remove if
not using readline. Check whether the current UI is using command
editing instead of checking the async_command_editing_p global.
(set_async_editing_command): Delete.
(gdb_setup_readline): Add 'editing' parameter. Only allow editing
on the main UI. Don't touch readline state if editing is off.
(gdb_disable_readline): Don't touch readline state if editing is
off.
* event-top.h (gdb_setup_readline): Add 'int' parameter.
(set_async_editing_command): Delete declaration.
(change_line_handler, command_line_handler): Declare.
(async_command_editing_p): Rename to ...
(set_editing_cmd_var): ... this.
* infrun.c (reinstall_readline_callback_handler_cleanup): Check
whether the current UI has editing enabled rather than checking
the async_command_editing_p global.
* interps.c (interp_supports_command_editing): New function.
* interps.h (interp_supports_command_editing_ftype): New typedef.
(struct interp_procs) <supports_command_editing_proc>: New field.
(interp_supports_command_editing): Declare.
* mi/mi-interp.c (mi_interpreter_resume): Pass 0 to
gdb_setup_readline. Don't clear the async_command_editing_p
global. Update comments.
* top.c (gdb_readline_wrapper_line, gdb_readline_wrapper): Check
whether the current UI has editing enabled rather than checking
the async_command_editing_p global. Don't touch readline state if
editing is off.
(undo_terminal_modifications_before_exit): Switch to the main UI.
Unconditionally call gdb_disable_readline.
(set_editing): New function.
(show_async_command_editing_p): Rename to ...
(show_editing): ... this. Show the state of the current UI.
(_initialize_top): Adjust.
* top.h (struct ui) <command_editing>: New field.
* tui/tui-interp.c: Include cli/cli-interp.h.
(tui_resume): Pass 1 to gdb_setup_readline. Set the UI's
input_handler.
(tui_interp_procs): Install
cli_interpreter_supports_command_editing.
* tui/tui-io.c (tui_getc): Check whether the current UI has
editing enabled rather than checking the async_command_editing_p
global.
gdb/testsuite/ChangeLog:
2016-06-21 Pedro Alves <palves@redhat.com>
PR mi/20034
* gdb.mi/mi-editing.exp: New file.
Make each UI have its own interpreter list, top level interpreter,
current interpreter, etc. The "interpreter_async" global is not
really specific to an struct interp (it crosses interpreter-exec ...),
so I moved it to "struct ui" directly, while the other globals were
left hidden in interps.c, opaque to the rest of GDB.
gdb/ChangeLog:
2016-06-21 Pedro Alves <palves@redhat.com>
* breakpoint.c (bpstat_do_actions_1): Access the current UI's
async field instead of the interpreter_async global.
* cli/cli-script.c (execute_user_command, while_command)
(if_command, script_from_file): Likewise.
* compile/compile.c: Include top.h instead of interps.h.
(compile_file_command, compile_code_command)
(compile_print_command): Access the current UI's async field
instead of the interpreter_async global.
* guile/guile.c: Include top.h instead of interps.h.
(guile_repl_command, guile_command, gdbscm_execute_gdb_command):
Access the current UI's async field instead of the
interpreter_async global.
* guile/scm-ports.c: Include top.h instead of interps.h.
(ioscm_with_output_to_port_worker): Access the current UI's async
field instead of the interpreter_async global.
* inf-loop.c (inferior_event_handler): Likewise.
* infcall.c (run_inferior_call): Likewise.
* infrun.c (reinstall_readline_callback_handler_cleanup)
(fetch_inferior_event): Likewise.
* interps.c (interpreter_async): Delete.
(struct ui_interp_info): New.
(get_current_interp_info): New function.
(interp_list, current_interpreter, top_level_interpreter_ptr):
Delete.
(interp_add, interp_set, interp_lookup, interp_ui_out)
(current_interp_set_logging, interp_set_temp)
(current_interp_named_p): Adjust to per-UI interpreters.
(command_interpreter): Delete.
(command_interp, current_interp_command_loop, interp_quiet_p)
(interp_exec, interpreter_exec_cmd, interpreter_completer)
(top_level_interpreter, top_level_interpreter_data): Adjust to
per-UI interpreters.
* interps.h (interpreter_async): Delete.
* main.c (captured_command_loop): Access the current UI's async
field instead of the interpreter_async global.
* python/python.c (python_interactive_command, python_command)
(execute_gdb_command): Likewise.
* top.c (maybe_wait_sync_command_done, execute_command_to_string):
Access the current UI's async field instead of the
interpreter_async global.
* top.h (struct tl_interp_info): Forward declare.
(struct ui) <interp_info, async>: New fields.