diff options
Diffstat (limited to 'gdb')
30 files changed, 961 insertions, 330 deletions
diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 9275f8d..68b5e56 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -769,6 +769,7 @@ ALL_64_TARGET_OBS = \ mips-sde-tdep.o \ mips-tdep.o \ mips64-obsd-tdep.o \ + riscv-canonicalize-syscall-gen.o \ riscv-fbsd-tdep.o \ riscv-linux-tdep.o \ riscv-none-tdep.o \ @@ -40,6 +40,12 @@ namespace into which the library was loaded, if more than one namespace is active. +* New built-in convenience variables $_active_linker_namespaces and + $_current_linker_namespace. These show the number of active linkage + namespaces, and the namespace to which the current location belongs to. + In systems that don't support linkage namespaces, these always return 1 + and [[0]] respectively. + * Add record full support for rv64gc architectures * New commands @@ -56,6 +62,11 @@ show riscv numeric-register-names (e.g 'x1') or their abi names (e.g. 'ra'). Defaults to 'off', matching the old behaviour (abi names). +info linker-namespaces +info linker-namespaces [[N]] + Print information about the given linker namespace (identified as N), + or about all the namespaces if no argument is given. + * Changed commands info sharedlibrary diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index d54ad65..48b193b 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -13046,6 +13046,18 @@ variable which may be @samp{truecolor} or @samp{24bit}. Other color spaces are determined by the "Co" termcap which in turn depends on the @env{TERM} environment variable. +@vindex $_active_linker_namespaces@r{, convenience variable} +@item $_active_linker_namespaces +Number of active linkage namespaces in the inferior. In systems with no +support for linkage namespaces, this variable will always be set to @samp{1}. + +@vindex $_current_linker_namespace@r{, convenience variable} +@item $_current_linker_namespace +The namespace which contains the current location in the inferior. This +returns GDB's internal identifier for namespaces, which is @samp{[[@var{n}]]} +where @var{n} is a zero-based namespace number. In systems with no support +for linkage namespaces, this variable will always be set to @samp{[[0]]}. + @end table @node Convenience Funs @@ -22212,6 +22224,22 @@ less useful than setting a catchpoint, because it does not allow for conditions or commands as a catchpoint does. @table @code +@kindex info linker-namespaces +@item info linker-namespaces +@item info linker-namespaces @code{[[@var{n}]]} + +With no argument, print the number of linker namespaces which are +currently active --- that is, namespaces that have libraries loaded +into them. Then, it prints the number of libraries loaded into each +namespace, and all the libraries loaded into them, in the same way +as @code{info sharedlibrary}. + +If an argument @code{[[@var{n}]]} is provided, only prints the +library count and the libraried for the provided namespace @var{n}. +The surrounding square brackets are optional. +@end table + +@table @code @item set stop-on-solib-events @kindex set stop-on-solib-events This command controls whether @value{GDBN} should give you control diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi index 80f4c14..45f5f70 100644 --- a/gdb/doc/python.texi +++ b/gdb/doc/python.texi @@ -7136,6 +7136,8 @@ Direct 24-bit RGB colors. @end table +It is not possible to sub-class the @code{Color} class. + @node Architectures In Python @subsubsection Python representation of architectures @cindex Python architectures diff --git a/gdb/infrun.c b/gdb/infrun.c index 3d5ede8..0b87287 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -3972,7 +3972,8 @@ delete_just_stopped_threads_single_step_breakpoints (void) void print_target_wait_results (ptid_t waiton_ptid, ptid_t result_ptid, - const struct target_waitstatus &ws) + const struct target_waitstatus &ws, + process_stratum_target *proc_target) { infrun_debug_printf ("target_wait (%s [%s], status) =", waiton_ptid.to_string ().c_str (), @@ -3981,6 +3982,20 @@ print_target_wait_results (ptid_t waiton_ptid, ptid_t result_ptid, result_ptid.to_string ().c_str (), target_pid_to_str (result_ptid).c_str ()); infrun_debug_printf (" %s", ws.to_string ().c_str ()); + + if (proc_target != nullptr) + infrun_debug_printf (" from target %d (%s)", + proc_target->connection_number, + proc_target->shortname ()); +} + +/* Wrapper for print_target_wait_results above for convenience. */ + +static void +print_target_wait_results (ptid_t waiton_ptid, + const execution_control_state &ecs) +{ + print_target_wait_results (waiton_ptid, ecs.ptid, ecs.ws, ecs.target); } /* Select a thread at random, out of those which are resumed and have @@ -4332,7 +4347,8 @@ prepare_for_detach (void) event.ptid = do_target_wait_1 (inf, pid_ptid, &event.ws, 0); if (debug_infrun) - print_target_wait_results (pid_ptid, event.ptid, event.ws); + print_target_wait_results (pid_ptid, event.ptid, event.ws, + event.target); handle_one (event); } @@ -4388,7 +4404,7 @@ wait_for_inferior (inferior *inf) ecs.target = inf->process_target (); if (debug_infrun) - print_target_wait_results (minus_one_ptid, ecs.ptid, ecs.ws); + print_target_wait_results (minus_one_ptid, ecs); /* Now figure out what to do with the result of the result. */ handle_inferior_event (&ecs); @@ -4669,7 +4685,7 @@ fetch_inferior_event () switch_to_target_no_thread (ecs.target); if (debug_infrun) - print_target_wait_results (minus_one_ptid, ecs.ptid, ecs.ws); + print_target_wait_results (minus_one_ptid, ecs); /* If an error happens while handling the event, propagate GDB's knowledge of the executing state to the frontend/user running @@ -5232,7 +5248,8 @@ poll_one_curr_target (struct target_waitstatus *ws) event_ptid = target_wait (minus_one_ptid, ws, TARGET_WNOHANG); if (debug_infrun) - print_target_wait_results (minus_one_ptid, event_ptid, *ws); + print_target_wait_results (minus_one_ptid, event_ptid, *ws, + current_inferior ()->process_target ()); return event_ptid; } diff --git a/gdb/infrun.h b/gdb/infrun.h index 2067fd5..b9b64ac 100644 --- a/gdb/infrun.h +++ b/gdb/infrun.h @@ -256,7 +256,8 @@ extern void print_stop_event (struct ui_out *uiout, bool displays = true); /* Pretty print the results of target_wait, for debugging purposes. */ extern void print_target_wait_results (ptid_t waiton_ptid, ptid_t result_ptid, - const struct target_waitstatus &ws); + const struct target_waitstatus &ws, + process_stratum_target *proc_target); extern int signal_stop_state (int); diff --git a/gdb/python/py-color.c b/gdb/python/py-color.c index 9e29ee2..c48d14e 100644 --- a/gdb/python/py-color.c +++ b/gdb/python/py-color.c @@ -64,7 +64,8 @@ create_color_object (const ui_file_style::color &color) bool gdbpy_is_color (PyObject *obj) { - return PyObject_IsInstance (obj, (PyObject *) &colorpy_object_type); + gdb_assert (obj != nullptr); + return PyObject_TypeCheck (obj, &colorpy_object_type) != 0; } /* See py-color.h. */ @@ -312,7 +313,7 @@ PyTypeObject colorpy_object_type = get_attr, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ "GDB color object", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ diff --git a/gdb/python/py-disasm.c b/gdb/python/py-disasm.c index 9ca8d22..17064dc 100644 --- a/gdb/python/py-disasm.c +++ b/gdb/python/py-disasm.c @@ -1311,12 +1311,13 @@ gdbpy_print_insn (struct gdbarch *gdbarch, CORE_ADDR memaddr, return {}; } - /* Check the result is a DisassemblerResult (or a sub-class). */ - if (!PyObject_IsInstance (result.get (), - (PyObject *) &disasm_result_object_type)) + /* Check the result is a DisassemblerResult. */ + if (!PyObject_TypeCheck (result.get (), &disasm_result_object_type)) { - PyErr_SetString (PyExc_TypeError, - _("Result is not a DisassemblerResult.")); + PyErr_Format + (PyExc_TypeError, + _("Result from Disassembler must be gdb.DisassemblerResult, not %s."), + Py_TYPE (result.get ())->tp_name); gdbpy_print_stack (); return std::optional<int> (-1); } diff --git a/gdb/python/py-registers.c b/gdb/python/py-registers.c index 78a806c..9be2e3c 100644 --- a/gdb/python/py-registers.c +++ b/gdb/python/py-registers.c @@ -403,8 +403,7 @@ gdbpy_parse_register_id (struct gdbarch *gdbarch, PyObject *pyo_reg_id, PyErr_SetString (PyExc_ValueError, "Bad register"); } /* The register could be a gdb.RegisterDescriptor object. */ - else if (PyObject_IsInstance (pyo_reg_id, - (PyObject *) ®ister_descriptor_object_type)) + else if (PyObject_TypeCheck (pyo_reg_id, ®ister_descriptor_object_type)) { register_descriptor_object *reg = (register_descriptor_object *) pyo_reg_id; diff --git a/gdb/remote.c b/gdb/remote.c index 7dc057c..75cc21c 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -4943,7 +4943,7 @@ remote_target::process_initial_stop_replies (int from_tty) event_ptid = target_wait (waiton_ptid, &ws, TARGET_WNOHANG); if (remote_debug) - print_target_wait_results (waiton_ptid, event_ptid, ws); + print_target_wait_results (waiton_ptid, event_ptid, ws, this); switch (ws.kind ()) { diff --git a/gdb/riscv-canonicalize-syscall-gen.c b/gdb/riscv-canonicalize-syscall-gen.c index 3749fc3..67e5410 100644 --- a/gdb/riscv-canonicalize-syscall-gen.c +++ b/gdb/riscv-canonicalize-syscall-gen.c @@ -250,7 +250,7 @@ riscv64_canonicalize_syscall (int syscall) case 219: return gdb_sys_keyctl; case 220: return gdb_sys_clone; case 221: return gdb_sys_execve; - case 222: return gdb_old_mmap; + case 222: return gdb_sys_old_mmap; case 223: return gdb_sys_fadvise64; case 224: return gdb_sys_swapon; case 225: return gdb_sys_swapoff; @@ -270,7 +270,7 @@ riscv64_canonicalize_syscall (int syscall) case 239: return gdb_sys_move_pages; /* case 240: return gdb_sys_rt_tgsigqueueinfo; */ /* case 241: return gdb_sys_perf_event_open; */ - /* case 242: return gdb_sys_accept4; */ + case 242: return gdb_sys_accept4; /* case 243: return gdb_sys_recvmmsg; */ /* case 258: return gdb_sys_riscv_hwprobe; */ /* case 259: return gdb_sys_riscv_flush_icache; */ @@ -336,6 +336,22 @@ riscv64_canonicalize_syscall (int syscall) /* case 448: return gdb_sys_process_mrelease; */ /* case 449: return gdb_sys_futex_waitv; */ /* case 450: return gdb_sys_set_mempolicy_home_node; */ + /* case 451: return gdb_sys_cachestat; */ + /* case 452: return gdb_sys_fchmodat2; */ + /* case 453: return gdb_sys_map_shadow_stack; */ + /* case 454: return gdb_sys_futex_wake; */ + /* case 455: return gdb_sys_futex_wait; */ + /* case 456: return gdb_sys_futex_requeue; */ + /* case 457: return gdb_sys_statmount; */ + /* case 458: return gdb_sys_listmount; */ + /* case 459: return gdb_sys_lsm_get_self_attr; */ + /* case 460: return gdb_sys_lsm_set_self_attr; */ + /* case 461: return gdb_sys_lsm_list_modules; */ + /* case 462: return gdb_sys_mseal; */ + /* case 463: return gdb_sys_setxattrat; */ + /* case 464: return gdb_sys_getxattrat; */ + /* case 465: return gdb_sys_listxattrat; */ + /* case 466: return gdb_sys_removexattrat; */ default: return gdb_sys_no_syscall; } diff --git a/gdb/riscv-linux-tdep.h b/gdb/riscv-linux-tdep.h index 0f481b1..9dd9e37 100644 --- a/gdb/riscv-linux-tdep.h +++ b/gdb/riscv-linux-tdep.h @@ -15,8 +15,8 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef RISCV_LINUX_TDEP_H -#define RISCV_LINUX_TDEP_H +#ifndef GDB_RISCV_LINUX_TDEP_H +#define GDB_RISCV_LINUX_TDEP_H #include "linux-record.h" @@ -26,4 +26,4 @@ extern enum gdb_syscall riscv64_canonicalize_syscall (int syscall); -#endif /* RISCV_LINUX_TDEP_H */ +#endif /* GDB_RISCV_LINUX_TDEP_H */ diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c index 83cb389..2a2745d 100644 --- a/gdb/solib-svr4.c +++ b/gdb/solib-svr4.c @@ -451,6 +451,12 @@ svr4_maybe_add_namespace (svr4_info *info, CORE_ADDR lmid) info->namespace_id.push_back (lmid); info->active_namespaces.insert (i); + + /* Create or update the convenience variable "active_namespaces". + It only needs to be updated here, as this only changes when a + dlmopen or dlclose call happens. */ + set_internalvar_integer (lookup_internalvar ("_active_linker_namespaces"), + info->active_namespaces.size ()); } /* Return whether DEBUG_BASE is the default namespace of INFO. */ @@ -3552,6 +3558,54 @@ svr4_num_active_namespaces () return info->active_namespaces.size (); } +/* See solib_ops::get_solibs_in_ns in solist.h. */ +static std::vector<const solib *> +svr4_get_solibs_in_ns (int nsid) +{ + std::vector<const solib*> ns_solibs; + svr4_info *info = get_svr4_info (current_program_space); + + /* If the namespace ID is inactive, there will be no active + libraries, so we can have an early exit, as a treat. */ + if (info->active_namespaces.count (nsid) != 1) + return ns_solibs; + + /* Since we only have the names of solibs in a given namespace, + we'll need to walk through the solib list of the inferior and + find which solib objects correspond to which svr4_so. We create + an unordered map with the names and lm_info to check things + faster, and to be able to remove SOs from the map, to avoid + returning the dynamic linker multiple times. */ + CORE_ADDR debug_base = info->namespace_id[nsid]; + std::unordered_map<std::string, const lm_info_svr4 *> namespace_solibs; + for (svr4_so &so : info->solib_lists[debug_base]) + { + namespace_solibs[so.name] + = gdb::checked_static_cast<const lm_info_svr4 *> + (so.lm_info.get ()); + } + for (const solib &so: current_program_space->solibs ()) + { + auto *lm_inferior + = gdb::checked_static_cast<const lm_info_svr4 *> (so.lm_info.get ()); + + /* This is inspired by the svr4_same, by finding the svr4_so object + in the map, and then double checking if the lm_info is considered + the same. */ + if (namespace_solibs.count (so.so_original_name) > 0 + && namespace_solibs[so.so_original_name]->l_addr_inferior + == lm_inferior->l_addr_inferior) + { + ns_solibs.push_back (&so); + /* Remove the SO from the map, so that we don't end up + printing the dynamic linker multiple times. */ + namespace_solibs.erase (so.so_original_name); + } + } + + return ns_solibs; +} + const struct solib_ops svr4_so_ops = { svr4_relocate_section_addresses, @@ -3569,6 +3623,7 @@ const struct solib_ops svr4_so_ops = svr4_find_solib_addr, svr4_find_solib_ns, svr4_num_active_namespaces, + svr4_get_solibs_in_ns, }; void _initialize_svr4_solib (); diff --git a/gdb/solib.c b/gdb/solib.c index 4876f1a..5c5cfbd 100644 --- a/gdb/solib.c +++ b/gdb/solib.c @@ -1010,84 +1010,61 @@ solib_add (const char *pattern, int from_tty, int readsyms) } } -/* Implement the "info sharedlibrary" command. Walk through the - shared library list and print information about each attached - library matching PATTERN. If PATTERN is elided, print them - all. */ +/* Helper function for "info sharedlibrary" and "info namespace". + This receives a list of solibs to be printed, and prints a table + with all the relevant data. If PRINT_NAMESPACE is true, figure out + the solib_ops of the current gdbarch, to calculate the namespace + that contains an solib. + Returns true if one or more solibs are missing debug information, + false otherwise. */ static void -info_sharedlibrary_command (const char *pattern, int from_tty) +print_solib_list_table (std::vector<const solib *> solib_list, + bool print_namespace) { - bool so_missing_debug_info = false; - int addr_width; - int nr_libs; gdbarch *gdbarch = current_inferior ()->arch (); - struct ui_out *uiout = current_uiout; - - if (pattern) - { - char *re_err = re_comp (pattern); - - if (re_err) - error (_ ("Invalid regexp: %s"), re_err); - } - /* "0x", a little whitespace, and two hex digits per byte of pointers. */ - addr_width = 4 + (gdbarch_ptr_bit (gdbarch) / 4); - - update_solib_list (from_tty); - - /* ui_out_emit_table table_emitter needs to know the number of rows, - so we need to make two passes over the libs. */ + int addr_width = 4 + (gdbarch_ptr_bit (gdbarch) / 4); + const solib_ops *ops = gdbarch_so_ops (gdbarch); + struct ui_out *uiout = current_uiout; + bool so_missing_debug_info = false; - nr_libs = 0; - for (const solib &so : current_program_space->solibs ()) - { - if (!so.so_name.empty ()) - { - if (pattern && !re_exec (so.so_name.c_str ())) - continue; - ++nr_libs; - } - } + /* There are 3 conditions for this command to print solib namespaces, + first PRINT_NAMESPACE has to be true, second the solib_ops has to + support multiple namespaces, and third there must be more than one + active namespace. Fold all these into the PRINT_NAMESPACE condition. */ + print_namespace = print_namespace && ops->num_active_namespaces != nullptr + && ops->num_active_namespaces () > 1; - /* How many columns the table should have. If the inferior has - more than one namespace active, we need a column to show that. */ int num_cols = 4; - const solib_ops *ops = gdbarch_so_ops (gdbarch); - if (ops->num_active_namespaces != nullptr - && ops->num_active_namespaces () > 1) + if (print_namespace) num_cols++; { - ui_out_emit_table table_emitter (uiout, num_cols, nr_libs, + ui_out_emit_table table_emitter (uiout, num_cols, solib_list.size (), "SharedLibraryTable"); /* The "- 1" is because ui_out adds one space between columns. */ uiout->table_header (addr_width - 1, ui_left, "from", "From"); uiout->table_header (addr_width - 1, ui_left, "to", "To"); - if (ops->num_active_namespaces != nullptr - && ops->num_active_namespaces () > 1) + if (print_namespace) uiout->table_header (5, ui_left, "namespace", "NS"); uiout->table_header (12 - 1, ui_left, "syms-read", "Syms Read"); uiout->table_header (0, ui_noalign, "name", "Shared Object Library"); uiout->table_body (); - for (const solib &so : current_program_space->solibs ()) + for (const solib *so : solib_list) { - if (so.so_name.empty ()) - continue; - - if (pattern && !re_exec (so.so_name.c_str ())) + if (so->so_name.empty ()) continue; ui_out_emit_tuple tuple_emitter (uiout, "lib"); - if (so.addr_high != 0) + if (so->addr_high != 0) { - uiout->field_core_addr ("from", gdbarch, so.addr_low); - uiout->field_core_addr ("to", gdbarch, so.addr_high); + uiout->field_core_addr ("from", gdbarch, so->addr_low); + uiout->field_core_addr ("to", gdbarch, so->addr_high); } else { @@ -1095,12 +1072,11 @@ info_sharedlibrary_command (const char *pattern, int from_tty) uiout->field_skip ("to"); } - if (ops->num_active_namespaces != nullptr - && ops->num_active_namespaces ()> 1) + if (print_namespace) { try { - uiout->field_fmt ("namespace", "[[%d]]", ops->find_solib_ns (so)); + uiout->field_fmt ("namespace", "[[%d]]", ops->find_solib_ns (*so)); } catch (const gdb_exception_error &er) { @@ -1109,32 +1085,157 @@ info_sharedlibrary_command (const char *pattern, int from_tty) } if (!top_level_interpreter ()->interp_ui_out ()->is_mi_like_p () - && so.symbols_loaded && !objfile_has_symbols (so.objfile)) + && so->symbols_loaded && !objfile_has_symbols (so->objfile)) { so_missing_debug_info = true; uiout->field_string ("syms-read", "Yes (*)"); } else - uiout->field_string ("syms-read", so.symbols_loaded ? "Yes" : "No"); + uiout->field_string ("syms-read", so->symbols_loaded ? "Yes" : "No"); - uiout->field_string ("name", so.so_name, file_name_style.style ()); + uiout->field_string ("name", so->so_name, file_name_style.style ()); uiout->text ("\n"); } } - if (nr_libs == 0) + if (so_missing_debug_info) + uiout->message (_ ("(*): Shared library is missing " + "debugging information.\n")); +} + +/* Implement the "info sharedlibrary" command. Walk through the + shared library list and print information about each attached + library matching PATTERN. If PATTERN is elided, print them + all. */ + +static void +info_sharedlibrary_command (const char *pattern, int from_tty) +{ + struct ui_out *uiout = current_uiout; + + if (pattern) + { + char *re_err = re_comp (pattern); + + if (re_err) + error (_ ("Invalid regexp: %s"), re_err); + } + + update_solib_list (from_tty); + + /* ui_out_emit_table table_emitter needs to know the number of rows, + so we need to make two passes over the libs. */ + + std::vector<const solib *> print_libs; + for (const solib &so : current_program_space->solibs ()) + { + if (!so.so_name.empty ()) + { + if (pattern && !re_exec (so.so_name.c_str ())) + continue; + print_libs.push_back (&so); + } + } + + print_solib_list_table (print_libs, true); + + if (print_libs.size () == 0) { if (pattern) uiout->message (_ ("No shared libraries matched.\n")); else uiout->message (_ ("No shared libraries loaded at this time.\n")); } +} + +/* Implement the "info linker-namespaces" command. If the current + gdbarch's solib_ops object does not support multiple namespaces, + this command would just look like "info sharedlibrary", so point + the user to that command instead. + If solib_ops does support multiple namespaces, this command + will group the libraries by linker namespace, or only print the + libraries in the supplied namespace. */ +static void +info_linker_namespace_command (const char *pattern, int from_tty) +{ + const solib_ops *ops = gdbarch_so_ops (current_inferior ()->arch ()); + /* This command only really makes sense for inferiors that support + linker namespaces, so we can leave early. */ + if (ops->num_active_namespaces == nullptr) + error (_("Current inferior does not support linker namespaces." \ + "Use \"info sharedlibrary\" instead")); + + struct ui_out *uiout = current_uiout; + std::vector<std::pair<int, std::vector<const solib *>>> all_solibs_to_print; + + if (pattern != nullptr) + while (*pattern == ' ') + pattern++; + + if (pattern == nullptr || pattern[0] == '\0') + { + uiout->message (_ ("There are %d linker namespaces loaded\n"), + ops->num_active_namespaces ()); + + int printed = 0; + for (int i = 0; printed < ops->num_active_namespaces (); i++) + { + std::vector<const solib *> solibs_to_print + = ops->get_solibs_in_ns (i); + if (solibs_to_print.size () > 0) + { + all_solibs_to_print.push_back (std::make_pair + (i, solibs_to_print)); + printed++; + } + } + } else { - if (so_missing_debug_info) - uiout->message (_ ("(*): Shared library is missing " - "debugging information.\n")); + int ns; + /* Check if the pattern includes the optional [[ and ]] decorators. + To match multiple occurrences, '+' needs to be escaped, and every + escape sequence must be doubled to survive the compiler pass. */ + re_comp ("^\\[\\[[0-9]\\+\\]\\]$"); + if (re_exec (pattern)) + ns = strtol (pattern+2, nullptr, 10); + else + { + char * end = nullptr; + ns = strtol (pattern, &end, 10); + if (end[0] != '\0') + error (_ ("Invalid linker namespace identifier: %s"), pattern); + } + + all_solibs_to_print.push_back + (std::make_pair (ns, ops->get_solibs_in_ns (ns))); + } + + bool ns_separator = false; + + for (auto &solibs_pair : all_solibs_to_print) + { + if (ns_separator) + uiout->message ("\n\n"); + else + ns_separator = true; + int ns = solibs_pair.first; + std::vector<const solib *> solibs_to_print = solibs_pair.second; + if (solibs_to_print.size () == 0) + { + uiout->message (_("Linker namespace [[%d]] is not active.\n"), ns); + /* If we got here, a specific namespace was requested, so there + will only be one vector. We can leave early. */ + break; + } + uiout->message + (_ ("There are %ld libraries loaded in linker namespace [[%d]]\n"), + solibs_to_print.size (), ns); + uiout->message + (_ ("Displaying libraries for linker namespace [[%d]]:\n"), ns); + + print_solib_list_table (solibs_to_print, false); } } @@ -1715,6 +1816,44 @@ default_find_solib_addr (solib &so) return {}; } +/* Implementation of the current_linker_namespace convenience variable. + This returns the GDB internal identifier of the linker namespace, + for the current frame, in the form '[[<number>]]'. If the inferior + doesn't support linker namespaces, this always returns [[0]]. */ + +static value * +current_linker_namespace_make_value (gdbarch *gdbarch, internalvar *var, + void *ignore) +{ + const solib_ops *ops = gdbarch_so_ops (gdbarch); + const language_defn *lang = language_def (get_frame_language + (get_current_frame ())); + std::string nsid = "[[0]]"; + if (ops->find_solib_ns != nullptr) + { + CORE_ADDR curr_pc = get_frame_pc (get_current_frame ()); + for (const solib &so : current_program_space->solibs ()) + if (solib_contains_address_p (so, curr_pc)) + { + nsid = string_printf ("[[%d]]", ops->find_solib_ns (so)); + break; + } + } + + + /* If the PC is not in an SO, or the solib_ops doesn't support + linker namespaces, the inferior is in the default namespace. */ + return lang->value_string (gdbarch, nsid.c_str (), nsid.length ()); +} + +/* Implementation of `$_current_linker_namespace' variable. */ + +static const struct internalvar_funcs current_linker_namespace_funcs = +{ + current_linker_namespace_make_value, + nullptr, +}; + void _initialize_solib (); void @@ -1727,6 +1866,13 @@ _initialize_solib () }, "solib"); + /* Convenience variables for debugging linker namespaces. These are + set here, even if the solib_ops doesn't support them, + for consistency. */ + create_internalvar_type_lazy ("_current_linker_namespace", + ¤t_linker_namespace_funcs, nullptr); + set_internalvar_integer (lookup_internalvar ("_active_linker_namespaces"), 1); + add_com ( "sharedlibrary", class_files, sharedlibrary_command, _ ("Load shared object library symbols for files matching REGEXP.")); @@ -1737,6 +1883,9 @@ _initialize_solib () add_com ("nosharedlibrary", class_files, no_shared_libraries_command, _ ("Unload all shared object library symbols.")); + add_info ("linker-namespaces", info_linker_namespace_command, + _ ("Get information about linker namespaces in the inferior.")); + add_setshow_boolean_cmd ("auto-solib-add", class_support, &auto_solib_add, _ ("\ Set autoloading of shared library symbols."), diff --git a/gdb/solist.h b/gdb/solist.h index 0b7bbf9..6ab5a06 100644 --- a/gdb/solist.h +++ b/gdb/solist.h @@ -194,6 +194,10 @@ struct solib_ops /* Returns the number of active namespaces in the inferior. */ int (*num_active_namespaces) (); + + /* Returns all solibs for a given namespace. If the namespace is not + active, returns an empty vector. */ + std::vector<const solib *> (*get_solibs_in_ns) (int ns); }; /* A unique pointer to a so_list. */ diff --git a/gdb/syscalls/riscv-canonicalize-syscall-gen.py b/gdb/syscalls/riscv-canonicalize-syscall-gen.py index aa07ac1..30e52b7 100755 --- a/gdb/syscalls/riscv-canonicalize-syscall-gen.py +++ b/gdb/syscalls/riscv-canonicalize-syscall-gen.py @@ -32,7 +32,7 @@ # options: # -h, --help show this help message and exit # -i INPUT, --input INPUT -# path to riscv linux syscalls (riscv-glibc/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h) +# path to riscv linux syscalls (glibc/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h) import argparse import re @@ -142,7 +142,7 @@ def setup_parser() -> argparse.ArgumentParser: "--input", type=_Path, required=True, - help="path to riscv linux syscalls (riscv-glibc/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h)", + help="path to riscv linux syscalls (glibc/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h)", ) return parser diff --git a/gdb/testsuite/gdb.base/bg-execution-repeat.exp b/gdb/testsuite/gdb.base/bg-execution-repeat.exp index b1496ee..d5580fb 100644 --- a/gdb/testsuite/gdb.base/bg-execution-repeat.exp +++ b/gdb/testsuite/gdb.base/bg-execution-repeat.exp @@ -67,6 +67,17 @@ proc test {continue_cmd} { # enable the "set var" command with an interrupt / continue& pair. gdb_test -no-prompt-anchor "interrupt" + set test "interrupt received" + set re [string_to_regexp "Program received signal SIGINT, Interrupt."] + gdb_expect { + -re $re { + pass $test + } + timeout { + fail "$test (timeout)" + } + } + # Allow the breakpoint to trigger. gdb_test -no-prompt-anchor "set var do_wait=0" diff --git a/gdb/testsuite/gdb.base/default.exp b/gdb/testsuite/gdb.base/default.exp index d4d6b20..3abd049 100644 --- a/gdb/testsuite/gdb.base/default.exp +++ b/gdb/testsuite/gdb.base/default.exp @@ -699,6 +699,8 @@ set show_conv_list \ {$_gdb_minor = 1} \ {$_shell_exitsignal = void} \ {$_shell_exitcode = 0} \ + {$_active_linker_namespaces = 1} \ + {$_current_linker_namespace = <error: No registers.>}\ } if [allow_python_tests] { append show_conv_list \ diff --git a/gdb/testsuite/gdb.base/dlmopen-ns-ids-main.c b/gdb/testsuite/gdb.base/dlmopen-ns-ids-main.c index 3bcd819..c7c038a 100644 --- a/gdb/testsuite/gdb.base/dlmopen-ns-ids-main.c +++ b/gdb/testsuite/gdb.base/dlmopen-ns-ids-main.c @@ -41,6 +41,12 @@ main (void) handle[2] = dlmopen (LM_ID_NEWLM, DSO_NAME, RTLD_LAZY | RTLD_LOCAL); assert (handle[2] != NULL); + for (dl = 2; dl >= 0; dl--) + { + fun = dlsym (handle[dl], "inc"); + fun (dl); + } + dlclose (handle[0]); /* TAG: first dlclose */ dlclose (handle[1]); /* TAG: second dlclose */ dlclose (handle[2]); /* TAG: third dlclose */ diff --git a/gdb/testsuite/gdb.base/dlmopen-ns-ids.exp b/gdb/testsuite/gdb.base/dlmopen-ns-ids.exp index 3ddc07e..8f52199 100644 --- a/gdb/testsuite/gdb.base/dlmopen-ns-ids.exp +++ b/gdb/testsuite/gdb.base/dlmopen-ns-ids.exp @@ -105,4 +105,137 @@ proc test_info_shared {} { "after unloading everything" } +# Run all tests related to the linkage namespaces convenience +# variables, _active_namespaces and _current_namespaces. +proc_with_prefix test_conv_vars {} { + clean_restart $::binfile + + gdb_test "print \$_active_linker_namespaces" "1" \ + "1 namespace before starting inferior" + gdb_test "print \$_current_linker_namespace" "No registers." \ + "No current namespace before starting inferior" + + if { ![runto_main] } { + return + } + + gdb_test "print \$_active_linker_namespaces" "1" \ + "Before activating namespaces" + gdb_test "print \$_current_linker_namespace" ".*\"\\\[\\\[0\\\]\\\]\"" \ + "Still in the default namespace" + + gdb_breakpoint "inc" allow-pending + gdb_breakpoint [gdb_get_line_number "TAG: first dlclose"] + + foreach_with_prefix dl {3 2 1} { + gdb_continue_to_breakpoint "inc" + + gdb_test "print \$_current_linker_namespace" ".*\"\\\[\\\[$dl\\\]\\\]\"" \ + "Verify we're in namespace $dl" + } + + gdb_continue_to_breakpoint "first dlclose" + gdb_test "print \$_active_linker_namespaces" "4" "all SOs loaded" + + gdb_test "next" ".*second dlclose.*" "close one SO" + gdb_test "print \$_active_linker_namespaces" "3" "one SOs unloaded" + gdb_test "next" ".*third dlclose.*" "close another SO" + gdb_test "print \$_active_linker_namespaces" "2" "two SOs unloaded" + + # Restarting GDB so that we can test setting a breakpoint + # using the convenience variable, while a proper bp syntax + # isn't implemented for namespaces + clean_restart $::binfile + if {![runto_main]} { + return + } + + # We need to load one SO because you can't have confitional + # breakpoints and pending breakpoints at the same time with + # gdb_breakpoint. + gdb_test "next" ".*assert.*" "load the first SO" + gdb_breakpoint "inc if \$_streq(\$_current_linker_namespace, \"\[\[2\]\]\")" + gdb_continue_to_breakpoint "inc" + gdb_continue_to_end "" continue 1 +} + +# Run several tests relating to the command "info namespaces". +proc test_info_linker_namespaces {} { + clean_restart $::binfile + + if { ![runto_main] } { + return + } + + with_test_prefix "info linker-namespaces" { + gdb_breakpoint [gdb_get_line_number "TAG: first dlclose"] + gdb_continue_to_breakpoint "TAG: first dlclose" + } + + # First, test printing a single namespace, and ensure all of + # them are correct, using both syntaxes. + set found_all_libs false + gdb_test_multiple "info linker-namespaces \[\[0\]\]" "print namespace 0" -lbl { + -re "^\r\nThere are ($::decimal) libraries loaded in linker namespace \\\[\\\[0\\\]\\\]" { + # Some systems may add libc and libm to every loaded namespace, + # others may load only one or neither, because the SO doesn't + # actually use either library. The best we can do is check if + # we found the dynamic linker, and up to 2 more libraries. + set libs $expect_out(1,string) + set found_all_libs [expr $libs - 1 <= 2] + exp_continue + } + -re "^\r\n$::gdb_prompt $" { + gdb_assert $found_all_libs "the correct number of libraries was reported" + } + -re "(^\r\n)?\[^\r\n\]+(?=\r\n)" { + exp_continue + } + } + foreach_with_prefix ns {1 2 3} { + set found_test_so false + set found_all_libs false + gdb_test_multiple "info linker-namespaces $ns" "print namespace $ns" -lbl { + -re "^\r\nThere are ($::decimal) libraries loaded in linker namespace \\\[\\\[$ns\\\]\\\]" { + set libs $expect_out(1,string) + # Some systems may add libc and libm to every loaded namespace, + # others may load only one or neither, because the SO doesn't + # actually use either library. The best we can do is check if + # we found the dynamic linker, the test SO, and maybe up to 2 + # more libraries. + set found_all_libs [expr $libs - 2 <= 2] + exp_continue + } + -re "^\r\n\[^\r\n\]+${::binfile_lib}\[^\r\n\]*(?=\r\n)" { + set found_test_so true + exp_continue + } + -re "^\r\n$::gdb_prompt $" { + gdb_assert $found_test_so "this testfle's SO was reported" + gdb_assert $found_all_libs "the correct number of libraries was reported" + } + -re "(^\r\n)?\[^\r\n\]+(?=\r\n)" { + exp_continue + } + } + } + + # These patterns are simpler, and purposefully glob multiple lines. + # The point is to ensure that we find and display all the namespaces, + # without worrying about the libraries printed, since that was tested + # above. + gdb_test "info linker-namespaces" \ + [multi_line "There are 4 linker namespaces loaded" \ + "There are $::decimal libraries loaded in linker namespace ..0.." \ + ".*" \ + "There are $::decimal libraries loaded in linker namespace ..1.." \ + ".*" \ + "There are $::decimal libraries loaded in linker namespace ..2.." \ + ".*" \ + "There are $::decimal libraries loaded in linker namespace ..3.." \ + ".*" ] "print namespaces with no argument" +} + test_info_shared +test_conv_vars +test_info_linker_namespaces diff --git a/gdb/testsuite/gdb.dwarf2/macro-source-path-clang14-dw4.exp b/gdb/testsuite/gdb.dwarf2/macro-source-path-clang14-dw4.exp new file mode 100644 index 0000000..c0c2635 --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/macro-source-path-clang14-dw4.exp @@ -0,0 +1,71 @@ +# This testcase is part of GDB, the GNU debugger. + +# Copyright 2022-2025 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Generate binaries imitating different ways source file paths can be passed to +# compilers. Test printing macros from those binaries. + +# The do_test proc comes from macro-source-path.exp.tcl. +source $srcdir/$subdir/macro-source-path.exp.tcl + +# When adding a test here, please consider adding an equivalent case to +# `gdb.base/macro-source-path.exp`. + +# The following tests are based on the output of `clang-14 -gdwarf-4 +# -fdebug-macro -g3 <file>` (using its built-in assembler). With -gdwarf-4, +# clang produces a .debug_macinfo section, not a .debug_macro section. But +# this test still creates a .debug_macro section, that's good enough for what +# we want to test. + +## test.c +do_test filename 4 "test.c" 1 { +} { + {"test.c" 0} +} + +## ./test.c +do_test dot-filename 4 "test.c" 1 { + "." +} { + {"test.c" 1} +} + +## ../cwd/test.c +do_test dot-dot-cwd 4 "../cwd/test.c" 1 { + "../cwd" +} { + {"test.c" 1} +} + +## /tmp/cwd/test.c +do_test absolute-cwd 4 "/tmp/cwd/test.c" 1 { +} { + {"test.c" 0} +} + +## ../other/test.c +do_test dot-dot-other 4 "../other/test.c" 1 { + "../other" +} { + {"test.c" 1} +} + +## /tmp/other/test.c +do_test absolute-other 4 "/tmp/other/test.c" 1 { + "/tmp" +} { + {"other/test.c" 1} +} diff --git a/gdb/testsuite/gdb.dwarf2/macro-source-path-clang14-dw5.exp b/gdb/testsuite/gdb.dwarf2/macro-source-path-clang14-dw5.exp new file mode 100644 index 0000000..0b3239e --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/macro-source-path-clang14-dw5.exp @@ -0,0 +1,75 @@ +# This testcase is part of GDB, the GNU debugger. + +# Copyright 2022-2025 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Generate binaries imitating different ways source file paths can be passed to +# compilers. Test printing macros from those binaries. + +# The do_test proc comes from macro-source-path.exp.tcl. +source $srcdir/$subdir/macro-source-path.exp.tcl + +# When adding a test here, please consider adding an equivalent case to +# `gdb.base/macro-source-path.exp`. + +# The following tests are based on the output of `clang-14 -gdwarf-5 +# -fdebug-macro -g3 <file>` (using its built-in assembler) + +## test.c +do_test filename 5 "test.c" 0 { + "/tmp/cwd" +} { + {"test.c" 0} +} + +## ./test.c +do_test dot-filename 5 "test.c" 1 { + "/tmp/cwd" + "." +} { + {"test.c" 0} + {"test.c" 1} +} + +## ../cwd/test.c +do_test dot-dot-cwd 5 "../cwd/test.c" 0 { + "/tmp/cwd" +} { + {"../cwd/test.c" 0} +} + +## /tmp/cwd/test.c +do_test absolute-cwd 5 "/tmp/cwd/test.c" 1 { + "/tmp/cwd" +} { + {"/tmp/cwd/test.c" 0} + {"test.c" 0} +} + +## ../other/test.c +do_test dot-dot-other 5 "../other/test.c" 0 { + "/tmp/cwd" +} { + {"../other/test.c" 0} +} + +## /tmp/other/test.c +do_test absolute-other 5 "/tmp/other/test.c" 1 { + "/tmp/cwd" + "/tmp" +} { + {"/tmp/other/test.c" 0} + {"other/test.c" 1} +} diff --git a/gdb/testsuite/gdb.dwarf2/macro-source-path-gcc11-ld234-dw5.exp b/gdb/testsuite/gdb.dwarf2/macro-source-path-gcc11-ld234-dw5.exp new file mode 100644 index 0000000..940f997 --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/macro-source-path-gcc11-ld234-dw5.exp @@ -0,0 +1,70 @@ +# This testcase is part of GDB, the GNU debugger. + +# Copyright 2022-2025 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Generate binaries imitating different ways source file paths can be passed to +# compilers. Test printing macros from those binaries. + +# The do_test proc comes from macro-source-path.exp.tcl. +source $srcdir/$subdir/macro-source-path.exp.tcl + +# When adding a test here, please consider adding an equivalent case to +# `gdb.base/macro-source-path.exp`. + +# The following tests are based on the output of `gcc -gdwarf-5 -g3 <file>`, +# gcc 11 paired with gas from binutils 2.34 (Ubuntu 20.04). It generates a v5 +# .debug_macro section, but a v3 .debug_line section. + +## test.c +do_test filename 3 "test.c" 1 { +} { + {"test.c" 0} +} + +## ./test.c +do_test dot-filename 3 "./test.c" 1 { + "." +} { + {"test.c" 1} +} + +## ../cwd/test.c +do_test dot-dot-cwd 3 "../cwd/test.c" 1 { + "../cwd" +} { + {"test.c" 1} +} + +## /tmp/cwd/test.c +do_test absolute-cwd 3 "/tmp/cwd/test.c" 1 { + "/tmp/cwd" +} { + {"test.c" 1} +} + +## ../other/test.c +do_test dot-dot-other 3 "../other/test.c" 1 { + "../other" +} { + {"test.c" 1} +} + +## /tmp/other/test.c +do_test absolute-other 3 "/tmp/other/test.c" 1 { + "/tmp/other" +} { + {"test.c" 1} +} diff --git a/gdb/testsuite/gdb.dwarf2/macro-source-path-gcc11-ld238-dw4.exp b/gdb/testsuite/gdb.dwarf2/macro-source-path-gcc11-ld238-dw4.exp new file mode 100644 index 0000000..dea0308 --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/macro-source-path-gcc11-ld238-dw4.exp @@ -0,0 +1,70 @@ +# This testcase is part of GDB, the GNU debugger. + +# Copyright 2022-2025 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Generate binaries imitating different ways source file paths can be passed to +# compilers. Test printing macros from those binaries. + +# The do_test proc comes from macro-source-path.exp.tcl. +source $srcdir/$subdir/macro-source-path.exp.tcl + +# When adding a test here, please consider adding an equivalent case to +# `gdb.base/macro-source-path.exp`. + +# The following tests are based on the output of `gcc -gdwarf-4 -g3 <file>`, +# gcc 11 paired with gas from binutils 2.38. With -gdwarf-4, gcc generates a +# v4 (pre-standard) .debug_macro section. + +## test.c +do_test filename 4 "test.c" 1 { +} { + {"test.c" 0} +} + +## ./test.c +do_test dot-filename 4 "./test.c" 1 { + "." +} { + {"test.c" 1} +} + +## ../cwd/test.c +do_test dot-dot-cwd 4 "../cwd/test.c" 1 { + "../cwd" +} { + {"test.c" 1} +} + +## /tmp/cwd/test.c +do_test absolute-cwd 4 "/tmp/cwd/test.c" 1 { + "/tmp/cwd" +} { + {"test.c" 1} +} + +## ../other/test.c +do_test dot-dot-other 4 "../other/test.c" 1 { + "../other" +} { + {"test.c" 1} +} + +## /tmp/other/test.c +do_test absolute-other 4 "/tmp/other/test.c" 1 { + "/tmp/other" +} { + {"test.c" 1} +} diff --git a/gdb/testsuite/gdb.dwarf2/macro-source-path-gcc11-ld238-dw5.exp b/gdb/testsuite/gdb.dwarf2/macro-source-path-gcc11-ld238-dw5.exp new file mode 100644 index 0000000..98a278e --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/macro-source-path-gcc11-ld238-dw5.exp @@ -0,0 +1,81 @@ +# This testcase is part of GDB, the GNU debugger. + +# Copyright 2022-2025 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Generate binaries imitating different ways source file paths can be passed to +# compilers. Test printing macros from those binaries. + +# The do_test proc comes from macro-source-path.exp.tcl. +source $srcdir/$subdir/macro-source-path.exp.tcl + +# When adding a test here, please consider adding an equivalent case to +# `gdb.base/macro-source-path.exp`. + +# The following tests are based on the output of `gcc -gdwarf-5 -g3 <file>`, +# gcc 11 paired with gas from binutils 2.38. + +## test.c +do_test filename 5 "test.c" 1 { + "/tmp/cwd" +} { + {"test.c" 0} + {"test.c" 0} +} + +## ./test.c +do_test dot-filename 5 "./test.c" 1 { + "/tmp/cwd" + "." +} { + {"test.c" 1} + {"test.c" 1} +} + +## ../cwd/test.c +do_test dot-dot-cwd 5 "../cwd/test.c" 1 { + "/tmp/cwd" + "../cwd" +} { + {"test.c" 1} + {"test.c" 1} +} + +## /tmp/cwd/test.c +do_test absolute-cwd 5 "/tmp/cwd/test.c" 1 { + "/tmp/cwd" + "/tmp/cwd" +} { + {"test.c" 1} + {"test.c" 0} +} + +## ../other/test.c +do_test dot-dot-other 5 "../other/test.c" 1 { + "/tmp/cwd" + "../other" +} { + {"test.c" 1} + {"test.c" 1} +} + +## /tmp/other/test.c +do_test absolute-other 5 "/tmp/other/test.c" 1 { + "/tmp/cwd" + "/tmp/other" +} { + {"test.c" 1} + {"test.c" 1} +} diff --git a/gdb/testsuite/gdb.dwarf2/macro-source-path.exp b/gdb/testsuite/gdb.dwarf2/macro-source-path.exp.tcl index 1318f8e..ecaf685 100644 --- a/gdb/testsuite/gdb.dwarf2/macro-source-path.exp +++ b/gdb/testsuite/gdb.dwarf2/macro-source-path.exp.tcl @@ -17,12 +17,15 @@ # Generate binaries imitating different ways source file paths can be passed to # compilers. Test printing macros from those binaries. +# +# The entry points for this test are in the various +# gdb.dwarf2/macro-source-path-*.exp files. load_lib dwarf.exp require dwarf2_support -standard_testfile .c +standard_testfile macro-source-path.c lassign [function_range main $srcdir/$subdir/$srcfile] \ main_start main_len @@ -160,248 +163,3 @@ proc do_test { test_name lines_version DW_AT_name main_file_idx directories } } } - -# When adding a test here, please consider adding an equivalent case to the test -# of the same name in gdb.base. - -# The following tests are based on the output of `gcc -gdwarf-5 -g3 <file>`, -# gcc 11 paired with gas from binutils 2.38. - -## test.c -do_test gcc11-ld238-dw5-filename 5 "test.c" 1 { - "/tmp/cwd" -} { - {"test.c" 0} - {"test.c" 0} -} - -## ./test.c -do_test gcc11-ld238-dw5-dot-filename 5 "./test.c" 1 { - "/tmp/cwd" - "." -} { - {"test.c" 1} - {"test.c" 1} -} - -## ../cwd/test.c -do_test gcc11-ld238-dw5-dot-dot-cwd 5 "../cwd/test.c" 1 { - "/tmp/cwd" - "../cwd" -} { - {"test.c" 1} - {"test.c" 1} -} - -## /tmp/cwd/test.c -do_test gcc11-ld238-dw5-absolute-cwd 5 "/tmp/cwd/test.c" 1 { - "/tmp/cwd" - "/tmp/cwd" -} { - {"test.c" 1} - {"test.c" 0} -} - -## ../other/test.c -do_test gcc11-ld238-dw5-dot-dot-other 5 "../other/test.c" 1 { - "/tmp/cwd" - "../other" -} { - {"test.c" 1} - {"test.c" 1} -} - -## /tmp/other/test.c -do_test gcc11-ld238-dw5-absolute-other 5 "/tmp/other/test.c" 1 { - "/tmp/cwd" - "/tmp/other" -} { - {"test.c" 1} - {"test.c" 1} -} - -# The following tests are based on the output of `gcc -gdwarf-4 -g3 <file>`, -# gcc 11 paired with gas from binutils 2.38. With -gdwarf-4, gcc generates a -# v4 (pre-standard) .debug_macro section. - -## test.c -do_test gcc11-ld238-dw4-filename 4 "test.c" 1 { -} { - {"test.c" 0} -} - -## ./test.c -do_test gcc11-ld238-dw4-dot-filename 4 "./test.c" 1 { - "." -} { - {"test.c" 1} -} - -## ../cwd/test.c -do_test gcc11-ld238-dw4-dot-dot-cwd 4 "../cwd/test.c" 1 { - "../cwd" -} { - {"test.c" 1} -} - -## /tmp/cwd/test.c -do_test gcc11-ld238-dw4-absolute-cwd 4 "/tmp/cwd/test.c" 1 { - "/tmp/cwd" -} { - {"test.c" 1} -} - -## ../other/test.c -do_test gcc11-ld238-dw4-dot-dot-other 4 "../other/test.c" 1 { - "../other" -} { - {"test.c" 1} -} - -## /tmp/other/test.c -do_test gcc11-ld238-dw4-absolute-other 4 "/tmp/other/test.c" 1 { - "/tmp/other" -} { - {"test.c" 1} -} - -# The following tests are based on the output of `clang-14 -gdwarf-5 -# -fdebug-macro -g3 <file>` (using its built-in assembler) - -## test.c -do_test clang14-dw5-filename 5 "test.c" 0 { - "/tmp/cwd" -} { - {"test.c" 0} -} - -## ./test.c -do_test clang14-dw5-dot-filename 5 "test.c" 1 { - "/tmp/cwd" - "." -} { - {"test.c" 0} - {"test.c" 1} -} - -## ../cwd/test.c -do_test clang14-dw5-dot-dot-cwd 5 "../cwd/test.c" 0 { - "/tmp/cwd" -} { - {"../cwd/test.c" 0} -} - -## /tmp/cwd/test.c -do_test clang14-dw5-absolute-cwd 5 "/tmp/cwd/test.c" 1 { - "/tmp/cwd" -} { - {"/tmp/cwd/test.c" 0} - {"test.c" 0} -} - -## ../other/test.c -do_test clang14-dw5-dot-dot-other 5 "../other/test.c" 0 { - "/tmp/cwd" -} { - {"../other/test.c" 0} -} - -## /tmp/other/test.c -do_test clang14-dw5-absolute-other 5 "/tmp/other/test.c" 1 { - "/tmp/cwd" - "/tmp" -} { - {"/tmp/other/test.c" 0} - {"other/test.c" 1} -} - -# The following tests are based on the output of `clang-14 -gdwarf-4 -# -fdebug-macro -g3 <file>` (using its built-in assembler). With -gdwarf-4, -# clang produces a .debug_macinfo section, not a .debug_macro section. But -# this test still creates a .debug_macro section, that's good enough for what -# we want to test. - -## test.c -do_test clang14-dw4-filename 4 "test.c" 1 { -} { - {"test.c" 0} -} - -## ./test.c -do_test clang14-dw4-dot-filename 4 "test.c" 1 { - "." -} { - {"test.c" 1} -} - -## ../cwd/test.c -do_test clang14-dw4-dot-dot-cwd 4 "../cwd/test.c" 1 { - "../cwd" -} { - {"test.c" 1} -} - -## /tmp/cwd/test.c -do_test clang14-dw4-absolute-cwd 4 "/tmp/cwd/test.c" 1 { -} { - {"test.c" 0} -} - -## ../other/test.c -do_test clang14-dw4-dot-dot-other 4 "../other/test.c" 1 { - "../other" -} { - {"test.c" 1} -} - -## /tmp/other/test.c -do_test clang14-dw4-absolute-other 4 "/tmp/other/test.c" 1 { - "/tmp" -} { - {"other/test.c" 1} -} - -# The following tests are based on the output of `gcc -gdwarf-5 -g3 <file>`, -# gcc 11 paired with gas from binutils 2.34 (Ubuntu 20.04). It generates a v5 -# .debug_macro section, but a v3 .debug_line section. - -## test.c -do_test gcc11-ld234-dw5-filename 3 "test.c" 1 { -} { - {"test.c" 0} -} - -## ./test.c -do_test gcc11-ld234-dw5-dot-filename 3 "./test.c" 1 { - "." -} { - {"test.c" 1} -} - -## ../cwd/test.c -do_test gcc11-ld234-dw5-dot-dot-cwd 3 "../cwd/test.c" 1 { - "../cwd" -} { - {"test.c" 1} -} - -## /tmp/cwd/test.c -do_test gcc11-ld234-dw5-absolute-cwd 3 "/tmp/cwd/test.c" 1 { - "/tmp/cwd" -} { - {"test.c" 1} -} - -## ../other/test.c -do_test gcc11-ld234-dw5-dot-dot-other 3 "../other/test.c" 1 { - "../other" -} { - {"test.c" 1} -} - -## /tmp/other/test.c -do_test gcc11-ld234-dw5-absolute-other 3 "/tmp/other/test.c" 1 { - "/tmp/other" -} { - {"test.c" 1} -} diff --git a/gdb/testsuite/gdb.python/py-color.exp b/gdb/testsuite/gdb.python/py-color.exp index 1b8e0c5..99b4689 100644 --- a/gdb/testsuite/gdb.python/py-color.exp +++ b/gdb/testsuite/gdb.python/py-color.exp @@ -97,3 +97,36 @@ gdb_test [concat "python print (c_red.escape_sequence (True) + " \ "\033\\\[31m\033\\\[42mred on green\033\\\[49m red on default\033\\\[39m" \ "escape sequences" +gdb_test_multiline "Try to sub-class gdb.Color" \ + "python" "" \ + "class my_color(gdb.Color):" "" \ + " def __init__(self):" "" \ + " super().__init__('red')" "" \ + "end" \ + [multi_line \ + "Python Exception <class 'TypeError'>: type 'gdb\\.Color' is not an acceptable base type" \ + "Error occurred in Python: type 'gdb\\.Color' is not an acceptable base type"] + +gdb_test_multiline "Setup a color parameter and non gdb.Color object" \ + "python" "" \ + "class my_param(gdb.Parameter):" "" \ + " def __init__(self):" "" \ + " super().__init__('color-param', gdb.COMMAND_NONE, gdb.PARAM_COLOR)" "" \ + " self.value = gdb.Color('red')" "" \ + "color_param = my_param()" "" \ + " " "" \ + "class bad_type:" "" \ + " @property" "" \ + " def __class__(self):" "" \ + " raise RuntimeError('__class__ error for bad_type')" "" \ + "bad_obj = bad_type()" "" \ + "end" "" + +gdb_test_no_output "python color_param.value = gdb.Color('blue')" \ + "set color parameter to blue" + +gdb_test "python color_param.value = bad_obj" \ + [multi_line \ + "Python Exception <class 'RuntimeError'>: color argument must be a gdb\\.Color object\\." \ + "Error occurred in Python: color argument must be a gdb\\.Color object\\."] \ + "set color parameter to a non-color type" diff --git a/gdb/testsuite/gdb.python/py-disasm.exp.tcl b/gdb/testsuite/gdb.python/py-disasm.exp.tcl index 938326d..c5099ba 100644 --- a/gdb/testsuite/gdb.python/py-disasm.exp.tcl +++ b/gdb/testsuite/gdb.python/py-disasm.exp.tcl @@ -152,7 +152,10 @@ set test_plans \ "Buffer returned from read_memory is sized $decimal instead of the expected $decimal"]] \ [list "ResultOfWrongType" \ [make_exception_pattern "TypeError" \ - "Result is not a DisassemblerResult."]] \ + "Result from Disassembler must be gdb.DisassemblerResult, not Blah."]] \ + [list "ResultOfVeryWrongType" \ + [make_exception_pattern "TypeError" \ + "Result from Disassembler must be gdb.DisassemblerResult, not Blah."]] \ [list "ErrorCreatingTextPart_NoArgs" \ [make_exception_pattern "TypeError" \ [missing_arg_pattern "style" 1]]] \ diff --git a/gdb/testsuite/gdb.python/py-disasm.py b/gdb/testsuite/gdb.python/py-disasm.py index 32d6aa7..9761337 100644 --- a/gdb/testsuite/gdb.python/py-disasm.py +++ b/gdb/testsuite/gdb.python/py-disasm.py @@ -294,6 +294,24 @@ class ResultOfWrongType(TestDisassembler): return self.Blah(1, "ABC") +class ResultOfVeryWrongType(TestDisassembler): + """Return something that is not a DisassemblerResult from disassemble + method. The thing returned will raise an exception if used in an + isinstance() call, or in PyObject_IsInstance from C++. + """ + + class Blah: + def __init__(self): + pass + + @property + def __class__(self): + raise RuntimeError("error from __class__ in Blah") + + def disassemble(self, info): + return self.Blah() + + class TaggingDisassembler(TestDisassembler): """A simple disassembler that just tags the output.""" diff --git a/gdb/testsuite/gdb.python/py-frame.exp b/gdb/testsuite/gdb.python/py-frame.exp index 5668807..c1e3e33 100644 --- a/gdb/testsuite/gdb.python/py-frame.exp +++ b/gdb/testsuite/gdb.python/py-frame.exp @@ -188,6 +188,21 @@ gdb_test "python print(gdb.selected_frame().read_register(list()))" \ ".*Invalid type for register.*" \ "test Frame.read_register with list" +gdb_test_multiline "setup a bad object" \ + "python" "" \ + "class bad_type:" "" \ + " def __init__ (self):" "" \ + " pass" "" \ + " @property" "" \ + " def __class__(self):" "" \ + " raise RuntimeError('error from __class in bad_type')" "" \ + "bad_object = bad_type()" "" \ + "end" "" + +gdb_test "python print(gdb.selected_frame().read_register(bad_object))" \ + ".*Invalid type for register.*" \ + "test Frame.read_register with bad_type object" + # Compile again without debug info. gdb_exit if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} {}] } { |