X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gdb%2Flinux-tdep.c;h=5b3b8874d11a0d4dd829894a77463365dd56c3f3;hb=098caef485a4ece6096e6cdbb4cd9726e4a13386;hp=bacb61398fab6e384da3db3e50e3313f7dcee560;hpb=dda83cd783075941aabe9b0292b004b11f00c831;p=binutils-gdb.git diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c index bacb61398fa..5b3b8874d11 100644 --- a/gdb/linux-tdep.c +++ b/gdb/linux-tdep.c @@ -1,6 +1,6 @@ /* Target-dependent code for GNU/Linux, architecture independent. - Copyright (C) 2009-2020 Free Software Foundation, Inc. + Copyright (C) 2009-2021 Free Software Foundation, Inc. This file is part of GDB. @@ -166,14 +166,15 @@ enum static struct gdbarch_data *linux_gdbarch_data_handle; struct linux_gdbarch_data - { - struct type *siginfo_type; - }; +{ + struct type *siginfo_type; + int num_disp_step_buffers; +}; static void * -init_linux_gdbarch_data (struct gdbarch *gdbarch) +init_linux_gdbarch_data (struct obstack *obstack) { - return GDBARCH_OBSTACK_ZALLOC (gdbarch, struct linux_gdbarch_data); + return obstack_zalloc (obstack); } static struct linux_gdbarch_data * @@ -199,6 +200,9 @@ struct linux_info yet. Positive if we tried looking it up, and found it. Negative if we tried looking it up but failed. */ int vsyscall_range_p = 0; + + /* Inferior's displaced step buffers. */ + gdb::optional disp_step_bufs; }; /* Per-inferior data key. */ @@ -217,13 +221,11 @@ invalidate_linux_cache_inf (struct inferior *inf) valid INFO pointer. */ static struct linux_info * -get_linux_inferior_data (void) +get_linux_inferior_data (inferior *inf) { - struct linux_info *info; - struct inferior *inf = current_inferior (); + linux_info *info = linux_inferior_data.get (inf); - info = linux_inferior_data.get (inf); - if (info == NULL) + if (info == nullptr) info = linux_inferior_data.emplace (inf); return info; @@ -742,7 +744,7 @@ dump_note_entry_p (filter_flags filterflags, const struct smaps_vmflags *v, /* Otherwise, any other file-based mapping should be placed in the note. */ - return filename != nullptr; + return 1; } /* Implement the "info proc" command. */ @@ -1072,8 +1074,7 @@ linux_read_core_file_mappings (struct gdbarch *gdbarch, ULONGEST start, ULONGEST end, ULONGEST file_ofs, - const char *filename, - const void *other)> + const char *filename)> loop_cb) { /* Ensure that ULONGEST is big enough for reading 64-bit core files. */ @@ -1157,7 +1158,7 @@ linux_read_core_file_mappings (struct gdbarch *gdbarch, char * filename = filenames; filenames += strlen ((char *) filenames) + 1; - loop_cb (i, start, end, file_ofs, filename, nullptr); + loop_cb (i, start, end, file_ofs, filename); } } @@ -1186,7 +1187,7 @@ linux_core_info_proc_mappings (struct gdbarch *gdbarch, const char *args) } }, [=] (int num, ULONGEST start, ULONGEST end, ULONGEST file_ofs, - const char *filename, const void *other) + const char *filename) { if (gdbarch_addr_bit (gdbarch) == 32) printf_filtered ("\t%10s %10s %10s %10s %s\n", @@ -2408,7 +2409,7 @@ linux_vsyscall_range_raw (struct gdbarch *gdbarch, struct mem_range *range) static int linux_vsyscall_range (struct gdbarch *gdbarch, struct mem_range *range) { - struct linux_info *info = get_linux_inferior_data (); + struct linux_info *info = get_linux_inferior_data (current_inferior ()); if (info->vsyscall_range_p == 0) { @@ -2534,6 +2535,75 @@ linux_displaced_step_location (struct gdbarch *gdbarch) /* See linux-tdep.h. */ +displaced_step_prepare_status +linux_displaced_step_prepare (gdbarch *arch, thread_info *thread, + CORE_ADDR &displaced_pc) +{ + linux_info *per_inferior = get_linux_inferior_data (thread->inf); + + if (!per_inferior->disp_step_bufs.has_value ()) + { + /* Figure out the location of the buffers. They are contiguous, starting + at DISP_STEP_BUF_ADDR. They are all of size BUF_LEN. */ + CORE_ADDR disp_step_buf_addr + = linux_displaced_step_location (thread->inf->gdbarch); + int buf_len = gdbarch_max_insn_length (arch); + + linux_gdbarch_data *gdbarch_data = get_linux_gdbarch_data (arch); + gdb_assert (gdbarch_data->num_disp_step_buffers > 0); + + std::vector buffers; + for (int i = 0; i < gdbarch_data->num_disp_step_buffers; i++) + buffers.push_back (disp_step_buf_addr + i * buf_len); + + per_inferior->disp_step_bufs.emplace (buffers); + } + + return per_inferior->disp_step_bufs->prepare (thread, displaced_pc); +} + +/* See linux-tdep.h. */ + +displaced_step_finish_status +linux_displaced_step_finish (gdbarch *arch, thread_info *thread, gdb_signal sig) +{ + linux_info *per_inferior = get_linux_inferior_data (thread->inf); + + gdb_assert (per_inferior->disp_step_bufs.has_value ()); + + return per_inferior->disp_step_bufs->finish (arch, thread, sig); +} + +/* See linux-tdep.h. */ + +const displaced_step_copy_insn_closure * +linux_displaced_step_copy_insn_closure_by_addr (inferior *inf, CORE_ADDR addr) +{ + linux_info *per_inferior = linux_inferior_data.get (inf); + + if (per_inferior == nullptr + || !per_inferior->disp_step_bufs.has_value ()) + return nullptr; + + return per_inferior->disp_step_bufs->copy_insn_closure_by_addr (addr); +} + +/* See linux-tdep.h. */ + +void +linux_displaced_step_restore_all_in_ptid (inferior *parent_inf, ptid_t ptid) +{ + linux_info *per_inferior = linux_inferior_data.get (parent_inf); + + if (per_inferior == nullptr + || !per_inferior->disp_step_bufs.has_value ()) + return; + + per_inferior->disp_step_bufs->restore_in_ptid (ptid); +} + +/* See linux-tdep.h. */ + CORE_ADDR linux_get_hwcap (struct target_ops *target) { @@ -2577,11 +2647,29 @@ show_dump_excluded_mappings (struct ui_file *file, int from_tty, } /* To be called from the various GDB_OSABI_LINUX handlers for the - various GNU/Linux architectures and machine types. */ + various GNU/Linux architectures and machine types. + + NUM_DISP_STEP_BUFFERS is the number of displaced step buffers to use. If 0, + displaced stepping is not supported. */ void -linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch, + int num_disp_step_buffers) { + if (num_disp_step_buffers > 0) + { + linux_gdbarch_data *gdbarch_data = get_linux_gdbarch_data (gdbarch); + gdbarch_data->num_disp_step_buffers = num_disp_step_buffers; + + set_gdbarch_displaced_step_prepare (gdbarch, + linux_displaced_step_prepare); + set_gdbarch_displaced_step_finish (gdbarch, linux_displaced_step_finish); + set_gdbarch_displaced_step_copy_insn_closure_by_addr + (gdbarch, linux_displaced_step_copy_insn_closure_by_addr); + set_gdbarch_displaced_step_restore_all_in_ptid + (gdbarch, linux_displaced_step_restore_all_in_ptid); + } + set_gdbarch_core_pid_to_str (gdbarch, linux_core_pid_to_str); set_gdbarch_info_proc (gdbarch, linux_info_proc); set_gdbarch_core_info_proc (gdbarch, linux_core_info_proc); @@ -2606,11 +2694,12 @@ void _initialize_linux_tdep () { linux_gdbarch_data_handle = - gdbarch_data_register_post_init (init_linux_gdbarch_data); + gdbarch_data_register_pre_init (init_linux_gdbarch_data); /* Observers used to invalidate the cache when needed. */ gdb::observers::inferior_exit.attach (invalidate_linux_cache_inf); gdb::observers::inferior_appeared.attach (invalidate_linux_cache_inf); + gdb::observers::inferior_execd.attach (invalidate_linux_cache_inf); add_setshow_boolean_cmd ("use-coredump-filter", class_files, &use_coredump_filter, _("\