- Update to fedora rawhide @ a8e0b3d (gdb 15.1).
- Use gcc-9 for SLE-12 (default gcc 4.8.5 doesn't support C++17). - Maintenance script qa-local.sh: * Update version to 15.1. - Maintenance script qa.sh: * Add kfails due to gcc 4.8.5 DW_TAG_lexical_block oddity. * Extend PR24845 kfails. * Add PR31721 and PR32608 kfails. - Patches added: * gdb-guile-use-scm_debug_typing_strictness-0.patch * gdb-doc-fix-gdb.unwinder-docs.patch * gdb-doc-fix-qisaddresstagged-anchor.patch * gdb-doc-fix-standard-replies-xref.patch * gdb-testsuite-fix-gdb_py_module_available-for-python.patch * gdb-testsuite-fix-another-regexp-in-gdb.threads-step.patch * gdb-testsuite-fix-timeouts-in-gdb.threads-step-over-.patch - Patches updated: * gdb-6.3-gstack-20050411.patch * gdb-6.6-buildid-locate-solib-missing-ids.patch * gdb-6.6-buildid-locate.patch * gdb-add-rpm-suggestion-script.patch * gdb-gcore-bash.patch * gdb-python-avoid-depending-on-the-curses-library.patch * gdb-python-finishbreakpoint-update.patch - Patches dropped: * gdb-add-missing-debug-ext-lang-hook.patch * gdb-add-missing-debug-info-python-hook.patch * gdb-do-not-import-py-curses-ascii-module.patch * gdb-ftbs-swapped-calloc-args.patch * gdb-handle-no-python-gdb-module.patch * gdb-merge-debug-symbol-lookup.patch * gdb-refactor-find-and-add-separate-symbol-file.patch * gdb-reformat-missing-debug-py-file.patch * gdb-remove-path-in-test-name.patch * gdb-rhbz-2232086-cpp-ify-mapped-symtab.patch * gdb-rhbz-2232086-generate-dwarf-5-index-consistently.patch * gdb-rhbz-2232086-generate-gdb-index-consistently.patch * gdb-rhbz-2232086-reduce-size-of-gdb-index.patch * gdb-rhbz2232086-refactor-selftest-support.patch * gdb-rhbz2250652-avoid-PyOS_ReadlineTState.patch * gdb-rhbz2250652-gdbpy_gil.patch * gdb-rhbz2261580-intrusive_list-assertion-fix.patch * gdb-rhbz2277160-apx-disasm.patch * gdb-rhel2295897-pre-read-DWZ-file-in-DWARF-reader.patch * gdb-sync-coffread-with-elfread.patch * gdb-remove-use-of-py-isascii * change-gdb.base-examine-backwards.exp-for-aix.patch * fix-regression-on-aarch64-linux-gdbserver.patch * fix-the-gdb.ada-inline-section-gc.exp-test.patch * fixup-powerpc-and-aarch64-fix-reverse-stepping-failu.patch * gdb-arm-fix-epilogue-frame-id.patch * gdb-arm-remove-thumb-bit-in-arm_adjust_breakpoint_ad.patch * gdb-arm-remove-tpidruro-register-from-non-freebsd-ta.patch * gdb-build-fix-gdbserver-linux-aarch64-low.cc-build.patch * gdb-exp-fix-cast-handling-for-indirection.patch * gdb-exp-fix-printing-of-out-of-bounds-struct-members.patch * gdb-exp-redo-cast-handling-for-indirection.patch * gdb-fix-heap-use-after-free-in-select_event_lwp.patch * gdb-fix-segfault-in-for_each_block-part-1.patch * gdb-fix-segfault-in-for_each_block-part-2.patch * gdb-python-fix-gdb.python-py-disasm.exp-on-arm-linux.patch * gdb-python-make-gdb.unwindinfo.add_saved_register-mo-fixup.patch * gdb-python-make-gdb.unwindinfo.add_saved_register-mo.patch * gdb-remote-fix-abort-on-remote_close_error.patch * gdb-s390-add-arch14-record-replay-support.patch * gdb-symtab-add-producer_is_gas.patch * gdb-symtab-don-t-defer-backward-refs-inter-cu-intra-.patch * gdb-symtab-factor-out-m_deferred_entries-usage.patch * gdb-symtab-factor-out-m_die_range_map-usage.patch * gdb-symtab-fix-dw_tag_inlined_subroutine-entries-in-.patch * gdb-symtab-handle-nullptr-parent-in-parent_map-set_p.patch * gdb-symtab-keep-track-of-all-parents-for-cooked-inde.patch * gdb-symtab-keep-track-of-processed-dies-in-shard.patch * gdb-symtab-refactor-condition-in-scan_attributes.patch * gdb-symtab-resolve-deferred-entries-inter-shard-case.patch * gdb-symtab-resolve-deferred-entries-intra-shard-case.patch * gdb-symtab-work-around-gas-pr28629.patch * gdb-symtab-work-around-pr-gas-29517-dwarf2-case.patch * gdb-symtab-work-around-pr-gas-29517.patch * gdb-symtab-workaround-pr-gas-31115.patch * gdb-tdep-fix-catching-syscall-execve-exit-for-arm.patch * gdb-tdep-fix-gdb.base-watch-bitfields.exp-on-aarch64.patch * gdb-tdep-fix-gdb.base-watchpoint-running-on-arm-ppc6.patch * gdb-tdep-fix-gdb.base-watchpoint-unaligned.exp-on-aa.patch * gdb-tdep-fix-nr-array-elements-in-ppc64_aggregate_ca.patch * gdb-tdep-fix-reverse-execution-of-ldr-immediate-t4.patch * gdb-testsuite-add-gdb.dwarf2-backward-spec-inter-cu..patch * gdb-testsuite-add-gdb.dwarf2-forward-spec-inter-cu.e.patch * gdb-testsuite-add-missing-include-in-gdb.base-ctf-pt.patch * gdb-testsuite-add-missing-include-in-gdb.base-rtld-s.patch * gdb-testsuite-add-missing-includes-in-gdb.trace-coll.patch * gdb-testsuite-add-missing-no-prompt-anchor-in-gdb.ba.patch * gdb-testsuite-add-pr-gdb-26967-kfail-in-two-more-tes.patch * gdb-testsuite-call-ldd-version-in-gdb.testsuite-dump.patch * gdb-testsuite-factor-out-proc-get_portnum.patch * gdb-testsuite-factor-out-proc-lock_dir.patch * gdb-testsuite-factor-out-proc-with_lock.patch * gdb-testsuite-fix-gdb.ada-verylong.exp-on-32-bit-tar.patch * gdb-testsuite-fix-gdb.base-eh_return.exp.patch * gdb-testsuite-fix-gdb.base-ending-run.exp-on-manjaro.patch * gdb-testsuite-fix-gdb.base-list-no-debug.exp-on-debi.patch * gdb-testsuite-fix-gdb.cp-namespace.exp-with-read1.patch * gdb-testsuite-fix-gdb.dwarf2-dw2-gas-workaround.exp.patch * gdb-testsuite-fix-gdb.mi-mi-dprintf.exp-with-read1.patch * gdb-testsuite-fix-gdbserver-pid-in-gdb.server-server.patch * gdb-testsuite-fix-gdb.server-server-connect.exp-for-.patch * gdb-testsuite-fix-license-text-in-gdb.reverse-map-to.patch * gdb-testsuite-fix-missing-return-type-in-gdb.linespe.patch * gdb-testsuite-fix-regexp-in-vgdb_start.patch * gdb-testsuite-fix-spurious-fails-with-examine-backwa.patch * gdb-testsuite-fix-test-case-gdb.threads-attach-stopp.patch * gdb-testsuite-fix-test-in-gdb.python-py-finish-break.patch * gdb-testsuite-fix-typo-in-gdb.base-catch-syscall.exp.patch * gdb-testsuite-fix-valgrind-tests-on-debian.patch * gdb-testsuite-further-handle-long-filenames-in-gdb.b.patch * gdb-testsuite-handle-core-without-build-id-in-gdb.ba.patch * gdb-testsuite-handle-pac-marker.patch * gdb-testsuite-make-gdb.base-solib-search.exp-more-ro.patch * gdb-testsuite-make-portnum-a-persistent-global.patch * gdb-testsuite-move-gpu-parallel.lock-to-cache-dir.patch * gdb-testsuite-remove-spurious-in-save_vars.patch * gdb-testsuite-reset-errcnt-and-warncnt-in-default_gd.patch * gdb-testsuite-simplify-gdb.server-server-kill-python.patch * gdb-testsuite-use-find_gnatmake-instead-of-gdb_find_.patch * gdb-testsuite-use-more-progbits-for-arm.patch * gdb-testsuite-use-unique-portnum-in-parallel-testing-check-slash-slash-case.patch * gdb-testsuite-use-unique-portnum-in-parallel-testing.patch * gdb-tui-allow-command-window-of-1-or-2-lines.patch * gdb-tui-fix-resizing-of-terminal-to-1-or-2-lines.patch * gdb-tui-fix-wmaybe-uninitialized-in-tui_find_disasse.patch * make-pascal_language-print_type-handle-varstring-nul.patch * powerpc-and-aarch64-fix-reverse-stepping-failure.patch * powerpc-fix-test-gdb.ada-finish-large.exp.patch * riscv-lrsc.patch * rs6000-unwind-on-each-instruction-fix.patch * s390-provide-ibm-z16-arch14-instruction-descriptions.patch OBS-URL: https://build.opensuse.org/package/show/devel:gcc/gdb?expand=0&rev=425
This commit is contained in:
@@ -1,53 +0,0 @@
|
||||
From acc7b542a08819bec4aae767de547c531a7ab62e Mon Sep 17 00:00:00 2001
|
||||
From: Aditya Vidyadhar Kamath <Aditya.Kamath1@ibm.com>
|
||||
Date: Mon, 6 Nov 2023 07:26:24 -0600
|
||||
Subject: [PATCH 03/48] Change gdb.base/examine-backwards.exp for AIX.
|
||||
|
||||
In AIX unused or constant variables are collected as garbage by the linker and in the dwarf dump
|
||||
an address with all f's in hexadecimal are assigned. Hence the testcase fails with many failures stating
|
||||
it cannot access memory.
|
||||
|
||||
This patch is a small change to get it working in AIX as well.
|
||||
---
|
||||
gdb/testsuite/gdb.base/examine-backward.c | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/examine-backward.c b/gdb/testsuite/gdb.base/examine-backward.c
|
||||
index e30b58fb005..354c2e2f323 100644
|
||||
--- a/gdb/testsuite/gdb.base/examine-backward.c
|
||||
+++ b/gdb/testsuite/gdb.base/examine-backward.c
|
||||
@@ -36,11 +36,11 @@ literals. The content of each array is the same as followings:
|
||||
TestStrings, to avoid showing garbage when we look for strings
|
||||
backwards from TestStrings. */
|
||||
|
||||
-const unsigned char Barrier[] = {
|
||||
+unsigned char Barrier[] = {
|
||||
0x00,
|
||||
};
|
||||
|
||||
-const unsigned char TestStrings[] = {
|
||||
+unsigned char TestStrings[] = {
|
||||
0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
|
||||
0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
|
||||
0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
|
||||
@@ -54,7 +54,7 @@ const unsigned char TestStrings[] = {
|
||||
0x00
|
||||
};
|
||||
|
||||
-const short TestStringsH[] = {
|
||||
+short TestStringsH[] = {
|
||||
0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048,
|
||||
0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
|
||||
0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
|
||||
@@ -67,7 +67,7 @@ const short TestStringsH[] = {
|
||||
0x0000
|
||||
};
|
||||
|
||||
-const int TestStringsW[] = {
|
||||
+int TestStringsW[] = {
|
||||
0x00000041, 0x00000042, 0x00000043, 0x00000044,
|
||||
0x00000045, 0x00000046, 0x00000047, 0x00000048,
|
||||
0x00000049, 0x0000004a, 0x0000004b, 0x0000004c,
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,366 +0,0 @@
|
||||
From 2a7e48ca27f4c080151ce9da5a29239aa5d3b66f Mon Sep 17 00:00:00 2001
|
||||
From: Tom Tromey <tromey@adacore.com>
|
||||
Date: Fri, 19 Apr 2024 07:54:19 -0600
|
||||
Subject: [PATCH 15/48] Fix regression on aarch64-linux gdbserver
|
||||
|
||||
Commit 9a03f218 ("Fix gdb.base/watchpoint-unaligned.exp on aarch64")
|
||||
fixed a watchpoint bug in gdb -- but did not touch the corresponding
|
||||
code in gdbserver.
|
||||
|
||||
This patch moves the gdb code into gdb/nat, so that it can be shared
|
||||
with gdbserver, and then changes gdbserver to use it, fixing the bug.
|
||||
|
||||
This is yet another case where having a single back end would prevent
|
||||
bugs.
|
||||
|
||||
I tested this using the AdaCore internal gdb testsuite.
|
||||
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29423
|
||||
Approved-By: Luis Machado <luis.machado@arm.com>
|
||||
---
|
||||
gdb/aarch64-nat.c | 115 ---------------------------------
|
||||
gdb/aarch64-nat.h | 8 ---
|
||||
gdb/nat/aarch64-hw-point.c | 115 +++++++++++++++++++++++++++++++++
|
||||
gdb/nat/aarch64-hw-point.h | 8 +++
|
||||
gdbserver/linux-aarch64-low.cc | 38 +----------
|
||||
5 files changed, 126 insertions(+), 158 deletions(-)
|
||||
|
||||
diff --git a/gdb/aarch64-nat.c b/gdb/aarch64-nat.c
|
||||
index a173e4e18d5..97e3048568a 100644
|
||||
--- a/gdb/aarch64-nat.c
|
||||
+++ b/gdb/aarch64-nat.c
|
||||
@@ -225,121 +225,6 @@ aarch64_remove_watchpoint (CORE_ADDR addr, int len, enum target_hw_bp_type type,
|
||||
return ret;
|
||||
}
|
||||
|
||||
-/* See aarch64-nat.h. */
|
||||
-
|
||||
-bool
|
||||
-aarch64_stopped_data_address (const struct aarch64_debug_reg_state *state,
|
||||
- CORE_ADDR addr_trap, CORE_ADDR *addr_p)
|
||||
-{
|
||||
- bool found = false;
|
||||
- for (int phase = 0; phase <= 1; ++phase)
|
||||
- for (int i = aarch64_num_wp_regs - 1; i >= 0; --i)
|
||||
- {
|
||||
- if (!(state->dr_ref_count_wp[i]
|
||||
- && DR_CONTROL_ENABLED (state->dr_ctrl_wp[i])))
|
||||
- {
|
||||
- /* Watchpoint disabled. */
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- const enum target_hw_bp_type type
|
||||
- = aarch64_watchpoint_type (state->dr_ctrl_wp[i]);
|
||||
- if (type == hw_execute)
|
||||
- {
|
||||
- /* Watchpoint disabled. */
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- if (phase == 0)
|
||||
- {
|
||||
- /* Phase 0: No hw_write. */
|
||||
- if (type == hw_write)
|
||||
- continue;
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- /* Phase 1: Only hw_write. */
|
||||
- if (type != hw_write)
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- const unsigned int offset
|
||||
- = aarch64_watchpoint_offset (state->dr_ctrl_wp[i]);
|
||||
- const unsigned int len
|
||||
- = aarch64_watchpoint_length (state->dr_ctrl_wp[i]);
|
||||
- const CORE_ADDR addr_watch = state->dr_addr_wp[i] + offset;
|
||||
- const CORE_ADDR addr_watch_aligned
|
||||
- = align_down (state->dr_addr_wp[i], AARCH64_HWP_MAX_LEN_PER_REG);
|
||||
- const CORE_ADDR addr_orig = state->dr_addr_orig_wp[i];
|
||||
-
|
||||
- /* ADDR_TRAP reports the first address of the memory range
|
||||
- accessed by the CPU, regardless of what was the memory
|
||||
- range watched. Thus, a large CPU access that straddles
|
||||
- the ADDR_WATCH..ADDR_WATCH+LEN range may result in an
|
||||
- ADDR_TRAP that is lower than the
|
||||
- ADDR_WATCH..ADDR_WATCH+LEN range. E.g.:
|
||||
-
|
||||
- addr: | 4 | 5 | 6 | 7 | 8 |
|
||||
- |---- range watched ----|
|
||||
- |----------- range accessed ------------|
|
||||
-
|
||||
- In this case, ADDR_TRAP will be 4.
|
||||
-
|
||||
- The access size also can be larger than that of the watchpoint
|
||||
- itself. For instance, the access size of an stp instruction is 16.
|
||||
- So, if we use stp to store to address p, and set a watchpoint on
|
||||
- address p + 8, the reported ADDR_TRAP can be p + 8 (observed on
|
||||
- RK3399 SOC). But it also can be p (observed on M1 SOC). Checking
|
||||
- for this situation introduces the possibility of false positives,
|
||||
- so we only do this for hw_write watchpoints. */
|
||||
- const CORE_ADDR max_access_size = type == hw_write ? 16 : 8;
|
||||
- const CORE_ADDR addr_watch_base = addr_watch_aligned -
|
||||
- (max_access_size - AARCH64_HWP_MAX_LEN_PER_REG);
|
||||
- if (!(addr_trap >= addr_watch_base
|
||||
- && addr_trap < addr_watch + len))
|
||||
- {
|
||||
- /* Not a match. */
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- /* To match a watchpoint known to GDB core, we must never
|
||||
- report *ADDR_P outside of any ADDR_WATCH..ADDR_WATCH+LEN
|
||||
- range. ADDR_WATCH <= ADDR_TRAP < ADDR_ORIG is a false
|
||||
- positive on kernels older than 4.10. See PR
|
||||
- external/20207. */
|
||||
- if (addr_p != nullptr)
|
||||
- *addr_p = addr_orig;
|
||||
-
|
||||
- if (phase == 0)
|
||||
- {
|
||||
- /* Phase 0: Return first match. */
|
||||
- return true;
|
||||
- }
|
||||
-
|
||||
- /* Phase 1. */
|
||||
- if (addr_p == nullptr)
|
||||
- {
|
||||
- /* First match, and we don't need to report an address. No need
|
||||
- to look for other matches. */
|
||||
- return true;
|
||||
- }
|
||||
-
|
||||
- if (!found)
|
||||
- {
|
||||
- /* First match, and we need to report an address. Look for other
|
||||
- matches. */
|
||||
- found = true;
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- /* More than one match, and we need to return an address. No need to
|
||||
- look for further matches. */
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
- return found;
|
||||
-}
|
||||
-
|
||||
/* Define AArch64 maintenance commands. */
|
||||
|
||||
static void
|
||||
diff --git a/gdb/aarch64-nat.h b/gdb/aarch64-nat.h
|
||||
index fee6bda2577..f95a9d745e5 100644
|
||||
--- a/gdb/aarch64-nat.h
|
||||
+++ b/gdb/aarch64-nat.h
|
||||
@@ -45,14 +45,6 @@ struct aarch64_debug_reg_state *aarch64_get_debug_reg_state (pid_t pid);
|
||||
|
||||
void aarch64_remove_debug_reg_state (pid_t pid);
|
||||
|
||||
-/* Helper for the "stopped_data_address" target method. Returns TRUE
|
||||
- if a hardware watchpoint trap at ADDR_TRAP matches a set
|
||||
- watchpoint. The address of the matched watchpoint is returned in
|
||||
- *ADDR_P. */
|
||||
-
|
||||
-bool aarch64_stopped_data_address (const struct aarch64_debug_reg_state *state,
|
||||
- CORE_ADDR addr_trap, CORE_ADDR *addr_p);
|
||||
-
|
||||
/* Helper functions used by aarch64_nat_target below. See their
|
||||
definitions. */
|
||||
|
||||
diff --git a/gdb/nat/aarch64-hw-point.c b/gdb/nat/aarch64-hw-point.c
|
||||
index 3b8cdcba23b..9eb78923e86 100644
|
||||
--- a/gdb/nat/aarch64-hw-point.c
|
||||
+++ b/gdb/nat/aarch64-hw-point.c
|
||||
@@ -647,3 +647,118 @@ aarch64_region_ok_for_watchpoint (CORE_ADDR addr, int len)
|
||||
the checking is costly. */
|
||||
return 1;
|
||||
}
|
||||
+
|
||||
+/* See nat/aarch64-hw-point.h. */
|
||||
+
|
||||
+bool
|
||||
+aarch64_stopped_data_address (const struct aarch64_debug_reg_state *state,
|
||||
+ CORE_ADDR addr_trap, CORE_ADDR *addr_p)
|
||||
+{
|
||||
+ bool found = false;
|
||||
+ for (int phase = 0; phase <= 1; ++phase)
|
||||
+ for (int i = aarch64_num_wp_regs - 1; i >= 0; --i)
|
||||
+ {
|
||||
+ if (!(state->dr_ref_count_wp[i]
|
||||
+ && DR_CONTROL_ENABLED (state->dr_ctrl_wp[i])))
|
||||
+ {
|
||||
+ /* Watchpoint disabled. */
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ const enum target_hw_bp_type type
|
||||
+ = aarch64_watchpoint_type (state->dr_ctrl_wp[i]);
|
||||
+ if (type == hw_execute)
|
||||
+ {
|
||||
+ /* Watchpoint disabled. */
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (phase == 0)
|
||||
+ {
|
||||
+ /* Phase 0: No hw_write. */
|
||||
+ if (type == hw_write)
|
||||
+ continue;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /* Phase 1: Only hw_write. */
|
||||
+ if (type != hw_write)
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ const unsigned int offset
|
||||
+ = aarch64_watchpoint_offset (state->dr_ctrl_wp[i]);
|
||||
+ const unsigned int len
|
||||
+ = aarch64_watchpoint_length (state->dr_ctrl_wp[i]);
|
||||
+ const CORE_ADDR addr_watch = state->dr_addr_wp[i] + offset;
|
||||
+ const CORE_ADDR addr_watch_aligned
|
||||
+ = align_down (state->dr_addr_wp[i], AARCH64_HWP_MAX_LEN_PER_REG);
|
||||
+ const CORE_ADDR addr_orig = state->dr_addr_orig_wp[i];
|
||||
+
|
||||
+ /* ADDR_TRAP reports the first address of the memory range
|
||||
+ accessed by the CPU, regardless of what was the memory
|
||||
+ range watched. Thus, a large CPU access that straddles
|
||||
+ the ADDR_WATCH..ADDR_WATCH+LEN range may result in an
|
||||
+ ADDR_TRAP that is lower than the
|
||||
+ ADDR_WATCH..ADDR_WATCH+LEN range. E.g.:
|
||||
+
|
||||
+ addr: | 4 | 5 | 6 | 7 | 8 |
|
||||
+ |---- range watched ----|
|
||||
+ |----------- range accessed ------------|
|
||||
+
|
||||
+ In this case, ADDR_TRAP will be 4.
|
||||
+
|
||||
+ The access size also can be larger than that of the watchpoint
|
||||
+ itself. For instance, the access size of an stp instruction is 16.
|
||||
+ So, if we use stp to store to address p, and set a watchpoint on
|
||||
+ address p + 8, the reported ADDR_TRAP can be p + 8 (observed on
|
||||
+ RK3399 SOC). But it also can be p (observed on M1 SOC). Checking
|
||||
+ for this situation introduces the possibility of false positives,
|
||||
+ so we only do this for hw_write watchpoints. */
|
||||
+ const CORE_ADDR max_access_size = type == hw_write ? 16 : 8;
|
||||
+ const CORE_ADDR addr_watch_base = addr_watch_aligned -
|
||||
+ (max_access_size - AARCH64_HWP_MAX_LEN_PER_REG);
|
||||
+ if (!(addr_trap >= addr_watch_base
|
||||
+ && addr_trap < addr_watch + len))
|
||||
+ {
|
||||
+ /* Not a match. */
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* To match a watchpoint known to GDB core, we must never
|
||||
+ report *ADDR_P outside of any ADDR_WATCH..ADDR_WATCH+LEN
|
||||
+ range. ADDR_WATCH <= ADDR_TRAP < ADDR_ORIG is a false
|
||||
+ positive on kernels older than 4.10. See PR
|
||||
+ external/20207. */
|
||||
+ if (addr_p != nullptr)
|
||||
+ *addr_p = addr_orig;
|
||||
+
|
||||
+ if (phase == 0)
|
||||
+ {
|
||||
+ /* Phase 0: Return first match. */
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ /* Phase 1. */
|
||||
+ if (addr_p == nullptr)
|
||||
+ {
|
||||
+ /* First match, and we don't need to report an address. No need
|
||||
+ to look for other matches. */
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ if (!found)
|
||||
+ {
|
||||
+ /* First match, and we need to report an address. Look for other
|
||||
+ matches. */
|
||||
+ found = true;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* More than one match, and we need to return an address. No need to
|
||||
+ look for further matches. */
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ return found;
|
||||
+}
|
||||
diff --git a/gdb/nat/aarch64-hw-point.h b/gdb/nat/aarch64-hw-point.h
|
||||
index 71ae2864927..2386cf60f90 100644
|
||||
--- a/gdb/nat/aarch64-hw-point.h
|
||||
+++ b/gdb/nat/aarch64-hw-point.h
|
||||
@@ -110,6 +110,14 @@ unsigned int aarch64_watchpoint_offset (unsigned int ctrl);
|
||||
unsigned int aarch64_watchpoint_length (unsigned int ctrl);
|
||||
enum target_hw_bp_type aarch64_watchpoint_type (unsigned int ctrl);
|
||||
|
||||
+/* Helper for the "stopped_data_address" target method. Returns TRUE
|
||||
+ if a hardware watchpoint trap at ADDR_TRAP matches a set
|
||||
+ watchpoint. The address of the matched watchpoint is returned in
|
||||
+ *ADDR_P. */
|
||||
+
|
||||
+bool aarch64_stopped_data_address (const struct aarch64_debug_reg_state *state,
|
||||
+ CORE_ADDR addr_trap, CORE_ADDR *addr_p);
|
||||
+
|
||||
int aarch64_handle_breakpoint (enum target_hw_bp_type type, CORE_ADDR addr,
|
||||
int len, int is_insert, ptid_t ptid,
|
||||
struct aarch64_debug_reg_state *state);
|
||||
diff --git a/gdbserver/linux-aarch64-low.cc b/gdbserver/linux-aarch64-low.cc
|
||||
index fcbe7bb64d7..14346b89822 100644
|
||||
--- a/gdbserver/linux-aarch64-low.cc
|
||||
+++ b/gdbserver/linux-aarch64-low.cc
|
||||
@@ -577,41 +577,9 @@ aarch64_target::low_stopped_data_address ()
|
||||
|
||||
/* Check if the address matches any watched address. */
|
||||
state = aarch64_get_debug_reg_state (pid_of (current_thread));
|
||||
- for (i = aarch64_num_wp_regs - 1; i >= 0; --i)
|
||||
- {
|
||||
- const unsigned int offset
|
||||
- = aarch64_watchpoint_offset (state->dr_ctrl_wp[i]);
|
||||
- const unsigned int len = aarch64_watchpoint_length (state->dr_ctrl_wp[i]);
|
||||
- const CORE_ADDR addr_watch = state->dr_addr_wp[i] + offset;
|
||||
- const CORE_ADDR addr_watch_aligned = align_down (state->dr_addr_wp[i], 8);
|
||||
- const CORE_ADDR addr_orig = state->dr_addr_orig_wp[i];
|
||||
-
|
||||
- if (state->dr_ref_count_wp[i]
|
||||
- && DR_CONTROL_ENABLED (state->dr_ctrl_wp[i])
|
||||
- && addr_trap >= addr_watch_aligned
|
||||
- && addr_trap < addr_watch + len)
|
||||
- {
|
||||
- /* ADDR_TRAP reports the first address of the memory range
|
||||
- accessed by the CPU, regardless of what was the memory
|
||||
- range watched. Thus, a large CPU access that straddles
|
||||
- the ADDR_WATCH..ADDR_WATCH+LEN range may result in an
|
||||
- ADDR_TRAP that is lower than the
|
||||
- ADDR_WATCH..ADDR_WATCH+LEN range. E.g.:
|
||||
-
|
||||
- addr: | 4 | 5 | 6 | 7 | 8 |
|
||||
- |---- range watched ----|
|
||||
- |----------- range accessed ------------|
|
||||
-
|
||||
- In this case, ADDR_TRAP will be 4.
|
||||
-
|
||||
- To match a watchpoint known to GDB core, we must never
|
||||
- report *ADDR_P outside of any ADDR_WATCH..ADDR_WATCH+LEN
|
||||
- range. ADDR_WATCH <= ADDR_TRAP < ADDR_ORIG is a false
|
||||
- positive on kernels older than 4.10. See PR
|
||||
- external/20207. */
|
||||
- return addr_orig;
|
||||
- }
|
||||
- }
|
||||
+ CORE_ADDR result;
|
||||
+ if (aarch64_stopped_data_address (state, addr_trap, &result))
|
||||
+ return result;
|
||||
|
||||
return (CORE_ADDR) 0;
|
||||
}
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,80 +0,0 @@
|
||||
From c21fd9f7d5911fce0c17af7094d8861d1195dfda Mon Sep 17 00:00:00 2001
|
||||
From: Carl Love <cel@linux.ibm.com>
|
||||
Date: Mon, 13 Nov 2023 14:14:08 -0500
|
||||
Subject: [PATCH 01/48] Fix the gdb.ada/inline-section-gc.exp test
|
||||
|
||||
The original intention of the test appears to be checking to make sure
|
||||
setting a breakpoint in an inlined function didn't set multiple
|
||||
breakpoints where one of them was at address 0.
|
||||
|
||||
The gdb.ada/inline-section-gc.exp test may pass or fail depending on the
|
||||
version of gnat. Per the discussion on IRC, the ada inlining appears to
|
||||
have some target dependencies. In this test there are two functions,
|
||||
callee and caller. Function calee is inlined into caller. The test sets
|
||||
a breakpoint in function callee. The reported location where the
|
||||
breakpoint is set may be at the requested location in callee or the
|
||||
location in caller after callee has been inlined. The test needs to
|
||||
accept either location as correct provided the breakpoint address is not
|
||||
zero.
|
||||
|
||||
This patch checks to see if the reported breakpoint is in function callee
|
||||
or function caller and fails if the breakpoint address is 0x0. The line
|
||||
number where the breakpoint is set will match the requested line if the
|
||||
breakpoint location is reported is callee.adb. If the breakpoint is
|
||||
reported in caller.adb, the line number in caller is the breakpoint
|
||||
location in callee where it is inlined into caller.
|
||||
|
||||
This patch fixes the single regression failure for the test on PowerPC.
|
||||
It does not introduce any failures on X86-64.
|
||||
---
|
||||
gdb/testsuite/gdb.ada/inline-section-gc.exp | 21 ++++++++++++++++---
|
||||
.../gdb.ada/inline-section-gc/caller.adb | 3 ++-
|
||||
2 files changed, 20 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.ada/inline-section-gc.exp b/gdb/testsuite/gdb.ada/inline-section-gc.exp
|
||||
index b707335eb04..4f8b8c95395 100644
|
||||
--- a/gdb/testsuite/gdb.ada/inline-section-gc.exp
|
||||
+++ b/gdb/testsuite/gdb.ada/inline-section-gc.exp
|
||||
@@ -34,8 +34,23 @@ if {[gdb_compile_ada "${srcfile}" "${binfile}" executable $options] != ""} {
|
||||
|
||||
clean_restart ${testfile}
|
||||
|
||||
-set bp_location [gdb_get_line_number "BREAK" ${testdir}/callee.adb]
|
||||
+
|
||||
+# Depending on the version of gnat, the location of the set breakpoint may
|
||||
+# be reported as being at the requested location in file callee.adb or in
|
||||
+# file caller.adb where the callee function was inlined. Either way, only
|
||||
+# one breakpoint should be reported and its address should not be at 0x0.
|
||||
+set bp_location1 [gdb_get_line_number "BREAK" ${testdir}/callee.adb]
|
||||
+set bp_location2 [gdb_get_line_number "CALLEE_LOC" ${testdir}/caller.adb]
|
||||
+set test "break callee.adb:$bp_location1"
|
||||
+set message "Breakpoint set"
|
||||
+
|
||||
# The bug here was that gdb would set a breakpoint with two locations,
|
||||
# one of them at 0x0.
|
||||
-gdb_test "break callee.adb:$bp_location" \
|
||||
- "Breakpoint $decimal at $hex: file .*callee.adb, line $bp_location."
|
||||
+gdb_test_multiple $test $message {
|
||||
+ -re "Breakpoint $decimal at $hex: file .*callee.adb, line $bp_location1." {
|
||||
+ pass $test
|
||||
+ }
|
||||
+ -re "Breakpoint $decimal at $hex: file .*caller.adb, line $bp_location2." {
|
||||
+ pass $test
|
||||
+ }
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.ada/inline-section-gc/caller.adb b/gdb/testsuite/gdb.ada/inline-section-gc/caller.adb
|
||||
index 66eb2d9a910..161f3e85542 100644
|
||||
--- a/gdb/testsuite/gdb.ada/inline-section-gc/caller.adb
|
||||
+++ b/gdb/testsuite/gdb.ada/inline-section-gc/caller.adb
|
||||
@@ -18,4 +18,5 @@ with Callee;
|
||||
procedure Caller is
|
||||
begin
|
||||
Callee;
|
||||
-end Caller;
|
||||
+end Caller; -- CALLEE_LOC, this is where the inlined callee breakpoint
|
||||
+ -- is located.
|
||||
|
||||
base-commit: 582fc35843fdf71b82d645d83d2903e2546cc21a
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,70 +0,0 @@
|
||||
From d60b57fe1a98094a7e4f19481193b2b5a9bb1e57 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Thu, 2 May 2024 12:02:50 +0200
|
||||
Subject: [PATCH 079/147] fixup PowerPC and aarch64: Fix reverse stepping
|
||||
failure
|
||||
|
||||
---
|
||||
gdb/infrun.c | 2 +-
|
||||
gdb/symtab.c | 3 +--
|
||||
gdb/symtab.h | 3 +--
|
||||
3 files changed, 3 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/gdb/infrun.c b/gdb/infrun.c
|
||||
index 069ef144a76..7be98cfc252 100644
|
||||
--- a/gdb/infrun.c
|
||||
+++ b/gdb/infrun.c
|
||||
@@ -6897,7 +6897,7 @@ update_line_range_start (CORE_ADDR pc, struct execution_control_state *ecs)
|
||||
Given the PC, check the line table and return the PC that corresponds
|
||||
to the line table entry for the source line that PC is in. */
|
||||
CORE_ADDR start_line_pc = ecs->event_thread->control.step_range_start;
|
||||
- std::optional<CORE_ADDR> real_range_start;
|
||||
+ gdb::optional<CORE_ADDR> real_range_start;
|
||||
|
||||
/* Call find_line_range_start to get the smallest address in the
|
||||
linetable for multiple Line X entries in the line table. */
|
||||
diff --git a/gdb/symtab.c b/gdb/symtab.c
|
||||
index ef63ec93c5a..9a47796e5e0 100644
|
||||
--- a/gdb/symtab.c
|
||||
+++ b/gdb/symtab.c
|
||||
@@ -73,7 +73,6 @@
|
||||
#include "gdbsupport/gdb_string_view.h"
|
||||
#include "gdbsupport/pathstuff.h"
|
||||
#include "gdbsupport/common-utils.h"
|
||||
-#include <optional>
|
||||
|
||||
/* Forward declarations for local functions. */
|
||||
|
||||
@@ -3328,7 +3327,7 @@ sal_line_symtab_matches_p (const symtab_and_line &sal1,
|
||||
|
||||
/* See symtah.h. */
|
||||
|
||||
-std::optional<CORE_ADDR>
|
||||
+gdb::optional<CORE_ADDR>
|
||||
find_line_range_start (CORE_ADDR pc)
|
||||
{
|
||||
struct symtab_and_line current_sal = find_pc_line (pc, 0);
|
||||
diff --git a/gdb/symtab.h b/gdb/symtab.h
|
||||
index e17d15c595b..6a611d42880 100644
|
||||
--- a/gdb/symtab.h
|
||||
+++ b/gdb/symtab.h
|
||||
@@ -38,7 +38,6 @@
|
||||
#include "gdb-demangle.h"
|
||||
#include "split-name.h"
|
||||
#include "frame.h"
|
||||
-#include <optional>
|
||||
|
||||
/* Opaque declarations. */
|
||||
struct ui_file;
|
||||
@@ -2377,7 +2376,7 @@ extern struct symtab_and_line find_pc_sect_line (CORE_ADDR,
|
||||
the starting PC of line X, and the ranges are contiguous.
|
||||
*/
|
||||
|
||||
-extern std::optional<CORE_ADDR> find_line_range_start (CORE_ADDR pc);
|
||||
+extern gdb::optional<CORE_ADDR> find_line_range_start (CORE_ADDR pc);
|
||||
|
||||
/* Wrapper around find_pc_line to just return the symtab. */
|
||||
|
||||
--
|
||||
2.35.3
|
||||
|
BIN
gdb-14.2.tar.bz2
(Stored with Git LFS)
BIN
gdb-14.2.tar.bz2
(Stored with Git LFS)
Binary file not shown.
3
gdb-15.1.tar.bz2
Normal file
3
gdb-15.1.tar.bz2
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:21b05dad63d20bebec2c89505c40402f1bee509b732b2521bbb9723c2334d1d7
|
||||
size 32257814
|
@@ -16,7 +16,7 @@ Subject: gdb-6.3-gstack-20050411.patch
|
||||
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
|
||||
--- a/gdb/Makefile.in
|
||||
+++ b/gdb/Makefile.in
|
||||
@@ -2035,7 +2035,7 @@ info install-info clean-info dvi pdf install-pdf html install-html: force
|
||||
@@ -2071,7 +2071,7 @@ info install-info clean-info dvi install-dvi pdf install-pdf html install-html:
|
||||
install: all
|
||||
@$(MAKE) $(FLAGS_TO_PASS) install-only
|
||||
|
||||
@@ -25,7 +25,7 @@ diff --git a/gdb/Makefile.in b/gdb/Makefile.in
|
||||
transformed_name=`t='$(program_transform_name)'; \
|
||||
echo gdb | sed -e "$$t"` ; \
|
||||
if test "x$$transformed_name" = x; then \
|
||||
@@ -2085,7 +2085,25 @@ install-guile:
|
||||
@@ -2121,7 +2121,25 @@ install-guile:
|
||||
install-python:
|
||||
$(SHELL) $(srcdir)/../mkinstalldirs $(DESTDIR)$(GDB_DATADIR)/python/gdb
|
||||
|
||||
@@ -52,7 +52,7 @@ diff --git a/gdb/Makefile.in b/gdb/Makefile.in
|
||||
transformed_name=`t='$(program_transform_name)'; \
|
||||
echo gdb | sed -e $$t` ; \
|
||||
if test "x$$transformed_name" = x; then \
|
||||
@@ -2116,6 +2134,18 @@ uninstall: force $(CONFIG_UNINSTALL)
|
||||
@@ -2152,6 +2170,28 @@ uninstall: force $(CONFIG_UNINSTALL)
|
||||
rm -f $(DESTDIR)$(bindir)/$$transformed_name
|
||||
@$(MAKE) DO=uninstall "DODIRS=$(SUBDIRS)" $(FLAGS_TO_PASS) subdir_do
|
||||
|
||||
@@ -68,9 +68,19 @@ diff --git a/gdb/Makefile.in b/gdb/Makefile.in
|
||||
+ rm -f $(DESTDIR)$(bindir)/$$transformed_name$(EXEEXT) \
|
||||
+ $(DESTDIR)$(man1dir)/$$transformed_name.1
|
||||
+
|
||||
# The C++ name parser can be built standalone for testing.
|
||||
test-cp-name-parser.o: cp-name-parser.c
|
||||
$(COMPILE) -DTEST_CPNAMES cp-name-parser.c
|
||||
+# The C++ name parser can be built standalone for testing.
|
||||
+test-cp-name-parser.o: cp-name-parser.c
|
||||
+ $(COMPILE) -DTEST_CPNAMES cp-name-parser.c
|
||||
+ $(POSTCOMPILE)
|
||||
+
|
||||
+test-cp-name-parser$(EXEEXT): test-cp-name-parser.o $(LIBIBERTY)
|
||||
+ $(ECHO_CXXLD) $(CC_LD) $(INTERNAL_LDFLAGS) \
|
||||
+ -o test-cp-name-parser$(EXEEXT) test-cp-name-parser.o \
|
||||
+ $(LIBIBERTY)
|
||||
+
|
||||
# We do this by grepping through sources. If that turns out to be too slow,
|
||||
# maybe we could just require every .o file to have an initialization routine
|
||||
# of a given name (top.o -> _initialize_top, etc.).
|
||||
diff --git a/gdb/gstack.sh b/gdb/gstack.sh
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
|
@@ -14,62 +14,87 @@ https://bugzilla.redhat.com/show_bug.cgi?id=1339862
|
||||
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
|
||||
--- a/gdb/solib-svr4.c
|
||||
+++ b/gdb/solib-svr4.c
|
||||
@@ -1320,14 +1320,28 @@ svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
|
||||
@@ -347,11 +347,13 @@ lm_addr_check (const solib &so, bfd *abfd)
|
||||
|
||||
struct svr4_so
|
||||
{
|
||||
- svr4_so (const char *name, lm_info_svr4_up lm_info)
|
||||
- : name (name), lm_info (std::move (lm_info))
|
||||
+ svr4_so (const char *name, lm_info_svr4_up lm_info, const char *orig_name = nullptr)
|
||||
+ : name (name), original_name (orig_name == nullptr ? name : orig_name),
|
||||
+ lm_info (std::move (lm_info))
|
||||
{}
|
||||
|
||||
std::string name;
|
||||
+ std::string original_name;
|
||||
lm_info_svr4_up lm_info;
|
||||
};
|
||||
|
||||
@@ -1002,6 +1004,7 @@ so_list_from_svr4_sos (const std::vector<svr4_so> &sos)
|
||||
|
||||
newobj->so_name = so.name;
|
||||
newobj->so_original_name = so.name;
|
||||
+ newobj->so_original_name = so.original_name;
|
||||
newobj->lm_info = std::make_unique<lm_info_svr4> (*so.lm_info);
|
||||
|
||||
dst.push_back (*newobj);
|
||||
@@ -1263,11 +1266,28 @@ svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
|
||||
continue;
|
||||
}
|
||||
|
||||
{
|
||||
- struct bfd_build_id *build_id;
|
||||
+ struct bfd_build_id *build_id = NULL;
|
||||
+ /* Preserve original name since name may be changed below. */
|
||||
+ gdb::unique_xmalloc_ptr<char> original_name = make_unique_xstrdup (name.get ());
|
||||
{
|
||||
- struct bfd_build_id *build_id;
|
||||
+ struct bfd_build_id *build_id = nullptr;
|
||||
|
||||
strncpy (newobj->so_original_name, buffer.get (), SO_NAME_MAX_PATH_SIZE - 1);
|
||||
newobj->so_original_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
|
||||
/* May get overwritten below. */
|
||||
strcpy (newobj->so_name, newobj->so_original_name);
|
||||
|
||||
- build_id = build_id_addr_get (((lm_info_svr4 *) newobj->lm_info)->l_ld);
|
||||
+ /* In the case the main executable was found according to its build-id
|
||||
+ (from a core file) prevent loading a different build of a library
|
||||
+ with accidentally the same SO_NAME.
|
||||
- build_id = build_id_addr_get (li->l_ld);
|
||||
- if (build_id != NULL)
|
||||
+ /* In the case the main executable was found according to its build-id
|
||||
+ (from a core file) prevent loading a different build of a library
|
||||
+ with accidentally the same SO_NAME.
|
||||
+
|
||||
+ It suppresses bogus backtraces (and prints "??" there instead) if
|
||||
+ the on-disk files no longer match the running program version.
|
||||
+ It suppresses bogus backtraces (and prints "??" there instead) if
|
||||
+ the on-disk files no longer match the running program version.
|
||||
+ If the main executable was not loaded according to its build-id do
|
||||
+ not do any build-id checking of the libraries. There may be missing
|
||||
+ build-ids dumped in the core file and we would map all the libraries
|
||||
+ to the only existing file loaded that time - the executable. */
|
||||
+ if (current_program_space->symfile_object_file != NULL
|
||||
+ && (current_program_space->symfile_object_file->flags
|
||||
+ & OBJF_BUILD_ID_CORE_LOADED) != 0)
|
||||
+ build_id = build_id_addr_get (li->l_ld);
|
||||
+
|
||||
+ If the main executable was not loaded according to its build-id do
|
||||
+ not do any build-id checking of the libraries. There may be missing
|
||||
+ build-ids dumped in the core file and we would map all the libraries
|
||||
+ to the only existing file loaded that time - the executable. */
|
||||
+ if (current_program_space->symfile_object_file != NULL
|
||||
+ && (current_program_space->symfile_object_file->flags
|
||||
+ & OBJF_BUILD_ID_CORE_LOADED) != 0)
|
||||
+ build_id = build_id_addr_get (li->l_ld);
|
||||
if (build_id != NULL)
|
||||
{
|
||||
char *name, *build_id_filename;
|
||||
@@ -1342,23 +1356,7 @@ svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
|
||||
xfree (name);
|
||||
}
|
||||
else
|
||||
- {
|
||||
- debug_print_missing (newobj->so_name, build_id_filename);
|
||||
-
|
||||
- /* In the case the main executable was found according to
|
||||
- its build-id (from a core file) prevent loading
|
||||
- a different build of a library with accidentally the
|
||||
- same SO_NAME.
|
||||
-
|
||||
- It suppresses bogus backtraces (and prints "??" there
|
||||
- instead) if the on-disk files no longer match the
|
||||
- running program version. */
|
||||
-
|
||||
- if (current_program_space->symfile_object_file != NULL
|
||||
- && (current_program_space->symfile_object_file->flags
|
||||
- & OBJF_BUILD_ID_CORE_LOADED) != 0)
|
||||
- newobj->so_name[0] = 0;
|
||||
- }
|
||||
+ debug_print_missing (newobj->so_name, build_id_filename);
|
||||
+
|
||||
+ if (build_id != nullptr)
|
||||
{
|
||||
char *bid_name, *build_id_filename;
|
||||
|
||||
xfree (build_id_filename);
|
||||
xfree (build_id);
|
||||
@@ -1280,23 +1300,7 @@ svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
|
||||
xfree (bid_name);
|
||||
}
|
||||
else
|
||||
- {
|
||||
- debug_print_missing (name.get (), build_id_filename);
|
||||
-
|
||||
- /* In the case the main executable was found according to
|
||||
- its build-id (from a core file) prevent loading
|
||||
- a different build of a library with accidentally the
|
||||
- same SO_NAME.
|
||||
-
|
||||
- It suppresses bogus backtraces (and prints "??" there
|
||||
- instead) if the on-disk files no longer match the
|
||||
- running program version. */
|
||||
-
|
||||
- if (current_program_space->symfile_object_file != NULL
|
||||
- && (current_program_space->symfile_object_file->flags
|
||||
- & OBJF_BUILD_ID_CORE_LOADED) != 0)
|
||||
- name = make_unique_xstrdup ("");
|
||||
- }
|
||||
+ debug_print_missing (name.get (), build_id_filename);
|
||||
|
||||
xfree (build_id_filename);
|
||||
xfree (build_id);
|
||||
diff --git a/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib-lib.c b/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib-lib.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
|
@@ -9,7 +9,7 @@ Subject: gdb-6.6-buildid-locate.patch
|
||||
diff --git a/gdb/build-id.c b/gdb/build-id.c
|
||||
--- a/gdb/build-id.c
|
||||
+++ b/gdb/build-id.c
|
||||
@@ -24,9 +24,67 @@
|
||||
@@ -23,9 +23,67 @@
|
||||
#include "gdbsupport/gdb_vecs.h"
|
||||
#include "symfile.h"
|
||||
#include "objfiles.h"
|
||||
@@ -20,8 +20,8 @@ diff --git a/gdb/build-id.c b/gdb/build-id.c
|
||||
+#include "elf/internal.h"
|
||||
#include "filenames.h"
|
||||
+#include "gdb_bfd.h"
|
||||
+#include "gdbcmd.h"
|
||||
#include "gdbcore.h"
|
||||
+#include "cli/cli-cmds.h"
|
||||
#include "cli/cli-style.h"
|
||||
+#include "inferior.h"
|
||||
+#include "objfiles.h"
|
||||
@@ -77,7 +77,7 @@ diff --git a/gdb/build-id.c b/gdb/build-id.c
|
||||
|
||||
/* See build-id.h. */
|
||||
|
||||
@@ -50,6 +108,348 @@ build_id_bfd_get (bfd *abfd)
|
||||
@@ -49,6 +107,349 @@ build_id_bfd_get (bfd *abfd)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -386,12 +386,13 @@ diff --git a/gdb/build-id.c b/gdb/build-id.c
|
||||
+ bfd_vma loadbase = 0;
|
||||
+ unsigned e_phnum = 0;
|
||||
+
|
||||
+ if (core_bfd == NULL)
|
||||
+ if (current_program_space->core_bfd () == NULL)
|
||||
+ return NULL;
|
||||
+
|
||||
+ build_id_addr = addr;
|
||||
+ gdb_assert (build_id_addr_sect == NULL);
|
||||
+ bfd_map_over_sections (core_bfd, build_id_addr_candidate, NULL);
|
||||
+ bfd_map_over_sections (current_program_space->core_bfd (),
|
||||
+ build_id_addr_candidate, NULL);
|
||||
+
|
||||
+ /* Sections are sorted in the high-to-low VMAs order.
|
||||
+ Stop the search on the first ELF header we find.
|
||||
@@ -400,7 +401,7 @@ diff --git a/gdb/build-id.c b/gdb/build-id.c
|
||||
+ for (candidate = build_id_addr_sect; candidate != NULL;
|
||||
+ candidate = candidate->next)
|
||||
+ {
|
||||
+ i_phdr = elf_get_phdr (core_bfd,
|
||||
+ i_phdr = elf_get_phdr (current_program_space->core_bfd (),
|
||||
+ bfd_section_vma (candidate->sect),
|
||||
+ &e_phnum, &loadbase);
|
||||
+ if (i_phdr != NULL)
|
||||
@@ -409,7 +410,7 @@ diff --git a/gdb/build-id.c b/gdb/build-id.c
|
||||
+
|
||||
+ if (i_phdr != NULL)
|
||||
+ {
|
||||
+ retval = build_id_phdr_get (core_bfd, loadbase, e_phnum, i_phdr);
|
||||
+ retval = build_id_phdr_get (current_program_space->core_bfd (), loadbase, e_phnum, i_phdr);
|
||||
+ xfree (i_phdr);
|
||||
+ }
|
||||
+
|
||||
@@ -426,7 +427,7 @@ diff --git a/gdb/build-id.c b/gdb/build-id.c
|
||||
/* See build-id.h. */
|
||||
|
||||
int
|
||||
@@ -73,63 +473,166 @@ build_id_verify (bfd *abfd, size_t check_len, const bfd_byte *check)
|
||||
@@ -73,63 +474,166 @@ build_id_verify (bfd *abfd, size_t check_len, const bfd_byte *check)
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -488,7 +489,7 @@ diff --git a/gdb/build-id.c b/gdb/build-id.c
|
||||
- /* lrealpath() is expensive even for the usually non-existent files. */
|
||||
- gdb::unique_xmalloc_ptr<char> filename_holder;
|
||||
- const char *filename = nullptr;
|
||||
- if (startswith (link, TARGET_SYSROOT_PREFIX))
|
||||
- if (is_target_filename (link))
|
||||
- filename = link.c_str ();
|
||||
- else if (access (link.c_str (), F_OK) == 0)
|
||||
+ for (unsigned seqno = 0;; seqno++)
|
||||
@@ -627,7 +628,7 @@ diff --git a/gdb/build-id.c b/gdb/build-id.c
|
||||
}
|
||||
|
||||
/* Common code for finding BFDs of a given build-id. This function
|
||||
@@ -138,7 +641,7 @@ build_id_to_debug_bfd_1 (const std::string &link, size_t build_id_len,
|
||||
@@ -138,7 +642,7 @@ build_id_to_debug_bfd_1 (const std::string &link, size_t build_id_len,
|
||||
|
||||
static gdb_bfd_ref_ptr
|
||||
build_id_to_bfd_suffix (size_t build_id_len, const bfd_byte *build_id,
|
||||
@@ -636,7 +637,7 @@ diff --git a/gdb/build-id.c b/gdb/build-id.c
|
||||
{
|
||||
/* Keep backward compatibility so that DEBUG_FILE_DIRECTORY being "" will
|
||||
cause "/.build-id/..." lookups. */
|
||||
@@ -161,16 +664,17 @@ build_id_to_bfd_suffix (size_t build_id_len, const bfd_byte *build_id,
|
||||
@@ -161,16 +665,17 @@ build_id_to_bfd_suffix (size_t build_id_len, const bfd_byte *build_id,
|
||||
if (size > 0)
|
||||
{
|
||||
size--;
|
||||
@@ -657,7 +658,7 @@ diff --git a/gdb/build-id.c b/gdb/build-id.c
|
||||
if (debug_bfd != NULL)
|
||||
return debug_bfd;
|
||||
|
||||
@@ -181,7 +685,7 @@ build_id_to_bfd_suffix (size_t build_id_len, const bfd_byte *build_id,
|
||||
@@ -181,7 +686,7 @@ build_id_to_bfd_suffix (size_t build_id_len, const bfd_byte *build_id,
|
||||
if (!gdb_sysroot.empty ())
|
||||
{
|
||||
link = gdb_sysroot + link;
|
||||
@@ -666,7 +667,7 @@ diff --git a/gdb/build-id.c b/gdb/build-id.c
|
||||
if (debug_bfd != NULL)
|
||||
return debug_bfd;
|
||||
}
|
||||
@@ -190,20 +694,178 @@ build_id_to_bfd_suffix (size_t build_id_len, const bfd_byte *build_id,
|
||||
@@ -190,20 +695,178 @@ build_id_to_bfd_suffix (size_t build_id_len, const bfd_byte *build_id,
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -848,7 +849,7 @@ diff --git a/gdb/build-id.c b/gdb/build-id.c
|
||||
}
|
||||
|
||||
/* See build-id.h. */
|
||||
@@ -224,6 +886,7 @@ find_separate_debug_file_by_buildid (struct objfile *objfile,
|
||||
@@ -224,6 +887,7 @@ find_separate_debug_file_by_buildid (struct objfile *objfile,
|
||||
|
||||
gdb_bfd_ref_ptr abfd (build_id_to_debug_bfd (build_id->size,
|
||||
build_id->data));
|
||||
@@ -856,7 +857,7 @@ diff --git a/gdb/build-id.c b/gdb/build-id.c
|
||||
/* Prevent looping on a stripped .debug file. */
|
||||
if (abfd != NULL
|
||||
&& filename_cmp (bfd_get_filename (abfd.get ()),
|
||||
@@ -243,3 +906,22 @@ find_separate_debug_file_by_buildid (struct objfile *objfile,
|
||||
@@ -243,3 +907,22 @@ find_separate_debug_file_by_buildid (struct objfile *objfile,
|
||||
|
||||
return std::string ();
|
||||
}
|
||||
@@ -903,18 +904,17 @@ diff --git a/gdb/build-id.h b/gdb/build-id.h
|
||||
diff --git a/gdb/corelow.c b/gdb/corelow.c
|
||||
--- a/gdb/corelow.c
|
||||
+++ b/gdb/corelow.c
|
||||
@@ -22,6 +22,10 @@
|
||||
@@ -21,6 +21,9 @@
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include "frame.h"
|
||||
+#include "auxv.h"
|
||||
+#include "build-id.h"
|
||||
+#include "elf/common.h"
|
||||
+#include "gdbcmd.h"
|
||||
#include "inferior.h"
|
||||
#include "infrun.h"
|
||||
#include "symtab.h"
|
||||
@@ -380,6 +384,8 @@ add_to_thread_list (asection *asect, asection *reg_sect, inferior *inf)
|
||||
@@ -383,6 +386,8 @@ add_to_thread_list (asection *asect, asection *reg_sect, inferior *inf)
|
||||
switch_to_thread (thr); /* Yes, make it current. */
|
||||
}
|
||||
|
||||
@@ -923,7 +923,7 @@ diff --git a/gdb/corelow.c b/gdb/corelow.c
|
||||
/* Issue a message saying we have no core to debug, if FROM_TTY. */
|
||||
|
||||
static void
|
||||
@@ -567,8 +573,10 @@ locate_exec_from_corefile_build_id (bfd *abfd, int from_tty)
|
||||
@@ -570,8 +575,10 @@ locate_exec_from_corefile_build_id (bfd *abfd, int from_tty)
|
||||
if (build_id == nullptr)
|
||||
return;
|
||||
|
||||
@@ -935,7 +935,7 @@ diff --git a/gdb/corelow.c b/gdb/corelow.c
|
||||
|
||||
if (execbfd == nullptr)
|
||||
{
|
||||
@@ -596,7 +604,12 @@ locate_exec_from_corefile_build_id (bfd *abfd, int from_tty)
|
||||
@@ -599,7 +606,12 @@ locate_exec_from_corefile_build_id (bfd *abfd, int from_tty)
|
||||
exec_file_attach (bfd_get_filename (execbfd.get ()), from_tty);
|
||||
symbol_file_add_main (bfd_get_filename (execbfd.get ()),
|
||||
symfile_add_flag (from_tty ? SYMFILE_VERBOSE : 0));
|
||||
@@ -948,7 +948,7 @@ diff --git a/gdb/corelow.c b/gdb/corelow.c
|
||||
}
|
||||
|
||||
/* See gdbcore.h. */
|
||||
@@ -1506,4 +1519,11 @@ _initialize_corelow ()
|
||||
@@ -1524,4 +1536,11 @@ _initialize_corelow ()
|
||||
maintenance_print_core_file_backed_mappings,
|
||||
_("Print core file's file-backed mappings."),
|
||||
&maintenanceprintlist);
|
||||
@@ -963,7 +963,7 @@ diff --git a/gdb/corelow.c b/gdb/corelow.c
|
||||
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
|
||||
--- a/gdb/doc/gdb.texinfo
|
||||
+++ b/gdb/doc/gdb.texinfo
|
||||
@@ -22296,6 +22296,27 @@ information files.
|
||||
@@ -22487,6 +22487,27 @@ information files.
|
||||
|
||||
@end table
|
||||
|
||||
@@ -994,7 +994,7 @@ diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
|
||||
diff --git a/gdb/objfiles.h b/gdb/objfiles.h
|
||||
--- a/gdb/objfiles.h
|
||||
+++ b/gdb/objfiles.h
|
||||
@@ -884,6 +884,10 @@ struct objfile
|
||||
@@ -877,6 +877,10 @@ struct objfile
|
||||
bool object_format_has_copy_relocs = false;
|
||||
};
|
||||
|
||||
@@ -1016,61 +1016,53 @@ diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
|
||||
|
||||
#include <map>
|
||||
|
||||
@@ -1318,9 +1319,51 @@ svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
|
||||
@@ -1262,6 +1263,46 @@ svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
|
||||
continue;
|
||||
}
|
||||
|
||||
- strncpy (newobj->so_name, buffer.get (), SO_NAME_MAX_PATH_SIZE - 1);
|
||||
- newobj->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
|
||||
- strcpy (newobj->so_original_name, newobj->so_name);
|
||||
+ {
|
||||
+ struct bfd_build_id *build_id;
|
||||
+ {
|
||||
+ struct bfd_build_id *build_id;
|
||||
+
|
||||
+ strncpy (newobj->so_original_name, buffer.get (), SO_NAME_MAX_PATH_SIZE - 1);
|
||||
+ newobj->so_original_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
|
||||
+ /* May get overwritten below. */
|
||||
+ strcpy (newobj->so_name, newobj->so_original_name);
|
||||
+ build_id = build_id_addr_get (li->l_ld);
|
||||
+ if (build_id != NULL)
|
||||
+ {
|
||||
+ char *bid_name, *build_id_filename;
|
||||
+
|
||||
+ build_id = build_id_addr_get (((lm_info_svr4 *) newobj->lm_info)->l_ld);
|
||||
+ if (build_id != NULL)
|
||||
+ {
|
||||
+ char *name, *build_id_filename;
|
||||
+ /* Missing the build-id matching separate debug info file
|
||||
+ would be handled while SO_NAME gets loaded. */
|
||||
+ bid_name = build_id_to_filename (build_id, &build_id_filename);
|
||||
+ if (bid_name != NULL)
|
||||
+ {
|
||||
+ name = make_unique_xstrdup (bid_name);
|
||||
+ xfree (bid_name);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ debug_print_missing (name.get (), build_id_filename);
|
||||
+
|
||||
+ /* Missing the build-id matching separate debug info file
|
||||
+ would be handled while SO_NAME gets loaded. */
|
||||
+ name = build_id_to_filename (build_id, &build_id_filename);
|
||||
+ if (name != NULL)
|
||||
+ {
|
||||
+ strncpy (newobj->so_name, name, SO_NAME_MAX_PATH_SIZE - 1);
|
||||
+ newobj->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
|
||||
+ xfree (name);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ debug_print_missing (newobj->so_name, build_id_filename);
|
||||
+ /* In the case the main executable was found according to
|
||||
+ its build-id (from a core file) prevent loading
|
||||
+ a different build of a library with accidentally the
|
||||
+ same SO_NAME.
|
||||
+
|
||||
+ /* In the case the main executable was found according to
|
||||
+ its build-id (from a core file) prevent loading
|
||||
+ a different build of a library with accidentally the
|
||||
+ same SO_NAME.
|
||||
+ It suppresses bogus backtraces (and prints "??" there
|
||||
+ instead) if the on-disk files no longer match the
|
||||
+ running program version. */
|
||||
+
|
||||
+ It suppresses bogus backtraces (and prints "??" there
|
||||
+ instead) if the on-disk files no longer match the
|
||||
+ running program version. */
|
||||
+ if (current_program_space->symfile_object_file != NULL
|
||||
+ && (current_program_space->symfile_object_file->flags
|
||||
+ & OBJF_BUILD_ID_CORE_LOADED) != 0)
|
||||
+ name = make_unique_xstrdup ("");
|
||||
+ }
|
||||
+
|
||||
+ if (current_program_space->symfile_object_file != NULL
|
||||
+ && (current_program_space->symfile_object_file->flags
|
||||
+ & OBJF_BUILD_ID_CORE_LOADED) != 0)
|
||||
+ newobj->so_name[0] = 0;
|
||||
+ }
|
||||
+ xfree (build_id_filename);
|
||||
+ xfree (build_id);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ xfree (build_id_filename);
|
||||
+ xfree (build_id);
|
||||
+ }
|
||||
+ }
|
||||
|
||||
/* If this entry has no name, or its name matches the name
|
||||
for the main executable, don't include it in the list. */
|
||||
if (*name == '\0' || match_main (name.get ()))
|
||||
diff --git a/gdb/symfile.h b/gdb/symfile.h
|
||||
--- a/gdb/symfile.h
|
||||
+++ b/gdb/symfile.h
|
||||
@@ -1139,10 +1131,12 @@ diff --git a/gdb/testsuite/gdb.base/gdbinit-history.exp b/gdb/testsuite/gdb.base
|
||||
diff --git a/gdb/testsuite/gdb.base/new-ui-pending-input.exp b/gdb/testsuite/gdb.base/new-ui-pending-input.exp
|
||||
--- a/gdb/testsuite/gdb.base/new-ui-pending-input.exp
|
||||
+++ b/gdb/testsuite/gdb.base/new-ui-pending-input.exp
|
||||
@@ -62,6 +62,7 @@ proc test_command_line_new_ui_pending_input {} {
|
||||
@@ -60,6 +60,9 @@ proc test_command_line_new_ui_pending_input {} {
|
||||
set bpline [gdb_get_line_number "set breakpoint here"]
|
||||
|
||||
set options ""
|
||||
append options " -iex \"set height 0\""
|
||||
append options " -iex \"set width 0\""
|
||||
+ append options " -iex \"set height 0\""
|
||||
+ append options " -iex \"set width 0\""
|
||||
+ append options " -iex \"set build-id-verbose 0\""
|
||||
append options " -iex \"new-ui console $extra_tty_name\""
|
||||
append options " -ex \"b $bpline\""
|
||||
@@ -1150,7 +1144,7 @@ diff --git a/gdb/testsuite/gdb.base/new-ui-pending-input.exp b/gdb/testsuite/gdb
|
||||
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
|
||||
--- a/gdb/testsuite/lib/gdb.exp
|
||||
+++ b/gdb/testsuite/lib/gdb.exp
|
||||
@@ -226,7 +226,8 @@ if ![info exists INTERNAL_GDBFLAGS] {
|
||||
@@ -238,7 +238,8 @@ if ![info exists INTERNAL_GDBFLAGS] {
|
||||
"-nx" \
|
||||
"-q" \
|
||||
{-iex "set height 0"} \
|
||||
@@ -1160,7 +1154,7 @@ diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
|
||||
|
||||
# If DEBUGINFOD_URLS is set, gdb will try to download sources and
|
||||
# debug info for f.i. system libraries. Prevent this.
|
||||
@@ -2434,6 +2435,17 @@ proc default_gdb_start { } {
|
||||
@@ -2493,6 +2494,17 @@ proc default_gdb_start { } {
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,314 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Burgess <aburgess@redhat.com>
|
||||
Date: Fri, 13 Oct 2023 16:48:36 +0100
|
||||
Subject: gdb-add-missing-debug-ext-lang-hook.patch
|
||||
|
||||
;; Backport upstream commit 661d98a3331.
|
||||
|
||||
gdb: add an extension language hook for missing debug info
|
||||
|
||||
This commit adds a new extension_language_ops hook which allows an
|
||||
extension to handle the case where GDB can't find a separate debug
|
||||
information file for a particular objfile.
|
||||
|
||||
This commit doesn't actually implement the hook for any of GDB's
|
||||
extension languages, the next commit will do that. This commit just
|
||||
adds support for the hook to extension-priv.h and extension.[ch], and
|
||||
then reworks symfile-debug.c to call the hook.
|
||||
|
||||
Right now the hook will always return its default value, which means
|
||||
GDB should do nothing different. As such, there should be no user
|
||||
visible changes after this commit.
|
||||
|
||||
I'll give a brief description of what the hook does here so that we
|
||||
can understand the changes in symfile-debug.c. The next commit adds a
|
||||
Python implementation for this new hook, and gives a fuller
|
||||
description of the new functionality.
|
||||
|
||||
Currently, when looking for separate debug information GDB tries three
|
||||
things, in this order:
|
||||
|
||||
1. Use the build-id to find the required debug information,
|
||||
|
||||
2. Check for .gnu_debuglink section and use that to look up the
|
||||
required debug information,
|
||||
|
||||
3. Check with debuginfod to see if it can supply the required
|
||||
information.
|
||||
|
||||
The new extension_language_ops::handle_missing_debuginfo hook is
|
||||
called if all three steps fail to find any debug information. The
|
||||
hook has three possible return values:
|
||||
|
||||
a. Nothing, no debug information is found, GDB continues without the
|
||||
debug information for this objfile. This matches the current
|
||||
behaviour of GDB, and is the default if nothing is implementing this
|
||||
new hook,
|
||||
|
||||
b. Install debug information into a location that step #1 or #2
|
||||
above would normally check, and then request that GDB repeats steps
|
||||
#1 and #2 in the hope that GDB will now find the debug information.
|
||||
If the debug information is still not found then GDB carries on
|
||||
without the debug information. If the debug information is found
|
||||
the GDB loads it and carries on,
|
||||
|
||||
c. Return a filename for a file containing the required debug
|
||||
information. GDB loads the contents of this file and carries on.
|
||||
|
||||
The changes in this commit mostly involve placing the core of
|
||||
objfile::find_and_add_separate_symbol_file into a loop which allows
|
||||
for steps #1 and #2 to be repeated.
|
||||
|
||||
We take care to ensure that debuginfod is only queried once, the first
|
||||
time through. The assumption is that no extension is going to be able
|
||||
to control the replies from debuginfod, so there's no point making a
|
||||
second request -- and as these requests go over the network, they
|
||||
could potentially be slow.
|
||||
|
||||
The warnings that find_and_add_separate_symbol_file collects are
|
||||
displayed only once assuming that no debug information is found. If
|
||||
debug information is found, even after the extension has operated,
|
||||
then the warnings are not shown; remember, these are warnings from GDB
|
||||
about failure to find any suitable debug information, so it makes
|
||||
sense to hide these if debug information is found.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
diff --git a/gdb/extension-priv.h b/gdb/extension-priv.h
|
||||
--- a/gdb/extension-priv.h
|
||||
+++ b/gdb/extension-priv.h
|
||||
@@ -279,6 +279,13 @@ struct extension_language_ops
|
||||
gdb::optional<int> (*print_insn) (struct gdbarch *gdbarch,
|
||||
CORE_ADDR address,
|
||||
struct disassemble_info *info);
|
||||
+
|
||||
+ /* Give extension languages a chance to deal with missing debug
|
||||
+ information. OBJFILE is the file for which GDB was unable to find
|
||||
+ any debug information. */
|
||||
+ ext_lang_missing_debuginfo_result
|
||||
+ (*handle_missing_debuginfo) (const struct extension_language_defn *,
|
||||
+ struct objfile *objfile);
|
||||
};
|
||||
|
||||
/* State necessary to restore a signal handler to its previous value. */
|
||||
diff --git a/gdb/extension.c b/gdb/extension.c
|
||||
--- a/gdb/extension.c
|
||||
+++ b/gdb/extension.c
|
||||
@@ -997,6 +997,25 @@ ext_lang_print_insn (struct gdbarch *gdbarch, CORE_ADDR address,
|
||||
return {};
|
||||
}
|
||||
|
||||
+/* See extension.h. */
|
||||
+
|
||||
+ext_lang_missing_debuginfo_result
|
||||
+ext_lang_handle_missing_debuginfo (struct objfile *objfile)
|
||||
+{
|
||||
+ for (const struct extension_language_defn *extlang : extension_languages)
|
||||
+ {
|
||||
+ if (extlang->ops == nullptr
|
||||
+ || extlang->ops->handle_missing_debuginfo == nullptr)
|
||||
+ continue;
|
||||
+ ext_lang_missing_debuginfo_result result
|
||||
+ = extlang->ops->handle_missing_debuginfo (extlang, objfile);
|
||||
+ if (!result.filename ().empty () || result.try_again ())
|
||||
+ return result;
|
||||
+ }
|
||||
+
|
||||
+ return {};
|
||||
+}
|
||||
+
|
||||
/* Called via an observer before gdb prints its prompt.
|
||||
Iterate over the extension languages giving them a chance to
|
||||
change the prompt. The first one to change the prompt wins,
|
||||
diff --git a/gdb/extension.h b/gdb/extension.h
|
||||
--- a/gdb/extension.h
|
||||
+++ b/gdb/extension.h
|
||||
@@ -337,6 +337,68 @@ extern gdb::optional<std::string> ext_lang_colorize_disasm
|
||||
extern gdb::optional<int> ext_lang_print_insn
|
||||
(struct gdbarch *gdbarch, CORE_ADDR address, struct disassemble_info *info);
|
||||
|
||||
+/* When GDB calls into an extension language because an objfile was
|
||||
+ discovered for which GDB couldn't find any debug information, this
|
||||
+ structure holds the result that the extension language returns.
|
||||
+
|
||||
+ There are three possible actions that might be returned by an extension;
|
||||
+ first an extension can return a filename, this is the path to the file
|
||||
+ containing the required debug information. The second possibility is
|
||||
+ to return a flag indicating that GDB should check again for the missing
|
||||
+ debug information, this would imply that the extension has installed
|
||||
+ the debug information into a location where GDB can be expected to find
|
||||
+ it. And the third option is for the extension to just return a null
|
||||
+ result, indication there is nothing the extension can do to provide the
|
||||
+ missing debug information. */
|
||||
+struct ext_lang_missing_debuginfo_result
|
||||
+{
|
||||
+ /* Default result. The extension was unable to provide the missing debug
|
||||
+ info. */
|
||||
+ ext_lang_missing_debuginfo_result ()
|
||||
+ { /* Nothing. */ }
|
||||
+
|
||||
+ /* When TRY_AGAIN is true GDB should try searching again, the extension
|
||||
+ may have installed the missing debug info into a suitable location.
|
||||
+ When TRY_AGAIN is false this is equivalent to the default, no
|
||||
+ argument, constructor. */
|
||||
+ ext_lang_missing_debuginfo_result (bool try_again)
|
||||
+ : m_try_again (try_again)
|
||||
+ { /* Nothing. */ }
|
||||
+
|
||||
+ /* Look in FILENAME for the missing debug info. */
|
||||
+ ext_lang_missing_debuginfo_result (std::string &&filename)
|
||||
+ : m_filename (std::move (filename))
|
||||
+ { /* Nothing. */ }
|
||||
+
|
||||
+ /* The filename where GDB can find the missing debuginfo. This is empty
|
||||
+ if the extension didn't suggest a file that can be used. */
|
||||
+ const std::string &
|
||||
+ filename () const
|
||||
+ {
|
||||
+ return m_filename;
|
||||
+ }
|
||||
+
|
||||
+ /* Returns true if GDB should look again for the debug information. */
|
||||
+ const bool
|
||||
+ try_again () const
|
||||
+ {
|
||||
+ return m_try_again;
|
||||
+ }
|
||||
+
|
||||
+private:
|
||||
+ /* The filename where the missing debuginfo can now be found. */
|
||||
+ std::string m_filename;
|
||||
+
|
||||
+ /* When true GDB will search again for the debuginfo using its standard
|
||||
+ techniques. When false GDB will not search again. */
|
||||
+ bool m_try_again = false;
|
||||
+};
|
||||
+
|
||||
+/* Called when GDB failed to find any debug information for OBJFILE. */
|
||||
+
|
||||
+extern ext_lang_missing_debuginfo_result ext_lang_handle_missing_debuginfo
|
||||
+ (struct objfile *objfile);
|
||||
+
|
||||
#if GDB_SELF_TEST
|
||||
namespace selftests {
|
||||
extern void (*hook_set_active_ext_lang) ();
|
||||
diff --git a/gdb/symfile-debug.c b/gdb/symfile-debug.c
|
||||
--- a/gdb/symfile-debug.c
|
||||
+++ b/gdb/symfile-debug.c
|
||||
@@ -631,38 +631,88 @@ debuginfod_find_and_open_separate_symbol_file (struct objfile * objfile)
|
||||
bool
|
||||
objfile::find_and_add_separate_symbol_file (symfile_add_flags symfile_flags)
|
||||
{
|
||||
- bool has_dwarf = false;
|
||||
-
|
||||
- deferred_warnings warnings;
|
||||
-
|
||||
- gdb_bfd_ref_ptr debug_bfd;
|
||||
- std::string filename;
|
||||
-
|
||||
- std::tie (debug_bfd, filename) = simple_find_and_open_separate_symbol_file
|
||||
- (this, find_separate_debug_file_by_buildid, &warnings);
|
||||
-
|
||||
- if (debug_bfd == nullptr)
|
||||
- std::tie (debug_bfd, filename)
|
||||
- = simple_find_and_open_separate_symbol_file
|
||||
- (this, find_separate_debug_file_by_debuglink, &warnings);
|
||||
+ bool has_dwarf2 = false;
|
||||
+
|
||||
+ /* Usually we only make a single pass when looking for separate debug
|
||||
+ information. However, it is possible for an extension language hook
|
||||
+ to request that GDB make a second pass, in which case max_attempts
|
||||
+ will be updated, and the loop restarted. */
|
||||
+ for (unsigned attempt = 0, max_attempts = 1;
|
||||
+ attempt < max_attempts && !has_dwarf2;
|
||||
+ ++attempt)
|
||||
+ {
|
||||
+ gdb_assert (max_attempts <= 2);
|
||||
+
|
||||
+ deferred_warnings warnings;
|
||||
+ gdb_bfd_ref_ptr debug_bfd;
|
||||
+ std::string filename;
|
||||
+
|
||||
+ std::tie (debug_bfd, filename)
|
||||
+ = simple_find_and_open_separate_symbol_file
|
||||
+ (this, find_separate_debug_file_by_buildid, &warnings);
|
||||
+
|
||||
+ if (debug_bfd == nullptr)
|
||||
+ std::tie (debug_bfd, filename)
|
||||
+ = simple_find_and_open_separate_symbol_file
|
||||
+ (this, find_separate_debug_file_by_debuglink, &warnings);
|
||||
+
|
||||
+ /* Only try debuginfod on the first attempt. Sure, we could imagine
|
||||
+ an extension that somehow adds the required debug info to the
|
||||
+ debuginfod server but, at least for now, we don't support this
|
||||
+ scenario. Better for the extension to return new debug info
|
||||
+ directly to GDB. Plus, going to the debuginfod server might be
|
||||
+ slow, so that's a good argument for only doing this once. */
|
||||
+ if (debug_bfd == nullptr && attempt == 0)
|
||||
+ std::tie (debug_bfd, filename)
|
||||
+ = debuginfod_find_and_open_separate_symbol_file (this);
|
||||
+
|
||||
+ if (debug_bfd != nullptr)
|
||||
+ {
|
||||
+ /* We found a separate debug info symbol file. If this is our
|
||||
+ first attempt then setting HAS_DWARF2 will cause us to break
|
||||
+ from the attempt loop. */
|
||||
+ symbol_file_add_separate (debug_bfd, filename.c_str (),
|
||||
+ symfile_flags, this);
|
||||
+ has_dwarf2 = true;
|
||||
+ }
|
||||
+ else if (attempt == 0)
|
||||
+ {
|
||||
+ /* Failed to find a separate debug info symbol file. Call out to
|
||||
+ the extension languages. The user might have registered an
|
||||
+ extension that can find the debug info for us, or maybe give
|
||||
+ the user a system specific message that guides them to finding
|
||||
+ the missing debug info. */
|
||||
+
|
||||
+ ext_lang_missing_debuginfo_result ext_result
|
||||
+ = ext_lang_handle_missing_debuginfo (this);
|
||||
+ if (!ext_result.filename ().empty ())
|
||||
+ {
|
||||
+ /* Extension found a suitable debug file for us. */
|
||||
+ debug_bfd
|
||||
+ = symfile_bfd_open_no_error (ext_result.filename ().c_str ());
|
||||
|
||||
- if (debug_bfd == nullptr)
|
||||
- std::tie (debug_bfd, filename)
|
||||
- = debuginfod_find_and_open_separate_symbol_file (this);
|
||||
+ if (debug_bfd != nullptr)
|
||||
+ {
|
||||
+ symbol_file_add_separate (debug_bfd,
|
||||
+ ext_result.filename ().c_str (),
|
||||
+ symfile_flags, this);
|
||||
+ has_dwarf2 = true;
|
||||
+ }
|
||||
+ }
|
||||
+ else if (ext_result.try_again ())
|
||||
+ {
|
||||
+ max_attempts = 2;
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
- if (debug_bfd != nullptr)
|
||||
- {
|
||||
- symbol_file_add_separate (debug_bfd, filename.c_str (), symfile_flags,
|
||||
- this);
|
||||
- has_dwarf = true;
|
||||
+ /* If we still have not got a separate debug symbol file, then
|
||||
+ emit any warnings we've collected so far. */
|
||||
+ if (!has_dwarf2)
|
||||
+ warnings.emit ();
|
||||
}
|
||||
|
||||
- /* If we still have not got a separate debug symbol file, then
|
||||
- emit any warnings we've collected so far. */
|
||||
- if (!has_dwarf)
|
||||
- warnings.emit ();
|
||||
-
|
||||
- return has_dwarf;
|
||||
+ return has_dwarf2;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -14,7 +14,7 @@ suggests debuginfo RPMs to install.
|
||||
diff --git a/gdb/data-directory/Makefile.in b/gdb/data-directory/Makefile.in
|
||||
--- a/gdb/data-directory/Makefile.in
|
||||
+++ b/gdb/data-directory/Makefile.in
|
||||
@@ -86,6 +86,7 @@ PYTHON_FILE_LIST = \
|
||||
@@ -89,6 +89,7 @@ PYTHON_FILE_LIST = \
|
||||
gdb/command/missing_debug.py \
|
||||
gdb/command/pretty_printers.py \
|
||||
gdb/command/prompt.py \
|
||||
@@ -164,9 +164,9 @@ new file mode 100644
|
||||
diff --git a/gdb/testsuite/gdb.python/py-missing-debug.py b/gdb/testsuite/gdb.python/py-missing-debug.py
|
||||
--- a/gdb/testsuite/gdb.python/py-missing-debug.py
|
||||
+++ b/gdb/testsuite/gdb.python/py-missing-debug.py
|
||||
@@ -18,6 +18,13 @@ from gdb.missing_debug import MissingDebugHandler
|
||||
from enum import Enum
|
||||
import os
|
||||
@@ -19,6 +19,13 @@ from enum import Enum
|
||||
import gdb
|
||||
from gdb.missing_debug import MissingDebugHandler
|
||||
|
||||
+# This is a RHEL/Fedora work around: There's already a
|
||||
+# missing-debug-info handler registered for these versions of GDB.
|
||||
|
@@ -1,47 +0,0 @@
|
||||
From 40b2857e42b477832ca7fc2771b6cde910e22f05 Mon Sep 17 00:00:00 2001
|
||||
From: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
|
||||
Date: Tue, 23 Jan 2024 14:11:33 -0300
|
||||
Subject: [PATCH 4/7] gdb/arm: Fix epilogue frame id
|
||||
|
||||
arm_epilogue_frame_this_id has a comment saying that it fall backs to using
|
||||
the current PC if the function start address can't be identified, but it
|
||||
actually uses only the PC to make the frame id.
|
||||
|
||||
This patch makes the code match the comment. Another hint that it's what
|
||||
is intended is that arm_prologue_this_id, a function almost identical to
|
||||
it, does that.
|
||||
|
||||
The problem was found by code inspection. It fixes the following testsuite
|
||||
failures:
|
||||
|
||||
FAIL: gdb.base/unwind-on-each-insn.exp: foo: instruction 9: check frame-id matches
|
||||
FAIL: gdb.reverse/solib-reverse.exp: reverse-next third shr1
|
||||
FAIL: gdb.reverse/solib-reverse.exp: reverse-next second shr1
|
||||
FAIL: gdb.reverse/solib-reverse.exp: reverse-next first shr1
|
||||
FAIL: gdb.reverse/solib-reverse.exp: reverse-next generic
|
||||
FAIL: gdb.reverse/solib-reverse.exp: reverse-step into solib function one
|
||||
FAIL: gdb.reverse/solib-reverse.exp: reverse-step within solib function one
|
||||
FAIL: gdb.reverse/solib-reverse.exp: reverse-step into solib function two
|
||||
FAIL: gdb.reverse/solib-reverse.exp: reverse-step within solib function two
|
||||
|
||||
Tested on arm-linux-gnueabi-hf.
|
||||
---
|
||||
gdb/arm-tdep.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
|
||||
index 3b1682a2aea..21dad198dc7 100644
|
||||
--- a/gdb/arm-tdep.c
|
||||
+++ b/gdb/arm-tdep.c
|
||||
@@ -3252,7 +3252,7 @@ arm_epilogue_frame_this_id (frame_info_ptr this_frame,
|
||||
|
||||
arm_gdbarch_tdep *tdep
|
||||
= gdbarch_tdep<arm_gdbarch_tdep> (get_frame_arch (this_frame));
|
||||
- *this_id = frame_id_build (arm_cache_get_prev_sp_value (cache, tdep), pc);
|
||||
+ *this_id = frame_id_build (arm_cache_get_prev_sp_value (cache, tdep), func);
|
||||
}
|
||||
|
||||
/* Implementation of function hook 'prev_register' in
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,77 +0,0 @@
|
||||
From 51a5415b3313470cb62fda7ad6762fc1c41c8cbd Mon Sep 17 00:00:00 2001
|
||||
From: Simon Marchi <simon.marchi@efficios.com>
|
||||
Date: Tue, 7 Nov 2023 11:11:18 -0500
|
||||
Subject: [PATCH] gdb/arm: remove thumb bit in arm_adjust_breakpoint_address
|
||||
|
||||
When compiling gdb with -fsanitize=address on ARM, I get a crash in test
|
||||
gdb.arch/arm-disp-step.exp, reproduced easily with:
|
||||
|
||||
$ ./gdb -nx -q --data-directory=data-directory testsuite/outputs/gdb.arch/arm-disp-step/arm-disp-step -ex "break *test_call_end"
|
||||
Reading symbols from testsuite/outputs/gdb.arch/arm-disp-step/arm-disp-step...
|
||||
=================================================================
|
||||
==23295==ERROR: AddressSanitizer: heap-buffer-overflow on address 0xb4a14fd1 at pc 0x01a48871 bp 0xbeab8490 sp 0xbeab8494
|
||||
|
||||
Since it doesn't require running the program, it can be reproduced locally on a
|
||||
dev machine other than ARM, after acquiring the test binary.
|
||||
|
||||
The length of the allocate buffer `buf` is 1, and we try to extract an
|
||||
integer of size 2 from it. The length of 1 comes from the subtraction
|
||||
`bpaddr - boundary`. Normally, on ARM, all instructions are aligned on
|
||||
a multiple of 2, so it's weird for this subtraction to result in 1. In
|
||||
this case, boundary comes from the result of find_pc_partial_function
|
||||
returning 0x549:
|
||||
|
||||
(gdb) p/x bpaddr
|
||||
$2 = 0x54a
|
||||
(gdb) p/x boundary
|
||||
$3 = 0x549
|
||||
(gdb) p/x bpaddr - boundary
|
||||
$4 = 0x1
|
||||
|
||||
0x549 is the address of the test_call_subr label, 0x548, with the thumb
|
||||
bit enabled. Before doing some math with the address, I think we need
|
||||
to strip the thumb bit, like is done elsewhere (for instance for bpaddr
|
||||
earlier in the same function).
|
||||
|
||||
I wonder if find_pc_partial_function should do that itself, in order to
|
||||
return an address that is suitable for arithmetic. In any case, that
|
||||
would be a change with a broad impact, so for now just fix the issue
|
||||
locally.
|
||||
|
||||
After the patch:
|
||||
|
||||
$ ./gdb -nx -q --data-directory=data-directory testsuite/outputs/gdb.arch/arm-disp-step/arm-disp-step -ex "break *test_call_end"
|
||||
Reading symbols from testsuite/outputs/gdb.arch/arm-disp-step/arm-disp-step...
|
||||
Breakpoint 1 at 0x54a: file /home/smarchi/src/binutils-gdb/gdb/testsuite/gdb.arch/arm-disp-step.S, line 103.
|
||||
|
||||
Change-Id: I74fc458dbea0d2c1e1f5eadd90755188df089288
|
||||
Approved-By: Luis Machado <luis.machado@arm.com>
|
||||
---
|
||||
gdb/arm-tdep.c | 9 ++++++---
|
||||
1 file changed, 6 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
|
||||
index 21dad198dc7..e61342f3ccb 100644
|
||||
--- a/gdb/arm-tdep.c
|
||||
+++ b/gdb/arm-tdep.c
|
||||
@@ -5340,9 +5340,12 @@ arm_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr)
|
||||
|
||||
bpaddr = gdbarch_addr_bits_remove (gdbarch, bpaddr);
|
||||
|
||||
- if (find_pc_partial_function (bpaddr, NULL, &func_start, NULL)
|
||||
- && func_start > boundary)
|
||||
- boundary = func_start;
|
||||
+ if (find_pc_partial_function (bpaddr, NULL, &func_start, NULL))
|
||||
+ {
|
||||
+ func_start = gdbarch_addr_bits_remove (gdbarch, func_start);
|
||||
+ if (func_start > boundary)
|
||||
+ boundary = func_start;
|
||||
+ }
|
||||
|
||||
/* Search for a candidate IT instruction. We have to do some fancy
|
||||
footwork to distinguish a real IT instruction from the second
|
||||
|
||||
base-commit: eafca1ce3d589c731927e5481199db715bcbeff3
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,219 +0,0 @@
|
||||
From 7973eaf11e33ddd405830b9bd29495991db5901d Mon Sep 17 00:00:00 2001
|
||||
From: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
|
||||
Date: Mon, 26 Feb 2024 19:11:45 -0300
|
||||
Subject: [PATCH 2/7] gdb/arm: Remove tpidruro register from non-FreeBSD target
|
||||
descriptions
|
||||
|
||||
Commit 92d48a1e4eac ("Add an arm-tls feature which includes the tpidruro
|
||||
register from CP15.") introduced the org.gnu.gdb.arm.tls feature, which
|
||||
adds the tpidruro register, and unconditionally enabled it in
|
||||
aarch32_create_target_description.
|
||||
|
||||
In Linux, the tpidruro register isn't available via ptrace in the 32-bit
|
||||
kernel but it is available for an aarch32 program running under an arm64
|
||||
kernel via the ptrace compat interface. This isn't currently implemented
|
||||
however, which causes GDB on arm-linux with 64-bit kernel to list the
|
||||
register but show it as unavailable, as reported by Tom de Vries:
|
||||
|
||||
$ gdb -q -batch a.out -ex start -ex 'p $tpidruro'
|
||||
Temporary breakpoint 1 at 0x512
|
||||
|
||||
Temporary breakpoint 1, 0xaaaaa512 in main ()
|
||||
$1 = <unavailable>
|
||||
|
||||
Simon Marchi then clarified:
|
||||
|
||||
> The only time we should be seeing some "unavailable" registers or memory
|
||||
> is in the context of tracepoints, for things that are not collected.
|
||||
> Seeing an unavailable register here is a sign that something is not
|
||||
> right.
|
||||
|
||||
Therefore, disable the TLS feature in aarch32 target descriptions for Linux
|
||||
and NetBSD targets (the latter also doesn't seem to support accessing
|
||||
tpidruro either, based on a quick look at arm-netbsd-nat.c).
|
||||
|
||||
This patch fixes the following tests:
|
||||
|
||||
Running gdb.base/inline-frame-cycle-unwind.exp ...
|
||||
FAIL: gdb.base/inline-frame-cycle-unwind.exp: cycle at level 3: backtrace when the unwind is broken at frame 3
|
||||
FAIL: gdb.base/inline-frame-cycle-unwind.exp: cycle at level 5: backtrace when the unwind is broken at frame 5
|
||||
FAIL: gdb.base/inline-frame-cycle-unwind.exp: cycle at level 1: backtrace when the unwind is broken at frame 1
|
||||
|
||||
Tested with Ubuntu 22.04.3 on armv8l-linux-gnueabihf in native,
|
||||
native-gdbserver and native-extended-gdbserver targets with no regressions.
|
||||
|
||||
PR tdep/31418
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31418
|
||||
|
||||
Approved-By: John Baldwin <jhb@FreeBSD.org>
|
||||
---
|
||||
gdb/aarch32-tdep.c | 15 ++++++++++-----
|
||||
gdb/aarch32-tdep.h | 2 +-
|
||||
gdb/aarch64-linux-nat.c | 2 +-
|
||||
gdb/arch/aarch32.c | 5 +++--
|
||||
gdb/arch/aarch32.h | 2 +-
|
||||
gdb/arm-fbsd-tdep.c | 2 +-
|
||||
gdb/arm-linux-nat.c | 2 +-
|
||||
gdb/arm-linux-tdep.c | 2 +-
|
||||
gdb/arm-netbsd-nat.c | 2 +-
|
||||
gdbserver/linux-aarch32-tdesc.cc | 2 +-
|
||||
10 files changed, 21 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/gdb/aarch32-tdep.c b/gdb/aarch32-tdep.c
|
||||
index bfa88a96522..395328936e4 100644
|
||||
--- a/gdb/aarch32-tdep.c
|
||||
+++ b/gdb/aarch32-tdep.c
|
||||
@@ -22,15 +22,20 @@
|
||||
#include "gdbsupport/common-regcache.h"
|
||||
#include "arch/aarch32.h"
|
||||
|
||||
-static struct target_desc *tdesc_aarch32;
|
||||
+static struct target_desc *tdesc_aarch32_list[2];
|
||||
|
||||
/* See aarch32-tdep.h. */
|
||||
|
||||
const target_desc *
|
||||
-aarch32_read_description ()
|
||||
+aarch32_read_description (bool tls)
|
||||
{
|
||||
- if (tdesc_aarch32 == nullptr)
|
||||
- tdesc_aarch32 = aarch32_create_target_description ();
|
||||
+ struct target_desc *tdesc = tdesc_aarch32_list[tls];
|
||||
|
||||
- return tdesc_aarch32;
|
||||
+ if (tdesc == nullptr)
|
||||
+ {
|
||||
+ tdesc = aarch32_create_target_description (tls);
|
||||
+ tdesc_aarch32_list[tls] = tdesc;
|
||||
+ }
|
||||
+
|
||||
+ return tdesc;
|
||||
}
|
||||
diff --git a/gdb/aarch32-tdep.h b/gdb/aarch32-tdep.h
|
||||
index bee4d4e9fc0..efc93351298 100644
|
||||
--- a/gdb/aarch32-tdep.h
|
||||
+++ b/gdb/aarch32-tdep.h
|
||||
@@ -22,6 +22,6 @@ struct target_desc;
|
||||
|
||||
/* Get the AArch32 target description. */
|
||||
|
||||
-const target_desc *aarch32_read_description ();
|
||||
+const target_desc *aarch32_read_description (bool tls);
|
||||
|
||||
#endif /* aarch32-tdep.h. */
|
||||
diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
|
||||
index 768748a20db..c680d6de0c9 100644
|
||||
--- a/gdb/aarch64-linux-nat.c
|
||||
+++ b/gdb/aarch64-linux-nat.c
|
||||
@@ -887,7 +887,7 @@ aarch64_linux_nat_target::read_description ()
|
||||
|
||||
ret = ptrace (PTRACE_GETREGSET, tid, NT_ARM_VFP, &iovec);
|
||||
if (ret == 0)
|
||||
- return aarch32_read_description ();
|
||||
+ return aarch32_read_description (false);
|
||||
|
||||
CORE_ADDR hwcap = linux_get_hwcap ();
|
||||
CORE_ADDR hwcap2 = linux_get_hwcap2 ();
|
||||
diff --git a/gdb/arch/aarch32.c b/gdb/arch/aarch32.c
|
||||
index 5be2cc0156e..b7510ee41e9 100644
|
||||
--- a/gdb/arch/aarch32.c
|
||||
+++ b/gdb/arch/aarch32.c
|
||||
@@ -25,7 +25,7 @@
|
||||
/* See aarch32.h. */
|
||||
|
||||
target_desc *
|
||||
-aarch32_create_target_description ()
|
||||
+aarch32_create_target_description (bool tls)
|
||||
{
|
||||
target_desc_up tdesc = allocate_target_description ();
|
||||
|
||||
@@ -39,7 +39,8 @@ aarch32_create_target_description ()
|
||||
/* Create a vfpv3 feature, then a blank NEON feature. */
|
||||
regnum = create_feature_arm_arm_vfpv3 (tdesc.get (), regnum);
|
||||
tdesc_create_feature (tdesc.get (), "org.gnu.gdb.arm.neon");
|
||||
- regnum = create_feature_arm_arm_tls (tdesc.get (), regnum);
|
||||
+ if (tls)
|
||||
+ regnum = create_feature_arm_arm_tls (tdesc.get (), regnum);
|
||||
|
||||
return tdesc.release ();
|
||||
}
|
||||
diff --git a/gdb/arch/aarch32.h b/gdb/arch/aarch32.h
|
||||
index 6b24ae94335..e06e260e370 100644
|
||||
--- a/gdb/arch/aarch32.h
|
||||
+++ b/gdb/arch/aarch32.h
|
||||
@@ -22,6 +22,6 @@
|
||||
|
||||
/* Create the AArch32 target description. */
|
||||
|
||||
-target_desc *aarch32_create_target_description ();
|
||||
+target_desc *aarch32_create_target_description (bool tls);
|
||||
|
||||
#endif /* aarch32.h. */
|
||||
diff --git a/gdb/arm-fbsd-tdep.c b/gdb/arm-fbsd-tdep.c
|
||||
index b46fa91d0a0..a4cea77f388 100644
|
||||
--- a/gdb/arm-fbsd-tdep.c
|
||||
+++ b/gdb/arm-fbsd-tdep.c
|
||||
@@ -228,7 +228,7 @@ arm_fbsd_read_description_auxv (const gdb::optional<gdb::byte_vector> &auxv,
|
||||
if (arm_hwcap & HWCAP_VFP)
|
||||
{
|
||||
if (arm_hwcap & HWCAP_NEON)
|
||||
- return aarch32_read_description ();
|
||||
+ return aarch32_read_description (tls);
|
||||
else if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPD32))
|
||||
== (HWCAP_VFPv3 | HWCAP_VFPD32))
|
||||
return arm_read_description (ARM_FP_TYPE_VFPV3, tls);
|
||||
diff --git a/gdb/arm-linux-nat.c b/gdb/arm-linux-nat.c
|
||||
index 70c6bc684fa..07af23d3881 100644
|
||||
--- a/gdb/arm-linux-nat.c
|
||||
+++ b/gdb/arm-linux-nat.c
|
||||
@@ -568,7 +568,7 @@ arm_linux_nat_target::read_description ()
|
||||
/* NEON implies VFPv3-D32 or no-VFP unit. Say that we only support
|
||||
Neon with VFPv3-D32. */
|
||||
if (arm_hwcap & HWCAP_NEON)
|
||||
- return aarch32_read_description ();
|
||||
+ return aarch32_read_description (false);
|
||||
else if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPv3D16)) == HWCAP_VFPv3)
|
||||
return arm_read_description (ARM_FP_TYPE_VFPV3, false);
|
||||
|
||||
diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c
|
||||
index dfa816990ff..33748731cfd 100644
|
||||
--- a/gdb/arm-linux-tdep.c
|
||||
+++ b/gdb/arm-linux-tdep.c
|
||||
@@ -740,7 +740,7 @@ arm_linux_core_read_description (struct gdbarch *gdbarch,
|
||||
/* NEON implies VFPv3-D32 or no-VFP unit. Say that we only support
|
||||
Neon with VFPv3-D32. */
|
||||
if (arm_hwcap & HWCAP_NEON)
|
||||
- return aarch32_read_description ();
|
||||
+ return aarch32_read_description (false);
|
||||
else if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPv3D16)) == HWCAP_VFPv3)
|
||||
return arm_read_description (ARM_FP_TYPE_VFPV3, false);
|
||||
|
||||
diff --git a/gdb/arm-netbsd-nat.c b/gdb/arm-netbsd-nat.c
|
||||
index d83714a46c3..018964b010d 100644
|
||||
--- a/gdb/arm-netbsd-nat.c
|
||||
+++ b/gdb/arm-netbsd-nat.c
|
||||
@@ -350,7 +350,7 @@ arm_netbsd_nat_target::read_description ()
|
||||
|
||||
len = sizeof(flag);
|
||||
if (sysctlbyname("machdep.neon_present", &flag, &len, NULL, 0) == 0 && flag)
|
||||
- return aarch32_read_description ();
|
||||
+ return aarch32_read_description (false);
|
||||
|
||||
return arm_read_description (ARM_FP_TYPE_VFPV3, false);
|
||||
}
|
||||
diff --git a/gdbserver/linux-aarch32-tdesc.cc b/gdbserver/linux-aarch32-tdesc.cc
|
||||
index e1380fa2a40..443f91e3585 100644
|
||||
--- a/gdbserver/linux-aarch32-tdesc.cc
|
||||
+++ b/gdbserver/linux-aarch32-tdesc.cc
|
||||
@@ -32,7 +32,7 @@ aarch32_linux_read_description ()
|
||||
{
|
||||
if (tdesc_aarch32 == nullptr)
|
||||
{
|
||||
- tdesc_aarch32 = aarch32_create_target_description ();
|
||||
+ tdesc_aarch32 = aarch32_create_target_description (false);
|
||||
|
||||
static const char *expedite_regs[] = { "r11", "sp", "pc", 0 };
|
||||
init_target_desc (tdesc_aarch32, expedite_regs);
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,41 +0,0 @@
|
||||
From 0397481ff25b76d43b123f3d51828982ceb92834 Mon Sep 17 00:00:00 2001
|
||||
From: Mark Wielaard <mark@klomp.org>
|
||||
Date: Fri, 3 May 2024 15:17:42 +0200
|
||||
Subject: [PATCH] [gdb/build] Fix gdbserver/linux-aarch64-low.cc build
|
||||
|
||||
Commit 0ee25f97d21e ("Fix regression on aarch64-linux gdbserver")
|
||||
removed the last use of i in gdbserver/linux-aarch64-low.cc
|
||||
(aarch64_target::low_stopped_data_address). Breaking the build on
|
||||
aarch64 with:
|
||||
|
||||
gdbserver/linux-aarch64-low.cc: In member function ?virtual CORE_ADDR aarch64_target::low_stopped_data_address()?:
|
||||
gdbserver/linux-aarch64-low.cc:557:12: error: unused variable ?i? [-Werror=unused-variable]
|
||||
557 | int pid, i;
|
||||
| ^
|
||||
cc1plus: all warnings being treated as errors
|
||||
|
||||
Fix this by removing the variable i completely.
|
||||
|
||||
Fixes: 0ee25f97d21e ("Fix regression on aarch64-linux gdbserver")
|
||||
---
|
||||
gdbserver/linux-aarch64-low.cc | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdbserver/linux-aarch64-low.cc b/gdbserver/linux-aarch64-low.cc
|
||||
index 14346b89822..ce0029b885f 100644
|
||||
--- a/gdbserver/linux-aarch64-low.cc
|
||||
+++ b/gdbserver/linux-aarch64-low.cc
|
||||
@@ -555,7 +555,7 @@ CORE_ADDR
|
||||
aarch64_target::low_stopped_data_address ()
|
||||
{
|
||||
siginfo_t siginfo;
|
||||
- int pid, i;
|
||||
+ int pid;
|
||||
struct aarch64_debug_reg_state *state;
|
||||
|
||||
pid = lwpid_of (current_thread);
|
||||
|
||||
base-commit: b33811a85ff53af77cdad995ad8cb50431c8c362
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,64 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Wed, 22 Nov 2023 19:02:34 +0100
|
||||
Subject: gdb-do-not-import-py-curses-ascii-module.patch
|
||||
|
||||
;; Backport upstream commit e8c3dafa5f5.
|
||||
|
||||
[gdb/python] Don't import curses.ascii module unless necessary
|
||||
|
||||
I ran into a failure in test-case gdb.python/py-missing-debug.exp with python
|
||||
3.6, which was fixed by commit 7db795bc67a ("gdb/python: remove use of
|
||||
str.isascii()").
|
||||
|
||||
However, I subsequently ran into a failure with python 3.11:
|
||||
...
|
||||
(gdb) PASS: $exp: initial checks: debug info no longer found
|
||||
source py-missing-debug.py^M
|
||||
Traceback (most recent call last):^M
|
||||
File "py-missing-debug.py", line 17, in <module>^M
|
||||
from gdb.missing_debug import MissingDebugHandler^M
|
||||
File "missing_debug.py", line 21, in <module>^M
|
||||
from curses.ascii import isascii, isalnum^M
|
||||
File "/usr/lib64/python3.11/_import_failed/curses.py", line 16, in <module>^M
|
||||
raise ImportError(f"""Module '{failed_name}' is not installed.^M
|
||||
ImportError: Module 'curses' is not installed.^M
|
||||
Use:^M
|
||||
sudo zypper install python311-curses^M
|
||||
to install it.^M
|
||||
(gdb) FAIL: $exp: source python script
|
||||
...
|
||||
|
||||
Apparently I have the curses module installed for 3.6, but not 3.11.
|
||||
|
||||
I could just install it, but the test-case worked fine with 3.11 before commit
|
||||
7db795bc67a.
|
||||
|
||||
Fix this by only using the curses module when necessary, for python <= 3.7.
|
||||
|
||||
Tested on x86_64-linux, with both python 3.6 and 3.11.
|
||||
|
||||
diff --git a/gdb/python/lib/gdb/missing_debug.py b/gdb/python/lib/gdb/missing_debug.py
|
||||
--- a/gdb/python/lib/gdb/missing_debug.py
|
||||
+++ b/gdb/python/lib/gdb/missing_debug.py
|
||||
@@ -18,8 +18,18 @@ MissingDebugHandler base class, and register_handler function.
|
||||
"""
|
||||
|
||||
import gdb
|
||||
-from curses.ascii import isascii, isalnum
|
||||
-
|
||||
+import sys
|
||||
+if sys.version_info >= (3, 7):
|
||||
+ # Functions str.isascii() and str.isalnum are available starting Python
|
||||
+ # 3.7.
|
||||
+ def isascii(ch):
|
||||
+ return ch.isascii()
|
||||
+ def isalnum(ch):
|
||||
+ return ch.isalnum()
|
||||
+else:
|
||||
+ # Fall back to curses.ascii.isascii() and curses.ascii.isalnum() for
|
||||
+ # earlier versions.
|
||||
+ from curses.ascii import isascii, isalnum
|
||||
|
||||
def _validate_name(name):
|
||||
"""Validate a missing debug handler name string.
|
61
gdb-doc-fix-gdb.unwinder-docs.patch
Normal file
61
gdb-doc-fix-gdb.unwinder-docs.patch
Normal file
@@ -0,0 +1,61 @@
|
||||
From b57066d1eaafab3100a8d7d788feba5802c409b7 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Mon, 27 Jan 2025 10:33:28 +0100
|
||||
Subject: [PATCH] [gdb/doc] Fix gdb.unwinder docs
|
||||
|
||||
When building gdb with an older makeinfo (4.13), I run into:
|
||||
...
|
||||
gdb/doc/python.texi:3015: warning: `(' follows defined name \
|
||||
`gdb.unwinder.Unwinder.__init__' instead of whitespace.
|
||||
gdb/doc/python.texi:3041: warning: `(' follows defined name \
|
||||
`gdb.unwinder.FrameId.__init__' instead of whitespace.
|
||||
...
|
||||
|
||||
The warnings are related to these two lines:
|
||||
...
|
||||
@defun gdb.unwinder.Unwinder.__init__(name)
|
||||
...
|
||||
@defun gdb.unwinder.FrameId.__init__(sp, pc, special = @code{None})
|
||||
...
|
||||
|
||||
Indeed, when checking the command and variable index, we can see that it
|
||||
contains an incorrect entry:
|
||||
...
|
||||
gdb.unwinder.FrameId.__init__(sp,: Unwinding Frames in Python
|
||||
...
|
||||
|
||||
Fix this by adding a space before the left parenthesis.
|
||||
|
||||
Tested by rebuilding the documentation and checking the command and variable
|
||||
index.
|
||||
---
|
||||
gdb/doc/python.texi | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
|
||||
index e49cc580b1b..58904298c71 100644
|
||||
--- a/gdb/doc/python.texi
|
||||
+++ b/gdb/doc/python.texi
|
||||
@@ -3011,7 +3011,7 @@ unwinders can derive, though it is not required that unwinders derive
|
||||
from this class, so long as any user created unwinder has the required
|
||||
@code{name} and @code{enabled} attributes.
|
||||
|
||||
-@defun gdb.unwinder.Unwinder.__init__(name)
|
||||
+@defun gdb.unwinder.Unwinder.__init__ (name)
|
||||
The @var{name} is a string used to reference this unwinder within some
|
||||
@value{GDBN} commands (@pxref{Managing Registered Unwinders}).
|
||||
@end defun
|
||||
@@ -3037,7 +3037,7 @@ most cases this class will be sufficient.
|
||||
|
||||
@code{gdb.unwinder.FrameId} has the following method:
|
||||
|
||||
-@defun gdb.unwinder.FrameId.__init__(sp, pc, special = @code{None})
|
||||
+@defun gdb.unwinder.FrameId.__init__ (sp, pc, special = @code{None})
|
||||
The @var{sp} and @var{pc} arguments are required and should be either
|
||||
a @code{gdb.Value} object, or an integer.
|
||||
|
||||
|
||||
base-commit: fe0e6edbcb65ab5eca50c1a0ad8ddc9844f8ea98
|
||||
--
|
||||
2.43.0
|
||||
|
41
gdb-doc-fix-qisaddresstagged-anchor.patch
Normal file
41
gdb-doc-fix-qisaddresstagged-anchor.patch
Normal file
@@ -0,0 +1,41 @@
|
||||
From c23182d85ad9b5b6a45ba74993de55eac00a71bc Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Mon, 27 Jan 2025 11:22:12 +0100
|
||||
Subject: [PATCH] [gdb/doc] Fix qIsAddressTagged anchor
|
||||
|
||||
When building gdb with an older makeinfo (4.13), I run into:
|
||||
...
|
||||
gdb/doc/gdb.texinfo:44159: @anchor expected braces.
|
||||
gdb/doc/gdb.texinfo:44159: ` {qIsAddressTagged}
|
||||
...
|
||||
|
||||
This is related to this line:
|
||||
...
|
||||
@anchor {qIsAddressTagged}
|
||||
...
|
||||
|
||||
Fix this by removing the space before the left brace.
|
||||
|
||||
Tested by rebuilding the documentation.
|
||||
---
|
||||
gdb/doc/gdb.texinfo | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
|
||||
index 6b08838862c..97508863776 100644
|
||||
--- a/gdb/doc/gdb.texinfo
|
||||
+++ b/gdb/doc/gdb.texinfo
|
||||
@@ -44156,7 +44156,7 @@ tags found in the requested memory range.
|
||||
@cindex check if a given address is in a memory tagged region
|
||||
@cindex @samp{qIsAddressTagged} packet
|
||||
@item qIsAddressTagged:@var{address}
|
||||
-@anchor {qIsAddressTagged}
|
||||
+@anchor{qIsAddressTagged}
|
||||
Check if address @var{address} is in a memory tagged region; if it is, it's
|
||||
said to be @dfn{tagged}. The target is responsible for checking it, as this
|
||||
is architecture-specific.
|
||||
|
||||
base-commit: 3e2d8d7edd244dd5a82588c3e7145c47c7b539ab
|
||||
--
|
||||
2.43.0
|
||||
|
44
gdb-doc-fix-standard-replies-xref.patch
Normal file
44
gdb-doc-fix-standard-replies-xref.patch
Normal file
@@ -0,0 +1,44 @@
|
||||
From 2004e74e0e28ed0b762d98380972b1e6984b9c46 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Tue, 28 Jan 2025 08:01:46 +0100
|
||||
Subject: [PATCH] [gdb/doc] Fix "Standard Replies" xref
|
||||
|
||||
When building gdb with an older makeinfo (4.13), I run into:
|
||||
...
|
||||
gdb/doc/gdb.texinfo:42613: warning: `.' or `,' must follow @xref, not `f'.
|
||||
...
|
||||
|
||||
This is related to this line:
|
||||
...
|
||||
@xref{Standard Replies} for standard error responses, and how to
|
||||
respond indicating a command is not supported.
|
||||
...
|
||||
|
||||
Fix this by adding a comma.
|
||||
|
||||
Tested by rebuilding the docs.
|
||||
|
||||
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
|
||||
Co-Authored-By: Eli Zaretskii <eliz@gnu.org>
|
||||
---
|
||||
gdb/doc/gdb.texinfo | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
|
||||
index e5d562c00b4..0bfe6be6126 100644
|
||||
--- a/gdb/doc/gdb.texinfo
|
||||
+++ b/gdb/doc/gdb.texinfo
|
||||
@@ -42610,7 +42610,7 @@ seven repeats (@samp{$}) can be expanded using a repeat count of only
|
||||
five (@samp{"}). For example, @samp{00000000} can be encoded as
|
||||
@samp{0*"00}.
|
||||
|
||||
-@xref{Standard Replies} for standard error responses, and how to
|
||||
+@xref{Standard Replies}, for standard error responses, and how to
|
||||
respond indicating a command is not supported.
|
||||
|
||||
In describing packets (commands and responses), each description has a
|
||||
|
||||
base-commit: 7992b582e5a55bf2fd64f2f94b854d335c36c6a5
|
||||
--
|
||||
2.43.0
|
||||
|
@@ -1,150 +0,0 @@
|
||||
From b96d3adafdb636898913710ec40ee86647665ae8 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Fri, 3 May 2024 09:37:19 +0200
|
||||
Subject: [PATCH 24/48] [gdb/exp] Fix cast handling for indirection
|
||||
|
||||
Consider a test-case compiled without debug info, containing:
|
||||
...
|
||||
char a = 'a';
|
||||
|
||||
char *
|
||||
a_loc (void)
|
||||
{
|
||||
return &a;
|
||||
}
|
||||
...
|
||||
|
||||
We get:
|
||||
...
|
||||
(gdb) p (char)*a_loc ()
|
||||
Cannot access memory at address 0x10
|
||||
...
|
||||
|
||||
There's a bug in unop_ind_base_operation::evaluate that evaluates
|
||||
"(char)*a_loc ()" the same as:
|
||||
...
|
||||
(gdb) p (char)*(char)a_loc ()
|
||||
Cannot access memory at address 0x10
|
||||
...
|
||||
|
||||
Fix this by instead doing:
|
||||
...
|
||||
(gdb) p (char)*a_loc ()
|
||||
'a_loc' has unknown return type; cast the call to its declared return type
|
||||
...
|
||||
|
||||
Tested on x86_64-linux.
|
||||
|
||||
PR exp/31693
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31693
|
||||
---
|
||||
gdb/expop.h | 5 +--
|
||||
gdb/testsuite/gdb.base/cast-indirection.c | 31 ++++++++++++++++
|
||||
gdb/testsuite/gdb.base/cast-indirection.exp | 41 +++++++++++++++++++++
|
||||
3 files changed, 74 insertions(+), 3 deletions(-)
|
||||
create mode 100644 gdb/testsuite/gdb.base/cast-indirection.c
|
||||
create mode 100644 gdb/testsuite/gdb.base/cast-indirection.exp
|
||||
|
||||
diff --git a/gdb/expop.h b/gdb/expop.h
|
||||
index 25769d5b810..25d50fe00d0 100644
|
||||
--- a/gdb/expop.h
|
||||
+++ b/gdb/expop.h
|
||||
@@ -1513,9 +1513,8 @@ class unop_ind_base_operation
|
||||
struct expression *exp,
|
||||
enum noside noside) override
|
||||
{
|
||||
- if (expect_type != nullptr && expect_type->code () == TYPE_CODE_PTR)
|
||||
- expect_type = check_typedef (expect_type)->target_type ();
|
||||
- value *val = std::get<0> (m_storage)->evaluate (expect_type, exp, noside);
|
||||
+ value *val
|
||||
+ = std::get<0> (m_storage)->evaluate (nullptr, exp, noside);
|
||||
return eval_op_ind (expect_type, exp, noside, val);
|
||||
}
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/cast-indirection.c b/gdb/testsuite/gdb.base/cast-indirection.c
|
||||
new file mode 100644
|
||||
index 00000000000..d59c66ead35
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/cast-indirection.c
|
||||
@@ -0,0 +1,31 @@
|
||||
+/* This testcase is part of GDB, the GNU debugger.
|
||||
+
|
||||
+ Copyright 2024 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/>. */
|
||||
+
|
||||
+char a = 'a';
|
||||
+
|
||||
+char *
|
||||
+a_loc (void)
|
||||
+{
|
||||
+ return &a;
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+main (void)
|
||||
+{
|
||||
+ int res = *a_loc () == 'a';
|
||||
+ return !res;
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.base/cast-indirection.exp b/gdb/testsuite/gdb.base/cast-indirection.exp
|
||||
new file mode 100644
|
||||
index 00000000000..f1fe4302d27
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/cast-indirection.exp
|
||||
@@ -0,0 +1,41 @@
|
||||
+# Copyright (C) 2024 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/>.
|
||||
+
|
||||
+# Check that "p (char)*a_loc ()" is handled as "p (char)*(char *)a_loc ()".
|
||||
+
|
||||
+standard_testfile
|
||||
+
|
||||
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile \
|
||||
+ {nodebug}] == -1} {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+if ![runto_main] {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+gdb_test "p a_loc ()" \
|
||||
+ "'a_loc' has unknown return type; cast the call to its declared return type"
|
||||
+
|
||||
+gdb_test "p *a_loc ()" \
|
||||
+ "'a_loc' has unknown return type; cast the call to its declared return type"
|
||||
+
|
||||
+gdb_test "p *(char *)a_loc ()" " = 97 'a'"
|
||||
+
|
||||
+gdb_test "p (char)*(char *)a_loc ()" " = 97 'a'"
|
||||
+
|
||||
+# Regression test for PR31693.
|
||||
+gdb_test "p (char)*a_loc ()" \
|
||||
+ "'a_loc' has unknown return type; cast the call to its declared return type"
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,365 +0,0 @@
|
||||
From 86e379aa22ba5e77ba0c6fa26588c5fd1d9e6abe Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Mon, 19 Feb 2024 09:59:15 +0100
|
||||
Subject: [PATCH 13/48] [gdb/exp] Fix printing of out of bounds struct members
|
||||
|
||||
When building gdb with -O0 -fsanitize=address, and running test-case
|
||||
gdb.ada/uninitialized_vars.exp, I run into:
|
||||
...
|
||||
(gdb) info locals
|
||||
a = 0
|
||||
z = (a => 1, b => false, c => 2.0)
|
||||
=================================================================
|
||||
==66372==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000097f58 at pc 0xffff52c0da1c bp 0xffffc90a1d40 sp 0xffffc90a1d80
|
||||
READ of size 4 at 0x602000097f58 thread T0
|
||||
#0 0xffff52c0da18 in memmove (/lib64/libasan.so.8+0x6da18)
|
||||
#1 0xbcab24 in unsigned char* std::__copy_move_backward<false, true, std::random_access_iterator_tag>::__copy_move_b<unsigned char const, unsigned char>(unsigned char const*, unsigned char const*, unsigned char*) /usr/include/c++/13/bits/stl_algobase.h:748
|
||||
#2 0xbc9bf4 in unsigned char* std::__copy_move_backward_a2<false, unsigned char const*, unsigned char*>(unsigned char const*, unsigned char const*, unsigned char*) /usr/include/c++/13/bits/stl_algobase.h:769
|
||||
#3 0xbc898c in unsigned char* std::__copy_move_backward_a1<false, unsigned char const*, unsigned char*>(unsigned char const*, unsigned char const*, unsigned char*) /usr/include/c++/13/bits/stl_algobase.h:778
|
||||
#4 0xbc715c in unsigned char* std::__copy_move_backward_a<false, unsigned char const*, unsigned char*>(unsigned char const*, unsigned char const*, unsigned char*) /usr/include/c++/13/bits/stl_algobase.h:807
|
||||
#5 0xbc4e6c in unsigned char* std::copy_backward<unsigned char const*, unsigned char*>(unsigned char const*, unsigned char const*, unsigned char*) /usr/include/c++/13/bits/stl_algobase.h:867
|
||||
#6 0xbc2934 in void gdb::copy<unsigned char const, unsigned char>(gdb::array_view<unsigned char const>, gdb::array_view<unsigned char>) gdb/../gdbsupport/array-view.h:223
|
||||
#7 0x20e0100 in value::contents_copy_raw(value*, long, long, long) gdb/value.c:1239
|
||||
#8 0x20e9830 in value::primitive_field(long, int, type*) gdb/value.c:3078
|
||||
#9 0x20e98f8 in value_field(value*, int) gdb/value.c:3095
|
||||
#10 0xcafd64 in print_field_values gdb/ada-valprint.c:658
|
||||
#11 0xcb0fa0 in ada_val_print_struct_union gdb/ada-valprint.c:857
|
||||
#12 0xcb1bb4 in ada_value_print_inner(value*, ui_file*, int, value_print_options const*) gdb/ada-valprint.c:1042
|
||||
#13 0xc66e04 in ada_language::value_print_inner(value*, ui_file*, int, value_print_options const*) const (/home/vries/gdb/build/gdb/gdb+0xc66e04)
|
||||
#14 0x20ca1e8 in common_val_print(value*, ui_file*, int, value_print_options const*, language_defn const*) gdb/valprint.c:1092
|
||||
#15 0x20caabc in common_val_print_checked(value*, ui_file*, int, value_print_options const*, language_defn const*) gdb/valprint.c:1184
|
||||
#16 0x196c524 in print_variable_and_value(char const*, symbol*, frame_info_ptr, ui_file*, int) gdb/printcmd.c:2355
|
||||
#17 0x1d99ca0 in print_variable_and_value_data::operator()(char const*, symbol*) gdb/stack.c:2308
|
||||
#18 0x1dabca0 in gdb::function_view<void (char const*, symbol*)>::bind<print_variable_and_value_data>(print_variable_and_value_data&)::{lambda(gdb::fv_detail::erased_callable, char const*, symbol*)#1}::operator()(gdb::fv_detail::erased_callable, char const*, symbol*) const gdb/../gdbsupport/function-view.h:305
|
||||
#19 0x1dabd14 in gdb::function_view<void (char const*, symbol*)>::bind<print_variable_and_value_data>(print_variable_and_value_data&)::{lambda(gdb::fv_detail::erased_callable, char const*, symbol*)#1}::_FUN(gdb::fv_detail::erased_callable, char const*, symbol*) gdb/../gdbsupport/function-view.h:299
|
||||
#20 0x1dab34c in gdb::function_view<void (char const*, symbol*)>::operator()(char const*, symbol*) const gdb/../gdbsupport/function-view.h:289
|
||||
#21 0x1d9963c in iterate_over_block_locals gdb/stack.c:2240
|
||||
#22 0x1d99790 in iterate_over_block_local_vars(block const*, gdb::function_view<void (char const*, symbol*)>) gdb/stack.c:2259
|
||||
#23 0x1d9a598 in print_frame_local_vars gdb/stack.c:2380
|
||||
#24 0x1d9afac in info_locals_command(char const*, int) gdb/stack.c:2458
|
||||
#25 0xfd7b30 in do_simple_func gdb/cli/cli-decode.c:95
|
||||
#26 0xfe5a2c in cmd_func(cmd_list_element*, char const*, int) gdb/cli/cli-decode.c:2735
|
||||
#27 0x1f03790 in execute_command(char const*, int) gdb/top.c:575
|
||||
#28 0x1384080 in command_handler(char const*) gdb/event-top.c:566
|
||||
#29 0x1384e2c in command_line_handler(std::unique_ptr<char, gdb::xfree_deleter<char> >&&) gdb/event-top.c:802
|
||||
#30 0x1f731e4 in tui_command_line_handler gdb/tui/tui-interp.c:104
|
||||
#31 0x1382a58 in gdb_rl_callback_handler gdb/event-top.c:259
|
||||
#32 0x21dbb80 in rl_callback_read_char readline/readline/callback.c:290
|
||||
#33 0x1382510 in gdb_rl_callback_read_char_wrapper_noexcept gdb/event-top.c:195
|
||||
#34 0x138277c in gdb_rl_callback_read_char_wrapper gdb/event-top.c:234
|
||||
#35 0x1fe9b40 in stdin_event_handler gdb/ui.c:155
|
||||
#36 0x35ff1bc in handle_file_event gdbsupport/event-loop.cc:573
|
||||
#37 0x35ff9d8 in gdb_wait_for_event gdbsupport/event-loop.cc:694
|
||||
#38 0x35fd284 in gdb_do_one_event(int) gdbsupport/event-loop.cc:264
|
||||
#39 0x1768080 in start_event_loop gdb/main.c:408
|
||||
#40 0x17684c4 in captured_command_loop gdb/main.c:472
|
||||
#41 0x176cfc8 in captured_main gdb/main.c:1342
|
||||
#42 0x176d088 in gdb_main(captured_main_args*) gdb/main.c:1361
|
||||
#43 0xb73edc in main gdb/gdb.c:39
|
||||
#44 0xffff519b09d8 in __libc_start_call_main (/lib64/libc.so.6+0x309d8)
|
||||
#45 0xffff519b0aac in __libc_start_main@@GLIBC_2.34 (/lib64/libc.so.6+0x30aac)
|
||||
#46 0xb73c2c in _start (/home/vries/gdb/build/gdb/gdb+0xb73c2c)
|
||||
|
||||
0x602000097f58 is located 0 bytes after 8-byte region [0x602000097f50,0x602000097f58)
|
||||
allocated by thread T0 here:
|
||||
#0 0xffff52c65218 in calloc (/lib64/libasan.so.8+0xc5218)
|
||||
#1 0xcbc278 in xcalloc gdb/alloc.c:97
|
||||
#2 0x35f21e8 in xzalloc(unsigned long) gdbsupport/common-utils.cc:29
|
||||
#3 0x20de270 in value::allocate_contents(bool) gdb/value.c:937
|
||||
#4 0x20edc08 in value::fetch_lazy() gdb/value.c:4033
|
||||
#5 0x20dadc0 in value::entirely_covered_by_range_vector(std::vector<range, std::allocator<range> > const&) gdb/value.c:229
|
||||
#6 0xcb2298 in value::entirely_optimized_out() gdb/value.h:560
|
||||
#7 0x20ca6fc in value_check_printable gdb/valprint.c:1133
|
||||
#8 0x20caa8c in common_val_print_checked(value*, ui_file*, int, value_print_options const*, language_defn const*) gdb/valprint.c:1182
|
||||
#9 0x196c524 in print_variable_and_value(char const*, symbol*, frame_info_ptr, ui_file*, int) gdb/printcmd.c:2355
|
||||
#10 0x1d99ca0 in print_variable_and_value_data::operator()(char const*, symbol*) gdb/stack.c:2308
|
||||
#11 0x1dabca0 in gdb::function_view<void (char const*, symbol*)>::bind<print_variable_and_value_data>(print_variable_and_value_data&)::{lambda(gdb::fv_detail::erased_callable, char const*, symbol*)#1}::operator()(gdb::fv_detail::erased_callable, char const*, symbol*) const gdb/../gdbsupport/function-view.h:305
|
||||
#12 0x1dabd14 in gdb::function_view<void (char const*, symbol*)>::bind<print_variable_and_value_data>(print_variable_and_value_data&)::{lambda(gdb::fv_detail::erased_callable, char const*, symbol*)#1}::_FUN(gdb::fv_detail::erased_callable, char const*, symbol*) gdb/../gdbsupport/function-view.h:299
|
||||
#13 0x1dab34c in gdb::function_view<void (char const*, symbol*)>::operator()(char const*, symbol*) const gdb/../gdbsupport/function-view.h:289
|
||||
#14 0x1d9963c in iterate_over_block_locals gdb/stack.c:2240
|
||||
#15 0x1d99790 in iterate_over_block_local_vars(block const*, gdb::function_view<void (char const*, symbol*)>) gdb/stack.c:2259
|
||||
#16 0x1d9a598 in print_frame_local_vars gdb/stack.c:2380
|
||||
#17 0x1d9afac in info_locals_command(char const*, int) gdb/stack.c:2458
|
||||
#18 0xfd7b30 in do_simple_func gdb/cli/cli-decode.c:95
|
||||
#19 0xfe5a2c in cmd_func(cmd_list_element*, char const*, int) gdb/cli/cli-decode.c:2735
|
||||
#20 0x1f03790 in execute_command(char const*, int) gdb/top.c:575
|
||||
#21 0x1384080 in command_handler(char const*) gdb/event-top.c:566
|
||||
#22 0x1384e2c in command_line_handler(std::unique_ptr<char, gdb::xfree_deleter<char> >&&) gdb/event-top.c:802
|
||||
#23 0x1f731e4 in tui_command_line_handler gdb/tui/tui-interp.c:104
|
||||
#24 0x1382a58 in gdb_rl_callback_handler gdb/event-top.c:259
|
||||
#25 0x21dbb80 in rl_callback_read_char readline/readline/callback.c:290
|
||||
#26 0x1382510 in gdb_rl_callback_read_char_wrapper_noexcept gdb/event-top.c:195
|
||||
#27 0x138277c in gdb_rl_callback_read_char_wrapper gdb/event-top.c:234
|
||||
#28 0x1fe9b40 in stdin_event_handler gdb/ui.c:155
|
||||
#29 0x35ff1bc in handle_file_event gdbsupport/event-loop.cc:573
|
||||
|
||||
SUMMARY: AddressSanitizer: heap-buffer-overflow (/lib64/libasan.so.8+0x6da18) in memmove
|
||||
...
|
||||
|
||||
The error happens when trying to print either variable y or y2:
|
||||
...
|
||||
type Variable_Record (A : Boolean := True) is record
|
||||
case A is
|
||||
when True =>
|
||||
B : Integer;
|
||||
when False =>
|
||||
C : Float;
|
||||
D : Integer;
|
||||
end case;
|
||||
end record;
|
||||
Y : Variable_Record := (A => True, B => 1);
|
||||
Y2 : Variable_Record := (A => False, C => 1.0, D => 2);
|
||||
...
|
||||
when the variables are uninitialized.
|
||||
|
||||
The error happens only when printing the entire variable:
|
||||
...
|
||||
(gdb) p y.a
|
||||
$2 = 216
|
||||
(gdb) p y.b
|
||||
There is no member named b.
|
||||
(gdb) p y.c
|
||||
$3 = 9.18340949e-41
|
||||
(gdb) p y.d
|
||||
$4 = 1
|
||||
(gdb) p y
|
||||
<AddressSanitizer: heap-buffer-overflow>
|
||||
...
|
||||
|
||||
The error happens as follows:
|
||||
- field a functions as discriminant, choosing either the b, or c+d variant.
|
||||
- when y.a happens to be set to 216, as above, gdb interprets this as the
|
||||
variable having the c+d variant (which is why trying to print y.b fails).
|
||||
- when printing y, gdb allocates a value, copies the bytes into it from the
|
||||
target, and then prints the value.
|
||||
- gdb allocates the value using the type size, which is 8. It's 8 because
|
||||
that's what the DW_AT_byte_size indicates. Note that for valid values of a,
|
||||
it gives correct results: if a is 0 (c+d variant), size is 12, if a is 1
|
||||
(b variant), size is 8.
|
||||
- gdb tries to print field d, which is at an 8 byte offset, and that results
|
||||
in a out-of-bounds access for the allocated 8-byte value.
|
||||
|
||||
Fix this by handling this case in value::contents_copy_raw, such that we have:
|
||||
...
|
||||
(gdb) p y
|
||||
$1 = (a => 24, c => 9.18340949e-41,
|
||||
d => <error reading variable: access outside bounds of object>)
|
||||
...
|
||||
|
||||
An alternative (additional) fix could be this: in compute_variant_fields_inner
|
||||
gdb reads the discriminant y.a to decide which variant is active. It would be
|
||||
nice to detect that the value (y.a == 24) is not a valid Boolean, and give up
|
||||
on choosing a variant altoghether. However, the situation regarding the
|
||||
internal type CODE_TYPE_BOOL is currently ambiguous (see PR31282) and it's not
|
||||
possible to reliably decide what valid values are.
|
||||
|
||||
The test-case source file gdb.ada/uninitialized-variable-record/parse.adb is
|
||||
a reduced version of gdb.ada/uninitialized_vars/parse.adb, so it copies the
|
||||
copyright years.
|
||||
|
||||
Note that the test-case needs gcc-12 or newer, it's unsupported for older gcc
|
||||
versions. [ So, it would be nice to rewrite it into a dwarf assembly
|
||||
test-case. ]
|
||||
|
||||
The test-case loops over all languages. This is inherited from an earlier
|
||||
attempt to fix this, which had language-specific fixes (in print_field_values,
|
||||
cp_print_value_fields, pascal_object_print_value_fields and
|
||||
f_language::value_print_inner). I've left this in, but I suppose it's not
|
||||
strictly necessary anymore.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
|
||||
PR exp/31258
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31258
|
||||
---
|
||||
.../gdb.ada/uninitialized-variable-record.exp | 122 ++++++++++++++++++
|
||||
.../uninitialized-variable-record/parse.adb | 33 +++++
|
||||
gdb/value.c | 3 +
|
||||
3 files changed, 158 insertions(+)
|
||||
create mode 100644 gdb/testsuite/gdb.ada/uninitialized-variable-record.exp
|
||||
create mode 100644 gdb/testsuite/gdb.ada/uninitialized-variable-record/parse.adb
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.ada/uninitialized-variable-record.exp b/gdb/testsuite/gdb.ada/uninitialized-variable-record.exp
|
||||
new file mode 100644
|
||||
index 00000000000..7fc72395edf
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.ada/uninitialized-variable-record.exp
|
||||
@@ -0,0 +1,122 @@
|
||||
+# Copyright 2024 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/>.
|
||||
+
|
||||
+load_lib "ada.exp"
|
||||
+
|
||||
+require allow_ada_tests
|
||||
+
|
||||
+standard_ada_testfile parse
|
||||
+
|
||||
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable {debug}] != "" } {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+clean_restart ${testfile}
|
||||
+
|
||||
+set bp_location [gdb_get_line_number "START" ${testdir}/parse.adb]
|
||||
+runto "parse.adb:$bp_location"
|
||||
+
|
||||
+# Check that we have the expected value for variable y2.
|
||||
+
|
||||
+gdb_test "p y2" [string_to_regexp " = (a => false, c => 1.0, d => 2)"]
|
||||
+
|
||||
+# Shorthand.
|
||||
+
|
||||
+proc set_lang { lang } {
|
||||
+ gdb_test_multiple "set language $lang" "" {
|
||||
+ -re -wrap "" {
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+# Calculate the offset of y2.d.
|
||||
+
|
||||
+set re_cast [string_to_regexp "(access integer)"]
|
||||
+gdb_test_multiple "print &y2.d - &y2" "" {
|
||||
+ -re -wrap " = $re_cast ($hex)" {
|
||||
+ set offset_d $expect_out(1,string)
|
||||
+ pass $gdb_test_name
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+# Try to find a interesting discriminator value, such that at the same time:
|
||||
+# - the d field is part of the variable, and
|
||||
+# - the type size is too small to contain d.
|
||||
+
|
||||
+set interesting_discriminator -1
|
||||
+set_lang c
|
||||
+for { set i 0 } { $i < 256 } { incr i } {
|
||||
+ with_test_prefix $i {
|
||||
+
|
||||
+ # Patch in the discriminator value.
|
||||
+ gdb_test_multiple "set var *(unsigned char *)(&y2.a)=$i" "" {
|
||||
+ -re -wrap "" {
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ # Check that we have the variant with fields c+d instead of b.
|
||||
+ set have_b 0
|
||||
+ gdb_test_multiple "with language ada -- print y2.b" "" {
|
||||
+ -re -wrap " = $decimal" {
|
||||
+ set have_b 1
|
||||
+ }
|
||||
+ -re -wrap "" {
|
||||
+ }
|
||||
+ }
|
||||
+ if { $have_b } {
|
||||
+ # This is the variant with field b.
|
||||
+ continue
|
||||
+ }
|
||||
+
|
||||
+ set size 0
|
||||
+ gdb_test_multiple "print sizeof (y2)" "" {
|
||||
+ -re -wrap " = (.*)" {
|
||||
+ set size $expect_out(1,string)
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if { ! $size } {
|
||||
+ continue
|
||||
+ }
|
||||
+
|
||||
+ if { [expr $size > $offset_d] } {
|
||||
+ # Field d fits in the size.
|
||||
+ continue
|
||||
+ }
|
||||
+
|
||||
+ set interesting_discriminator $i
|
||||
+ break
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+require {expr $interesting_discriminator != -1}
|
||||
+
|
||||
+foreach lang [gdb_supported_languages] {
|
||||
+ with_test_prefix $lang {
|
||||
+ set_lang $lang
|
||||
+
|
||||
+ gdb_test_multiple "print y2" "" {
|
||||
+ -re -wrap ", d => $decimal.*" {
|
||||
+ fail $gdb_test_name
|
||||
+ }
|
||||
+ -re -wrap ", d = $decimal.*" {
|
||||
+ fail $gdb_test_name
|
||||
+ }
|
||||
+ -re -wrap "" {
|
||||
+ pass $gdb_test_name
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.ada/uninitialized-variable-record/parse.adb b/gdb/testsuite/gdb.ada/uninitialized-variable-record/parse.adb
|
||||
new file mode 100644
|
||||
index 00000000000..f00c75ca2dc
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.ada/uninitialized-variable-record/parse.adb
|
||||
@@ -0,0 +1,33 @@
|
||||
+-- Copyright 2009-2024 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/>.
|
||||
+
|
||||
+-- Based on gdb.ada/uninitialized_vars/parse.adb.
|
||||
+
|
||||
+procedure Parse is
|
||||
+
|
||||
+ type Variable_Record (A : Boolean := True) is record
|
||||
+ case A is
|
||||
+ when True =>
|
||||
+ B : Integer;
|
||||
+ when False =>
|
||||
+ C : Float;
|
||||
+ D : Integer;
|
||||
+ end case;
|
||||
+ end record;
|
||||
+ Y2 : Variable_Record := (A => False, C => 1.0, D => 2);
|
||||
+
|
||||
+begin
|
||||
+ null; -- START
|
||||
+end Parse;
|
||||
diff --git a/gdb/value.c b/gdb/value.c
|
||||
index 1cc32625629..56ae9db6603 100644
|
||||
--- a/gdb/value.c
|
||||
+++ b/gdb/value.c
|
||||
@@ -1188,6 +1188,9 @@ value::contents_copy_raw (struct value *dst, LONGEST dst_offset,
|
||||
gdb_assert (!dst->bits_any_optimized_out (TARGET_CHAR_BIT * dst_offset,
|
||||
TARGET_CHAR_BIT * length));
|
||||
|
||||
+ if ((src_offset + copy_length) * unit_size > enclosing_type ()-> length ())
|
||||
+ error (_("access outside bounds of object"));
|
||||
+
|
||||
/* Copy the data. */
|
||||
gdb::array_view<gdb_byte> dst_contents
|
||||
= dst->contents_all_raw ().slice (dst_offset * unit_size,
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,86 +0,0 @@
|
||||
From a6800d9c8145f25001dd39afc3571e3350573e81 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Mon, 6 May 2024 14:23:25 +0200
|
||||
Subject: [PATCH] [gdb/exp] Redo cast handling for indirection
|
||||
|
||||
In commit ed8fd0a342f ("[gdb/exp] Fix cast handling for indirection"), I
|
||||
introduced the behaviour that even though we have:
|
||||
...
|
||||
(gdb) p *a_loc ()
|
||||
'a_loc' has unknown return type; cast the call to its declared return type
|
||||
...
|
||||
we get:
|
||||
...
|
||||
(gdb) p (char)*a_loc ()
|
||||
$1 = 97 'a'
|
||||
...
|
||||
|
||||
In other words, the unknown return type of a_loc is inferred from the cast,
|
||||
effectually evaluating:
|
||||
...
|
||||
(gdb) p (char)*(char *)a_loc ()
|
||||
...
|
||||
|
||||
This is convient for the case that errno is defined as:
|
||||
...
|
||||
#define errno (*__errno_location ())
|
||||
...
|
||||
and the return type of __errno_location is unknown but the macro definition is
|
||||
known, such that we can use:
|
||||
...
|
||||
(gdb) p (int)errno
|
||||
...
|
||||
instead of
|
||||
...
|
||||
(gdb) p *(int *)__errno_location ()
|
||||
...
|
||||
|
||||
However, as Pedro has pointed out in post-commit review [1], this makes it
|
||||
harder to reason about the semantics of an expression.
|
||||
|
||||
For instance, this:
|
||||
...
|
||||
(gdb) p (long long)*a_loc ()"
|
||||
...
|
||||
would be evaluated without debug info as:
|
||||
...
|
||||
(gdb) p (long long)*(long long *)a_loc ()"
|
||||
...
|
||||
but with debug info as:
|
||||
...
|
||||
(gdb) p (long long)*(char *)a_loc ()"
|
||||
...
|
||||
|
||||
Fix this by instead simply erroring out for this case:
|
||||
...
|
||||
(gdb) p (char)*a_loc ()
|
||||
'a_loc' has unknown return type; cast the call to its declared return type
|
||||
...
|
||||
|
||||
Tested on x86_64-linux.
|
||||
|
||||
Approved-By: Pedro Alves <pedro@palves.net>
|
||||
|
||||
[1] https://sourceware.org/pipermail/gdb-patches/2024-May/208821.html
|
||||
---
|
||||
gdb/testsuite/gdb.base/cast-indirection.exp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/cast-indirection.exp b/gdb/testsuite/gdb.base/cast-indirection.exp
|
||||
index f1fe4302d27..7b9b5a5d677 100644
|
||||
--- a/gdb/testsuite/gdb.base/cast-indirection.exp
|
||||
+++ b/gdb/testsuite/gdb.base/cast-indirection.exp
|
||||
@@ -13,7 +13,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
-# Check that "p (char)*a_loc ()" is handled as "p (char)*(char *)a_loc ()".
|
||||
+# Check that "p (char)*a_loc ()" is handled correctly.
|
||||
|
||||
standard_testfile
|
||||
|
||||
|
||||
base-commit: fc73000faa1798573090994167b7e2d451c211db
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,144 +0,0 @@
|
||||
From 350172ea215c7074601e8424ff636563612f91e8 Mon Sep 17 00:00:00 2001
|
||||
From: Pedro Alves <pedro@palves.net>
|
||||
Date: Wed, 21 Feb 2024 16:23:55 +0000
|
||||
Subject: [PATCH 14/48] [gdb] Fix heap-use-after-free in select_event_lwp
|
||||
|
||||
PR gdb/31259 reveals one scenario where we run into a
|
||||
heap-use-after-free reported by thread sanitizer, while running
|
||||
gdb.base/vfork-follow-parent.exp.
|
||||
|
||||
The heap-use-after-free happens during the following scenario:
|
||||
|
||||
- linux_nat_wait_1 is about to return an event for T2. It stops all
|
||||
other threads, and while doing so, stop_wait_callback -> wait_lwp
|
||||
sees T1 exit, and decides to leave the exit event pending. It
|
||||
should have set the lp->stopped flag too, but does not -- this is
|
||||
the bug.
|
||||
|
||||
- The event for T2 is reported, is processed by infrun, and we're
|
||||
back at linux_nat_wait_1.
|
||||
|
||||
- linux_nat_wait_1 selects LWP T1 with the pending exit status to
|
||||
report.
|
||||
|
||||
- it sets variable lp to point to the corresponding lwp_info.
|
||||
|
||||
- it calls stop_callback and stop_wait_callback for all threads
|
||||
(because !target_is_non_stop_p ()).
|
||||
|
||||
- it calls select_event_lwp to maybe pick another thread than T1, to
|
||||
prevent starvation.
|
||||
|
||||
The problem is the following:
|
||||
|
||||
- while calling stop_wait_callback for all threads, it also does this
|
||||
for T1. While doing so, the corresponding lwp_info is deleted
|
||||
(callstack stop_wait_callback -> wait_lwp -> exit_lwp ->
|
||||
delete_lwp), leaving variable lp as a dangling pointer.
|
||||
|
||||
- variable lp is passed to select_event_lwp, which derefences it,
|
||||
which causes the heap-use-after-free.
|
||||
|
||||
Note that the comment here mentions "all other LWP's":
|
||||
...
|
||||
/* Now stop all other LWP's ... */
|
||||
iterate_over_lwps (minus_one_ptid, stop_callback);
|
||||
/* ... and wait until all of them have reported back that
|
||||
they're no longer running. */
|
||||
iterate_over_lwps (minus_one_ptid, stop_wait_callback);
|
||||
...
|
||||
|
||||
The reason the comments say "all other LWP's", and doesn't bother
|
||||
filtering out LP is that lp->stopped should be true at this point, and
|
||||
the callbacks (both stop_callback and stop_wait_callback) check that
|
||||
flag, and do nothing if set. I.e., they skip already-stopped threads,
|
||||
so they should skip LP.
|
||||
|
||||
In this particular scenario, though, we missed setting the stopped
|
||||
flag right in the first step described above, so LP was iterated over
|
||||
incorrectly.
|
||||
|
||||
The fix is to make wait_lwp set the lp->stopped flag when it decides
|
||||
to leave the exit event pending. However, going a bit further,
|
||||
gdbserver has a mark_lwp_dead function to centralize setting up
|
||||
various lwp flags such that the rest of the code doesn't mishandle
|
||||
them, and it seems like a good idea to do a similar thing in gdb as
|
||||
well. That is what this patch does.
|
||||
|
||||
PR gdb/31259
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31259
|
||||
Co-Authored-By: Tom de Vries <tdevries@suse.de>
|
||||
Change-Id: I4a6169976f89bf714c478cbb2b7d4c32365e62a9
|
||||
---
|
||||
gdb/linux-nat.c | 34 +++++++++++++++++++++++++---------
|
||||
1 file changed, 25 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
|
||||
index 7e36ced6292..ed445c5e5bb 100644
|
||||
--- a/gdb/linux-nat.c
|
||||
+++ b/gdb/linux-nat.c
|
||||
@@ -2029,6 +2029,27 @@ wait_for_signal ()
|
||||
}
|
||||
}
|
||||
|
||||
+/* Mark LWP dead, with STATUS as exit status pending to report
|
||||
+ later. */
|
||||
+
|
||||
+static void
|
||||
+mark_lwp_dead (lwp_info *lp, int status)
|
||||
+{
|
||||
+ /* Store the exit status lp->waitstatus, because lp->status would be
|
||||
+ ambiguous (W_EXITCODE(0,0) == 0). */
|
||||
+ lp->waitstatus = host_status_to_waitstatus (status);
|
||||
+
|
||||
+ /* If we're processing LP's status, there should be no other event
|
||||
+ already recorded as pending. */
|
||||
+ gdb_assert (lp->status == 0);
|
||||
+
|
||||
+ /* Dead LWPs aren't expected to report a pending sigstop. */
|
||||
+ lp->signalled = 0;
|
||||
+
|
||||
+ /* Prevent trying to stop it. */
|
||||
+ lp->stopped = 1;
|
||||
+}
|
||||
+
|
||||
/* Wait for LP to stop. Returns the wait status, or 0 if the LWP has
|
||||
exited. */
|
||||
|
||||
@@ -2114,9 +2135,8 @@ wait_lwp (struct lwp_info *lp)
|
||||
|
||||
/* If this is the leader exiting, it means the whole
|
||||
process is gone. Store the status to report to the
|
||||
- core. Store it in lp->waitstatus, because lp->status
|
||||
- would be ambiguous (W_EXITCODE(0,0) == 0). */
|
||||
- lp->waitstatus = host_status_to_waitstatus (status);
|
||||
+ core. */
|
||||
+ mark_lwp_dead (lp, status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2908,12 +2928,7 @@ linux_nat_filter_event (int lwpid, int status)
|
||||
linux_nat_debug_printf ("LWP %ld exited (resumed=%d)",
|
||||
lp->ptid.lwp (), lp->resumed);
|
||||
|
||||
- /* Dead LWP's aren't expected to reported a pending sigstop. */
|
||||
- lp->signalled = 0;
|
||||
-
|
||||
- /* Store the pending event in the waitstatus, because
|
||||
- W_EXITCODE(0,0) == 0. */
|
||||
- lp->waitstatus = host_status_to_waitstatus (status);
|
||||
+ mark_lwp_dead (lp, status);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3248,6 +3263,7 @@ linux_nat_wait_1 (ptid_t ptid, struct target_waitstatus *ourstatus,
|
||||
}
|
||||
|
||||
gdb_assert (lp);
|
||||
+ gdb_assert (lp->stopped);
|
||||
|
||||
status = lp->status;
|
||||
lp->status = 0;
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,636 +0,0 @@
|
||||
From 1d02ba0f4adcba2595a67e88fb1ba6d35c7f8e5b Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Tue, 7 May 2024 11:33:57 +0200
|
||||
Subject: [PATCH] [gdb] Fix segfault in for_each_block, part 1
|
||||
|
||||
When running test-case gdb.base/vfork-follow-parent.exp on powerpc64 (likewise
|
||||
on s390x), I run into:
|
||||
...
|
||||
(gdb) PASS: gdb.base/vfork-follow-parent.exp: \
|
||||
exec_file=vfork-follow-parent-exit: target-non-stop=on: non-stop=off: \
|
||||
resolution_method=schedule-multiple: print unblock_parent = 1
|
||||
continue^M
|
||||
Continuing.^M
|
||||
Reading symbols from vfork-follow-parent-exit...^M
|
||||
^M
|
||||
^M
|
||||
Fatal signal: Segmentation fault^M
|
||||
----- Backtrace -----^M
|
||||
0x1027d3e7 gdb_internal_backtrace_1^M
|
||||
src/gdb/bt-utils.c:122^M
|
||||
0x1027d54f _Z22gdb_internal_backtracev^M
|
||||
src/gdb/bt-utils.c:168^M
|
||||
0x1057643f handle_fatal_signal^M
|
||||
src/gdb/event-top.c:889^M
|
||||
0x10576677 handle_sigsegv^M
|
||||
src/gdb/event-top.c:962^M
|
||||
0x3fffa7610477 ???^M
|
||||
0x103f2144 for_each_block^M
|
||||
src/gdb/dcache.c:199^M
|
||||
0x103f235b _Z17dcache_invalidateP13dcache_struct^M
|
||||
src/gdb/dcache.c:251^M
|
||||
0x10bde8c7 _Z24target_dcache_invalidatev^M
|
||||
src/gdb/target-dcache.c:50^M
|
||||
...
|
||||
or similar.
|
||||
|
||||
The root cause for the segmentation fault is that linux_is_uclinux gives an
|
||||
incorrect result: it should always return false, given that we're running on a
|
||||
regular linux system, but instead it returns first true, then false.
|
||||
|
||||
In more detail, the segmentation fault happens as follows:
|
||||
- a program space with an address space is created
|
||||
- a second program space is about to be created. maybe_new_address_space
|
||||
is called, and because linux_is_uclinux returns true, maybe_new_address_space
|
||||
returns false, and no new address space is created
|
||||
- a second program space with the same address space is created
|
||||
- a program space is deleted. Because linux_is_uclinux now returns false,
|
||||
gdbarch_has_shared_address_space (current_inferior ()->arch ()) returns
|
||||
false, and the address space is deleted
|
||||
- when gdb uses the address space of the remaining program space, we run into
|
||||
the segfault, because the address space is deleted.
|
||||
|
||||
Hardcoding linux_is_uclinux to false makes the test-case pass.
|
||||
|
||||
We leave addressing the root cause for the following commit in this series.
|
||||
|
||||
For now, prevent the segmentation fault by making the address space a refcounted
|
||||
object.
|
||||
|
||||
This was already suggested here [1]:
|
||||
...
|
||||
A better solution might be to have the address spaces be reference counted
|
||||
...
|
||||
|
||||
Tested on top of trunk on x86_64-linux and ppc64le-linux.
|
||||
Tested on top of gdb-14-branch on ppc64-linux.
|
||||
|
||||
Co-Authored-By: Simon Marchi <simon.marchi@polymtl.ca>
|
||||
|
||||
PR gdb/30547
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30547
|
||||
|
||||
[1] https://sourceware.org/pipermail/gdb-patches/2023-October/202928.html
|
||||
---
|
||||
gdb/breakpoint.c | 29 ++++++++-------
|
||||
gdb/inferior.c | 8 ++---
|
||||
gdb/inferior.h | 2 +-
|
||||
gdb/infrun.c | 18 +++++-----
|
||||
gdb/linux-nat.c | 2 +-
|
||||
gdb/process-stratum-target.c | 2 +-
|
||||
gdb/progspace.c | 22 +++++-------
|
||||
gdb/progspace.h | 64 +++++++++++++++++++++-------------
|
||||
gdb/record-btrace.c | 2 +-
|
||||
gdb/regcache.c | 2 +-
|
||||
gdb/scoped-mock-context.h | 2 +-
|
||||
gdb/target-dcache.c | 11 +++---
|
||||
gdbsupport/refcounted-object.h | 17 +++++++++
|
||||
13 files changed, 102 insertions(+), 79 deletions(-)
|
||||
|
||||
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
|
||||
index 01f187ca4fe..a22bdb091cd 100644
|
||||
--- a/gdb/breakpoint.c
|
||||
+++ b/gdb/breakpoint.c
|
||||
@@ -1723,7 +1723,7 @@ one_breakpoint_xfer_memory (gdb_byte *readbuf, gdb_byte *writebuf,
|
||||
int bptoffset = 0;
|
||||
|
||||
if (!breakpoint_address_match (target_info->placed_address_space, 0,
|
||||
- current_program_space->aspace, 0))
|
||||
+ current_program_space->aspace.get (), 0))
|
||||
{
|
||||
/* The breakpoint is inserted in a different address space. */
|
||||
return;
|
||||
@@ -2409,7 +2409,7 @@ should_be_inserted (struct bp_location *bl)
|
||||
a breakpoint. */
|
||||
if ((bl->loc_type == bp_loc_software_breakpoint
|
||||
|| bl->loc_type == bp_loc_hardware_breakpoint)
|
||||
- && stepping_past_instruction_at (bl->pspace->aspace,
|
||||
+ && stepping_past_instruction_at (bl->pspace->aspace.get (),
|
||||
bl->address)
|
||||
/* The single-step breakpoint may be inserted at the location
|
||||
we're trying to step if the instruction branches to itself.
|
||||
@@ -2847,7 +2847,7 @@ insert_bp_location (struct bp_location *bl,
|
||||
read the breakpoint instead of returning the data saved in
|
||||
the breakpoint location's shadow contents. */
|
||||
bl->target_info.reqstd_address = bl->address;
|
||||
- bl->target_info.placed_address_space = bl->pspace->aspace;
|
||||
+ bl->target_info.placed_address_space = bl->pspace->aspace.get ();
|
||||
bl->target_info.length = bl->length;
|
||||
|
||||
/* When working with target-side conditions, we must pass all the conditions
|
||||
@@ -4429,7 +4429,7 @@ bp_location_inserted_here_p (const struct bp_location *bl,
|
||||
const address_space *aspace, CORE_ADDR pc)
|
||||
{
|
||||
if (bl->inserted
|
||||
- && breakpoint_address_match (bl->pspace->aspace, bl->address,
|
||||
+ && breakpoint_address_match (bl->pspace->aspace.get (), bl->address,
|
||||
aspace, pc))
|
||||
{
|
||||
/* An unmapped overlay can't be a match. */
|
||||
@@ -4508,7 +4508,7 @@ hardware_watchpoint_inserted_in_range (const address_space *aspace,
|
||||
continue;
|
||||
|
||||
for (bp_location &loc : bpt.locations ())
|
||||
- if (loc.pspace->aspace == aspace && loc.inserted)
|
||||
+ if (loc.pspace->aspace.get () == aspace && loc.inserted)
|
||||
{
|
||||
CORE_ADDR l, h;
|
||||
|
||||
@@ -7330,10 +7330,10 @@ breakpoint_location_address_match (struct bp_location *bl,
|
||||
const address_space *aspace,
|
||||
CORE_ADDR addr)
|
||||
{
|
||||
- return (breakpoint_address_match (bl->pspace->aspace, bl->address,
|
||||
+ return (breakpoint_address_match (bl->pspace->aspace.get (), bl->address,
|
||||
aspace, addr)
|
||||
|| (bl->length
|
||||
- && breakpoint_address_match_range (bl->pspace->aspace,
|
||||
+ && breakpoint_address_match_range (bl->pspace->aspace.get (),
|
||||
bl->address, bl->length,
|
||||
aspace, addr)));
|
||||
}
|
||||
@@ -7350,7 +7350,7 @@ breakpoint_location_address_range_overlap (struct bp_location *bl,
|
||||
CORE_ADDR addr, int len)
|
||||
{
|
||||
if (gdbarch_has_global_breakpoints (target_gdbarch ())
|
||||
- || bl->pspace->aspace == aspace)
|
||||
+ || bl->pspace->aspace.get () == aspace)
|
||||
{
|
||||
int bl_len = bl->length != 0 ? bl->length : 1;
|
||||
|
||||
@@ -7407,8 +7407,10 @@ breakpoint_locations_match (const struct bp_location *loc1,
|
||||
/* We compare bp_location.length in order to cover ranged
|
||||
breakpoints. Keep this in sync with
|
||||
bp_location_is_less_than. */
|
||||
- return (breakpoint_address_match (loc1->pspace->aspace, loc1->address,
|
||||
- loc2->pspace->aspace, loc2->address)
|
||||
+ return (breakpoint_address_match (loc1->pspace->aspace.get (),
|
||||
+ loc1->address,
|
||||
+ loc2->pspace->aspace.get (),
|
||||
+ loc2->address)
|
||||
&& (loc1->loc_type == loc2->loc_type || sw_hw_bps_match)
|
||||
&& loc1->length == loc2->length);
|
||||
}
|
||||
@@ -9568,8 +9570,9 @@ ranged_breakpoint::breakpoint_hit (const struct bp_location *bl,
|
||||
|| ws.sig () != GDB_SIGNAL_TRAP)
|
||||
return 0;
|
||||
|
||||
- return breakpoint_address_match_range (bl->pspace->aspace, bl->address,
|
||||
- bl->length, aspace, bp_addr);
|
||||
+ return breakpoint_address_match_range (bl->pspace->aspace.get (),
|
||||
+ bl->address, bl->length, aspace,
|
||||
+ bp_addr);
|
||||
}
|
||||
|
||||
/* Implement the "resources_needed" method for ranged breakpoints. */
|
||||
@@ -12018,7 +12021,7 @@ code_breakpoint::breakpoint_hit (const struct bp_location *bl,
|
||||
|| ws.sig () != GDB_SIGNAL_TRAP)
|
||||
return 0;
|
||||
|
||||
- if (!breakpoint_address_match (bl->pspace->aspace, bl->address,
|
||||
+ if (!breakpoint_address_match (bl->pspace->aspace.get (), bl->address,
|
||||
aspace, bp_addr))
|
||||
return 0;
|
||||
|
||||
diff --git a/gdb/inferior.c b/gdb/inferior.c
|
||||
index 550bbd2827c..461f4fc076a 100644
|
||||
--- a/gdb/inferior.c
|
||||
+++ b/gdb/inferior.c
|
||||
@@ -831,15 +831,13 @@ remove_inferior_command (const char *args, int from_tty)
|
||||
struct inferior *
|
||||
add_inferior_with_spaces (void)
|
||||
{
|
||||
- struct address_space *aspace;
|
||||
struct program_space *pspace;
|
||||
struct inferior *inf;
|
||||
|
||||
/* If all inferiors share an address space on this system, this
|
||||
doesn't really return a new address space; otherwise, it
|
||||
really does. */
|
||||
- aspace = maybe_new_address_space ();
|
||||
- pspace = new program_space (aspace);
|
||||
+ pspace = new program_space (maybe_new_address_space ());
|
||||
inf = add_inferior (0);
|
||||
inf->pspace = pspace;
|
||||
inf->aspace = pspace->aspace;
|
||||
@@ -1002,15 +1000,13 @@ clone_inferior_command (const char *args, int from_tty)
|
||||
|
||||
for (i = 0; i < copies; ++i)
|
||||
{
|
||||
- struct address_space *aspace;
|
||||
struct program_space *pspace;
|
||||
struct inferior *inf;
|
||||
|
||||
/* If all inferiors share an address space on this system, this
|
||||
doesn't really return a new address space; otherwise, it
|
||||
really does. */
|
||||
- aspace = maybe_new_address_space ();
|
||||
- pspace = new program_space (aspace);
|
||||
+ pspace = new program_space (maybe_new_address_space ());
|
||||
inf = add_inferior (0);
|
||||
inf->pspace = pspace;
|
||||
inf->aspace = pspace->aspace;
|
||||
diff --git a/gdb/inferior.h b/gdb/inferior.h
|
||||
index 29c90d15efa..4139791740f 100644
|
||||
--- a/gdb/inferior.h
|
||||
+++ b/gdb/inferior.h
|
||||
@@ -577,7 +577,7 @@ class inferior : public refcounted_object,
|
||||
bool removable = false;
|
||||
|
||||
/* The address space bound to this inferior. */
|
||||
- struct address_space *aspace = NULL;
|
||||
+ address_space_ref_ptr aspace;
|
||||
|
||||
/* The program space bound to this inferior. */
|
||||
struct program_space *pspace = NULL;
|
||||
diff --git a/gdb/infrun.c b/gdb/infrun.c
|
||||
index 7be98cfc252..3854c66bf6c 100644
|
||||
--- a/gdb/infrun.c
|
||||
+++ b/gdb/infrun.c
|
||||
@@ -531,8 +531,8 @@ holding the child stopped. Try \"set detach-on-fork\" or \
|
||||
}
|
||||
else
|
||||
{
|
||||
- child_inf->aspace = new address_space ();
|
||||
- child_inf->pspace = new program_space (child_inf->aspace);
|
||||
+ child_inf->pspace = new program_space (new_address_space ());
|
||||
+ child_inf->aspace = child_inf->pspace->aspace;
|
||||
child_inf->removable = true;
|
||||
clone_program_space (child_inf->pspace, parent_inf->pspace);
|
||||
}
|
||||
@@ -610,8 +610,8 @@ holding the child stopped. Try \"set detach-on-fork\" or \
|
||||
|
||||
child_inf->aspace = parent_inf->aspace;
|
||||
child_inf->pspace = parent_inf->pspace;
|
||||
- parent_inf->aspace = new address_space ();
|
||||
- parent_inf->pspace = new program_space (parent_inf->aspace);
|
||||
+ parent_inf->pspace = new program_space (new_address_space ());
|
||||
+ parent_inf->aspace = parent_inf->pspace->aspace;
|
||||
clone_program_space (parent_inf->pspace, child_inf->pspace);
|
||||
|
||||
/* The parent inferior is still the current one, so keep things
|
||||
@@ -620,8 +620,8 @@ holding the child stopped. Try \"set detach-on-fork\" or \
|
||||
}
|
||||
else
|
||||
{
|
||||
- child_inf->aspace = new address_space ();
|
||||
- child_inf->pspace = new program_space (child_inf->aspace);
|
||||
+ child_inf->pspace = new program_space (new_address_space ());
|
||||
+ child_inf->aspace = child_inf->pspace->aspace;
|
||||
child_inf->removable = true;
|
||||
child_inf->symfile_flags = SYMFILE_NO_READ;
|
||||
clone_program_space (child_inf->pspace, parent_inf->pspace);
|
||||
@@ -1031,7 +1031,6 @@ handle_vfork_child_exec_or_exit (int exec)
|
||||
if (vfork_parent->pending_detach)
|
||||
{
|
||||
struct program_space *pspace;
|
||||
- struct address_space *aspace;
|
||||
|
||||
/* follow-fork child, detach-on-fork on. */
|
||||
|
||||
@@ -1056,9 +1055,8 @@ handle_vfork_child_exec_or_exit (int exec)
|
||||
of" a hack. */
|
||||
|
||||
pspace = inf->pspace;
|
||||
- aspace = inf->aspace;
|
||||
- inf->aspace = nullptr;
|
||||
inf->pspace = nullptr;
|
||||
+ address_space_ref_ptr aspace = std::move (inf->aspace);
|
||||
|
||||
if (print_inferior_events)
|
||||
{
|
||||
@@ -5906,7 +5904,7 @@ handle_inferior_event (struct execution_control_state *ecs)
|
||||
= get_thread_arch_aspace_regcache (parent_inf,
|
||||
ecs->ws.child_ptid (),
|
||||
gdbarch,
|
||||
- parent_inf->aspace);
|
||||
+ parent_inf->aspace.get ());
|
||||
/* Read PC value of parent process. */
|
||||
parent_pc = regcache_read_pc (regcache);
|
||||
|
||||
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
|
||||
index ed445c5e5bb..c8991cc3da4 100644
|
||||
--- a/gdb/linux-nat.c
|
||||
+++ b/gdb/linux-nat.c
|
||||
@@ -4365,7 +4365,7 @@ linux_nat_target::thread_address_space (ptid_t ptid)
|
||||
|
||||
inf = find_inferior_pid (this, pid);
|
||||
gdb_assert (inf != NULL);
|
||||
- return inf->aspace;
|
||||
+ return inf->aspace.get ();
|
||||
}
|
||||
|
||||
/* Return the cached value of the processor core for thread PTID. */
|
||||
diff --git a/gdb/process-stratum-target.c b/gdb/process-stratum-target.c
|
||||
index 5c031203e89..4bcca4f39c2 100644
|
||||
--- a/gdb/process-stratum-target.c
|
||||
+++ b/gdb/process-stratum-target.c
|
||||
@@ -37,7 +37,7 @@ process_stratum_target::thread_address_space (ptid_t ptid)
|
||||
"address space of thread %s\n"),
|
||||
target_pid_to_str (ptid).c_str ());
|
||||
|
||||
- return inf->aspace;
|
||||
+ return inf->aspace.get ();
|
||||
}
|
||||
|
||||
struct gdbarch *
|
||||
diff --git a/gdb/progspace.c b/gdb/progspace.c
|
||||
index 1dbcd5875dd..b4d25ba6196 100644
|
||||
--- a/gdb/progspace.c
|
||||
+++ b/gdb/progspace.c
|
||||
@@ -55,8 +55,8 @@ address_space::address_space ()
|
||||
return a pointer to an existing address space, in case inferiors
|
||||
share an address space on this target system. */
|
||||
|
||||
-struct address_space *
|
||||
-maybe_new_address_space (void)
|
||||
+address_space_ref_ptr
|
||||
+maybe_new_address_space ()
|
||||
{
|
||||
int shared_aspace = gdbarch_has_shared_address_space (target_gdbarch ());
|
||||
|
||||
@@ -66,7 +66,7 @@ maybe_new_address_space (void)
|
||||
return program_spaces[0]->aspace;
|
||||
}
|
||||
|
||||
- return new address_space ();
|
||||
+ return new_address_space ();
|
||||
}
|
||||
|
||||
/* Start counting over from scratch. */
|
||||
@@ -94,9 +94,9 @@ remove_program_space (program_space *pspace)
|
||||
|
||||
/* See progspace.h. */
|
||||
|
||||
-program_space::program_space (address_space *aspace_)
|
||||
+program_space::program_space (address_space_ref_ptr aspace_)
|
||||
: num (++last_program_space_num),
|
||||
- aspace (aspace_)
|
||||
+ aspace (std::move (aspace_))
|
||||
{
|
||||
program_spaces.push_back (this);
|
||||
gdb::observers::new_program_space.notify (this);
|
||||
@@ -121,8 +121,6 @@ program_space::~program_space ()
|
||||
/* Defer breakpoint re-set because we don't want to create new
|
||||
locations for this pspace which we're tearing down. */
|
||||
clear_symtab_users (SYMFILE_DEFER_BP_RESET);
|
||||
- if (!gdbarch_has_shared_address_space (target_gdbarch ()))
|
||||
- delete this->aspace;
|
||||
}
|
||||
|
||||
/* See progspace.h. */
|
||||
@@ -408,18 +406,14 @@ update_address_spaces (void)
|
||||
|
||||
if (shared_aspace)
|
||||
{
|
||||
- struct address_space *aspace = new address_space ();
|
||||
+ address_space_ref_ptr aspace = new_address_space ();
|
||||
|
||||
- delete current_program_space->aspace;
|
||||
for (struct program_space *pspace : program_spaces)
|
||||
pspace->aspace = aspace;
|
||||
}
|
||||
else
|
||||
for (struct program_space *pspace : program_spaces)
|
||||
- {
|
||||
- delete pspace->aspace;
|
||||
- pspace->aspace = new address_space ();
|
||||
- }
|
||||
+ pspace->aspace = new_address_space ();
|
||||
|
||||
for (inferior *inf : all_inferiors ())
|
||||
if (gdbarch_has_global_solist (target_gdbarch ()))
|
||||
@@ -456,5 +450,5 @@ initialize_progspace (void)
|
||||
modules have done that. Do this before
|
||||
initialize_current_architecture, because that accesses the ebfd
|
||||
of current_program_space. */
|
||||
- current_program_space = new program_space (new address_space ());
|
||||
+ current_program_space = new program_space (new_address_space ());
|
||||
}
|
||||
diff --git a/gdb/progspace.h b/gdb/progspace.h
|
||||
index ee12d89c173..12f113f6d9c 100644
|
||||
--- a/gdb/progspace.h
|
||||
+++ b/gdb/progspace.h
|
||||
@@ -28,6 +28,8 @@
|
||||
#include "solist.h"
|
||||
#include "gdbsupport/next-iterator.h"
|
||||
#include "gdbsupport/safe-iterator.h"
|
||||
+#include "gdbsupport/refcounted-object.h"
|
||||
+#include "gdbsupport/gdb_ref_ptr.h"
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
@@ -42,6 +44,40 @@ struct so_list;
|
||||
|
||||
typedef std::list<std::unique_ptr<objfile>> objfile_list;
|
||||
|
||||
+/* An address space. It is used for comparing if
|
||||
+ pspaces/inferior/threads see the same address space and for
|
||||
+ associating caches to each address space. */
|
||||
+struct address_space : public refcounted_object
|
||||
+{
|
||||
+ /* Create a new address space object, and add it to the list. */
|
||||
+ address_space ();
|
||||
+ DISABLE_COPY_AND_ASSIGN (address_space);
|
||||
+
|
||||
+ /* Returns the integer address space id of this address space. */
|
||||
+ int num () const
|
||||
+ {
|
||||
+ return m_num;
|
||||
+ }
|
||||
+
|
||||
+ /* Per aspace data-pointers required by other GDB modules. */
|
||||
+ registry<address_space> registry_fields;
|
||||
+
|
||||
+private:
|
||||
+ int m_num;
|
||||
+};
|
||||
+
|
||||
+using address_space_ref_ptr
|
||||
+ = gdb::ref_ptr<address_space,
|
||||
+ refcounted_object_delete_ref_policy<address_space>>;
|
||||
+
|
||||
+/* Create a new address space. */
|
||||
+
|
||||
+static inline address_space_ref_ptr
|
||||
+new_address_space ()
|
||||
+{
|
||||
+ return address_space_ref_ptr::new_reference (new address_space);
|
||||
+}
|
||||
+
|
||||
/* An iterator that wraps an iterator over std::unique_ptr<objfile>,
|
||||
and dereferences the returned object. This is useful for iterating
|
||||
over a list of shared pointers and returning raw pointers -- which
|
||||
@@ -191,7 +227,7 @@ struct program_space
|
||||
{
|
||||
/* Constructs a new empty program space, binds it to ASPACE, and
|
||||
adds it to the program space list. */
|
||||
- explicit program_space (address_space *aspace);
|
||||
+ explicit program_space (address_space_ref_ptr aspace);
|
||||
|
||||
/* Releases a program space, and all its contents (shared libraries,
|
||||
objfiles, and any other references to the program space in other
|
||||
@@ -336,7 +372,7 @@ struct program_space
|
||||
are global, then this field is ignored (we don't currently
|
||||
support inferiors sharing a program space if the target doesn't
|
||||
make breakpoints global). */
|
||||
- struct address_space *aspace = NULL;
|
||||
+ address_space_ref_ptr aspace;
|
||||
|
||||
/* True if this program space's section offsets don't yet represent
|
||||
the final offsets of the "live" address space (that is, the
|
||||
@@ -383,28 +419,6 @@ struct program_space
|
||||
target_section_table m_target_sections;
|
||||
};
|
||||
|
||||
-/* An address space. It is used for comparing if
|
||||
- pspaces/inferior/threads see the same address space and for
|
||||
- associating caches to each address space. */
|
||||
-struct address_space
|
||||
-{
|
||||
- /* Create a new address space object, and add it to the list. */
|
||||
- address_space ();
|
||||
- DISABLE_COPY_AND_ASSIGN (address_space);
|
||||
-
|
||||
- /* Returns the integer address space id of this address space. */
|
||||
- int num () const
|
||||
- {
|
||||
- return m_num;
|
||||
- }
|
||||
-
|
||||
- /* Per aspace data-pointers required by other GDB modules. */
|
||||
- registry<address_space> registry_fields;
|
||||
-
|
||||
-private:
|
||||
- int m_num;
|
||||
-};
|
||||
-
|
||||
/* The list of all program spaces. There's always at least one. */
|
||||
extern std::vector<struct program_space *>program_spaces;
|
||||
|
||||
@@ -447,7 +461,7 @@ class scoped_restore_current_program_space
|
||||
/* Maybe create a new address space object, and add it to the list, or
|
||||
return a pointer to an existing address space, in case inferiors
|
||||
share an address space. */
|
||||
-extern struct address_space *maybe_new_address_space (void);
|
||||
+extern address_space_ref_ptr maybe_new_address_space ();
|
||||
|
||||
/* Update all program spaces matching to address spaces. The user may
|
||||
have created several program spaces, and loaded executables into
|
||||
diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
|
||||
index 97447d3e8f8..a4d6c1b5bf2 100644
|
||||
--- a/gdb/record-btrace.c
|
||||
+++ b/gdb/record-btrace.c
|
||||
@@ -2321,7 +2321,7 @@ record_btrace_replay_at_breakpoint (struct thread_info *tp)
|
||||
if (insn == NULL)
|
||||
return 0;
|
||||
|
||||
- return record_check_stopped_by_breakpoint (tp->inf->aspace, insn->pc,
|
||||
+ return record_check_stopped_by_breakpoint (tp->inf->aspace.get (), insn->pc,
|
||||
&btinfo->stop_reason);
|
||||
}
|
||||
|
||||
diff --git a/gdb/regcache.c b/gdb/regcache.c
|
||||
index 91b20b7a2a2..a78fe0a80e7 100644
|
||||
--- a/gdb/regcache.c
|
||||
+++ b/gdb/regcache.c
|
||||
@@ -1628,7 +1628,7 @@ get_thread_arch_aspace_regcache_and_check (inferior *inf_for_target_calls,
|
||||
the current inferior's gdbarch. Also use the current inferior's address
|
||||
space. */
|
||||
gdbarch *arch = inf_for_target_calls->gdbarch;
|
||||
- address_space *aspace = inf_for_target_calls->aspace;
|
||||
+ address_space *aspace = inf_for_target_calls->aspace.get ();
|
||||
regcache *regcache = get_thread_arch_aspace_regcache (inf_for_target_calls,
|
||||
ptid, arch, aspace);
|
||||
|
||||
diff --git a/gdb/scoped-mock-context.h b/gdb/scoped-mock-context.h
|
||||
index 9ad7ebf5f0c..5f25dc7ed6b 100644
|
||||
--- a/gdb/scoped-mock-context.h
|
||||
+++ b/gdb/scoped-mock-context.h
|
||||
@@ -38,7 +38,7 @@ struct scoped_mock_context
|
||||
|
||||
Target mock_target;
|
||||
ptid_t mock_ptid {1, 1};
|
||||
- program_space mock_pspace {new address_space ()};
|
||||
+ program_space mock_pspace {new_address_space ()};
|
||||
inferior mock_inferior {mock_ptid.pid ()};
|
||||
thread_info mock_thread {&mock_inferior, mock_ptid};
|
||||
|
||||
diff --git a/gdb/target-dcache.c b/gdb/target-dcache.c
|
||||
index 13c2888e7ea..b1b772ab76e 100644
|
||||
--- a/gdb/target-dcache.c
|
||||
+++ b/gdb/target-dcache.c
|
||||
@@ -33,7 +33,7 @@ int
|
||||
target_dcache_init_p (void)
|
||||
{
|
||||
DCACHE *dcache
|
||||
- = target_dcache_aspace_key.get (current_program_space->aspace);
|
||||
+ = target_dcache_aspace_key.get (current_program_space->aspace.get ());
|
||||
|
||||
return (dcache != NULL);
|
||||
}
|
||||
@@ -44,7 +44,7 @@ void
|
||||
target_dcache_invalidate (void)
|
||||
{
|
||||
DCACHE *dcache
|
||||
- = target_dcache_aspace_key.get (current_program_space->aspace);
|
||||
+ = target_dcache_aspace_key.get (current_program_space->aspace.get ());
|
||||
|
||||
if (dcache != NULL)
|
||||
dcache_invalidate (dcache);
|
||||
@@ -56,7 +56,7 @@ target_dcache_invalidate (void)
|
||||
DCACHE *
|
||||
target_dcache_get (void)
|
||||
{
|
||||
- return target_dcache_aspace_key.get (current_program_space->aspace);
|
||||
+ return target_dcache_aspace_key.get (current_program_space->aspace.get ());
|
||||
}
|
||||
|
||||
/* Return the target dcache. If it is not initialized yet, initialize
|
||||
@@ -66,12 +66,13 @@ DCACHE *
|
||||
target_dcache_get_or_init (void)
|
||||
{
|
||||
DCACHE *dcache
|
||||
- = target_dcache_aspace_key.get (current_program_space->aspace);
|
||||
+ = target_dcache_aspace_key.get (current_program_space->aspace.get ());
|
||||
|
||||
if (dcache == NULL)
|
||||
{
|
||||
dcache = dcache_init ();
|
||||
- target_dcache_aspace_key.set (current_program_space->aspace, dcache);
|
||||
+ target_dcache_aspace_key.set (current_program_space->aspace.get (),
|
||||
+ dcache);
|
||||
}
|
||||
|
||||
return dcache;
|
||||
diff --git a/gdbsupport/refcounted-object.h b/gdbsupport/refcounted-object.h
|
||||
index d8fdb950043..294fd873df1 100644
|
||||
--- a/gdbsupport/refcounted-object.h
|
||||
+++ b/gdbsupport/refcounted-object.h
|
||||
@@ -67,4 +67,21 @@ struct refcounted_object_ref_policy
|
||||
}
|
||||
};
|
||||
|
||||
+/* A policy class to interface gdb::ref_ptr with a refcounted_object, that
|
||||
+ deletes the object once the refcount reaches 0.. */
|
||||
+
|
||||
+template<typename T>
|
||||
+struct refcounted_object_delete_ref_policy
|
||||
+{
|
||||
+ static void incref (T *obj)
|
||||
+ { obj->incref (); }
|
||||
+
|
||||
+ static void decref (T *obj)
|
||||
+ {
|
||||
+ obj->decref ();
|
||||
+ if (obj->refcount () == 0)
|
||||
+ delete obj;
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
#endif /* COMMON_REFCOUNTED_OBJECT_H */
|
||||
|
||||
base-commit: 0bb6f49bb9ad577667075550ca2ad4cb49931078
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,168 +0,0 @@
|
||||
From 3490f51a80a10d46dc1885ba672d9390a8221170 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Thu, 2 Nov 2023 14:51:02 +0100
|
||||
Subject: [PATCH] Fix segfault in for_each_block, part 2
|
||||
|
||||
The previous commit describes PR gdb/30547, a segfault when running test-case
|
||||
gdb.base/vfork-follow-parent.exp on powerpc64 (likewise on s390x).
|
||||
|
||||
The root cause for the segmentation fault is that linux_is_uclinux gives an
|
||||
incorrect result: it returns true instead of false.
|
||||
|
||||
So, why does linux_is_uclinux:
|
||||
...
|
||||
int
|
||||
linux_is_uclinux (void)
|
||||
{
|
||||
CORE_ADDR dummy;
|
||||
|
||||
return (target_auxv_search (AT_NULL, &dummy) > 0
|
||||
&& target_auxv_search (AT_PAGESZ, &dummy) == 0);
|
||||
...
|
||||
return true?
|
||||
|
||||
This is because ppc_linux_target_wordsize returns 4 instead of 8, causing
|
||||
ppc_linux_nat_target::auxv_parse to misinterpret the auxv vector.
|
||||
|
||||
So, why does ppc_linux_target_wordsize:
|
||||
...
|
||||
int
|
||||
ppc_linux_target_wordsize (int tid)
|
||||
{
|
||||
int wordsize = 4;
|
||||
|
||||
/* Check for 64-bit inferior process. This is the case when the host is
|
||||
64-bit, and in addition the top bit of the MSR register is set. */
|
||||
long msr;
|
||||
|
||||
errno = 0;
|
||||
msr = (long) ptrace (PTRACE_PEEKUSER, tid, PT_MSR * 8, 0);
|
||||
if (errno == 0 && ppc64_64bit_inferior_p (msr))
|
||||
wordsize = 8;
|
||||
|
||||
return wordsize;
|
||||
}
|
||||
...
|
||||
return 4?
|
||||
|
||||
Specifically, we get this result because because tid == 0, so we get
|
||||
errno == ESRCH.
|
||||
|
||||
The tid == 0 is caused by the switch_to_no_thread in
|
||||
handle_vfork_child_exec_or_exit:
|
||||
...
|
||||
/* Switch to no-thread while running clone_program_space, so
|
||||
that clone_program_space doesn't want to read the
|
||||
selected frame of a dead process. */
|
||||
scoped_restore_current_thread restore_thread;
|
||||
switch_to_no_thread ();
|
||||
|
||||
inf->pspace = new program_space (maybe_new_address_space ());
|
||||
...
|
||||
but moving the maybe_new_address_space call to before that gives us the
|
||||
same result. The tid is no longer 0, but we still get ESRCH because the
|
||||
thread has exited.
|
||||
|
||||
Fix this in handle_vfork_child_exec_or_exit by doing the
|
||||
maybe_new_address_space call in the context of the vfork parent.
|
||||
|
||||
Tested on top of trunk on x86_64-linux and ppc64le-linux.
|
||||
Tested on top of gdb-14-branch on ppc64-linux.
|
||||
|
||||
Co-Authored-By: Simon Marchi <simon.marchi@polymtl.ca>
|
||||
|
||||
PR gdb/30547
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30547
|
||||
---
|
||||
gdb/infrun.c | 16 +++++++++++-----
|
||||
gdb/nat/ppc-linux.c | 2 ++
|
||||
gdb/ppc-linux-nat.c | 2 ++
|
||||
gdb/s390-linux-nat.c | 5 ++++-
|
||||
4 files changed, 19 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/gdb/infrun.c b/gdb/infrun.c
|
||||
index 3854c66bf6c..d259e81df84 100644
|
||||
--- a/gdb/infrun.c
|
||||
+++ b/gdb/infrun.c
|
||||
@@ -1105,13 +1105,19 @@ handle_vfork_child_exec_or_exit (int exec)
|
||||
go ahead and create a new one for this exiting
|
||||
inferior. */
|
||||
|
||||
- /* Switch to no-thread while running clone_program_space, so
|
||||
- that clone_program_space doesn't want to read the
|
||||
- selected frame of a dead process. */
|
||||
scoped_restore_current_thread restore_thread;
|
||||
- switch_to_no_thread ();
|
||||
|
||||
- inf->pspace = new program_space (maybe_new_address_space ());
|
||||
+ /* Temporarily switch to the vfork parent, to facilitate ptrace
|
||||
+ calls done during maybe_new_address_space. */
|
||||
+ switch_to_thread (any_live_thread_of_inferior (vfork_parent));
|
||||
+ address_space_ref_ptr aspace = maybe_new_address_space ();
|
||||
+
|
||||
+ /* Switch back to the vfork child inferior. Switch to no-thread
|
||||
+ while running clone_program_space, so that clone_program_space
|
||||
+ doesn't want to read the selected frame of a dead process. */
|
||||
+ switch_to_inferior_no_thread (inf);
|
||||
+
|
||||
+ inf->pspace = new program_space (std::move (aspace));
|
||||
inf->aspace = inf->pspace->aspace;
|
||||
set_current_program_space (inf->pspace);
|
||||
inf->removable = true;
|
||||
diff --git a/gdb/nat/ppc-linux.c b/gdb/nat/ppc-linux.c
|
||||
index 0957d1b58a7..74549754806 100644
|
||||
--- a/gdb/nat/ppc-linux.c
|
||||
+++ b/gdb/nat/ppc-linux.c
|
||||
@@ -78,6 +78,8 @@ ppc64_64bit_inferior_p (long msr)
|
||||
int
|
||||
ppc_linux_target_wordsize (int tid)
|
||||
{
|
||||
+ gdb_assert (tid != 0);
|
||||
+
|
||||
int wordsize = 4;
|
||||
|
||||
/* Check for 64-bit inferior process. This is the case when the host is
|
||||
diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c
|
||||
index d14aba694e5..817505ea73e 100644
|
||||
--- a/gdb/ppc-linux-nat.c
|
||||
+++ b/gdb/ppc-linux-nat.c
|
||||
@@ -1914,6 +1914,8 @@ ppc_linux_nat_target::auxv_parse (const gdb_byte **readptr,
|
||||
const gdb_byte *endptr, CORE_ADDR *typep,
|
||||
CORE_ADDR *valp)
|
||||
{
|
||||
+ gdb_assert (inferior_ptid != null_ptid);
|
||||
+
|
||||
int tid = inferior_ptid.lwp ();
|
||||
if (tid == 0)
|
||||
tid = inferior_ptid.pid ();
|
||||
diff --git a/gdb/s390-linux-nat.c b/gdb/s390-linux-nat.c
|
||||
index 8f54e9f6322..54167f49480 100644
|
||||
--- a/gdb/s390-linux-nat.c
|
||||
+++ b/gdb/s390-linux-nat.c
|
||||
@@ -949,10 +949,12 @@ s390_target_wordsize (void)
|
||||
/* Check for 64-bit inferior process. This is the case when the host is
|
||||
64-bit, and in addition bit 32 of the PSW mask is set. */
|
||||
#ifdef __s390x__
|
||||
+ int tid = s390_inferior_tid ();
|
||||
+ gdb_assert (tid != 0);
|
||||
long pswm;
|
||||
|
||||
errno = 0;
|
||||
- pswm = (long) ptrace (PTRACE_PEEKUSER, s390_inferior_tid (), PT_PSWMASK, 0);
|
||||
+ pswm = (long) ptrace (PTRACE_PEEKUSER, tid, PT_PSWMASK, 0);
|
||||
if (errno == 0 && (pswm & 0x100000000ul) != 0)
|
||||
wordsize = 8;
|
||||
#endif
|
||||
@@ -965,6 +967,7 @@ s390_linux_nat_target::auxv_parse (const gdb_byte **readptr,
|
||||
const gdb_byte *endptr, CORE_ADDR *typep,
|
||||
CORE_ADDR *valp)
|
||||
{
|
||||
+ gdb_assert (inferior_ptid != null_ptid);
|
||||
int sizeof_auxv_field = s390_target_wordsize ();
|
||||
enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
|
||||
const gdb_byte *ptr = *readptr;
|
||||
|
||||
base-commit: 1d02ba0f4adcba2595a67e88fb1ba6d35c7f8e5b
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,42 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Buettner <kevinb@redhat.com>
|
||||
Date: Wed, 17 Jan 2024 12:53:53 -0700
|
||||
Subject: gdb-ftbs-swapped-calloc-args.patch
|
||||
|
||||
Backport upstream commit 54195469c18ec9873cc5ba6907f768509473fa9b
|
||||
which fixes a build problem in which arguments to calloc were swapped.
|
||||
|
||||
[opcodes] ARC + PPC: Fix -Walloc-size warnings
|
||||
|
||||
Recently, -Walloc-size warnings started to kick in. Fix these two
|
||||
calloc() calls to match the intended usage pattern.
|
||||
|
||||
opcodes/ChangeLog:
|
||||
|
||||
* arc-dis.c (init_arc_disasm_info): Fix calloc() call.
|
||||
* ppc-dis.c (powerpc_init_dialect): Ditto.
|
||||
|
||||
diff --git a/opcodes/arc-dis.c b/opcodes/arc-dis.c
|
||||
--- a/opcodes/arc-dis.c
|
||||
+++ b/opcodes/arc-dis.c
|
||||
@@ -147,7 +147,7 @@ static bool
|
||||
init_arc_disasm_info (struct disassemble_info *info)
|
||||
{
|
||||
struct arc_disassemble_info *arc_infop
|
||||
- = calloc (sizeof (*arc_infop), 1);
|
||||
+ = calloc (1, sizeof (*arc_infop));
|
||||
|
||||
if (arc_infop == NULL)
|
||||
return false;
|
||||
diff --git a/opcodes/ppc-dis.c b/opcodes/ppc-dis.c
|
||||
--- a/opcodes/ppc-dis.c
|
||||
+++ b/opcodes/ppc-dis.c
|
||||
@@ -348,7 +348,7 @@ powerpc_init_dialect (struct disassemble_info *info)
|
||||
{
|
||||
ppc_cpu_t dialect = 0;
|
||||
ppc_cpu_t sticky = 0;
|
||||
- struct dis_private *priv = calloc (sizeof (*priv), 1);
|
||||
+ struct dis_private *priv = calloc (1, sizeof (*priv));
|
||||
|
||||
if (priv == NULL)
|
||||
return;
|
@@ -6,5 +6,5 @@ index b9770ea415..3149f6e1fe 100644
|
||||
-#!/usr/bin/env bash
|
||||
+#!/bin/bash
|
||||
|
||||
# Copyright (C) 2003-2023 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2003-2024 Free Software Foundation, Inc.
|
||||
|
||||
|
68
gdb-guile-use-scm_debug_typing_strictness-0.patch
Normal file
68
gdb-guile-use-scm_debug_typing_strictness-0.patch
Normal file
@@ -0,0 +1,68 @@
|
||||
From fe0e6edbcb65ab5eca50c1a0ad8ddc9844f8ea98 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Mon, 27 Jan 2025 09:23:18 +0100
|
||||
Subject: [PATCH] [gdb/guile] Use SCM_DEBUG_TYPING_STRICTNESS 0
|
||||
|
||||
I build gdb with libguile v2.0.9, and ran into:
|
||||
...
|
||||
In file included from /usr/include/guile/2.0/libguile.h:56,
|
||||
from ../../gdb/guile/guile-internal.h:30,
|
||||
from ../../gdb/guile/scm-arch.c:26:
|
||||
/usr/include/guile/2.0/libguile/inline.h: In function 'int scm_is_pair(SCM)':
|
||||
/usr/include/guile/2.0/libguile/tags.h:97:53: error: \
|
||||
operation on '*0' may be undefined [-Werror=sequence-point]
|
||||
# define SCM_UNPACK(x) ((scm_t_bits) (0? (*(SCM*)0=(x)): x))
|
||||
~~~~~~~~~^~~~~
|
||||
...
|
||||
|
||||
Fix this by using SCM_DEBUG_TYPING_STRICTNESS 0.
|
||||
|
||||
We were already using this for c++20 due to a Werror=volatile in SCM_UNPACK
|
||||
when using libguile v2.0.10.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
---
|
||||
gdb/guile/guile-internal.h | 22 +++++++++++++++++++++-
|
||||
1 file changed, 21 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/guile/guile-internal.h b/gdb/guile/guile-internal.h
|
||||
index be16fee0dd2..6665bfc7813 100644
|
||||
--- a/gdb/guile/guile-internal.h
|
||||
+++ b/gdb/guile/guile-internal.h
|
||||
@@ -27,10 +27,30 @@
|
||||
#include "hashtab.h"
|
||||
#include "extension-priv.h"
|
||||
#include "symtab.h"
|
||||
-#include "libguile.h"
|
||||
#include "objfiles.h"
|
||||
#include "top.h"
|
||||
|
||||
+/* For libguile v2.0.9 and SCM_DEBUG_TYPING_STRICTNESS == 1, SCM_UNPACK(x) is
|
||||
+ defined as:
|
||||
+
|
||||
+ ((scm_t_bits) (0? (*(SCM*)0=(x)): x))
|
||||
+
|
||||
+ and for v2.0.10 it's defined as:
|
||||
+
|
||||
+ ((scm_t_bits) (0? (*(volatile SCM *)0=(x)): x))
|
||||
+
|
||||
+ The volatile was added to avoid a clang warning.
|
||||
+
|
||||
+ The latter form causes a Werror=volatile with C++20.
|
||||
+ This was reported upstream (
|
||||
+ https://debbugs.gnu.org/cgi/bugreport.cgi?bug=65333 ).
|
||||
+
|
||||
+ The former form causes a Werror=sequence-point with gcc 7-14.
|
||||
+
|
||||
+ Work around these problem by using SCM_DEBUG_TYPING_STRICTNESS == 0. */
|
||||
+#define SCM_DEBUG_TYPING_STRICTNESS 0
|
||||
+#include "libguile.h"
|
||||
+
|
||||
struct block;
|
||||
struct frame_info;
|
||||
struct objfile;
|
||||
|
||||
base-commit: 94df6741bbabaa9a51960446b2af4c0bed01b54b
|
||||
--
|
||||
2.43.0
|
||||
|
@@ -1,30 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Tom Tromey <tromey@adacore.com>
|
||||
Date: Wed, 15 Nov 2023 06:48:55 -0700
|
||||
Subject: gdb-handle-no-python-gdb-module.patch
|
||||
|
||||
;; Backport upstream commit 7d21600b31fe.
|
||||
|
||||
Check gdb_python_module in gdbpy_handle_missing_debuginfo
|
||||
|
||||
If you run gdb in the build tree without --data-directory, on a
|
||||
program that does not have debug info, it will crash, because
|
||||
gdbpy_handle_missing_debuginfo unconditionally uses gdb_python_module.
|
||||
|
||||
Other code in gdb using gdb_python_module checks it first and it
|
||||
seemes harmless to do the same thing here. (gdb_python_initialized
|
||||
does not cover this case so that python can be partially initialized
|
||||
and still somewhat work.)
|
||||
|
||||
diff --git a/gdb/python/python.c b/gdb/python/python.c
|
||||
--- a/gdb/python/python.c
|
||||
+++ b/gdb/python/python.c
|
||||
@@ -1676,7 +1676,7 @@ gdbpy_handle_missing_debuginfo (const struct extension_language_defn *extlang,
|
||||
struct objfile *objfile)
|
||||
{
|
||||
/* Early exit if Python is not initialised. */
|
||||
- if (!gdb_python_initialized)
|
||||
+ if (!gdb_python_initialized || gdb_python_module == nullptr)
|
||||
return {};
|
||||
|
||||
struct gdbarch *gdbarch = objfile->arch ();
|
@@ -1,265 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Burgess <aburgess@redhat.com>
|
||||
Date: Fri, 13 Oct 2023 09:50:33 +0100
|
||||
Subject: gdb-merge-debug-symbol-lookup.patch
|
||||
|
||||
;; Backport upstream commit 27807da5849.
|
||||
|
||||
gdb: merge debug symbol file lookup code from coffread & elfread paths
|
||||
|
||||
This commit merges the code that looks for and loads the separate
|
||||
debug symbol files from coffread.c and elfread.c. The factored out
|
||||
code is moved into a new objfile::find_and_add_separate_symbol_file()
|
||||
method.
|
||||
|
||||
For the elfread.c path there should be no user visible changes after
|
||||
this commit.
|
||||
|
||||
For the coffread.c path GDB will now attempt to perform a debuginfod
|
||||
lookup for the missing debug information, assuming that GDB can find a
|
||||
build-id in the COFF file.
|
||||
|
||||
I don't know if COFF files can include a build-id, but I the existing
|
||||
coffread.c code already includes a call to
|
||||
find_separate_debug_file_by_build-id, so I know that it is at least OK
|
||||
for GDB to ask a COFF file for a build-id. If the COFF file doesn't
|
||||
include a build-id then the debuginfod lookup code will not trigger
|
||||
and the new code is harmless.
|
||||
|
||||
If the COFF file does include a build-id, then we're going to end up
|
||||
asking debuginfod for the debug file. As build-ids should be unique,
|
||||
this should be harmless, even if debuginfod doesn't contain any
|
||||
suitable debug data, it just costs us one debuginfod lookup, so I'm
|
||||
not too worried about this for now.
|
||||
|
||||
As with the previous commit, I've done some minimal testing using the
|
||||
mingw toolchain on a Linux machine, GDB seems to still access the
|
||||
split debug information just fine.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
diff --git a/gdb/coffread.c b/gdb/coffread.c
|
||||
--- a/gdb/coffread.c
|
||||
+++ b/gdb/coffread.c
|
||||
@@ -40,8 +40,6 @@
|
||||
|
||||
#include "coff-pe-read.h"
|
||||
|
||||
-#include "build-id.h"
|
||||
-
|
||||
/* The objfile we are currently reading. */
|
||||
|
||||
static struct objfile *coffread_objfile;
|
||||
@@ -729,26 +727,8 @@ coff_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
|
||||
&& objfile->separate_debug_objfile == NULL
|
||||
&& objfile->separate_debug_objfile_backlink == NULL)
|
||||
{
|
||||
- deferred_warnings warnings;
|
||||
- std::string debugfile
|
||||
- = find_separate_debug_file_by_buildid (objfile, &warnings);
|
||||
-
|
||||
- if (debugfile.empty ())
|
||||
- debugfile
|
||||
- = find_separate_debug_file_by_debuglink (objfile, &warnings);
|
||||
-
|
||||
- if (!debugfile.empty ())
|
||||
- {
|
||||
- gdb_bfd_ref_ptr debug_bfd (symfile_bfd_open (debugfile.c_str ()));
|
||||
-
|
||||
- symbol_file_add_separate (debug_bfd, debugfile.c_str (),
|
||||
- symfile_flags, objfile);
|
||||
- }
|
||||
- /* If all the methods to collect the debuginfo failed, print any
|
||||
- warnings that were collected, this is a no-op if there are no
|
||||
- warnings. */
|
||||
- if (debugfile.empty ())
|
||||
- warnings.emit ();
|
||||
+ if (objfile->find_and_add_separate_symbol_file (symfile_flags))
|
||||
+ gdb_assert (objfile->separate_debug_objfile != nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/gdb/elfread.c b/gdb/elfread.c
|
||||
--- a/gdb/elfread.c
|
||||
+++ b/gdb/elfread.c
|
||||
@@ -41,14 +41,12 @@
|
||||
#include "regcache.h"
|
||||
#include "bcache.h"
|
||||
#include "gdb_bfd.h"
|
||||
-#include "build-id.h"
|
||||
#include "location.h"
|
||||
#include "auxv.h"
|
||||
#include "mdebugread.h"
|
||||
#include "ctfread.h"
|
||||
#include "gdbsupport/gdb_string_view.h"
|
||||
#include "gdbsupport/scoped_fd.h"
|
||||
-#include "debuginfod-support.h"
|
||||
#include "dwarf2/public.h"
|
||||
#include "cli/cli-cmds.h"
|
||||
|
||||
@@ -1218,59 +1216,10 @@ elf_symfile_read_dwarf2 (struct objfile *objfile,
|
||||
&& objfile->separate_debug_objfile == NULL
|
||||
&& objfile->separate_debug_objfile_backlink == NULL)
|
||||
{
|
||||
- deferred_warnings warnings;
|
||||
-
|
||||
- std::string debugfile
|
||||
- = find_separate_debug_file_by_buildid (objfile, &warnings);
|
||||
-
|
||||
- if (debugfile.empty ())
|
||||
- debugfile = find_separate_debug_file_by_debuglink (objfile, &warnings);
|
||||
-
|
||||
- if (!debugfile.empty ())
|
||||
- {
|
||||
- gdb_bfd_ref_ptr debug_bfd
|
||||
- (symfile_bfd_open_no_error (debugfile.c_str ()));
|
||||
-
|
||||
- if (debug_bfd != nullptr)
|
||||
- symbol_file_add_separate (debug_bfd, debugfile.c_str (),
|
||||
- symfile_flags, objfile);
|
||||
- }
|
||||
+ if (objfile->find_and_add_separate_symbol_file (symfile_flags))
|
||||
+ gdb_assert (objfile->separate_debug_objfile != nullptr);
|
||||
else
|
||||
- {
|
||||
- has_dwarf2 = false;
|
||||
- const struct bfd_build_id *build_id
|
||||
- = build_id_bfd_get (objfile->obfd.get ());
|
||||
- const char *filename = bfd_get_filename (objfile->obfd.get ());
|
||||
-
|
||||
- if (build_id != nullptr)
|
||||
- {
|
||||
- gdb::unique_xmalloc_ptr<char> symfile_path;
|
||||
- scoped_fd fd (debuginfod_debuginfo_query (build_id->data,
|
||||
- build_id->size,
|
||||
- filename,
|
||||
- &symfile_path));
|
||||
-
|
||||
- if (fd.get () >= 0)
|
||||
- {
|
||||
- /* File successfully retrieved from server. */
|
||||
- gdb_bfd_ref_ptr debug_bfd
|
||||
- (symfile_bfd_open_no_error (symfile_path.get ()));
|
||||
-
|
||||
- if (debug_bfd != nullptr
|
||||
- && build_id_verify (debug_bfd.get (), build_id->size,
|
||||
- build_id->data))
|
||||
- {
|
||||
- symbol_file_add_separate (debug_bfd, symfile_path.get (),
|
||||
- symfile_flags, objfile);
|
||||
- has_dwarf2 = true;
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
- /* If all the methods to collect the debuginfo failed, print the
|
||||
- warnings, this is a no-op if there are no warnings. */
|
||||
- if (debugfile.empty () && !has_dwarf2)
|
||||
- warnings.emit ();
|
||||
+ has_dwarf2 = false;
|
||||
}
|
||||
|
||||
return has_dwarf2;
|
||||
diff --git a/gdb/objfiles.h b/gdb/objfiles.h
|
||||
--- a/gdb/objfiles.h
|
||||
+++ b/gdb/objfiles.h
|
||||
@@ -513,6 +513,16 @@ struct objfile
|
||||
|
||||
bool has_partial_symbols ();
|
||||
|
||||
+ /* Look for a separate debug symbol file for this objfile, make use of
|
||||
+ build-id, debug-link, and debuginfod as necessary. If a suitable
|
||||
+ separate debug symbol file is found then it is loaded using a call to
|
||||
+ symbol_file_add_separate (SYMFILE_FLAGS is passed through unmodified
|
||||
+ to this call) and this function returns true. If no suitable separate
|
||||
+ debug symbol file is found and loaded then this function returns
|
||||
+ false. */
|
||||
+
|
||||
+ bool find_and_add_separate_symbol_file (symfile_add_flags symfile_flags);
|
||||
+
|
||||
/* Return true if this objfile has any unexpanded symbols. A return
|
||||
value of false indicates either, that this objfile has all its
|
||||
symbols fully expanded (i.e. fully read in), or that this objfile has
|
||||
diff --git a/gdb/symfile-debug.c b/gdb/symfile-debug.c
|
||||
--- a/gdb/symfile-debug.c
|
||||
+++ b/gdb/symfile-debug.c
|
||||
@@ -35,6 +35,8 @@
|
||||
#include "block.h"
|
||||
#include "filenames.h"
|
||||
#include "cli/cli-style.h"
|
||||
+#include "build-id.h"
|
||||
+#include "debuginfod-support.h"
|
||||
|
||||
/* We need to save a pointer to the real symbol functions.
|
||||
Plus, the debug versions are malloc'd because we have to NULL out the
|
||||
@@ -558,6 +560,70 @@ objfile::require_partial_symbols (bool verbose)
|
||||
}
|
||||
}
|
||||
|
||||
+/* See objfiles.h. */
|
||||
+
|
||||
+bool
|
||||
+objfile::find_and_add_separate_symbol_file (symfile_add_flags symfile_flags)
|
||||
+{
|
||||
+ bool has_dwarf2 = true;
|
||||
+
|
||||
+ deferred_warnings warnings;
|
||||
+
|
||||
+ std::string debugfile
|
||||
+ = find_separate_debug_file_by_buildid (this, &warnings);
|
||||
+
|
||||
+ if (debugfile.empty ())
|
||||
+ debugfile = find_separate_debug_file_by_debuglink (this, &warnings);
|
||||
+
|
||||
+ if (!debugfile.empty ())
|
||||
+ {
|
||||
+ gdb_bfd_ref_ptr debug_bfd
|
||||
+ (symfile_bfd_open_no_error (debugfile.c_str ()));
|
||||
+
|
||||
+ if (debug_bfd != nullptr)
|
||||
+ symbol_file_add_separate (debug_bfd, debugfile.c_str (),
|
||||
+ symfile_flags, this);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ has_dwarf2 = false;
|
||||
+ const struct bfd_build_id *build_id
|
||||
+ = build_id_bfd_get (this->obfd.get ());
|
||||
+ const char *filename = bfd_get_filename (this->obfd.get ());
|
||||
+
|
||||
+ if (build_id != nullptr)
|
||||
+ {
|
||||
+ gdb::unique_xmalloc_ptr<char> symfile_path;
|
||||
+ scoped_fd fd (debuginfod_debuginfo_query (build_id->data,
|
||||
+ build_id->size,
|
||||
+ filename,
|
||||
+ &symfile_path));
|
||||
+
|
||||
+ if (fd.get () >= 0)
|
||||
+ {
|
||||
+ /* File successfully retrieved from server. */
|
||||
+ gdb_bfd_ref_ptr debug_bfd
|
||||
+ (symfile_bfd_open_no_error (symfile_path.get ()));
|
||||
+
|
||||
+ if (debug_bfd != nullptr
|
||||
+ && build_id_verify (debug_bfd.get (), build_id->size,
|
||||
+ build_id->data))
|
||||
+ {
|
||||
+ symbol_file_add_separate (debug_bfd, symfile_path.get (),
|
||||
+ symfile_flags, this);
|
||||
+ has_dwarf2 = true;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ /* If all the methods to collect the debuginfo failed, print the
|
||||
+ warnings, this is a no-op if there are no warnings. */
|
||||
+ if (debugfile.empty () && !has_dwarf2)
|
||||
+ warnings.emit ();
|
||||
+
|
||||
+ return has_dwarf2;
|
||||
+}
|
||||
+
|
||||
|
||||
/* Debugging version of struct sym_probe_fns. */
|
||||
|
@@ -1,4 +1,4 @@
|
||||
From ed298cb88f0345d32a412c481898d867677726b8 Mon Sep 17 00:00:00 2001
|
||||
From a4ebf1e476b56777474584b653485bf3dc7068cc Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Burgess <aburgess@redhat.com>
|
||||
Date: Mon, 9 Sep 2024 17:33:54 +0100
|
||||
Subject: [PATCH] gdb/python: avoid depending on the curses library
|
||||
@@ -45,16 +45,16 @@ Approved-By: Tom de Vries <tdevries@suse.de>
|
||||
1 file changed, 27 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/gdb/python/lib/gdb/missing_debug.py b/gdb/python/lib/gdb/missing_debug.py
|
||||
index 7a768e5e05b..be6aacb1f41 100644
|
||||
index 4256947ff77..cdeea30256d 100644
|
||||
--- a/gdb/python/lib/gdb/missing_debug.py
|
||||
+++ b/gdb/python/lib/gdb/missing_debug.py
|
||||
@@ -30,9 +30,33 @@ if sys.version_info >= (3, 7):
|
||||
@@ -32,9 +32,33 @@ if sys.version_info >= (3, 7):
|
||||
return ch.isalnum()
|
||||
|
||||
else:
|
||||
- # Fall back to curses.ascii.isascii() and curses.ascii.isalnum() for
|
||||
- # earlier versions.
|
||||
- from curses.ascii import isascii, isalnum
|
||||
- from curses.ascii import isalnum, isascii
|
||||
+ # Older version of Python doesn't have str.isascii() and
|
||||
+ # str.isalnum() so provide our own.
|
||||
+ #
|
||||
@@ -86,7 +86,23 @@ index 7a768e5e05b..be6aacb1f41 100644
|
||||
|
||||
def _validate_name(name):
|
||||
|
||||
base-commit: cdf77e047eba662880a85ca55489a96c83c34cfb
|
||||
base-commit: b3f9f8454fe3f83754b130dd7aa26b62d4311bde
|
||||
prerequisite-patch-id: 77507b16457eeed54f9c51f9d3899c91bc6739ca
|
||||
prerequisite-patch-id: aec1fa16069ec9c14b671130354a5006b1739a34
|
||||
prerequisite-patch-id: a02aede530a3b3d0c64cd96ef7c2181e2886c3c5
|
||||
prerequisite-patch-id: 720d8081d37ae4b658b7e82ec96a39a82fdc8015
|
||||
prerequisite-patch-id: de6a537726187fa4b145246307af23449ae8fd3b
|
||||
prerequisite-patch-id: 4c8aa2b7f59cde2aa886b3a8e134b58f58ed92de
|
||||
prerequisite-patch-id: 913a84de7152200996b8bc6c6d241f95b4206294
|
||||
prerequisite-patch-id: af18dce2bc2a8c529dfd4b67c4514d4a94fe1f28
|
||||
prerequisite-patch-id: 07d1b82048ab34b0a037cf1c0ba1cb25bf7ec6eb
|
||||
prerequisite-patch-id: f7311861f758921d385103bcae9d72ccfb12db4d
|
||||
prerequisite-patch-id: 15dbe4af0de7b6c098c38a8c767d7166033e03c1
|
||||
prerequisite-patch-id: d27daff5cb15b862e7b48a41389b219040702c9d
|
||||
prerequisite-patch-id: 581089bf2af1e30e5e1e00d01df5b164cb5794cf
|
||||
prerequisite-patch-id: d2419f88c98cd8c7be804fd246eeb38d18dd0bda
|
||||
prerequisite-patch-id: b1806f9e902e5ceb32f31438cb059843461d78eb
|
||||
prerequisite-patch-id: c73d4526570e04107c3278cb8b5142d4a6665374
|
||||
--
|
||||
2.43.0
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
From adfcabe4cc43766996a61bdf08ce1e9db7f18dcc Mon Sep 17 00:00:00 2001
|
||||
From 086a725aa02b1195f63b2df4c2a2b4516788b2c6 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Thu, 18 Apr 2024 14:27:04 +0200
|
||||
Subject: [PATCH] gdb-python-finishbreakpoint-update
|
||||
Subject: [PATCH 42/46] gdb-python-finishbreakpoint-update
|
||||
|
||||
[gdb/python] FinishBreakPoint update
|
||||
|
||||
@@ -337,10 +337,10 @@ and running the test-cases:
|
||||
4 files changed, 35 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
|
||||
index db7d2e6a8e5..01f187ca4fe 100644
|
||||
index 5653842ce76..6e10914a316 100644
|
||||
--- a/gdb/breakpoint.c
|
||||
+++ b/gdb/breakpoint.c
|
||||
@@ -14683,6 +14683,10 @@ breakpoint_free_objfile (struct objfile *objfile)
|
||||
@@ -14693,6 +14693,10 @@ breakpoint_free_objfile (struct objfile *objfile)
|
||||
|
||||
static struct cmd_list_element *enablebreaklist = NULL;
|
||||
|
||||
@@ -351,7 +351,7 @@ index db7d2e6a8e5..01f187ca4fe 100644
|
||||
/* See breakpoint.h. */
|
||||
|
||||
cmd_list_element *commands_cmd_element = nullptr;
|
||||
@@ -15243,8 +15247,14 @@ This is useful for formatted output in user-defined commands."));
|
||||
@@ -15255,8 +15259,14 @@ This is useful for formatted output in user-defined commands."));
|
||||
|
||||
gdb::observers::about_to_proceed.attach (breakpoint_about_to_proceed,
|
||||
"breakpoint");
|
||||
@@ -367,10 +367,10 @@ index db7d2e6a8e5..01f187ca4fe 100644
|
||||
"breakpoint");
|
||||
}
|
||||
diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
|
||||
index 99670cca025..ba414b4e2c3 100644
|
||||
index 86ccc140c6d..e49cc580b1b 100644
|
||||
--- a/gdb/doc/python.texi
|
||||
+++ b/gdb/doc/python.texi
|
||||
@@ -6648,7 +6648,7 @@ is not writable.
|
||||
@@ -6882,7 +6882,7 @@ is not writable.
|
||||
@tindex gdb.FinishBreakpoint
|
||||
|
||||
A finish breakpoint is a temporary breakpoint set at the return address of
|
||||
@@ -379,7 +379,7 @@ index 99670cca025..ba414b4e2c3 100644
|
||||
extends @code{gdb.Breakpoint}. The underlying breakpoint will be disabled
|
||||
and deleted when the execution will run out of the breakpoint scope (i.e.@:
|
||||
@code{Breakpoint.stop} or @code{FinishBreakpoint.out_of_scope} triggered).
|
||||
@@ -6667,7 +6667,9 @@ details about this argument.
|
||||
@@ -6901,7 +6901,9 @@ details about this argument.
|
||||
In some circumstances (e.g.@: @code{longjmp}, C@t{++} exceptions, @value{GDBN}
|
||||
@code{return} command, @dots{}), a function may not properly terminate, and
|
||||
thus never hit the finish breakpoint. When @value{GDBN} notices such a
|
||||
@@ -391,7 +391,7 @@ index 99670cca025..ba414b4e2c3 100644
|
||||
You may want to sub-class @code{gdb.FinishBreakpoint} and override this
|
||||
method:
|
||||
diff --git a/gdb/python/py-finishbreakpoint.c b/gdb/python/py-finishbreakpoint.c
|
||||
index 42a7e0706d2..fa7ec43fbb4 100644
|
||||
index c74a2473a81..957d4ebc142 100644
|
||||
--- a/gdb/python/py-finishbreakpoint.c
|
||||
+++ b/gdb/python/py-finishbreakpoint.c
|
||||
@@ -433,6 +433,24 @@ bpfinishpy_handle_exit (struct inferior *inf)
|
||||
@@ -402,9 +402,9 @@ index 42a7e0706d2..fa7ec43fbb4 100644
|
||||
+ scope notifications. */
|
||||
+
|
||||
+static void
|
||||
+bpfinishpy_handle_thread_exit (struct thread_info *tp, gdb::optional<ULONGEST>, bool)
|
||||
+bpfinishpy_handle_thread_exit (struct thread_info *tp, std::optional<ULONGEST>, bool)
|
||||
+{
|
||||
+ gdbpy_enter enter_py (target_gdbarch (), current_language);
|
||||
+ gdbpy_enter enter_py (target_thread_architecture (tp->ptid), current_language);
|
||||
+
|
||||
+ for (breakpoint &bp : all_breakpoints_safe ())
|
||||
+ {
|
||||
@@ -429,7 +429,7 @@ index 42a7e0706d2..fa7ec43fbb4 100644
|
||||
return 0;
|
||||
}
|
||||
diff --git a/gdb/testsuite/gdb.python/py-finish-breakpoint2.exp b/gdb/testsuite/gdb.python/py-finish-breakpoint2.exp
|
||||
index 66587b8b9a0..31479a05e6f 100644
|
||||
index b837bb3a108..7d99aad2fd2 100644
|
||||
--- a/gdb/testsuite/gdb.python/py-finish-breakpoint2.exp
|
||||
+++ b/gdb/testsuite/gdb.python/py-finish-breakpoint2.exp
|
||||
@@ -87,6 +87,7 @@ if { $need_continue } {
|
||||
@@ -440,8 +440,6 @@ index 66587b8b9a0..31479a05e6f 100644
|
||||
gdb_test "python ExceptionFinishBreakpoint(gdb.newest_frame())" \
|
||||
"init ExceptionFinishBreakpoint" "set FinishBP after the exception again"
|
||||
|
||||
|
||||
base-commit: 6de9111c512de99fd8cb3ea89f9890b1d72f6ef0
|
||||
--
|
||||
2.35.3
|
||||
2.43.0
|
||||
|
||||
|
@@ -1,125 +0,0 @@
|
||||
From 4c7dab250c3581e691c2da87395e80244074d8bf Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Mon, 10 Jun 2024 17:53:30 +0200
|
||||
Subject: [PATCH] [gdb/python] Fix gdb.python/py-disasm.exp on arm-linux
|
||||
|
||||
After fixing test-case gdb.python/py-disasm.exp to recognize the arm nop:
|
||||
...
|
||||
nop {0}
|
||||
...
|
||||
we run into:
|
||||
...
|
||||
disassemble test^M
|
||||
Dump of assembler code for function test:^M
|
||||
0x004004d8 <+0>: push {r11} @ (str r11, [sp, #-4]!)^M
|
||||
0x004004dc <+4>: add r11, sp, #0^M
|
||||
0x004004e0 <+8>: nop {0}^M
|
||||
=> 0x004004e4 <+12>: Python Exception <class 'ValueError'>: Buffer \
|
||||
returned from read_memory is sized 0 instead of the expected 4^M
|
||||
^M
|
||||
unknown disassembler error (error = -1)^M
|
||||
(gdb) FAIL: $exp: global_disassembler=ShowInfoRepr: disassemble test
|
||||
...
|
||||
|
||||
This is caused by this code in gdbpy_disassembler::read_memory_func:
|
||||
...
|
||||
gdbpy_ref<> result_obj (PyObject_CallMethod ((PyObject *) obj,
|
||||
"read_memory",
|
||||
"KL", len, offset));
|
||||
...
|
||||
where len has type "unsigned int", while "K" means "unsigned long long" [1].
|
||||
|
||||
Fix this by using "I" instead, meaning "unsigned int".
|
||||
|
||||
Also, offset has type LONGEST, which is typedef'ed to int64_t, while "L" means
|
||||
"long long".
|
||||
|
||||
Fix this by using type gdb_py_longest for offset, in combination with format
|
||||
character "GDB_PY_LL_ARG". Likewise in disasmpy_info_read_memory.
|
||||
|
||||
Tested on arm-linux.
|
||||
|
||||
Reviewed-By: Alexandra Petlanova Hajkova <ahajkova@redhat.com>
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
PR python/31845
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31845
|
||||
|
||||
[1] https://docs.python.org/3/c-api/arg.html
|
||||
|
||||
(cherry picked from commit 4cd214dce4579f86a85a96c882e0fc8c4d94601c)
|
||||
---
|
||||
gdb/python/py-disasm.c | 12 +++++++-----
|
||||
gdb/testsuite/gdb.python/py-disasm.exp | 2 +-
|
||||
gdb/testsuite/gdb.python/py-disasm.py | 2 +-
|
||||
3 files changed, 9 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/gdb/python/py-disasm.c b/gdb/python/py-disasm.c
|
||||
index 6f0fed137e6..b2e95b3cba6 100644
|
||||
--- a/gdb/python/py-disasm.c
|
||||
+++ b/gdb/python/py-disasm.c
|
||||
@@ -668,12 +668,13 @@ disasmpy_info_read_memory (PyObject *self, PyObject *args, PyObject *kw)
|
||||
disasm_info_object *obj = (disasm_info_object *) self;
|
||||
DISASMPY_DISASM_INFO_REQUIRE_VALID (obj);
|
||||
|
||||
- LONGEST length, offset = 0;
|
||||
+ gdb_py_longest length, offset = 0;
|
||||
gdb::unique_xmalloc_ptr<gdb_byte> buffer;
|
||||
static const char *keywords[] = { "length", "offset", nullptr };
|
||||
|
||||
- if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "L|L", keywords,
|
||||
- &length, &offset))
|
||||
+ if (!gdb_PyArg_ParseTupleAndKeywords (args, kw,
|
||||
+ GDB_PY_LL_ARG "|" GDB_PY_LL_ARG,
|
||||
+ keywords, &length, &offset))
|
||||
return nullptr;
|
||||
|
||||
/* The apparent address from which we are reading memory. Note that in
|
||||
@@ -850,13 +851,14 @@ gdbpy_disassembler::read_memory_func (bfd_vma memaddr, gdb_byte *buff,
|
||||
/* The DisassembleInfo.read_memory method expects an offset from the
|
||||
address stored within the DisassembleInfo object; calculate that
|
||||
offset here. */
|
||||
- LONGEST offset = (LONGEST) memaddr - (LONGEST) obj->address;
|
||||
+ gdb_py_longest offset
|
||||
+ = (gdb_py_longest) memaddr - (gdb_py_longest) obj->address;
|
||||
|
||||
/* Now call the DisassembleInfo.read_memory method. This might have been
|
||||
overridden by the user. */
|
||||
gdbpy_ref<> result_obj (PyObject_CallMethod ((PyObject *) obj,
|
||||
"read_memory",
|
||||
- "KL", len, offset));
|
||||
+ "I" GDB_PY_LL_ARG, len, offset));
|
||||
|
||||
/* Handle any exceptions. */
|
||||
if (result_obj == nullptr)
|
||||
diff --git a/gdb/testsuite/gdb.python/py-disasm.exp b/gdb/testsuite/gdb.python/py-disasm.exp
|
||||
index f2f9225168a..9d0f6ec1d01 100644
|
||||
--- a/gdb/testsuite/gdb.python/py-disasm.exp
|
||||
+++ b/gdb/testsuite/gdb.python/py-disasm.exp
|
||||
@@ -65,7 +65,7 @@ proc py_remove_all_disassemblers {} {
|
||||
#
|
||||
# Each different disassembler tests some different feature of the
|
||||
# Python disassembler API.
|
||||
-set nop "(nop|nop\t0)"
|
||||
+set nop "(nop|nop\t0|[string_to_regexp nop\t{0}])"
|
||||
set unknown_error_pattern "unknown disassembler error \\(error = -1\\)"
|
||||
set addr_pattern "\r\n=> ${curr_pc_pattern} <\[^>\]+>:\\s+"
|
||||
set base_pattern "${addr_pattern}${nop}"
|
||||
diff --git a/gdb/testsuite/gdb.python/py-disasm.py b/gdb/testsuite/gdb.python/py-disasm.py
|
||||
index 67ba6756ea9..6a39b0764e6 100644
|
||||
--- a/gdb/testsuite/gdb.python/py-disasm.py
|
||||
+++ b/gdb/testsuite/gdb.python/py-disasm.py
|
||||
@@ -46,7 +46,7 @@ def check_building_disassemble_result():
|
||||
|
||||
|
||||
def is_nop(s):
|
||||
- return s == "nop" or s == "nop\t0"
|
||||
+ return s == "nop" or s == "nop\t0" or s == "nop\t{0}"
|
||||
|
||||
|
||||
# Remove all currently registered disassemblers.
|
||||
|
||||
base-commit: 22383ac8031b0e626e8ecd62e4378266065d067c
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,70 +0,0 @@
|
||||
From fc73000faa1798573090994167b7e2d451c211db Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Fri, 10 May 2024 08:46:21 +0200
|
||||
Subject: [PATCH] [gdb/python] Make gdb.UnwindInfo.add_saved_register more
|
||||
robust (fixup)
|
||||
|
||||
In commit 2236c5e384d ("[gdb/python] Make gdb.UnwindInfo.add_saved_register
|
||||
more robust") I added this code in unwind_infopy_add_saved_register:
|
||||
...
|
||||
if (value->optimized_out () || !value->entirely_available ())
|
||||
...
|
||||
which may throw c++ exceptions.
|
||||
|
||||
This needs to be caught and transformed into a python exception.
|
||||
|
||||
Fix this by using GDB_PY_HANDLE_EXCEPTION.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
Fixes: 2236c5e384d ("[gdb/python] Make gdb.UnwindInfo.add_saved_register more robust")
|
||||
(cherry picked from commit 408bc9c5fc757bd4b8adb1c3d54ecd672beaedb7)
|
||||
---
|
||||
gdb/python/py-unwind.c | 26 +++++++++++++++++---------
|
||||
1 file changed, 17 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/gdb/python/py-unwind.c b/gdb/python/py-unwind.c
|
||||
index 471eb851674..e57c8c1adcf 100644
|
||||
--- a/gdb/python/py-unwind.c
|
||||
+++ b/gdb/python/py-unwind.c
|
||||
@@ -354,16 +354,24 @@ unwind_infopy_add_saved_register (PyObject *self, PyObject *args, PyObject *kw)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
- if (value->optimized_out () || !value->entirely_available ())
|
||||
+
|
||||
+ try
|
||||
+ {
|
||||
+ if (value->optimized_out () || !value->entirely_available ())
|
||||
+ {
|
||||
+ /* If we allow this value to be registered here, pyuw_sniffer is going
|
||||
+ to run into an exception when trying to access its contents.
|
||||
+ Throwing an exception here just puts a burden on the user to
|
||||
+ implement the same checks on the user side. We could return False
|
||||
+ here and True otherwise, but again that might require changes in
|
||||
+ user code. So, handle this with minimal impact for the user, while
|
||||
+ improving robustness: silently ignore the register/value pair. */
|
||||
+ Py_RETURN_NONE;
|
||||
+ }
|
||||
+ }
|
||||
+ catch (const gdb_exception &except)
|
||||
{
|
||||
- /* If we allow this value to be registered here, pyuw_sniffer is going
|
||||
- to run into an exception when trying to access its contents.
|
||||
- Throwing an exception here just puts a burden on the user to
|
||||
- implement the same checks on the user side. We could return False
|
||||
- here and True otherwise, but again that might require changes in user
|
||||
- code. So, handle this with minimal impact for the user, while
|
||||
- improving robustness: silently ignore the register/value pair. */
|
||||
- Py_RETURN_NONE;
|
||||
+ GDB_PY_HANDLE_EXCEPTION (except);
|
||||
}
|
||||
|
||||
gdbpy_ref<> new_value = gdbpy_ref<>::new_reference (pyo_reg_value);
|
||||
|
||||
base-commit: a6f598be3d0477c5c59bd490573a5d457949658e
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,61 +0,0 @@
|
||||
From eafca1ce3d589c731927e5481199db715bcbeff3 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Sat, 2 Mar 2024 09:35:22 +0100
|
||||
Subject: [PATCH 2/2] [gdb/python] Make gdb.UnwindInfo.add_saved_register more
|
||||
robust
|
||||
|
||||
On arm-linux, until commit bbb12eb9c84 ("gdb/arm: Remove tpidruro register
|
||||
from non-FreeBSD target descriptions") I ran into:
|
||||
...
|
||||
FAIL: gdb.base/inline-frame-cycle-unwind.exp: cycle at level 5: \
|
||||
backtrace when the unwind is broken at frame 5
|
||||
...
|
||||
|
||||
What happens is the following:
|
||||
- the TestUnwinder from inline-frame-cycle-unwind.py calls
|
||||
gdb.UnwindInfo.add_saved_register with reg == tpidruro and value
|
||||
"<unavailable>",
|
||||
- pyuw_sniffer calls value->contents ().data () to access the value of the
|
||||
register, which throws an UNAVAILABLE_ERROR,
|
||||
- this causes the TestUnwinder unwinder to fail, after which another unwinder
|
||||
succeeds and returns the correct frame, and
|
||||
- the test-case fails because it's counting on the TestUnwinder to succeed and
|
||||
return an incorrect frame.
|
||||
|
||||
Fix this by checking for !value::entirely_available as well as
|
||||
valued::optimized_out in unwind_infopy_add_saved_register.
|
||||
|
||||
Tested on x86_64-linux and arm-linux.
|
||||
|
||||
PR python/31437
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31437
|
||||
---
|
||||
gdb/python/py-unwind.c | 12 ++++++++++++
|
||||
1 file changed, 12 insertions(+)
|
||||
|
||||
diff --git a/gdb/python/py-unwind.c b/gdb/python/py-unwind.c
|
||||
index 1856e41e2a1..471eb851674 100644
|
||||
--- a/gdb/python/py-unwind.c
|
||||
+++ b/gdb/python/py-unwind.c
|
||||
@@ -354,6 +354,18 @@ unwind_infopy_add_saved_register (PyObject *self, PyObject *args, PyObject *kw)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
+ if (value->optimized_out () || !value->entirely_available ())
|
||||
+ {
|
||||
+ /* If we allow this value to be registered here, pyuw_sniffer is going
|
||||
+ to run into an exception when trying to access its contents.
|
||||
+ Throwing an exception here just puts a burden on the user to
|
||||
+ implement the same checks on the user side. We could return False
|
||||
+ here and True otherwise, but again that might require changes in user
|
||||
+ code. So, handle this with minimal impact for the user, while
|
||||
+ improving robustness: silently ignore the register/value pair. */
|
||||
+ Py_RETURN_NONE;
|
||||
+ }
|
||||
+
|
||||
gdbpy_ref<> new_value = gdbpy_ref<>::new_reference (pyo_reg_value);
|
||||
bool found = false;
|
||||
for (saved_reg ® : *unwind_info->saved_regs)
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,190 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Burgess <aburgess@redhat.com>
|
||||
Date: Fri, 13 Oct 2023 16:17:20 +0100
|
||||
Subject: gdb-refactor-find-and-add-separate-symbol-file.patch
|
||||
|
||||
;; Backport upstream commit 6234ba17598.
|
||||
|
||||
gdb: refactor objfile::find_and_add_separate_symbol_file
|
||||
|
||||
This is purely a refactoring commit.
|
||||
|
||||
This commit splits objfile::find_and_add_separate_symbol_file into
|
||||
some separate helper functions. My hope is that the steps for looking
|
||||
up separate debug information are now clearer.
|
||||
|
||||
In a later commit I'm going to extend
|
||||
objfile::find_and_add_separate_symbol_file, with some additional
|
||||
logic, so starting with a simpler function will make the following
|
||||
changes easier.
|
||||
|
||||
When reading objfile::find_and_add_separate_symbol_file after this
|
||||
commit, you might be tempted to think that removing the `has_dwarf`
|
||||
local variable would be a good additional cleanup. After the next
|
||||
commit though it makes more sense to retain this local, so I've left
|
||||
this in place for now.
|
||||
|
||||
There should be no user visible changes after this commit.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
diff --git a/gdb/symfile-debug.c b/gdb/symfile-debug.c
|
||||
--- a/gdb/symfile-debug.c
|
||||
+++ b/gdb/symfile-debug.c
|
||||
@@ -560,68 +560,109 @@ objfile::require_partial_symbols (bool verbose)
|
||||
}
|
||||
}
|
||||
|
||||
+/* Call LOOKUP_FUNC to find the filename of a file containing the separate
|
||||
+ debug information matching OBJFILE. If LOOKUP_FUNC does return a
|
||||
+ filename then open this file and return a std::pair containing the
|
||||
+ gdb_bfd_ref_ptr of the open file and the filename returned by
|
||||
+ LOOKUP_FUNC, otherwise this function returns an empty pair; the first
|
||||
+ item will be nullptr, and the second will be an empty string.
|
||||
+
|
||||
+ Any warnings generated by this function, or by calling LOOKUP_FUNC are
|
||||
+ placed into WARNINGS, these warnings are only displayed to the user if
|
||||
+ GDB is unable to find the separate debug information via any route. */
|
||||
+static std::pair<gdb_bfd_ref_ptr, std::string>
|
||||
+simple_find_and_open_separate_symbol_file
|
||||
+ (struct objfile *objfile,
|
||||
+ std::string (*lookup_func) (struct objfile *, deferred_warnings *),
|
||||
+ deferred_warnings *warnings)
|
||||
+{
|
||||
+ std::string filename = lookup_func (objfile, warnings);
|
||||
+
|
||||
+ if (!filename.empty ())
|
||||
+ {
|
||||
+ gdb_bfd_ref_ptr symfile_bfd
|
||||
+ = symfile_bfd_open_no_error (filename.c_str ());
|
||||
+ if (symfile_bfd != nullptr)
|
||||
+ return { symfile_bfd, filename };
|
||||
+ }
|
||||
+
|
||||
+ return {};
|
||||
+}
|
||||
+
|
||||
+/* Lookup separate debug information for OBJFILE via debuginfod. If
|
||||
+ successful the debug information will be have been downloaded into the
|
||||
+ debuginfod cache and this function will return a std::pair containing a
|
||||
+ gdb_bfd_ref_ptr of the open debug information file and the filename for
|
||||
+ the file within the debuginfod cache. If no debug information could be
|
||||
+ found then this function returns an empty pair; the first item will be
|
||||
+ nullptr, and the second will be an empty string. */
|
||||
+
|
||||
+static std::pair<gdb_bfd_ref_ptr, std::string>
|
||||
+debuginfod_find_and_open_separate_symbol_file (struct objfile * objfile)
|
||||
+{
|
||||
+ const struct bfd_build_id *build_id
|
||||
+ = build_id_bfd_get (objfile->obfd.get ());
|
||||
+ const char *filename = bfd_get_filename (objfile->obfd.get ());
|
||||
+
|
||||
+ if (build_id != nullptr)
|
||||
+ {
|
||||
+ gdb::unique_xmalloc_ptr<char> symfile_path;
|
||||
+ scoped_fd fd (debuginfod_debuginfo_query (build_id->data, build_id->size,
|
||||
+ filename, &symfile_path));
|
||||
+
|
||||
+ if (fd.get () >= 0)
|
||||
+ {
|
||||
+ /* File successfully retrieved from server. */
|
||||
+ gdb_bfd_ref_ptr debug_bfd
|
||||
+ (symfile_bfd_open_no_error (symfile_path.get ()));
|
||||
+
|
||||
+ if (debug_bfd != nullptr
|
||||
+ && build_id_verify (debug_bfd.get (),
|
||||
+ build_id->size, build_id->data))
|
||||
+ return { debug_bfd, std::string (symfile_path.get ()) };
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return {};
|
||||
+}
|
||||
+
|
||||
/* See objfiles.h. */
|
||||
|
||||
bool
|
||||
objfile::find_and_add_separate_symbol_file (symfile_add_flags symfile_flags)
|
||||
{
|
||||
- bool has_dwarf2 = true;
|
||||
+ bool has_dwarf = false;
|
||||
|
||||
deferred_warnings warnings;
|
||||
|
||||
- std::string debugfile
|
||||
- = find_separate_debug_file_by_buildid (this, &warnings);
|
||||
-
|
||||
- if (debugfile.empty ())
|
||||
- debugfile = find_separate_debug_file_by_debuglink (this, &warnings);
|
||||
+ gdb_bfd_ref_ptr debug_bfd;
|
||||
+ std::string filename;
|
||||
|
||||
- if (!debugfile.empty ())
|
||||
- {
|
||||
- gdb_bfd_ref_ptr debug_bfd
|
||||
- (symfile_bfd_open_no_error (debugfile.c_str ()));
|
||||
+ std::tie (debug_bfd, filename) = simple_find_and_open_separate_symbol_file
|
||||
+ (this, find_separate_debug_file_by_buildid, &warnings);
|
||||
|
||||
- if (debug_bfd != nullptr)
|
||||
- symbol_file_add_separate (debug_bfd, debugfile.c_str (),
|
||||
- symfile_flags, this);
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- has_dwarf2 = false;
|
||||
- const struct bfd_build_id *build_id
|
||||
- = build_id_bfd_get (this->obfd.get ());
|
||||
- const char *filename = bfd_get_filename (this->obfd.get ());
|
||||
-
|
||||
- if (build_id != nullptr)
|
||||
- {
|
||||
- gdb::unique_xmalloc_ptr<char> symfile_path;
|
||||
- scoped_fd fd (debuginfod_debuginfo_query (build_id->data,
|
||||
- build_id->size,
|
||||
- filename,
|
||||
- &symfile_path));
|
||||
+ if (debug_bfd == nullptr)
|
||||
+ std::tie (debug_bfd, filename)
|
||||
+ = simple_find_and_open_separate_symbol_file
|
||||
+ (this, find_separate_debug_file_by_debuglink, &warnings);
|
||||
|
||||
- if (fd.get () >= 0)
|
||||
- {
|
||||
- /* File successfully retrieved from server. */
|
||||
- gdb_bfd_ref_ptr debug_bfd
|
||||
- (symfile_bfd_open_no_error (symfile_path.get ()));
|
||||
+ if (debug_bfd == nullptr)
|
||||
+ std::tie (debug_bfd, filename)
|
||||
+ = debuginfod_find_and_open_separate_symbol_file (this);
|
||||
|
||||
- if (debug_bfd != nullptr
|
||||
- && build_id_verify (debug_bfd.get (), build_id->size,
|
||||
- build_id->data))
|
||||
- {
|
||||
- symbol_file_add_separate (debug_bfd, symfile_path.get (),
|
||||
- symfile_flags, this);
|
||||
- has_dwarf2 = true;
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
+ if (debug_bfd != nullptr)
|
||||
+ {
|
||||
+ symbol_file_add_separate (debug_bfd, filename.c_str (), symfile_flags,
|
||||
+ this);
|
||||
+ has_dwarf = true;
|
||||
}
|
||||
- /* If all the methods to collect the debuginfo failed, print the
|
||||
- warnings, this is a no-op if there are no warnings. */
|
||||
- if (debugfile.empty () && !has_dwarf2)
|
||||
+
|
||||
+ /* If we still have not got a separate debug symbol file, then
|
||||
+ emit any warnings we've collected so far. */
|
||||
+ if (!has_dwarf)
|
||||
warnings.emit ();
|
||||
|
||||
- return has_dwarf2;
|
||||
+ return has_dwarf;
|
||||
}
|
||||
|
||||
|
@@ -1,38 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Thu, 23 Nov 2023 07:37:19 +0100
|
||||
Subject: gdb-reformat-missing-debug-py-file.patch
|
||||
|
||||
;; Backport upstream commit dd5516bf98f.
|
||||
|
||||
[gdb/python] Reformat missing_debug.py using black
|
||||
|
||||
Reformat gdb/python/lib/gdb/missing_debug.py with black after commit
|
||||
e8c3dafa5f5 ("[gdb/python] Don't import curses.ascii module unless necessary").
|
||||
|
||||
diff --git a/gdb/python/lib/gdb/missing_debug.py b/gdb/python/lib/gdb/missing_debug.py
|
||||
--- a/gdb/python/lib/gdb/missing_debug.py
|
||||
+++ b/gdb/python/lib/gdb/missing_debug.py
|
||||
@@ -19,18 +19,22 @@ MissingDebugHandler base class, and register_handler function.
|
||||
|
||||
import gdb
|
||||
import sys
|
||||
+
|
||||
if sys.version_info >= (3, 7):
|
||||
# Functions str.isascii() and str.isalnum are available starting Python
|
||||
# 3.7.
|
||||
def isascii(ch):
|
||||
return ch.isascii()
|
||||
+
|
||||
def isalnum(ch):
|
||||
return ch.isalnum()
|
||||
+
|
||||
else:
|
||||
# Fall back to curses.ascii.isascii() and curses.ascii.isalnum() for
|
||||
# earlier versions.
|
||||
from curses.ascii import isascii, isalnum
|
||||
|
||||
+
|
||||
def _validate_name(name):
|
||||
"""Validate a missing debug handler name string.
|
||||
|
@@ -1,229 +0,0 @@
|
||||
From 0ad71e3088f345101085a1f72e81a000a100db18 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Sat, 27 Apr 2024 17:48:22 +0200
|
||||
Subject: [PATCH 25/48] [gdb/remote] Fix abort on REMOTE_CLOSE_ERROR
|
||||
|
||||
When running test-case gdb.server/connect-with-no-symbol-file.exp on
|
||||
aarch64-linux (specifically, an opensuse leap 15.5 container on a
|
||||
fedora asahi 39 system), I run into:
|
||||
...
|
||||
(gdb) detach^M
|
||||
Detaching from program: target:connect-with-no-symbol-file, process 185104^M
|
||||
Ending remote debugging.^M
|
||||
terminate called after throwing an instance of 'gdb_exception_error'^M
|
||||
...
|
||||
|
||||
The detailed backtrace of the corefile is:
|
||||
...
|
||||
(gdb) bt
|
||||
#0 0x0000ffff75504f54 in raise () from /lib64/libpthread.so.0
|
||||
#1 0x00000000007a86b4 in handle_fatal_signal (sig=6)
|
||||
at gdb/event-top.c:926
|
||||
#2 <signal handler called>
|
||||
#3 0x0000ffff74b977b4 in raise () from /lib64/libc.so.6
|
||||
#4 0x0000ffff74b98c18 in abort () from /lib64/libc.so.6
|
||||
#5 0x0000ffff74ea26f4 in __gnu_cxx::__verbose_terminate_handler() ()
|
||||
from /usr/lib64/libstdc++.so.6
|
||||
#6 0x0000ffff74ea011c in ?? () from /usr/lib64/libstdc++.so.6
|
||||
#7 0x0000ffff74ea0180 in std::terminate() () from /usr/lib64/libstdc++.so.6
|
||||
#8 0x0000ffff74ea0464 in __cxa_throw () from /usr/lib64/libstdc++.so.6
|
||||
#9 0x0000000001548870 in throw_it (reason=RETURN_ERROR,
|
||||
error=TARGET_CLOSE_ERROR, fmt=0x16c7810 "Remote connection closed", ap=...)
|
||||
at gdbsupport/common-exceptions.cc:203
|
||||
#10 0x0000000001548920 in throw_verror (error=TARGET_CLOSE_ERROR,
|
||||
fmt=0x16c7810 "Remote connection closed", ap=...)
|
||||
at gdbsupport/common-exceptions.cc:211
|
||||
#11 0x0000000001548a00 in throw_error (error=TARGET_CLOSE_ERROR,
|
||||
fmt=0x16c7810 "Remote connection closed")
|
||||
at gdbsupport/common-exceptions.cc:226
|
||||
#12 0x0000000000ac8f2c in remote_target::readchar (this=0x233d3d90, timeout=2)
|
||||
at gdb/remote.c:9856
|
||||
#13 0x0000000000ac9f04 in remote_target::getpkt (this=0x233d3d90,
|
||||
buf=0x233d40a8, forever=false, is_notif=0x0) at gdb/remote.c:10326
|
||||
#14 0x0000000000acf3d0 in remote_target::remote_hostio_send_command
|
||||
(this=0x233d3d90, command_bytes=13, which_packet=17,
|
||||
remote_errno=0xfffff1a3cf38, attachment=0xfffff1a3ce88,
|
||||
attachment_len=0xfffff1a3ce90) at gdb/remote.c:12567
|
||||
#15 0x0000000000ad03bc in remote_target::fileio_fstat (this=0x233d3d90, fd=3,
|
||||
st=0xfffff1a3d020, remote_errno=0xfffff1a3cf38)
|
||||
at gdb/remote.c:12979
|
||||
#16 0x0000000000c39878 in target_fileio_fstat (fd=0, sb=0xfffff1a3d020,
|
||||
target_errno=0xfffff1a3cf38) at gdb/target.c:3315
|
||||
#17 0x00000000007eee5c in target_fileio_stream::stat (this=0x233d4400,
|
||||
abfd=0x2323fc40, sb=0xfffff1a3d020) at gdb/gdb_bfd.c:467
|
||||
#18 0x00000000007f012c in <lambda(bfd*, void*, stat*)>::operator()(bfd *,
|
||||
void *, stat *) const (__closure=0x0, abfd=0x2323fc40, stream=0x233d4400,
|
||||
sb=0xfffff1a3d020) at gdb/gdb_bfd.c:955
|
||||
#19 0x00000000007f015c in <lambda(bfd*, void*, stat*)>::_FUN(bfd *, void *,
|
||||
stat *) () at gdb/gdb_bfd.c:956
|
||||
#20 0x0000000000f9b838 in opncls_bstat (abfd=0x2323fc40, sb=0xfffff1a3d020)
|
||||
at bfd/opncls.c:665
|
||||
#21 0x0000000000f90adc in bfd_stat (abfd=0x2323fc40, statbuf=0xfffff1a3d020)
|
||||
at bfd/bfdio.c:431
|
||||
#22 0x000000000065fe20 in reopen_exec_file () at gdb/corefile.c:52
|
||||
#23 0x0000000000c3a3e8 in generic_mourn_inferior ()
|
||||
at gdb/target.c:3642
|
||||
#24 0x0000000000abf3f0 in remote_unpush_target (target=0x233d3d90)
|
||||
at gdb/remote.c:6067
|
||||
#25 0x0000000000aca8b0 in remote_target::mourn_inferior (this=0x233d3d90)
|
||||
at gdb/remote.c:10587
|
||||
#26 0x0000000000c387cc in target_mourn_inferior (
|
||||
ptid=<error reading variable: Cannot access memory at address 0x2d310>)
|
||||
at gdb/target.c:2738
|
||||
#27 0x0000000000abfff0 in remote_target::remote_detach_1 (this=0x233d3d90,
|
||||
inf=0x22fce540, from_tty=1) at gdb/remote.c:6421
|
||||
#28 0x0000000000ac0094 in remote_target::detach (this=0x233d3d90,
|
||||
inf=0x22fce540, from_tty=1) at gdb/remote.c:6436
|
||||
#29 0x0000000000c37c3c in target_detach (inf=0x22fce540, from_tty=1)
|
||||
at gdb/target.c:2526
|
||||
#30 0x0000000000860424 in detach_command (args=0x0, from_tty=1)
|
||||
at gdb/infcmd.c:2817
|
||||
#31 0x000000000060b594 in do_simple_func (args=0x0, from_tty=1, c=0x231431a0)
|
||||
at gdb/cli/cli-decode.c:94
|
||||
#32 0x00000000006108c8 in cmd_func (cmd=0x231431a0, args=0x0, from_tty=1)
|
||||
at gdb/cli/cli-decode.c:2741
|
||||
#33 0x0000000000c65a94 in execute_command (p=0x232e52f6 "", from_tty=1)
|
||||
at gdb/top.c:570
|
||||
#34 0x00000000007a7d2c in command_handler (command=0x232e52f0 "")
|
||||
at gdb/event-top.c:566
|
||||
#35 0x00000000007a8290 in command_line_handler (rl=...)
|
||||
at gdb/event-top.c:802
|
||||
#36 0x0000000000c9092c in tui_command_line_handler (rl=...)
|
||||
at gdb/tui/tui-interp.c:103
|
||||
#37 0x00000000007a750c in gdb_rl_callback_handler (rl=0x23385330 "detach")
|
||||
at gdb/event-top.c:258
|
||||
#38 0x0000000000d910f4 in rl_callback_read_char ()
|
||||
at readline/readline/callback.c:290
|
||||
#39 0x00000000007a7338 in gdb_rl_callback_read_char_wrapper_noexcept ()
|
||||
at gdb/event-top.c:194
|
||||
#40 0x00000000007a73f0 in gdb_rl_callback_read_char_wrapper
|
||||
(client_data=0x22fbf640) at gdb/event-top.c:233
|
||||
#41 0x0000000000cbee1c in stdin_event_handler (error=0, client_data=0x22fbf640)
|
||||
at gdb/ui.c:154
|
||||
#42 0x000000000154ed60 in handle_file_event (file_ptr=0x232be730, ready_mask=1)
|
||||
at gdbsupport/event-loop.cc:572
|
||||
#43 0x000000000154f21c in gdb_wait_for_event (block=1)
|
||||
at gdbsupport/event-loop.cc:693
|
||||
#44 0x000000000154dec4 in gdb_do_one_event (mstimeout=-1)
|
||||
at gdbsupport/event-loop.cc:263
|
||||
#45 0x0000000000910f98 in start_event_loop () at gdb/main.c:400
|
||||
#46 0x0000000000911130 in captured_command_loop () at gdb/main.c:464
|
||||
#47 0x0000000000912b5c in captured_main (data=0xfffff1a3db58)
|
||||
at gdb/main.c:1338
|
||||
#48 0x0000000000912bf4 in gdb_main (args=0xfffff1a3db58)
|
||||
at gdb/main.c:1357
|
||||
#49 0x00000000004170f4 in main (argc=10, argv=0xfffff1a3dcc8)
|
||||
at gdb/gdb.c:38
|
||||
(gdb)
|
||||
...
|
||||
|
||||
The abort happens because a c++ exception escapes to c code, specifically
|
||||
opncls_bstat in bfd/opncls.c. Compiling with -fexceptions works around this.
|
||||
|
||||
Fix this by catching the exception just before it escapes, in stat_trampoline
|
||||
and likewise in few similar spot.
|
||||
|
||||
Add a new template catch_exceptions to do so in a consistent way.
|
||||
|
||||
Tested on aarch64-linux.
|
||||
|
||||
Approved-by: Pedro Alves <pedro@palves.net>
|
||||
|
||||
PR remote/31577
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31577
|
||||
---
|
||||
gdb/gdb_bfd.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++---
|
||||
1 file changed, 56 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/gdb/gdb_bfd.c b/gdb/gdb_bfd.c
|
||||
index 217753cf914..3c34cc5693f 100644
|
||||
--- a/gdb/gdb_bfd.c
|
||||
+++ b/gdb/gdb_bfd.c
|
||||
@@ -887,6 +887,29 @@ gdb_bfd_openw (const char *filename, const char *target)
|
||||
return gdb_bfd_ref_ptr::new_reference (result);
|
||||
}
|
||||
|
||||
+/* Wrap f (args) and handle exceptions by:
|
||||
+ - returning val, and
|
||||
+ - calling set_quit_flag or set_force_quit_flag, if needed. */
|
||||
+
|
||||
+template <typename R, R val, typename F, typename... Args>
|
||||
+static R
|
||||
+catch_exceptions (F &&f, Args&&... args)
|
||||
+{
|
||||
+ try
|
||||
+ {
|
||||
+ return f (std::forward<Args> (args)...);
|
||||
+ }
|
||||
+ catch (const gdb_exception &ex)
|
||||
+ {
|
||||
+ if (ex.reason == RETURN_QUIT)
|
||||
+ set_quit_flag ();
|
||||
+ else if (ex.reason == RETURN_FORCED_QUIT)
|
||||
+ set_force_quit_flag ();
|
||||
+ }
|
||||
+
|
||||
+ return val;
|
||||
+}
|
||||
+
|
||||
/* See gdb_bfd.h. */
|
||||
|
||||
gdb_bfd_ref_ptr
|
||||
@@ -896,21 +919,51 @@ gdb_bfd_openr_iovec (const char *filename, const char *target,
|
||||
auto do_open = [] (bfd *nbfd, void *closure) -> void *
|
||||
{
|
||||
auto real_opener = static_cast<gdb_iovec_opener_ftype *> (closure);
|
||||
- return (*real_opener) (nbfd);
|
||||
+ /* Prevent exceptions from escaping to C code and triggering an abort. */
|
||||
+ auto res = catch_exceptions<gdb_bfd_iovec_base *, nullptr> ([&]
|
||||
+ {
|
||||
+ return (*real_opener) (nbfd);
|
||||
+ });
|
||||
+ if (res == nullptr)
|
||||
+ {
|
||||
+ errno = EIO;
|
||||
+ bfd_set_error (bfd_error_system_call);
|
||||
+ }
|
||||
+ return res;
|
||||
};
|
||||
|
||||
auto read_trampoline = [] (bfd *nbfd, void *stream, void *buf,
|
||||
file_ptr nbytes, file_ptr offset) -> file_ptr
|
||||
{
|
||||
gdb_bfd_iovec_base *obj = static_cast<gdb_bfd_iovec_base *> (stream);
|
||||
- return obj->read (nbfd, buf, nbytes, offset);
|
||||
+ /* Prevent exceptions from escaping to C code and triggering an abort. */
|
||||
+ auto res = catch_exceptions<long int, -1> ([&]
|
||||
+ {
|
||||
+ return obj->read (nbfd, buf, nbytes, offset);
|
||||
+ });
|
||||
+ if (res == -1)
|
||||
+ {
|
||||
+ errno = EIO;
|
||||
+ bfd_set_error (bfd_error_system_call);
|
||||
+ }
|
||||
+ return res;
|
||||
};
|
||||
|
||||
auto stat_trampoline = [] (struct bfd *abfd, void *stream,
|
||||
struct stat *sb) -> int
|
||||
{
|
||||
gdb_bfd_iovec_base *obj = static_cast<gdb_bfd_iovec_base *> (stream);
|
||||
- return obj->stat (abfd, sb);
|
||||
+ /* Prevent exceptions from escaping to C code and triggering an abort. */
|
||||
+ auto res = catch_exceptions<int, -1> ([&]
|
||||
+ {
|
||||
+ return obj->stat (abfd, sb);
|
||||
+ });
|
||||
+ if (res == -1)
|
||||
+ {
|
||||
+ errno = EIO;
|
||||
+ bfd_set_error (bfd_error_system_call);
|
||||
+ }
|
||||
+ return res;
|
||||
};
|
||||
|
||||
auto close_trampoline = [] (struct bfd *nbfd, void *stream) -> int
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,29 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Tom Tromey <tromey@adacore.com>
|
||||
Date: Tue, 14 Nov 2023 11:47:27 -0700
|
||||
Subject: gdb-remove-path-in-test-name.patch
|
||||
|
||||
;; Backport upstream commit 1146d27749f.
|
||||
|
||||
Remove path name from test case
|
||||
|
||||
'runtest' complains about a path in a test name, from the new test
|
||||
case py-missing-debug.exp.
|
||||
|
||||
This patch fixes the problem by providing an explicit test name to
|
||||
gdb_test. I chose something very basic because the block in question
|
||||
is already wrapped in with_test_prefix.
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.python/py-missing-debug.exp b/gdb/testsuite/gdb.python/py-missing-debug.exp
|
||||
--- a/gdb/testsuite/gdb.python/py-missing-debug.exp
|
||||
+++ b/gdb/testsuite/gdb.python/py-missing-debug.exp
|
||||
@@ -321,7 +321,8 @@ with_test_prefix "enable 'abc-def'" {
|
||||
set re [string_to_regexp $binfile]
|
||||
|
||||
gdb_test "enable missing-debug-handler \"$re\" abc-def" \
|
||||
- "^1 missing debug handler enabled"
|
||||
+ "^1 missing debug handler enabled" \
|
||||
+ "enable missing-debug-handler"
|
||||
|
||||
gdb_test "info missing-debug-handlers" \
|
||||
[multi_line \
|
@@ -1,46 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Burgess <aburgess@redhat.com>
|
||||
Date: Thu, 16 Nov 2023 10:53:34 +0000
|
||||
Subject: gdb-remove-use-of-py-isascii
|
||||
|
||||
;; Backport upstream commit 7db795bc67a.
|
||||
|
||||
gdb/python: remove use of str.isascii()
|
||||
|
||||
This commit:
|
||||
|
||||
commit 8f6c452b5a4e50fbb55ff1d13328b392ad1fd416
|
||||
Date: Sun Oct 15 22:48:42 2023 +0100
|
||||
|
||||
gdb: implement missing debug handler hook for Python
|
||||
|
||||
introduced a use of str.isascii(), which was only added in Python 3.7.
|
||||
|
||||
This commit switches to use curses.ascii.isascii(), as this was
|
||||
available in 3.6.
|
||||
|
||||
The same is true for str.isalnum(), which is replaced with
|
||||
curses.ascii.isalnum().
|
||||
|
||||
There should be no user visible changes after this commit.
|
||||
|
||||
diff --git a/gdb/python/lib/gdb/missing_debug.py b/gdb/python/lib/gdb/missing_debug.py
|
||||
--- a/gdb/python/lib/gdb/missing_debug.py
|
||||
+++ b/gdb/python/lib/gdb/missing_debug.py
|
||||
@@ -18,6 +18,7 @@ MissingDebugHandler base class, and register_handler function.
|
||||
"""
|
||||
|
||||
import gdb
|
||||
+from curses.ascii import isascii, isalnum
|
||||
|
||||
|
||||
def _validate_name(name):
|
||||
@@ -38,7 +39,7 @@ def _validate_name(name):
|
||||
name.
|
||||
"""
|
||||
for ch in name:
|
||||
- if not ch.isascii() or not (ch.isalnum() or ch in "_-"):
|
||||
+ if not isascii(ch) or not (isalnum(ch) or ch in "_-"):
|
||||
raise ValueError("invalid character '%s' in handler name: %s" % (ch, name))
|
||||
|
||||
|
@@ -1,264 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Burgess <aburgess@redhat.com>
|
||||
Date: Sat, 25 Nov 2023 10:35:37 +0000
|
||||
Subject: gdb-rhbz-2232086-cpp-ify-mapped-symtab.patch
|
||||
|
||||
;; Back-port upstream commit acc117b57f7 as part of a fix for
|
||||
;; non-deterministic gdb-index generation (RH BZ 2232086).
|
||||
|
||||
gdb: C++-ify mapped_symtab from dwarf2/index-write.c
|
||||
|
||||
Make static the functions add_index_entry, find_slot, and hash_expand,
|
||||
member functions of the mapped_symtab class.
|
||||
|
||||
Fold an additional snippet of code from write_gdbindex into
|
||||
mapped_symtab::minimize, this code relates to minimisation, so this
|
||||
seems like a good home for it.
|
||||
|
||||
Make the n_elements, data, and m_string_obstack member variables of
|
||||
mapped_symtab private. Provide a new obstack() member function to
|
||||
provide access to the obstack when needed, and also add member
|
||||
functions begin(), end(), cbegin(), and cend() so that the
|
||||
mapped_symtab class can be treated like a contained and iterated
|
||||
over.
|
||||
|
||||
I've also taken this opportunity to split out the logic for whether
|
||||
the hash table (m_data) needs expanding, this is the new function
|
||||
hash_needs_expanding. This will be useful in a later commit.
|
||||
|
||||
There should be no user visible changes after this commit.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
diff --git a/gdb/dwarf2/index-write.c b/gdb/dwarf2/index-write.c
|
||||
--- a/gdb/dwarf2/index-write.c
|
||||
+++ b/gdb/dwarf2/index-write.c
|
||||
@@ -187,86 +187,135 @@ struct mapped_symtab
|
||||
{
|
||||
mapped_symtab ()
|
||||
{
|
||||
- data.resize (1024);
|
||||
+ m_data.resize (1024);
|
||||
}
|
||||
|
||||
- /* Minimize each entry in the symbol table, removing duplicates. */
|
||||
+ /* If there are no elements in the symbol table, then reduce the table
|
||||
+ size to zero. Otherwise call symtab_index_entry::minimize each entry
|
||||
+ in the symbol table. */
|
||||
+
|
||||
void minimize ()
|
||||
{
|
||||
- for (symtab_index_entry &item : data)
|
||||
+ if (m_element_count == 0)
|
||||
+ m_data.resize (0);
|
||||
+
|
||||
+ for (symtab_index_entry &item : m_data)
|
||||
item.minimize ();
|
||||
}
|
||||
|
||||
- offset_type n_elements = 0;
|
||||
- std::vector<symtab_index_entry> data;
|
||||
+ /* Add an entry to SYMTAB. NAME is the name of the symbol. CU_INDEX is
|
||||
+ the index of the CU in which the symbol appears. IS_STATIC is one if
|
||||
+ the symbol is static, otherwise zero (global). */
|
||||
+
|
||||
+ void add_index_entry (const char *name, int is_static,
|
||||
+ gdb_index_symbol_kind kind, offset_type cu_index);
|
||||
+
|
||||
+ /* Access the obstack. */
|
||||
+ struct obstack *obstack ()
|
||||
+ { return &m_string_obstack; }
|
||||
+
|
||||
+private:
|
||||
+
|
||||
+ /* Find a slot in SYMTAB for the symbol NAME. Returns a reference to
|
||||
+ the slot.
|
||||
+
|
||||
+ Function is used only during write_hash_table so no index format
|
||||
+ backward compatibility is needed. */
|
||||
+
|
||||
+ symtab_index_entry &find_slot (const char *name);
|
||||
+
|
||||
+ /* Expand SYMTAB's hash table. */
|
||||
+
|
||||
+ void hash_expand ();
|
||||
+
|
||||
+ /* Return true if the hash table in data needs to grow. */
|
||||
+
|
||||
+ bool hash_needs_expanding () const
|
||||
+ { return 4 * m_element_count / 3 >= m_data.size (); }
|
||||
+
|
||||
+ /* A vector that is used as a hash table. */
|
||||
+ std::vector<symtab_index_entry> m_data;
|
||||
+
|
||||
+ /* The number of elements stored in the m_data hash. */
|
||||
+ offset_type m_element_count = 0;
|
||||
|
||||
/* Temporary storage for names. */
|
||||
auto_obstack m_string_obstack;
|
||||
-};
|
||||
|
||||
-/* Find a slot in SYMTAB for the symbol NAME. Returns a reference to
|
||||
- the slot.
|
||||
+public:
|
||||
+ using iterator = decltype (m_data)::iterator;
|
||||
+ using const_iterator = decltype (m_data)::const_iterator;
|
||||
|
||||
- Function is used only during write_hash_table so no index format backward
|
||||
- compatibility is needed. */
|
||||
+ iterator begin ()
|
||||
+ { return m_data.begin (); }
|
||||
|
||||
-static symtab_index_entry &
|
||||
-find_slot (struct mapped_symtab *symtab, const char *name)
|
||||
+ iterator end ()
|
||||
+ { return m_data.end (); }
|
||||
+
|
||||
+ const_iterator cbegin ()
|
||||
+ { return m_data.cbegin (); }
|
||||
+
|
||||
+ const_iterator cend ()
|
||||
+ { return m_data.cend (); }
|
||||
+};
|
||||
+
|
||||
+/* See class definition. */
|
||||
+
|
||||
+symtab_index_entry &
|
||||
+mapped_symtab::find_slot (const char *name)
|
||||
{
|
||||
offset_type index, step, hash = mapped_index_string_hash (INT_MAX, name);
|
||||
|
||||
- index = hash & (symtab->data.size () - 1);
|
||||
- step = ((hash * 17) & (symtab->data.size () - 1)) | 1;
|
||||
+ index = hash & (m_data.size () - 1);
|
||||
+ step = ((hash * 17) & (m_data.size () - 1)) | 1;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
- if (symtab->data[index].name == NULL
|
||||
- || strcmp (name, symtab->data[index].name) == 0)
|
||||
- return symtab->data[index];
|
||||
- index = (index + step) & (symtab->data.size () - 1);
|
||||
+ if (m_data[index].name == NULL
|
||||
+ || strcmp (name, m_data[index].name) == 0)
|
||||
+ return m_data[index];
|
||||
+ index = (index + step) & (m_data.size () - 1);
|
||||
}
|
||||
}
|
||||
|
||||
-/* Expand SYMTAB's hash table. */
|
||||
+/* See class definition. */
|
||||
|
||||
-static void
|
||||
-hash_expand (struct mapped_symtab *symtab)
|
||||
+void
|
||||
+mapped_symtab::hash_expand ()
|
||||
{
|
||||
- auto old_entries = std::move (symtab->data);
|
||||
+ auto old_entries = std::move (m_data);
|
||||
|
||||
- symtab->data.clear ();
|
||||
- symtab->data.resize (old_entries.size () * 2);
|
||||
+ gdb_assert (m_data.size () == 0);
|
||||
+ m_data.resize (old_entries.size () * 2);
|
||||
|
||||
for (auto &it : old_entries)
|
||||
if (it.name != NULL)
|
||||
{
|
||||
- auto &ref = find_slot (symtab, it.name);
|
||||
+ auto &ref = this->find_slot (it.name);
|
||||
ref = std::move (it);
|
||||
}
|
||||
}
|
||||
|
||||
-/* Add an entry to SYMTAB. NAME is the name of the symbol.
|
||||
- CU_INDEX is the index of the CU in which the symbol appears.
|
||||
- IS_STATIC is one if the symbol is static, otherwise zero (global). */
|
||||
+/* See class definition. */
|
||||
|
||||
-static void
|
||||
-add_index_entry (struct mapped_symtab *symtab, const char *name,
|
||||
- int is_static, gdb_index_symbol_kind kind,
|
||||
- offset_type cu_index)
|
||||
+void
|
||||
+mapped_symtab::add_index_entry (const char *name, int is_static,
|
||||
+ gdb_index_symbol_kind kind,
|
||||
+ offset_type cu_index)
|
||||
{
|
||||
- symtab_index_entry *slot = &find_slot (symtab, name);
|
||||
+ symtab_index_entry *slot = &this->find_slot (name);
|
||||
if (slot->name == NULL)
|
||||
{
|
||||
/* This is a new element in the hash table. */
|
||||
- ++symtab->n_elements;
|
||||
+ ++this->m_element_count;
|
||||
|
||||
/* We might need to grow the hash table. */
|
||||
- if (4 * symtab->n_elements / 3 >= symtab->data.size ())
|
||||
+ if (this->hash_needs_expanding ())
|
||||
{
|
||||
- hash_expand (symtab);
|
||||
+ this->hash_expand ();
|
||||
|
||||
/* This element will have a different slot in the new table. */
|
||||
- slot = &find_slot (symtab, name);
|
||||
+ slot = &this->find_slot (name);
|
||||
|
||||
/* But it should still be a new element in the hash table. */
|
||||
gdb_assert (slot->name == nullptr);
|
||||
@@ -387,7 +436,7 @@ write_hash_table (mapped_symtab *symtab, data_buf &output, data_buf &cpool)
|
||||
|
||||
/* We add all the index vectors to the constant pool first, to
|
||||
ensure alignment is ok. */
|
||||
- for (symtab_index_entry &entry : symtab->data)
|
||||
+ for (symtab_index_entry &entry : *symtab)
|
||||
{
|
||||
if (entry.name == NULL)
|
||||
continue;
|
||||
@@ -416,7 +465,7 @@ write_hash_table (mapped_symtab *symtab, data_buf &output, data_buf &cpool)
|
||||
|
||||
/* Now write out the hash table. */
|
||||
std::unordered_map<c_str_view, offset_type, c_str_view_hasher> str_table;
|
||||
- for (const auto &entry : symtab->data)
|
||||
+ for (const auto &entry : *symtab)
|
||||
{
|
||||
offset_type str_off, vec_off;
|
||||
|
||||
@@ -1151,7 +1200,7 @@ write_cooked_index (cooked_index *table,
|
||||
const auto it = cu_index_htab.find (entry->per_cu);
|
||||
gdb_assert (it != cu_index_htab.cend ());
|
||||
|
||||
- const char *name = entry->full_name (&symtab->m_string_obstack);
|
||||
+ const char *name = entry->full_name (symtab->obstack ());
|
||||
|
||||
if (entry->per_cu->lang () == language_ada)
|
||||
{
|
||||
@@ -1159,7 +1208,7 @@ write_cooked_index (cooked_index *table,
|
||||
gdb, it has to use the encoded name, with any
|
||||
suffixes stripped. */
|
||||
std::string encoded = ada_encode (name, false);
|
||||
- name = obstack_strdup (&symtab->m_string_obstack,
|
||||
+ name = obstack_strdup (symtab->obstack (),
|
||||
encoded.c_str ());
|
||||
}
|
||||
else if (entry->per_cu->lang () == language_cplus
|
||||
@@ -1191,8 +1240,8 @@ write_cooked_index (cooked_index *table,
|
||||
else
|
||||
kind = GDB_INDEX_SYMBOL_KIND_TYPE;
|
||||
|
||||
- add_index_entry (symtab, name, (entry->flags & IS_STATIC) != 0,
|
||||
- kind, it->second);
|
||||
+ symtab->add_index_entry (name, (entry->flags & IS_STATIC) != 0,
|
||||
+ kind, it->second);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1267,8 +1316,6 @@ write_gdbindex (dwarf2_per_bfd *per_bfd, cooked_index *table,
|
||||
symtab.minimize ();
|
||||
|
||||
data_buf symtab_vec, constant_pool;
|
||||
- if (symtab.n_elements == 0)
|
||||
- symtab.data.resize (0);
|
||||
|
||||
write_hash_table (&symtab, symtab_vec, constant_pool);
|
||||
|
@@ -1,101 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Burgess <aburgess@redhat.com>
|
||||
Date: Mon, 27 Nov 2023 13:19:39 +0000
|
||||
Subject: gdb-rhbz-2232086-generate-dwarf-5-index-consistently.patch
|
||||
|
||||
;; Back-port upstream commit 3644f41dc80 as part of a fix for
|
||||
;; non-deterministic gdb-index generation (RH BZ 2232086).
|
||||
|
||||
gdb: generate dwarf-5 index identically as worker-thread count changes
|
||||
|
||||
Similar to the previous commit, this commit ensures that the dwarf-5
|
||||
index files are generated identically as the number of worker-threads
|
||||
changes.
|
||||
|
||||
Building the dwarf-5 index makes use of a closed hash table, the
|
||||
bucket_hash local within debug_names::build(). Entries are added to
|
||||
bucket_hash from m_name_to_value_set, which, in turn, is populated
|
||||
by calls to debug_names::insert() in write_debug_names. The insert
|
||||
calls are ordered based on the entries within the cooked_index, and
|
||||
the ordering within cooked_index depends on the number of worker
|
||||
threads that GDB is using.
|
||||
|
||||
My proposal is to sort each chain within the bucket_hash closed hash
|
||||
table prior to using this to build the dwarf-5 index.
|
||||
|
||||
The buckets within bucket_hash will always have the same ordering (for
|
||||
a given GDB build with a given executable), and by sorting the chains
|
||||
within each bucket, we can be sure that GDB will see each entry in a
|
||||
deterministic order.
|
||||
|
||||
I've extended the index creation test to cover this case.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
diff --git a/gdb/dwarf2/index-write.c b/gdb/dwarf2/index-write.c
|
||||
--- a/gdb/dwarf2/index-write.c
|
||||
+++ b/gdb/dwarf2/index-write.c
|
||||
@@ -452,6 +452,11 @@ class c_str_view
|
||||
return strcmp (m_cstr, other.m_cstr) == 0;
|
||||
}
|
||||
|
||||
+ bool operator< (const c_str_view &other) const
|
||||
+ {
|
||||
+ return strcmp (m_cstr, other.m_cstr) < 0;
|
||||
+ }
|
||||
+
|
||||
/* Return the underlying C string. Note, the returned string is
|
||||
only a reference with lifetime of this object. */
|
||||
const char *c_str () const
|
||||
@@ -771,10 +776,18 @@ class debug_names
|
||||
}
|
||||
for (size_t bucket_ix = 0; bucket_ix < bucket_hash.size (); ++bucket_ix)
|
||||
{
|
||||
- const std::forward_list<hash_it_pair> &hashitlist
|
||||
- = bucket_hash[bucket_ix];
|
||||
+ std::forward_list<hash_it_pair> &hashitlist = bucket_hash[bucket_ix];
|
||||
if (hashitlist.empty ())
|
||||
continue;
|
||||
+
|
||||
+ /* Sort the items within each bucket. This ensures that the
|
||||
+ generated index files will be the same no matter the order in
|
||||
+ which symbols were added into the index. */
|
||||
+ hashitlist.sort ([] (const hash_it_pair &a, const hash_it_pair &b)
|
||||
+ {
|
||||
+ return a.it->first < b.it->first;
|
||||
+ });
|
||||
+
|
||||
uint32_t &bucket_slot = m_bucket_table[bucket_ix];
|
||||
/* The hashes array is indexed starting at 1. */
|
||||
store_unsigned_integer (reinterpret_cast<gdb_byte *> (&bucket_slot),
|
||||
diff --git a/gdb/testsuite/gdb.gdb/index-file.exp b/gdb/testsuite/gdb.gdb/index-file.exp
|
||||
--- a/gdb/testsuite/gdb.gdb/index-file.exp
|
||||
+++ b/gdb/testsuite/gdb.gdb/index-file.exp
|
||||
@@ -47,6 +47,9 @@ remote_exec host "mkdir -p ${dir1}"
|
||||
with_timeout_factor $timeout_factor {
|
||||
gdb_test_no_output "save gdb-index $dir1" \
|
||||
"create gdb-index file"
|
||||
+
|
||||
+ gdb_test_no_output "save gdb-index -dwarf-5 $dir1" \
|
||||
+ "create dwarf-index files"
|
||||
}
|
||||
|
||||
# Close GDB.
|
||||
@@ -143,13 +146,16 @@ if { $worker_threads > 1 } {
|
||||
with_timeout_factor $timeout_factor {
|
||||
gdb_test_no_output "save gdb-index $dir2" \
|
||||
"create second gdb-index file"
|
||||
+
|
||||
+ gdb_test_no_output "save gdb-index -dwarf-5 $dir2" \
|
||||
+ "create second dwarf-index files"
|
||||
}
|
||||
|
||||
# Close GDB.
|
||||
gdb_exit
|
||||
|
||||
# Now check that the index files are identical.
|
||||
- foreach suffix { gdb-index } {
|
||||
+ foreach suffix { gdb-index debug_names debug_str } {
|
||||
set result \
|
||||
[remote_exec host \
|
||||
"cmp -s \"$dir1/${index_filename_base}.${suffix}\" \"$dir2/${index_filename_base}.${suffix}\""]
|
@@ -1,230 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Burgess <aburgess@redhat.com>
|
||||
Date: Fri, 24 Nov 2023 12:04:36 +0000
|
||||
Subject: gdb-rhbz-2232086-generate-gdb-index-consistently.patch
|
||||
|
||||
;; Back-port upstream commit aff250145af as part of a fix for
|
||||
;; non-deterministic gdb-index generation (RH BZ 2232086).
|
||||
|
||||
gdb: generate gdb-index identically regardless of work thread count
|
||||
|
||||
It was observed that changing the number of worker threads that GDB
|
||||
uses (maintenance set worker-threads NUM) would have an impact on the
|
||||
layout of the generated gdb-index.
|
||||
|
||||
The cause seems to be how the CU are distributed between threads, and
|
||||
then symbols that appear in multiple CU can be encountered earlier or
|
||||
later depending on whether a particular CU moves between threads.
|
||||
|
||||
I certainly found this behaviour was reproducible when generating an
|
||||
index for GDB itself, like:
|
||||
|
||||
gdb -q -nx -nh -batch \
|
||||
-eiex 'maint set worker-threads NUM' \
|
||||
-ex 'save gdb-index /tmp/'
|
||||
|
||||
And then setting different values for NUM will change the generated
|
||||
index.
|
||||
|
||||
Now, the question is: does this matter?
|
||||
|
||||
I would like to suggest that yes, this does matter. At Red Hat we
|
||||
generate a gdb-index as part of the build process, and we would
|
||||
ideally like to have reproducible builds: for the same source,
|
||||
compiled with the same tool-chain, we should get the exact same output
|
||||
binary. And we do .... except for the index.
|
||||
|
||||
Now we could simply force GDB to only use a single worker thread when
|
||||
we build the index, but, I don't think the idea of reproducible builds
|
||||
is that strange, so I think we should ensure that our generated
|
||||
indexes are always reproducible.
|
||||
|
||||
To achieve this, I propose that we add an extra step when building the
|
||||
gdb-index file. After constructing the initial symbol hash table
|
||||
contents, we will pull all the symbols out of the hash, sort them,
|
||||
then re-insert them in sorted order. This will ensure that the
|
||||
structure of the generated hash will remain consistent (given the same
|
||||
set of symbols).
|
||||
|
||||
I've extended the existing index-file test to check that the generated
|
||||
index doesn't change if we adjust the number of worker threads used.
|
||||
Given that this test is already rather slow, I've only made one change
|
||||
to the worker-thread count. Maybe this test should be changed to use
|
||||
a smaller binary, which is quicker to load, and for which we could
|
||||
then try many different worker thread counts.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
diff --git a/gdb/dwarf2/index-write.c b/gdb/dwarf2/index-write.c
|
||||
--- a/gdb/dwarf2/index-write.c
|
||||
+++ b/gdb/dwarf2/index-write.c
|
||||
@@ -210,6 +210,13 @@ struct mapped_symtab
|
||||
void add_index_entry (const char *name, int is_static,
|
||||
gdb_index_symbol_kind kind, offset_type cu_index);
|
||||
|
||||
+ /* When entries are originally added into the data hash the order will
|
||||
+ vary based on the number of worker threads GDB is configured to use.
|
||||
+ This function will rebuild the hash such that the final layout will be
|
||||
+ deterministic regardless of the number of worker threads used. */
|
||||
+
|
||||
+ void sort ();
|
||||
+
|
||||
/* Access the obstack. */
|
||||
struct obstack *obstack ()
|
||||
{ return &m_string_obstack; }
|
||||
@@ -296,6 +303,65 @@ mapped_symtab::hash_expand ()
|
||||
}
|
||||
}
|
||||
|
||||
+/* See mapped_symtab class declaration. */
|
||||
+
|
||||
+void mapped_symtab::sort ()
|
||||
+{
|
||||
+ /* Move contents out of this->data vector. */
|
||||
+ std::vector<symtab_index_entry> original_data = std::move (m_data);
|
||||
+
|
||||
+ /* Restore the size of m_data, this will avoid having to expand the hash
|
||||
+ table (and rehash all elements) when we reinsert after sorting.
|
||||
+ However, we do reset the element count, this allows for some sanity
|
||||
+ checking asserts during the reinsert phase. */
|
||||
+ gdb_assert (m_data.size () == 0);
|
||||
+ m_data.resize (original_data.size ());
|
||||
+ m_element_count = 0;
|
||||
+
|
||||
+ /* Remove empty entries from ORIGINAL_DATA, this makes sorting quicker. */
|
||||
+ auto it = std::remove_if (original_data.begin (), original_data.end (),
|
||||
+ [] (const symtab_index_entry &entry) -> bool
|
||||
+ {
|
||||
+ return entry.name == nullptr;
|
||||
+ });
|
||||
+ original_data.erase (it, original_data.end ());
|
||||
+
|
||||
+ /* Sort the existing contents. */
|
||||
+ std::sort (original_data.begin (), original_data.end (),
|
||||
+ [] (const symtab_index_entry &a,
|
||||
+ const symtab_index_entry &b) -> bool
|
||||
+ {
|
||||
+ /* Return true if A is before B. */
|
||||
+ gdb_assert (a.name != nullptr);
|
||||
+ gdb_assert (b.name != nullptr);
|
||||
+
|
||||
+ return strcmp (a.name, b.name) < 0;
|
||||
+ });
|
||||
+
|
||||
+ /* Re-insert each item from the sorted list. */
|
||||
+ for (auto &entry : original_data)
|
||||
+ {
|
||||
+ /* We know that ORIGINAL_DATA contains no duplicates, this data was
|
||||
+ taken from a hash table that de-duplicated entries for us, so
|
||||
+ count this as a new item.
|
||||
+
|
||||
+ As we retained the original size of m_data (see above) then we
|
||||
+ should never need to grow m_data_ during this re-insertion phase,
|
||||
+ assert that now. */
|
||||
+ ++m_element_count;
|
||||
+ gdb_assert (!this->hash_needs_expanding ());
|
||||
+
|
||||
+ /* Lookup a slot. */
|
||||
+ symtab_index_entry &slot = this->find_slot (entry.name);
|
||||
+
|
||||
+ /* As discussed above, we should not find duplicates. */
|
||||
+ gdb_assert (slot.name == nullptr);
|
||||
+
|
||||
+ /* Move this item into the slot we found. */
|
||||
+ slot = std::move (entry);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/* See class definition. */
|
||||
|
||||
void
|
||||
@@ -1311,6 +1377,9 @@ write_gdbindex (dwarf2_per_bfd *per_bfd, cooked_index *table,
|
||||
for (auto map : table->get_addrmaps ())
|
||||
write_address_map (map, addr_vec, cu_index_htab);
|
||||
|
||||
+ /* Ensure symbol hash is built domestically. */
|
||||
+ symtab.sort ();
|
||||
+
|
||||
/* Now that we've processed all symbols we can shrink their cu_indices
|
||||
lists. */
|
||||
symtab.minimize ();
|
||||
diff --git a/gdb/testsuite/gdb.gdb/index-file.exp b/gdb/testsuite/gdb.gdb/index-file.exp
|
||||
--- a/gdb/testsuite/gdb.gdb/index-file.exp
|
||||
+++ b/gdb/testsuite/gdb.gdb/index-file.exp
|
||||
@@ -38,6 +38,9 @@ with_timeout_factor $timeout_factor {
|
||||
clean_restart $filename
|
||||
}
|
||||
|
||||
+# Record how many worker threads GDB is using.
|
||||
+set worker_threads [gdb_get_worker_threads]
|
||||
+
|
||||
# Generate an index file.
|
||||
set dir1 [standard_output_file "index_1"]
|
||||
remote_exec host "mkdir -p ${dir1}"
|
||||
@@ -116,3 +119,41 @@ proc check_symbol_table_usage { filename } {
|
||||
|
||||
set index_filename_base [file tail $filename]
|
||||
check_symbol_table_usage "$dir1/${index_filename_base}.gdb-index"
|
||||
+
|
||||
+# If GDB is using more than 1 worker thread then reduce the number of
|
||||
+# worker threads, regenerate the index, and check that we get the same
|
||||
+# index file back. At one point the layout of the index would vary
|
||||
+# based on the number of worker threads used.
|
||||
+if { $worker_threads > 1 } {
|
||||
+ # Start GDB, but don't load a file yet.
|
||||
+ clean_restart
|
||||
+
|
||||
+ # Adjust the number of threads to use.
|
||||
+ set reduced_threads [expr $worker_threads / 2]
|
||||
+ gdb_test_no_output "maint set worker-threads $reduced_threads"
|
||||
+
|
||||
+ with_timeout_factor $timeout_factor {
|
||||
+ # Now load the test binary.
|
||||
+ gdb_file_cmd $filename
|
||||
+ }
|
||||
+
|
||||
+ # Generate an index file.
|
||||
+ set dir2 [standard_output_file "index_2"]
|
||||
+ remote_exec host "mkdir -p ${dir2}"
|
||||
+ with_timeout_factor $timeout_factor {
|
||||
+ gdb_test_no_output "save gdb-index $dir2" \
|
||||
+ "create second gdb-index file"
|
||||
+ }
|
||||
+
|
||||
+ # Close GDB.
|
||||
+ gdb_exit
|
||||
+
|
||||
+ # Now check that the index files are identical.
|
||||
+ foreach suffix { gdb-index } {
|
||||
+ set result \
|
||||
+ [remote_exec host \
|
||||
+ "cmp -s \"$dir1/${index_filename_base}.${suffix}\" \"$dir2/${index_filename_base}.${suffix}\""]
|
||||
+ gdb_assert { [lindex $result 0] == 0 } \
|
||||
+ "$suffix files are identical"
|
||||
+ }
|
||||
+}
|
||||
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
|
||||
--- a/gdb/testsuite/lib/gdb.exp
|
||||
+++ b/gdb/testsuite/lib/gdb.exp
|
||||
@@ -10033,6 +10033,21 @@ proc is_target_non_stop { {testname ""} } {
|
||||
return $is_non_stop
|
||||
}
|
||||
|
||||
+# Return the number of worker threads that GDB is currently using.
|
||||
+
|
||||
+proc gdb_get_worker_threads { {testname ""} } {
|
||||
+ set worker_threads "UNKNOWN"
|
||||
+ gdb_test_multiple "maintenance show worker-threads" $testname {
|
||||
+ -wrap -re "The number of worker threads GDB can use is unlimited \\(currently ($::decimal)\\)\\." {
|
||||
+ set worker_threads $expect_out(1,string)
|
||||
+ }
|
||||
+ -wrap -re "The number of worker threads GDB can use is ($::decimal)\\." {
|
||||
+ set worker_threads $expect_out(1,string)
|
||||
+ }
|
||||
+ }
|
||||
+ return $worker_threads
|
||||
+}
|
||||
+
|
||||
# Check if the compiler emits epilogue information associated
|
||||
# with the closing brace or with the last statement line.
|
||||
#
|
@@ -1,222 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Burgess <aburgess@redhat.com>
|
||||
Date: Fri, 24 Nov 2023 11:50:35 +0000
|
||||
Subject: gdb-rhbz-2232086-reduce-size-of-gdb-index.patch
|
||||
|
||||
;; Back-port upstream commit aa19bc1d259 as part of a fix for
|
||||
;; non-deterministic gdb-index generation (RH BZ 2232086).
|
||||
|
||||
gdb: reduce size of generated gdb-index file
|
||||
|
||||
I noticed in passing that out algorithm for generating the gdb-index
|
||||
file is incorrect. When building the hash table in add_index_entry we
|
||||
count every incoming entry rehash when the number of entries gets too
|
||||
large. However, some of the incoming entries will be duplicates,
|
||||
which don't actually result in new items being added to the hash
|
||||
table.
|
||||
|
||||
As a result, we grow the gdb-index hash table far too often.
|
||||
|
||||
With an unmodified GDB, generating a gdb-index for GDB, I see a file
|
||||
size of 90M, with a hash usage (in the generated index file) of just
|
||||
2.6%.
|
||||
|
||||
With a patched GDB, generating a gdb-index for the _same_ GDB binary,
|
||||
I now see a gdb-index file size of 30M, with a hash usage of 41.9%.
|
||||
|
||||
This is a 67% reduction in gdb-index file size.
|
||||
|
||||
Obviously, not every gdb-index file is going to see such big savings,
|
||||
however, the larger a program, and the more symbols that are
|
||||
duplicated between compilation units, the more GDB would over count,
|
||||
and so, over-grow the index.
|
||||
|
||||
The gdb-index hash table we create has a minimum size of 1024, and
|
||||
then we grow the hash when it is 75% full, doubling the hash table at
|
||||
that time. Given this, then we expect that either:
|
||||
|
||||
a. The hash table is size 1024, and less than 75% full, or
|
||||
b. The hash table is between 37.5% and 75% full.
|
||||
|
||||
I've include a test that checks some of these constraints -- I've not
|
||||
bothered to check the upper limit, and over full hash table isn't
|
||||
really a problem here, but if the fill percentage is less than 37.5%
|
||||
then this indicates that we've done something wrong (obviously, I also
|
||||
check for the 1024 minimum size).
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
diff --git a/gdb/dwarf2/index-write.c b/gdb/dwarf2/index-write.c
|
||||
--- a/gdb/dwarf2/index-write.c
|
||||
+++ b/gdb/dwarf2/index-write.c
|
||||
@@ -254,20 +254,29 @@ add_index_entry (struct mapped_symtab *symtab, const char *name,
|
||||
int is_static, gdb_index_symbol_kind kind,
|
||||
offset_type cu_index)
|
||||
{
|
||||
- offset_type cu_index_and_attrs;
|
||||
+ symtab_index_entry *slot = &find_slot (symtab, name);
|
||||
+ if (slot->name == NULL)
|
||||
+ {
|
||||
+ /* This is a new element in the hash table. */
|
||||
+ ++symtab->n_elements;
|
||||
|
||||
- ++symtab->n_elements;
|
||||
- if (4 * symtab->n_elements / 3 >= symtab->data.size ())
|
||||
- hash_expand (symtab);
|
||||
+ /* We might need to grow the hash table. */
|
||||
+ if (4 * symtab->n_elements / 3 >= symtab->data.size ())
|
||||
+ {
|
||||
+ hash_expand (symtab);
|
||||
|
||||
- symtab_index_entry &slot = find_slot (symtab, name);
|
||||
- if (slot.name == NULL)
|
||||
- {
|
||||
- slot.name = name;
|
||||
+ /* This element will have a different slot in the new table. */
|
||||
+ slot = &find_slot (symtab, name);
|
||||
+
|
||||
+ /* But it should still be a new element in the hash table. */
|
||||
+ gdb_assert (slot->name == nullptr);
|
||||
+ }
|
||||
+
|
||||
+ slot->name = name;
|
||||
/* index_offset is set later. */
|
||||
}
|
||||
|
||||
- cu_index_and_attrs = 0;
|
||||
+ offset_type cu_index_and_attrs = 0;
|
||||
DW2_GDB_INDEX_CU_SET_VALUE (cu_index_and_attrs, cu_index);
|
||||
DW2_GDB_INDEX_SYMBOL_STATIC_SET_VALUE (cu_index_and_attrs, is_static);
|
||||
DW2_GDB_INDEX_SYMBOL_KIND_SET_VALUE (cu_index_and_attrs, kind);
|
||||
@@ -279,7 +288,7 @@ add_index_entry (struct mapped_symtab *symtab, const char *name,
|
||||
the last entry pushed), but a symbol could have multiple kinds in one CU.
|
||||
To keep things simple we don't worry about the duplication here and
|
||||
sort and uniquify the list after we've processed all symbols. */
|
||||
- slot.cu_indices.push_back (cu_index_and_attrs);
|
||||
+ slot->cu_indices.push_back (cu_index_and_attrs);
|
||||
}
|
||||
|
||||
/* See symtab_index_entry. */
|
||||
diff --git a/gdb/testsuite/gdb.gdb/index-file.exp b/gdb/testsuite/gdb.gdb/index-file.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.gdb/index-file.exp
|
||||
@@ -0,0 +1,118 @@
|
||||
+# Copyright 2023 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/>.
|
||||
+
|
||||
+# Load the GDB executable, and then 'save gdb-index', and make some
|
||||
+# checks of the generated index file.
|
||||
+
|
||||
+load_lib selftest-support.exp
|
||||
+
|
||||
+# Can't save an index with readnow.
|
||||
+if {[readnow]} {
|
||||
+ untested "cannot create an index when readnow is in use"
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+# A multiplier used to ensure slow tasks are less likely to timeout.
|
||||
+set timeout_factor 20
|
||||
+
|
||||
+set filename [selftest_prepare]
|
||||
+if { $filename eq "" } {
|
||||
+ unsupported "${gdb_test_file_name}.exp"
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+with_timeout_factor $timeout_factor {
|
||||
+ # Start GDB, load FILENAME.
|
||||
+ clean_restart $filename
|
||||
+}
|
||||
+
|
||||
+# Generate an index file.
|
||||
+set dir1 [standard_output_file "index_1"]
|
||||
+remote_exec host "mkdir -p ${dir1}"
|
||||
+with_timeout_factor $timeout_factor {
|
||||
+ gdb_test_no_output "save gdb-index $dir1" \
|
||||
+ "create gdb-index file"
|
||||
+}
|
||||
+
|
||||
+# Close GDB.
|
||||
+gdb_exit
|
||||
+
|
||||
+# Validate that the index-file FILENAME has made efficient use of its
|
||||
+# symbol hash table. Calculate the number of symbols in the hash
|
||||
+# table and the total hash table size. The hash table starts with
|
||||
+# 1024 entries, and then doubles each time it is filled to 75%. At
|
||||
+# 75% filled, doubling the size takes it to 37.5% filled.
|
||||
+#
|
||||
+# Thus, the hash table is correctly filled if:
|
||||
+# 1. Its size is 1024 (i.e. it has not yet had its first doubling), or
|
||||
+# 2. Its filled percentage is over 37%
|
||||
+#
|
||||
+# We could check that it is not over filled, but I don't as that's not
|
||||
+# really an issue. But we did once have a bug where the table was
|
||||
+# doubled incorrectly, in which case we'd see a filled percentage of
|
||||
+# around 2% in some cases, which is a huge waste of disk space.
|
||||
+proc check_symbol_table_usage { filename } {
|
||||
+ # Open the file in binary mode and read-only mode.
|
||||
+ set fp [open $filename rb]
|
||||
+
|
||||
+ # Configure the channel to use binary translation.
|
||||
+ fconfigure $fp -translation binary
|
||||
+
|
||||
+ # Read the first 8 bytes of the file, which contain the header of
|
||||
+ # the index section.
|
||||
+ set header [read $fp [expr 7 * 4]]
|
||||
+
|
||||
+ # Scan the header to get the version, the CU list offset, and the
|
||||
+ # types CU list offset.
|
||||
+ binary scan $header iiiiii version \
|
||||
+ _ _ _ symbol_table_offset shortcut_offset
|
||||
+
|
||||
+ # The length of the symbol hash table (in entries).
|
||||
+ set len [expr ($shortcut_offset - $symbol_table_offset) / 8]
|
||||
+
|
||||
+ # Now walk the hash table and count how many entries are in use.
|
||||
+ set offset $symbol_table_offset
|
||||
+ set count 0
|
||||
+ while { $offset < $shortcut_offset } {
|
||||
+ seek $fp $offset
|
||||
+ set entry [read $fp 8]
|
||||
+ binary scan $entry ii name_ptr flags
|
||||
+ if { $name_ptr != 0 } {
|
||||
+ incr count
|
||||
+ }
|
||||
+
|
||||
+ incr offset 8
|
||||
+ }
|
||||
+
|
||||
+ # Close the file.
|
||||
+ close $fp
|
||||
+
|
||||
+ # Calculate how full the cache is.
|
||||
+ set pct [expr (100 * double($count)) / $len]
|
||||
+
|
||||
+ # Write our results out to the gdb.log.
|
||||
+ verbose -log "Hash table size: $len"
|
||||
+ verbose -log "Hash table entries: $count"
|
||||
+ verbose -log "Percentage usage: $pct%"
|
||||
+
|
||||
+ # The minimum fill percentage is actually 37.5%, but we give TCL a
|
||||
+ # little flexibility in case the FP maths give a result a little
|
||||
+ # off.
|
||||
+ gdb_assert { $len == 1024 || $pct > 37 } \
|
||||
+ "symbol hash table usage"
|
||||
+}
|
||||
+
|
||||
+set index_filename_base [file tail $filename]
|
||||
+check_symbol_table_usage "$dir1/${index_filename_base}.gdb-index"
|
@@ -1,77 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Burgess <aburgess@redhat.com>
|
||||
Date: Fri, 24 Nov 2023 11:10:08 +0000
|
||||
Subject: gdb-rhbz2232086-refactor-selftest-support.patch
|
||||
|
||||
;; Back-port upstream commit 1f0fab7ff86 as part of a fix for
|
||||
;; non-deterministic gdb-index generation (RH BZ 2232086).
|
||||
|
||||
gdb/testsuite: small refactor in selftest-support.exp
|
||||
|
||||
Split out the code that makes a copy of the GDB executable ready for
|
||||
self testing into a new proc. A later commit in this series wants to
|
||||
load the GDB executable into GDB (for creating an on-disk debug
|
||||
index), but doesn't need to make use of the full do_self_tests proc.
|
||||
|
||||
There should be no changes in what is tested after this commit.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
diff --git a/gdb/testsuite/lib/selftest-support.exp b/gdb/testsuite/lib/selftest-support.exp
|
||||
--- a/gdb/testsuite/lib/selftest-support.exp
|
||||
+++ b/gdb/testsuite/lib/selftest-support.exp
|
||||
@@ -92,11 +92,13 @@ proc selftest_setup { executable function } {
|
||||
return 0
|
||||
}
|
||||
|
||||
-# A simple way to run some self-tests.
|
||||
-
|
||||
-proc do_self_tests {function body} {
|
||||
- global GDB tool
|
||||
-
|
||||
+# Prepare for running a self-test by moving the GDB executable to a
|
||||
+# location where we can use it as the inferior. Return the filename
|
||||
+# of the new location.
|
||||
+#
|
||||
+# If the current testing setup is not suitable for running a
|
||||
+# self-test, then return an empty string.
|
||||
+proc selftest_prepare {} {
|
||||
# Are we testing with a remote board? In that case, the target
|
||||
# won't have access to the GDB's auxilliary data files
|
||||
# (data-directory, etc.). It's simpler to just skip.
|
||||
@@ -120,19 +122,31 @@ proc do_self_tests {function body} {
|
||||
# Run the test with self. Copy the file executable file in case
|
||||
# this OS doesn't like to edit its own text space.
|
||||
|
||||
- set GDB_FULLPATH [find_gdb $GDB]
|
||||
+ set gdb_fullpath [find_gdb $::GDB]
|
||||
|
||||
if {[is_remote host]} {
|
||||
- set xgdb x$tool
|
||||
+ set xgdb x$::tool
|
||||
} else {
|
||||
- set xgdb [standard_output_file x$tool]
|
||||
+ set xgdb [standard_output_file x$::tool]
|
||||
}
|
||||
|
||||
# Remove any old copy lying around.
|
||||
remote_file host delete $xgdb
|
||||
|
||||
+ set filename [remote_download host $gdb_fullpath $xgdb]
|
||||
+
|
||||
+ return $filename
|
||||
+}
|
||||
+
|
||||
+# A simple way to run some self-tests.
|
||||
+
|
||||
+proc do_self_tests {function body} {
|
||||
+ set file [selftest_prepare]
|
||||
+ if { $file eq "" } {
|
||||
+ return
|
||||
+ }
|
||||
+
|
||||
gdb_start
|
||||
- set file [remote_download host $GDB_FULLPATH $xgdb]
|
||||
|
||||
# When debugging GDB with GDB, some operations can take a relatively long
|
||||
# time, especially if the build is non-optimized. Bump the timeout for the
|
@@ -1,48 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Alexandra=20H=C3=A1jkov=C3=A1?= <ahajkova@redhat.com>
|
||||
Date: Mon, 8 Jan 2024 13:24:05 +0100
|
||||
Subject: gdb-rhbz2250652-avoid-PyOS_ReadlineTState.patch
|
||||
|
||||
gdb/python: avoid use of _PyOS_ReadlineTState
|
||||
|
||||
In python/py-gdb-readline.c we make use of _PyOS_ReadlineTState,
|
||||
however, this variable is no longer public in Python 3.13, and so GDB
|
||||
no longer builds.
|
||||
|
||||
We are making use of _PyOS_ReadlineTState in order to re-acquire the
|
||||
Python Global Interpreter Lock (GIL). The _PyOS_ReadlineTState
|
||||
variable is set in Python's outer readline code prior to calling the
|
||||
user (GDB) supplied readline callback function, which for us is
|
||||
gdbpy_readline_wrapper. The gdbpy_readline_wrapper function is called
|
||||
without the GIL held.
|
||||
|
||||
Instead of using _PyOS_ReadlineTState, I propose that we switch to
|
||||
calling PyGILState_Ensure() and PyGILState_Release(). These functions
|
||||
will acquire the GIL based on the current thread. I think this should
|
||||
be sufficient; I can't imagine why we'd be running
|
||||
gdbpy_readline_wrapper on one thread on behalf of a different Python
|
||||
thread.... that would be unexpected I think.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
diff --git a/gdb/python/py-gdb-readline.c b/gdb/python/py-gdb-readline.c
|
||||
--- a/gdb/python/py-gdb-readline.c
|
||||
+++ b/gdb/python/py-gdb-readline.c
|
||||
@@ -56,13 +56,11 @@ gdbpy_readline_wrapper (FILE *sys_stdin, FILE *sys_stdout,
|
||||
if (except.reason == RETURN_QUIT)
|
||||
return NULL;
|
||||
|
||||
- /* The thread state is nulled during gdbpy_readline_wrapper,
|
||||
- with the original value saved in the following undocumented
|
||||
- variable (see Python's Parser/myreadline.c and
|
||||
- Modules/readline.c). */
|
||||
- PyEval_RestoreThread (_PyOS_ReadlineTState);
|
||||
+
|
||||
+ /* This readline callback is called without the GIL held. */
|
||||
+ gdbpy_gil gil;
|
||||
+
|
||||
gdbpy_convert_exception (except);
|
||||
- PyEval_SaveThread ();
|
||||
return NULL;
|
||||
}
|
||||
|
@@ -1,81 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Alexandra=20H=C3=A1jkov=C3=A1?= <ahajkova@redhat.com>
|
||||
Date: Mon, 8 Jan 2024 13:12:15 +0100
|
||||
Subject: gdb-rhbz2250652-gdbpy_gil.patch
|
||||
|
||||
gdb: move gdbpy_gil into python-internal.h
|
||||
|
||||
Move gdbpy_gil class into python-internal.h, the next
|
||||
commit wants to make use of this class from a file other
|
||||
than python.c.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
|
||||
--- a/gdb/python/python-internal.h
|
||||
+++ b/gdb/python/python-internal.h
|
||||
@@ -754,6 +754,30 @@ class gdbpy_allow_threads
|
||||
PyThreadState *m_save;
|
||||
};
|
||||
|
||||
+/* A helper class to save and restore the GIL, but without touching
|
||||
+ the other globals that are handled by gdbpy_enter. */
|
||||
+
|
||||
+class gdbpy_gil
|
||||
+{
|
||||
+public:
|
||||
+
|
||||
+ gdbpy_gil ()
|
||||
+ : m_state (PyGILState_Ensure ())
|
||||
+ {
|
||||
+ }
|
||||
+
|
||||
+ ~gdbpy_gil ()
|
||||
+ {
|
||||
+ PyGILState_Release (m_state);
|
||||
+ }
|
||||
+
|
||||
+ DISABLE_COPY_AND_ASSIGN (gdbpy_gil);
|
||||
+
|
||||
+private:
|
||||
+
|
||||
+ PyGILState_STATE m_state;
|
||||
+};
|
||||
+
|
||||
/* Use this after a TRY_EXCEPT to throw the appropriate Python
|
||||
exception. */
|
||||
#define GDB_PY_HANDLE_EXCEPTION(Exception) \
|
||||
diff --git a/gdb/python/python.c b/gdb/python/python.c
|
||||
--- a/gdb/python/python.c
|
||||
+++ b/gdb/python/python.c
|
||||
@@ -257,30 +257,6 @@ gdbpy_enter::finalize ()
|
||||
python_gdbarch = target_gdbarch ();
|
||||
}
|
||||
|
||||
-/* A helper class to save and restore the GIL, but without touching
|
||||
- the other globals that are handled by gdbpy_enter. */
|
||||
-
|
||||
-class gdbpy_gil
|
||||
-{
|
||||
-public:
|
||||
-
|
||||
- gdbpy_gil ()
|
||||
- : m_state (PyGILState_Ensure ())
|
||||
- {
|
||||
- }
|
||||
-
|
||||
- ~gdbpy_gil ()
|
||||
- {
|
||||
- PyGILState_Release (m_state);
|
||||
- }
|
||||
-
|
||||
- DISABLE_COPY_AND_ASSIGN (gdbpy_gil);
|
||||
-
|
||||
-private:
|
||||
-
|
||||
- PyGILState_STATE m_state;
|
||||
-};
|
||||
-
|
||||
/* Set the quit flag. */
|
||||
|
||||
static void
|
@@ -1,55 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Buettner <kevinb@redhat.com>
|
||||
Date: Mon, 29 Jan 2024 14:51:22 -0700
|
||||
Subject: gdb-rhbz2261580-intrusive_list-assertion-fix.patch
|
||||
|
||||
;; Backport upstream workaround for GCC 14 problem which cause assertion
|
||||
;; failures in GDB.
|
||||
|
||||
[gdb/build] Workaround gcc PR113599
|
||||
|
||||
Since gcc commit d3f48f68227 ("c++: non-dependent .* operand folding
|
||||
[PR112427]"), with gdb we run into PR gcc/113599 [1], a wrong-code bug, as
|
||||
reported in PR build/31281.
|
||||
|
||||
Work around this by flipping inherit order:
|
||||
...
|
||||
-class thread_info : public refcounted_object,
|
||||
- public intrusive_list_node<thread_info>
|
||||
+class thread_info : public intrusive_list_node<thread_info>,
|
||||
+ public refcounted_object
|
||||
...
|
||||
|
||||
An argument could be made that this isn't necessary, because this occurred in
|
||||
an unreleased gcc version.
|
||||
|
||||
However, I think it could be useful when bisecting gcc for other problems in
|
||||
building gdb. Having this workaround means the bisect won't reintroduce the
|
||||
problem. Furthermore, the workaround is harmless.
|
||||
|
||||
Tested on Fedora rawhide x86_64.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31281
|
||||
|
||||
[1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113599
|
||||
|
||||
diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
|
||||
--- a/gdb/gdbthread.h
|
||||
+++ b/gdb/gdbthread.h
|
||||
@@ -242,10 +242,11 @@ using private_thread_info_up = std::unique_ptr<private_thread_info>;
|
||||
strong reference, and is thus not accounted for in the thread's
|
||||
refcount.
|
||||
|
||||
- The intrusive_list_node base links threads in a per-inferior list. */
|
||||
+ The intrusive_list_node base links threads in a per-inferior list.
|
||||
+ We place it first in the inherit order to work around PR gcc/113599. */
|
||||
|
||||
-class thread_info : public refcounted_object,
|
||||
- public intrusive_list_node<thread_info>
|
||||
+class thread_info : public intrusive_list_node<thread_info>,
|
||||
+ public refcounted_object
|
||||
{
|
||||
public:
|
||||
explicit thread_info (inferior *inf, ptid_t ptid);
|
File diff suppressed because it is too large
Load Diff
@@ -1,149 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Tom Tromey <tom@tromey.com>
|
||||
Date: Mon, 23 Oct 2023 16:44:53 -0600
|
||||
Subject: gdb-rhel2295897-pre-read-DWZ-file-in-DWARF-reader.patch
|
||||
|
||||
;; backport of upstream commit 91874afabcd
|
||||
;; This (somehow) solves a double-free when reading minimal symbols
|
||||
|
||||
Pre-read DWZ file in DWARF reader
|
||||
|
||||
While working on background reading of DWARF, I came across the
|
||||
DWZ-reading code. This code can query the user (via the debuginfod
|
||||
support) -- something that cannot be done off the main thread.
|
||||
|
||||
Looking into it, I realized that this code can be run much earlier,
|
||||
avoiding this problem. Digging a bit deeper, I also found a
|
||||
discrepancy here between how the DWARF reader works in "readnow" mode
|
||||
as compared to the normal modes.
|
||||
|
||||
This patch cleans this up by trying to read the DWZ file earlier, and
|
||||
also by having the DWARF reader convert any exception here into a
|
||||
warning. This unifies the various cases, but also makes it so that
|
||||
errors do not prevent gdb from continuing on to the extent possible.
|
||||
|
||||
Regression tested on x86-64 Fedora 38.
|
||||
|
||||
diff --git a/gdb/dwarf2/dwz.c b/gdb/dwarf2/dwz.c
|
||||
--- a/gdb/dwarf2/dwz.c
|
||||
+++ b/gdb/dwarf2/dwz.c
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "gdbcore.h"
|
||||
#include "gdbsupport/pathstuff.h"
|
||||
#include "gdbsupport/scoped_fd.h"
|
||||
+#include "run-on-main-thread.h"
|
||||
|
||||
const char *
|
||||
dwz_file::read_string (struct objfile *objfile, LONGEST str_offset)
|
||||
@@ -196,8 +197,20 @@ dwarf2_get_dwz_file (dwarf2_per_bfd *per_bfd, bool require)
|
||||
size_t buildid_len;
|
||||
bfd_byte *buildid;
|
||||
|
||||
- if (per_bfd->dwz_file != NULL)
|
||||
- return per_bfd->dwz_file.get ();
|
||||
+ if (per_bfd->dwz_file.has_value ())
|
||||
+ {
|
||||
+ dwz_file *result = per_bfd->dwz_file->get ();
|
||||
+ if (require && result == nullptr)
|
||||
+ error (_("could not read '.gnu_debugaltlink' section"));
|
||||
+ return result;
|
||||
+ }
|
||||
+
|
||||
+ /* This may query the user via the debuginfod support, so it may
|
||||
+ only be run in the main thread. */
|
||||
+ gdb_assert (is_main_thread ());
|
||||
+
|
||||
+ /* Set this early, so that on error it remains NULL. */
|
||||
+ per_bfd->dwz_file.emplace (nullptr);
|
||||
|
||||
bfd_set_error (bfd_error_no_error);
|
||||
gdb::unique_xmalloc_ptr<char> data
|
||||
@@ -283,5 +296,5 @@ dwarf2_get_dwz_file (dwarf2_per_bfd *per_bfd, bool require)
|
||||
|
||||
gdb_bfd_record_inclusion (per_bfd->obfd, result->dwz_bfd.get ());
|
||||
per_bfd->dwz_file = std::move (result);
|
||||
- return per_bfd->dwz_file.get ();
|
||||
+ return per_bfd->dwz_file->get ();
|
||||
}
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -3387,6 +3387,17 @@ dwarf2_initialize_objfile (struct objfile *objfile)
|
||||
|
||||
dwarf_read_debug_printf ("called");
|
||||
|
||||
+ /* Try to fetch any potential dwz file early, while still on the
|
||||
+ main thread. */
|
||||
+ try
|
||||
+ {
|
||||
+ dwarf2_get_dwz_file (per_bfd);
|
||||
+ }
|
||||
+ catch (const gdb_exception_error &err)
|
||||
+ {
|
||||
+ warning (_("%s"), err.what ());
|
||||
+ }
|
||||
+
|
||||
/* If we're about to read full symbols, don't bother with the
|
||||
indices. In this case we also don't care if some other debug
|
||||
format is making psymtabs, because they are all about to be
|
||||
@@ -5294,16 +5305,7 @@ create_all_units (dwarf2_per_objfile *per_objfile)
|
||||
&per_objfile->per_bfd->abbrev, 0,
|
||||
types_htab, rcuh_kind::TYPE);
|
||||
|
||||
- dwz_file *dwz;
|
||||
- try
|
||||
- {
|
||||
- dwz = dwarf2_get_dwz_file (per_objfile->per_bfd);
|
||||
- }
|
||||
- catch (const gdb_exception_error &)
|
||||
- {
|
||||
- per_objfile->per_bfd->all_units.clear ();
|
||||
- throw;
|
||||
- }
|
||||
+ dwz_file *dwz = dwarf2_get_dwz_file (per_objfile->per_bfd);
|
||||
if (dwz != NULL)
|
||||
{
|
||||
/* Pre-read the sections we'll need to construct an index. */
|
||||
diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h
|
||||
--- a/gdb/dwarf2/read.h
|
||||
+++ b/gdb/dwarf2/read.h
|
||||
@@ -520,7 +520,7 @@ struct dwarf2_per_bfd
|
||||
|
||||
/* The shared '.dwz' file, if one exists. This is used when the
|
||||
original data was compressed using 'dwz -m'. */
|
||||
- std::unique_ptr<struct dwz_file> dwz_file;
|
||||
+ gdb::optional<std::unique_ptr<struct dwz_file>> dwz_file;
|
||||
|
||||
/* Whether copy relocations are supported by this object format. */
|
||||
bool can_copy;
|
||||
diff --git a/gdb/testsuite/gdb.dwarf2/dwzbuildid.exp b/gdb/testsuite/gdb.dwarf2/dwzbuildid.exp
|
||||
--- a/gdb/testsuite/gdb.dwarf2/dwzbuildid.exp
|
||||
+++ b/gdb/testsuite/gdb.dwarf2/dwzbuildid.exp
|
||||
@@ -142,13 +142,6 @@ proc do_test {} {
|
||||
|
||||
gdb_load ${::binfile}-${::testname}
|
||||
|
||||
- if { $::testname == "mismatch" && [readnow] } {
|
||||
- # Main is found in the minimal symbols. When using readnow, a
|
||||
- # failure to read the dwarf also causes the minimal symbols to be
|
||||
- # unavailable.
|
||||
- # Setup a kfail for "FAIL: gdb_breakpoint: set breakpoint at main".
|
||||
- setup_kfail "symtab/26797" *-*-*
|
||||
- }
|
||||
if {![runto_main]} {
|
||||
return
|
||||
}
|
||||
diff --git a/gdb/testsuite/gdb.dwarf2/no-gnu-debuglink.exp b/gdb/testsuite/gdb.dwarf2/no-gnu-debuglink.exp
|
||||
--- a/gdb/testsuite/gdb.dwarf2/no-gnu-debuglink.exp
|
||||
+++ b/gdb/testsuite/gdb.dwarf2/no-gnu-debuglink.exp
|
||||
@@ -37,8 +37,8 @@ if { [build_executable $testfile.exp $testfile [list $srcfile $asm_file]] } {
|
||||
|
||||
clean_restart
|
||||
|
||||
-set msg "\r\ncould not find '\.gnu_debugaltlink' file for \[^\r\n\]*"
|
||||
+set msg "\r\nwarning: could not find '\.gnu_debugaltlink' file for \[^\r\n\]*"
|
||||
gdb_test "file $binfile" "$msg" "file command"
|
||||
|
||||
set question "Load new symbol table from .*\? .y or n. "
|
||||
-gdb_test "file $binfile" "$msg" "file command, again" $question "y"
|
||||
+gdb_test "file $binfile" "" "file command, again" $question "y"
|
@@ -1,50 +0,0 @@
|
||||
From 6cfb7bf81be3ab6f131dbc6a27eefca516cf7517 Mon Sep 17 00:00:00 2001
|
||||
From: Andreas Arnez <arnez@linux.ibm.com>
|
||||
Date: Tue, 13 Feb 2024 18:55:29 +0100
|
||||
Subject: [PATCH 2/2] gdb: s390: Add arch14 record/replay support
|
||||
|
||||
Enable recording of the new "arch14" instructions on z/Architecture
|
||||
targets, except for the specialized-function-assist instruction NNPA.
|
||||
---
|
||||
gdb/s390-tdep.c | 13 +++++++++++++
|
||||
1 file changed, 13 insertions(+)
|
||||
|
||||
diff --git a/gdb/s390-tdep.c b/gdb/s390-tdep.c
|
||||
index 54b5c89e5e3..dcac407caef 100644
|
||||
--- a/gdb/s390-tdep.c
|
||||
+++ b/gdb/s390-tdep.c
|
||||
@@ -5534,6 +5534,14 @@ s390_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
|
||||
case 0xe635: /* VLRL - vector load rightmost with immed. length */
|
||||
case 0xe637: /* VLRLR - vector load rightmost with length */
|
||||
case 0xe649: /* VLIP - vector load immediate decimal */
|
||||
+ case 0xe656: /* VCLFNH - vector fp convert and lengthen from NNP high */
|
||||
+ case 0xe65e: /* VCLFNL - vector fp convert and lengthen from NNP low */
|
||||
+ case 0xe655: /* VCNF - vector fp convert to NNP */
|
||||
+ case 0xe65d: /* VCFN - vector fp convert from NNP */
|
||||
+ case 0xe674: /* VSCHP - decimal scale and convert to HFP */
|
||||
+ case 0xe675: /* VCRNF - vector fp convert and round to NNP */
|
||||
+ case 0xe67c: /* VSCSHP - decimal scale and convert and split to HFP */
|
||||
+ case 0xe67d: /* VCSPH - vector convert HFP to scaled decimal */
|
||||
case 0xe700: /* VLEB - vector load element */
|
||||
case 0xe701: /* VLEH - vector load element */
|
||||
case 0xe702: /* VLEG - vector load element */
|
||||
@@ -5791,11 +5799,16 @@ s390_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
|
||||
|
||||
/* 0xe747-0xe749 undefined */
|
||||
|
||||
+ case 0xe651: /* VCLZDP - vector count leading zero digits */
|
||||
+ case 0xe654: /* VUPKZH - vector unpack zoned high */
|
||||
case 0xe658: /* VCVD - vector convert to decimal 32 bit */
|
||||
case 0xe659: /* VSRP - vector shift and round decimal */
|
||||
case 0xe65a: /* VCVDG - vector convert to decimal 64 bit*/
|
||||
case 0xe65b: /* VPSOP - vector perform sign operation decimal */
|
||||
+ case 0xe65c: /* VUPKZL - vector unpack zoned low */
|
||||
+ case 0xe670: /* VPKZR - vector pack zoned register */
|
||||
case 0xe671: /* VAP - vector add decimal */
|
||||
+ case 0xe672: /* VSRPR - vector shift and round decimal register */
|
||||
case 0xe673: /* VSP - vector subtract decimal */
|
||||
case 0xe678: /* VMP - vector multiply decimal */
|
||||
case 0xe679: /* VMSP - vector multiply decimal */
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,125 +0,0 @@
|
||||
From aa8ba17b9a3fdfeeb65df4c3e0731a0e9e96cbf7 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Wed, 1 Nov 2023 00:33:12 +0100
|
||||
Subject: [PATCH 1/2] [gdb/symtab] Add producer_is_gas
|
||||
|
||||
Add producer_is_gas, a generic way to get the gas version from the
|
||||
producer string.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
---
|
||||
gdb/dwarf2/read.c | 4 ++--
|
||||
gdb/producer.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++
|
||||
gdb/producer.h | 5 +++++
|
||||
3 files changed, 63 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index 970dd54c7a5..472684a5817 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -13376,8 +13376,8 @@ check_producer (struct dwarf2_cu *cu)
|
||||
cu->producer_is_codewarrior = true;
|
||||
else if (producer_is_clang (cu->producer, &major, &minor))
|
||||
cu->producer_is_clang = true;
|
||||
- else if (startswith (cu->producer, "GNU AS 2.39.0"))
|
||||
- cu->producer_is_gas_2_39 = true;
|
||||
+ else if (producer_is_gas (cu->producer, &major, &minor))
|
||||
+ cu->producer_is_gas_2_39 = major == 2 && minor == 39;
|
||||
else
|
||||
{
|
||||
/* For other non-GCC compilers, expect their behavior is DWARF version
|
||||
diff --git a/gdb/producer.c b/gdb/producer.c
|
||||
index 9fcf749e3d4..cd83dfce128 100644
|
||||
--- a/gdb/producer.c
|
||||
+++ b/gdb/producer.c
|
||||
@@ -81,6 +81,45 @@ producer_is_gcc (const char *producer, int *major, int *minor)
|
||||
|
||||
/* See producer.h. */
|
||||
|
||||
+bool
|
||||
+producer_is_gas (const char *producer, int *major, int *minor)
|
||||
+{
|
||||
+ if (producer == nullptr)
|
||||
+ {
|
||||
+ /* No producer, don't know. */
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ /* Detect prefix. */
|
||||
+ const char prefix[] = "GNU AS ";
|
||||
+ if (!startswith (producer, prefix))
|
||||
+ {
|
||||
+ /* Producer is not gas. */
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ /* Skip prefix. */
|
||||
+ const char *cs = &producer[strlen (prefix)];
|
||||
+
|
||||
+ /* Ensure that major/minor are not nullptrs. */
|
||||
+ int maj, min;
|
||||
+ if (major == nullptr)
|
||||
+ major = &maj;
|
||||
+ if (minor == nullptr)
|
||||
+ minor = &min;
|
||||
+
|
||||
+ int scanned = sscanf (cs, "%d.%d", major, minor);
|
||||
+ if (scanned != 2)
|
||||
+ {
|
||||
+ /* Unable to scan major/minor version. */
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+ /* See producer.h. */
|
||||
+
|
||||
bool
|
||||
producer_is_icc_ge_19 (const char *producer)
|
||||
{
|
||||
@@ -251,6 +290,23 @@ Version 18.0 Beta";
|
||||
SELF_CHECK (!producer_is_gcc (flang_llvm_exp, &major, &minor));
|
||||
SELF_CHECK (producer_is_llvm (flang_llvm_exp));
|
||||
}
|
||||
+
|
||||
+ {
|
||||
+ static const char gas_exp[] = "GNU AS 2.39.0";
|
||||
+ int major = 0, minor = 0;
|
||||
+ SELF_CHECK (!producer_is_gcc (gas_exp, &major, &minor));
|
||||
+ SELF_CHECK (producer_is_gas (gas_exp, &major, &minor));
|
||||
+ SELF_CHECK (major == 2 && minor == 39);
|
||||
+
|
||||
+ static const char gas_incomplete_exp[] = "GNU AS ";
|
||||
+ SELF_CHECK (!producer_is_gas (gas_incomplete_exp, &major, &minor));
|
||||
+ SELF_CHECK (!producer_is_gcc (gas_incomplete_exp, &major, &minor));
|
||||
+
|
||||
+ static const char gas_incomplete_exp_2[] = "GNU AS 2";
|
||||
+ SELF_CHECK (!producer_is_gas (gas_incomplete_exp_2, &major, &minor));
|
||||
+ SELF_CHECK (!producer_is_gcc (gas_incomplete_exp_2, &major, &minor));
|
||||
+ }
|
||||
+
|
||||
}
|
||||
}
|
||||
}
|
||||
diff --git a/gdb/producer.h b/gdb/producer.h
|
||||
index c915979b122..00718511775 100644
|
||||
--- a/gdb/producer.h
|
||||
+++ b/gdb/producer.h
|
||||
@@ -30,6 +30,11 @@ extern int producer_is_gcc_ge_4 (const char *producer);
|
||||
is NULL or it isn't GCC. */
|
||||
extern int producer_is_gcc (const char *producer, int *major, int *minor);
|
||||
|
||||
+/* Returns nonzero if the given PRODUCER string is GAS and sets the MAJOR
|
||||
+ and MINOR versions when not NULL. Returns zero if the given PRODUCER
|
||||
+ is NULL or it isn't GAS. */
|
||||
+bool producer_is_gas (const char *producer, int *major, int *minor);
|
||||
+
|
||||
/* Check for Intel compilers >= 19.0. */
|
||||
extern bool producer_is_icc_ge_19 (const char *producer);
|
||||
|
||||
|
||||
base-commit: 39553c1e285c426946188ec2a890c1c1cb933060
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,74 +0,0 @@
|
||||
From 0218e033b415df76be0a14871447bbd94dce62a3 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Sat, 16 Sep 2023 04:07:22 +0200
|
||||
Subject: [PATCH 10/13] [gdb/symtab] Don't defer backward refs, inter-cu
|
||||
intra-shard case
|
||||
|
||||
In patch "[gdb/symtab] Resolve deferred entries, inter-shard case" we've
|
||||
solved the generic case of handling deferred entries.
|
||||
|
||||
Add an optimization that doesn't defer inter-CU intra-shard dependencies that
|
||||
are present in the shard's parent map.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
---
|
||||
gdb/dwarf2/read.c | 29 ++++++++++++++++++++++++++++-
|
||||
1 file changed, 28 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index a97f738a54e..e7904532434 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -4709,6 +4709,12 @@ class cooked_index_storage
|
||||
m_index->set_parent_valid (start, end);
|
||||
}
|
||||
|
||||
+ /* Return true if find_parents can be relied upon. */
|
||||
+ bool parent_valid (CORE_ADDR addr)
|
||||
+ {
|
||||
+ return m_index->parent_valid (addr);
|
||||
+ }
|
||||
+
|
||||
private:
|
||||
|
||||
/* Hash function for a cutu_reader. */
|
||||
@@ -4857,6 +4863,12 @@ class cooked_indexer
|
||||
{
|
||||
m_index_storage->set_parent_valid (start, end);
|
||||
}
|
||||
+
|
||||
+ /* Return true if find_parents can be relied upon. */
|
||||
+ bool parent_valid (CORE_ADDR addr)
|
||||
+ {
|
||||
+ return m_index_storage->parent_valid (addr);
|
||||
+ }
|
||||
};
|
||||
|
||||
/* Subroutine of dwarf2_build_psymtabs_hard to simplify it.
|
||||
@@ -16482,7 +16494,22 @@ cooked_indexer::scan_attributes (dwarf2_per_cu_data *scanning_per_cu,
|
||||
else
|
||||
{
|
||||
/* Inter-CU case. */
|
||||
- *maybe_defer = addr;
|
||||
+ if (parent_valid (addr))
|
||||
+ {
|
||||
+ auto tmp = find_parent (addr);
|
||||
+ if (tmp == &parent_map::deferred)
|
||||
+ {
|
||||
+ /* Defer because origin is deferred. */
|
||||
+ *maybe_defer = addr;
|
||||
+ }
|
||||
+ else
|
||||
+ *parent_entry = tmp;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /* Defer because origin is in other shard. */
|
||||
+ *maybe_defer = addr;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,76 +0,0 @@
|
||||
From 8a444a93d4bd78355fc4e6ecb1935cc2b0a6a997 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Fri, 15 Sep 2023 08:38:00 +0200
|
||||
Subject: [PATCH 04/13] [gdb/symtab] Factor out m_deferred_entries usage
|
||||
|
||||
Factor out usage of cooked_indexer::m_deferred_entries in new member
|
||||
functions defer_entry, handle_deferred_entries and resolve_deferred_entry.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
---
|
||||
gdb/dwarf2/read.c | 35 ++++++++++++++++++++++++++++-------
|
||||
1 file changed, 28 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index d48f3010063..afdf9e870a8 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -4822,6 +4822,32 @@ class cooked_indexer
|
||||
we'll know the containing context of all the DIEs that we might
|
||||
have scanned. This vector stores these deferred entries. */
|
||||
std::vector<deferred_entry> m_deferred_entries;
|
||||
+
|
||||
+ /* Defer creating a cooked_index_entry corresponding to deferred_entry DE. */
|
||||
+ void defer_entry (const deferred_entry &de)
|
||||
+ {
|
||||
+ m_deferred_entries.push_back (de);
|
||||
+ }
|
||||
+
|
||||
+ /* Create a cooked_index_entry corresponding to deferred_entry DE with
|
||||
+ parent PARENT_ENTRY. */
|
||||
+ const cooked_index_entry *resolve_deferred_entry
|
||||
+ (const deferred_entry &de, const cooked_index_entry *parent_entry)
|
||||
+ {
|
||||
+ return m_index_storage->add (de.die_offset, de.tag, de.flags, de.name,
|
||||
+ parent_entry, m_per_cu);
|
||||
+ }
|
||||
+
|
||||
+ /* Create cooked_index_entries for the deferred entries. */
|
||||
+ void handle_deferred_entries ()
|
||||
+ {
|
||||
+ for (const auto &entry : m_deferred_entries)
|
||||
+ {
|
||||
+ const cooked_index_entry *parent_entry
|
||||
+ = find_parent (entry.spec_offset);
|
||||
+ resolve_deferred_entry (entry, parent_entry);
|
||||
+ }
|
||||
+ }
|
||||
};
|
||||
|
||||
/* Subroutine of dwarf2_build_psymtabs_hard to simplify it.
|
||||
@@ -16611,7 +16637,7 @@ cooked_indexer::index_dies (cutu_reader *reader,
|
||||
if (name != nullptr)
|
||||
{
|
||||
if (defer != 0)
|
||||
- m_deferred_entries.push_back ({
|
||||
+ defer_entry ({
|
||||
this_die, name, defer, abbrev->tag, flags
|
||||
});
|
||||
else
|
||||
@@ -16716,12 +16742,7 @@ cooked_indexer::make_index (cutu_reader *reader)
|
||||
return;
|
||||
index_dies (reader, reader->info_ptr, nullptr, false);
|
||||
|
||||
- for (const auto &entry : m_deferred_entries)
|
||||
- {
|
||||
- const cooked_index_entry *parent = find_parent (entry.spec_offset);
|
||||
- m_index_storage->add (entry.die_offset, entry.tag, entry.flags,
|
||||
- entry.name, parent, m_per_cu);
|
||||
- }
|
||||
+ handle_deferred_entries ();
|
||||
}
|
||||
|
||||
/* An implementation of quick_symbol_functions for the cooked DWARF
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,151 +0,0 @@
|
||||
From b2f260d117dc11b8e90d4e9bf7f4b2cbd63d1d49 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Tue, 22 Aug 2023 13:17:47 +0200
|
||||
Subject: [PATCH 02/13] [gdb/symtab] Factor out m_die_range_map usage
|
||||
|
||||
Factor out usage of cooked_indexer::m_die_range_map into new class parent_map
|
||||
with member functions find_parent and set_parent, and static member function
|
||||
form_addr.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
---
|
||||
gdb/dwarf2/cooked-index.h | 32 +++++++++++++++++++++++++++
|
||||
gdb/dwarf2/read.c | 46 ++++++++++++++++++++-------------------
|
||||
2 files changed, 56 insertions(+), 22 deletions(-)
|
||||
|
||||
diff --git a/gdb/dwarf2/cooked-index.h b/gdb/dwarf2/cooked-index.h
|
||||
index 5aacb321c91..979541fbf60 100644
|
||||
--- a/gdb/dwarf2/cooked-index.h
|
||||
+++ b/gdb/dwarf2/cooked-index.h
|
||||
@@ -239,6 +239,38 @@ struct cooked_index_entry : public allocate_on_obstack
|
||||
bool for_name) const;
|
||||
};
|
||||
|
||||
+class parent_map
|
||||
+{
|
||||
+public:
|
||||
+ /* A helper function to turn a section offset into an address that
|
||||
+ can be used in a parent_map. */
|
||||
+ static CORE_ADDR form_addr (sect_offset offset, bool is_dwz)
|
||||
+ {
|
||||
+ CORE_ADDR value = to_underlying (offset);
|
||||
+ if (is_dwz)
|
||||
+ value |= ((CORE_ADDR) 1) << (8 * sizeof (CORE_ADDR) - 1);
|
||||
+ return value;
|
||||
+ }
|
||||
+
|
||||
+ /* Find the parent of DIE LOOKUP. */
|
||||
+ const cooked_index_entry *find_parent (CORE_ADDR lookup) const
|
||||
+ {
|
||||
+ const void *obj = m_parent_map.find (lookup);
|
||||
+ return static_cast<const cooked_index_entry *> (obj);
|
||||
+ }
|
||||
+
|
||||
+ /* Set the parent of DIES in range [START, END] to PARENT_ENTRY. */
|
||||
+ void set_parent (CORE_ADDR start, CORE_ADDR end,
|
||||
+ const cooked_index_entry *parent_entry)
|
||||
+ {
|
||||
+ m_parent_map.set_empty (start, end, (void *)parent_entry);
|
||||
+ }
|
||||
+
|
||||
+private:
|
||||
+ /* An addrmap that maps from section offsets to cooked_index_entry *. */
|
||||
+ addrmap_mutable m_parent_map;
|
||||
+};
|
||||
+
|
||||
class cooked_index;
|
||||
|
||||
/* An index of interesting DIEs. This is "cooked", in contrast to a
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index 466d3e59878..d48f3010063 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -4722,16 +4722,6 @@ class cooked_indexer
|
||||
|
||||
private:
|
||||
|
||||
- /* A helper function to turn a section offset into an address that
|
||||
- can be used in an addrmap. */
|
||||
- CORE_ADDR form_addr (sect_offset offset, bool is_dwz)
|
||||
- {
|
||||
- CORE_ADDR value = to_underlying (offset);
|
||||
- if (is_dwz)
|
||||
- value |= ((CORE_ADDR) 1) << (8 * sizeof (CORE_ADDR) - 1);
|
||||
- return value;
|
||||
- }
|
||||
-
|
||||
/* A helper function to scan the PC bounds of READER and record them
|
||||
in the storage's addrmap. */
|
||||
void check_bounds (cutu_reader *reader);
|
||||
@@ -4799,7 +4789,20 @@ class cooked_indexer
|
||||
/* An addrmap that maps from section offsets (see the form_addr
|
||||
method) to newly-created entries. See m_deferred_entries to
|
||||
understand this. */
|
||||
- addrmap_mutable m_die_range_map;
|
||||
+ parent_map m_die_range_map;
|
||||
+
|
||||
+ /* Find the parent of DIE LOOKUP. */
|
||||
+ const cooked_index_entry *find_parent (CORE_ADDR lookup) const
|
||||
+ {
|
||||
+ return m_die_range_map.find_parent (lookup);
|
||||
+ }
|
||||
+
|
||||
+ /* Set the parent of DIES in range [START, END] to PARENT_ENTRY. */
|
||||
+ void set_parent (CORE_ADDR start, CORE_ADDR end,
|
||||
+ const cooked_index_entry *parent_entry)
|
||||
+ {
|
||||
+ m_die_range_map.set_parent (start, end, parent_entry);
|
||||
+ }
|
||||
|
||||
/* A single deferred entry. */
|
||||
struct deferred_entry
|
||||
@@ -16412,15 +16415,13 @@ cooked_indexer::scan_attributes (dwarf2_per_cu_data *scanning_per_cu,
|
||||
|
||||
if (*parent_entry == nullptr)
|
||||
{
|
||||
- CORE_ADDR addr = form_addr (origin_offset, origin_is_dwz);
|
||||
+ CORE_ADDR addr
|
||||
+ = parent_map::form_addr (origin_offset, origin_is_dwz);
|
||||
if (new_reader->cu == reader->cu
|
||||
&& new_info_ptr > watermark_ptr)
|
||||
*maybe_defer = addr;
|
||||
else
|
||||
- {
|
||||
- void *obj = m_die_range_map.find (addr);
|
||||
- *parent_entry = static_cast <cooked_index_entry *> (obj);
|
||||
- }
|
||||
+ *parent_entry = find_parent (addr);
|
||||
}
|
||||
|
||||
unsigned int bytes_read;
|
||||
@@ -16538,11 +16539,13 @@ cooked_indexer::recurse (cutu_reader *reader,
|
||||
{
|
||||
/* Both start and end are inclusive, so use both "+ 1" and "- 1" to
|
||||
limit the range to the children of parent_entry. */
|
||||
- CORE_ADDR start = form_addr (parent_entry->die_offset + 1,
|
||||
- reader->cu->per_cu->is_dwz);
|
||||
- CORE_ADDR end = form_addr (sect_offset (info_ptr - 1 - reader->buffer),
|
||||
+ CORE_ADDR start
|
||||
+ = parent_map::form_addr (parent_entry->die_offset + 1,
|
||||
+ reader->cu->per_cu->is_dwz);
|
||||
+ CORE_ADDR end
|
||||
+ = parent_map::form_addr (sect_offset (info_ptr - 1 - reader->buffer),
|
||||
reader->cu->per_cu->is_dwz);
|
||||
- m_die_range_map.set_empty (start, end, (void *) parent_entry);
|
||||
+ set_parent (start, end, parent_entry);
|
||||
}
|
||||
|
||||
return info_ptr;
|
||||
@@ -16715,8 +16718,7 @@ cooked_indexer::make_index (cutu_reader *reader)
|
||||
|
||||
for (const auto &entry : m_deferred_entries)
|
||||
{
|
||||
- void *obj = m_die_range_map.find (entry.spec_offset);
|
||||
- cooked_index_entry *parent = static_cast<cooked_index_entry *> (obj);
|
||||
+ const cooked_index_entry *parent = find_parent (entry.spec_offset);
|
||||
m_index_storage->add (entry.die_offset, entry.tag, entry.flags,
|
||||
entry.name, parent, m_per_cu);
|
||||
}
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,112 +0,0 @@
|
||||
From c79ecacd3f75cfb0ec1a3afc49ca3f30b1759009 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Fri, 11 Aug 2023 01:36:50 +0200
|
||||
Subject: [PATCH 13/13] [gdb/symtab] Fix DW_TAG_inlined_subroutine entries in
|
||||
the cooked index
|
||||
|
||||
We get incorrect qualified names in the cooked index for
|
||||
DW_TAG_inlined_subroutine DIEs with abstract origin, due to the fact that the
|
||||
DIE parent is used instead of the abstract origin.
|
||||
|
||||
Fix this by preferring the abstract origin parent, if available.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
|
||||
PR symtab/30728
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30728
|
||||
---
|
||||
gdb/dwarf2/read.c | 67 ++++++++++++++++++++++-------------------------
|
||||
1 file changed, 32 insertions(+), 35 deletions(-)
|
||||
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index 93708ef11b9..a4f982962ae 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -16464,52 +16464,49 @@ cooked_indexer::scan_attributes (dwarf2_per_cu_data *scanning_per_cu,
|
||||
const gdb_byte *new_info_ptr = (new_reader->buffer
|
||||
+ to_underlying (origin_offset));
|
||||
|
||||
- if (*parent_entry == nullptr)
|
||||
+ gdb_assert (reader->cu->per_cu->is_debug_types
|
||||
+ == new_reader->cu->per_cu->is_debug_types);
|
||||
+ CORE_ADDR addr
|
||||
+ = parent_map::form_addr (origin_offset, origin_is_dwz,
|
||||
+ reader->cu->per_cu->is_debug_types);
|
||||
+ if (new_reader->cu == reader->cu)
|
||||
{
|
||||
- gdb_assert (reader->cu->per_cu->is_debug_types
|
||||
- == new_reader->cu->per_cu->is_debug_types);
|
||||
- CORE_ADDR addr
|
||||
- = parent_map::form_addr (origin_offset, origin_is_dwz,
|
||||
- reader->cu->per_cu->is_debug_types);
|
||||
- if (new_reader->cu == reader->cu)
|
||||
+ /* Intra-CU case. */
|
||||
+ if (new_info_ptr > watermark_ptr)
|
||||
{
|
||||
- /* Intra-CU case. */
|
||||
- if (new_info_ptr > watermark_ptr)
|
||||
- {
|
||||
- /* Defer because origin is not read yet. */
|
||||
- *maybe_defer = addr;
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- auto tmp = find_parent (addr);
|
||||
- if (tmp == &parent_map::deferred)
|
||||
- {
|
||||
- /* Defer because origin is deferred. */
|
||||
- *maybe_defer = addr;
|
||||
- }
|
||||
- else
|
||||
- *parent_entry = tmp;
|
||||
- }
|
||||
+ /* Defer because origin is not read yet. */
|
||||
+ *maybe_defer = addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
- /* Inter-CU case. */
|
||||
- if (parent_valid (addr))
|
||||
+ auto tmp = find_parent (addr);
|
||||
+ if (tmp == &parent_map::deferred)
|
||||
{
|
||||
- auto tmp = find_parent (addr);
|
||||
- if (tmp == &parent_map::deferred)
|
||||
- {
|
||||
- /* Defer because origin is deferred. */
|
||||
- *maybe_defer = addr;
|
||||
- }
|
||||
- else
|
||||
- *parent_entry = tmp;
|
||||
+ /* Defer because origin is deferred. */
|
||||
+ *maybe_defer = addr;
|
||||
}
|
||||
else
|
||||
+ *parent_entry = tmp;
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /* Inter-CU case. */
|
||||
+ if (parent_valid (addr))
|
||||
+ {
|
||||
+ auto tmp = find_parent (addr);
|
||||
+ if (tmp == &parent_map::deferred)
|
||||
{
|
||||
- /* Defer because origin is in other shard. */
|
||||
+ /* Defer because origin is deferred. */
|
||||
*maybe_defer = addr;
|
||||
}
|
||||
+ else
|
||||
+ *parent_entry = tmp;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /* Defer because origin is in other shard. */
|
||||
+ *maybe_defer = addr;
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,37 +0,0 @@
|
||||
From bc970668f83cf142c4955d1cbeaa24e8bcc4b238 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Fri, 25 Aug 2023 09:30:54 +0200
|
||||
Subject: [PATCH 03/13] [gdb/symtab] Handle nullptr parent in
|
||||
parent_map::set_parent
|
||||
|
||||
Set_parent uses m_die_range_map.set_empty, which doesn't allow
|
||||
parent_entry == nullptr.
|
||||
|
||||
So it may be necessary to guard calls to set_parent with
|
||||
"if (parent_entry != nullptr)".
|
||||
|
||||
Fix this by handling the parent_entry == nullptr case in set_parent.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
---
|
||||
gdb/dwarf2/cooked-index.h | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/dwarf2/cooked-index.h b/gdb/dwarf2/cooked-index.h
|
||||
index 979541fbf60..79fbfe88c03 100644
|
||||
--- a/gdb/dwarf2/cooked-index.h
|
||||
+++ b/gdb/dwarf2/cooked-index.h
|
||||
@@ -263,7 +263,9 @@ class parent_map
|
||||
void set_parent (CORE_ADDR start, CORE_ADDR end,
|
||||
const cooked_index_entry *parent_entry)
|
||||
{
|
||||
- m_parent_map.set_empty (start, end, (void *)parent_entry);
|
||||
+ /* Calling set_empty with nullptr is currently not allowed. */
|
||||
+ if (parent_entry != nullptr)
|
||||
+ m_parent_map.set_empty (start, end, (void *)parent_entry);
|
||||
}
|
||||
|
||||
private:
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,38 +0,0 @@
|
||||
From 0e706742f37ee90629350780263b573f326f1a5f Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Thu, 7 Dec 2023 10:38:05 +0100
|
||||
Subject: [PATCH 12/13] [gdb/symtab] Keep track of all parents for cooked index
|
||||
|
||||
Keep track of all parents for cooked index.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
---
|
||||
gdb/dwarf2/read.c | 12 +++++++++---
|
||||
1 file changed, 9 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index de7b655d26c..93708ef11b9 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -16718,9 +16718,15 @@ cooked_indexer::index_dies (cutu_reader *reader,
|
||||
});
|
||||
}
|
||||
else
|
||||
- this_entry = m_index_storage->add (this_die, abbrev->tag, flags,
|
||||
- name, this_parent_entry,
|
||||
- m_per_cu);
|
||||
+ {
|
||||
+ CORE_ADDR addr
|
||||
+ = parent_map::form_addr (this_die, reader->cu->per_cu->is_dwz,
|
||||
+ reader->cu->per_cu->is_debug_types);
|
||||
+ set_parent (addr, addr, this_parent_entry);
|
||||
+ this_entry = m_index_storage->add (this_die, abbrev->tag, flags,
|
||||
+ name, this_parent_entry,
|
||||
+ m_per_cu);
|
||||
+ }
|
||||
}
|
||||
|
||||
if (linkage_name != nullptr)
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,126 +0,0 @@
|
||||
From e8285c8b37d28033209cad6579db4b9f6a48a01a Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Sun, 24 Sep 2023 11:41:39 +0200
|
||||
Subject: [PATCH 08/13] [gdb/symtab] Keep track of processed DIEs in shard
|
||||
|
||||
For optimizations in two following patches, we keep track in each shard which
|
||||
DIEs have been processed.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
---
|
||||
gdb/dwarf2/cooked-index.c | 1 +
|
||||
gdb/dwarf2/cooked-index.h | 15 +++++++++++++++
|
||||
gdb/dwarf2/read.c | 24 ++++++++++++++++++++++++
|
||||
3 files changed, 40 insertions(+)
|
||||
|
||||
diff --git a/gdb/dwarf2/cooked-index.c b/gdb/dwarf2/cooked-index.c
|
||||
index 3231d25db5a..c096da57d62 100644
|
||||
--- a/gdb/dwarf2/cooked-index.c
|
||||
+++ b/gdb/dwarf2/cooked-index.c
|
||||
@@ -723,6 +723,7 @@ cooked_index::handle_deferred_entries ()
|
||||
{
|
||||
shard->m_die_range_map.reset (nullptr);
|
||||
shard->m_deferred_entries.reset (nullptr);
|
||||
+ shard->m_die_range_map_valid.reset (nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/gdb/dwarf2/cooked-index.h b/gdb/dwarf2/cooked-index.h
|
||||
index 66424c37f7c..fa895233035 100644
|
||||
--- a/gdb/dwarf2/cooked-index.h
|
||||
+++ b/gdb/dwarf2/cooked-index.h
|
||||
@@ -316,6 +316,7 @@ class cooked_index_shard
|
||||
{
|
||||
m_die_range_map.reset (new parent_map);
|
||||
m_deferred_entries.reset (new std::vector<deferred_entry>);
|
||||
+ m_die_range_map_valid.reset (new addrmap_mutable);
|
||||
}
|
||||
|
||||
DISABLE_COPY_AND_ASSIGN (cooked_index_shard);
|
||||
@@ -407,6 +408,18 @@ class cooked_index_shard
|
||||
const cooked_index_entry *resolve_deferred_entry
|
||||
(const deferred_entry &entry, const cooked_index_entry *parent_entry);
|
||||
|
||||
+ /* Mark parents in range [START, END] as valid . */
|
||||
+ void set_parent_valid (CORE_ADDR start, CORE_ADDR end)
|
||||
+ {
|
||||
+ m_die_range_map_valid->set_empty (start, end, (void *) 1);
|
||||
+ }
|
||||
+
|
||||
+ /* Return true if find_parents can be relied upon. */
|
||||
+ bool parent_valid (CORE_ADDR addr)
|
||||
+ {
|
||||
+ return m_die_range_map_valid->find (addr) != nullptr;
|
||||
+ }
|
||||
+
|
||||
private:
|
||||
|
||||
/* Return the entry that is believed to represent the program's
|
||||
@@ -470,6 +483,8 @@ class cooked_index_shard
|
||||
understand this. */
|
||||
std::unique_ptr<parent_map> m_die_range_map;
|
||||
|
||||
+ std::unique_ptr<addrmap> m_die_range_map_valid;
|
||||
+
|
||||
/* The generated DWARF can sometimes have the declaration for a
|
||||
method in a class (or perhaps namespace) scope, with the
|
||||
definition appearing outside this scope... just one of the many
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index 5b7c0969ed7..09598e702bc 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -4697,6 +4697,12 @@ class cooked_index_storage
|
||||
m_index->defer_entry (de);
|
||||
}
|
||||
|
||||
+ /* Mark parents in range [START, END] as valid . */
|
||||
+ void set_parent_valid (CORE_ADDR start, CORE_ADDR end)
|
||||
+ {
|
||||
+ m_index->set_parent_valid (start, end);
|
||||
+ }
|
||||
+
|
||||
private:
|
||||
|
||||
/* Hash function for a cutu_reader. */
|
||||
@@ -4840,6 +4846,11 @@ class cooked_indexer
|
||||
{
|
||||
m_index_storage->defer_entry (de);
|
||||
}
|
||||
+
|
||||
+ void set_parent_valid (CORE_ADDR start, CORE_ADDR end)
|
||||
+ {
|
||||
+ m_index_storage->set_parent_valid (start, end);
|
||||
+ }
|
||||
};
|
||||
|
||||
/* Subroutine of dwarf2_build_psymtabs_hard to simplify it.
|
||||
@@ -16604,6 +16615,11 @@ cooked_indexer::index_dies (cutu_reader *reader,
|
||||
+ to_underlying (reader->cu->header.sect_off)
|
||||
+ reader->cu->header.get_length_with_initial ());
|
||||
|
||||
+ const CORE_ADDR start_cu
|
||||
+ = parent_map::form_addr (sect_offset (info_ptr - reader->buffer),
|
||||
+ reader->cu->per_cu->is_dwz,
|
||||
+ reader->cu->per_cu->is_debug_types);
|
||||
+
|
||||
while (info_ptr < end_ptr)
|
||||
{
|
||||
sect_offset this_die = (sect_offset) (info_ptr - reader->buffer);
|
||||
@@ -16754,6 +16770,14 @@ cooked_indexer::index_dies (cutu_reader *reader,
|
||||
}
|
||||
}
|
||||
|
||||
+ {
|
||||
+ CORE_ADDR end_prev_die
|
||||
+ = parent_map::form_addr (sect_offset (info_ptr - reader->buffer - 1),
|
||||
+ reader->cu->per_cu->is_dwz,
|
||||
+ reader->cu->per_cu->is_debug_types);
|
||||
+ set_parent_valid (start_cu, end_prev_die);
|
||||
+ }
|
||||
+
|
||||
return info_ptr;
|
||||
}
|
||||
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,70 +0,0 @@
|
||||
From f72f115b4c012e3748a2e702d7b970be19974885 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Mon, 11 Dec 2023 15:41:26 +0100
|
||||
Subject: [PATCH 01/13] [gdb/symtab] Refactor condition in scan_attributes
|
||||
|
||||
In scan_attributes there's code:
|
||||
...
|
||||
if (new_reader->cu == reader->cu
|
||||
&& new_info_ptr > watermark_ptr
|
||||
&& *parent_entry == nullptr)
|
||||
...
|
||||
else if (*parent_entry == nullptr)
|
||||
...
|
||||
...
|
||||
that uses the "*parent_entry == nullptr" condition twice.
|
||||
|
||||
Make this somewhat more readable by factoring out the condition:
|
||||
...
|
||||
if (*parent_entry == nullptr)
|
||||
{
|
||||
if (new_reader->cu == reader->cu
|
||||
&& new_info_ptr > watermark_ptr)
|
||||
...
|
||||
else
|
||||
...
|
||||
}
|
||||
...
|
||||
|
||||
This also allows us to factor out "form_addr (origin_offset, origin_is_dwz)".
|
||||
|
||||
Tested on x86_64-linux.
|
||||
---
|
||||
gdb/dwarf2/read.c | 18 ++++++++++--------
|
||||
1 file changed, 10 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index 50fa302b43a..466d3e59878 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -16410,15 +16410,17 @@ cooked_indexer::scan_attributes (dwarf2_per_cu_data *scanning_per_cu,
|
||||
const gdb_byte *new_info_ptr = (new_reader->buffer
|
||||
+ to_underlying (origin_offset));
|
||||
|
||||
- if (new_reader->cu == reader->cu
|
||||
- && new_info_ptr > watermark_ptr
|
||||
- && *parent_entry == nullptr)
|
||||
- *maybe_defer = form_addr (origin_offset, origin_is_dwz);
|
||||
- else if (*parent_entry == nullptr)
|
||||
+ if (*parent_entry == nullptr)
|
||||
{
|
||||
- CORE_ADDR lookup = form_addr (origin_offset, origin_is_dwz);
|
||||
- void *obj = m_die_range_map.find (lookup);
|
||||
- *parent_entry = static_cast <cooked_index_entry *> (obj);
|
||||
+ CORE_ADDR addr = form_addr (origin_offset, origin_is_dwz);
|
||||
+ if (new_reader->cu == reader->cu
|
||||
+ && new_info_ptr > watermark_ptr)
|
||||
+ *maybe_defer = addr;
|
||||
+ else
|
||||
+ {
|
||||
+ void *obj = m_die_range_map.find (addr);
|
||||
+ *parent_entry = static_cast <cooked_index_entry *> (obj);
|
||||
+ }
|
||||
}
|
||||
|
||||
unsigned int bytes_read;
|
||||
|
||||
base-commit: 3490f51a80a10d46dc1885ba672d9390a8221170
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,500 +0,0 @@
|
||||
From e2d7097cf236c9ea6959785754d067833fc302af Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Tue, 22 Aug 2023 14:24:42 +0200
|
||||
Subject: [PATCH 05/13] [gdb/symtab] Resolve deferred entries, inter-shard case
|
||||
|
||||
Generically solve the case of inter-CU dependencies, including inter-shard
|
||||
dependencies:
|
||||
- mark deferred entries in new data structure m_deferred,
|
||||
- return &parent_map::deferred in find_parent for deferred entries,
|
||||
- defer all intra-CU dependencies that depend on deferred entries,
|
||||
- defer all inter-CU dependencies (note that two subsequent patches implement
|
||||
optimizations to deal with this more optimally),
|
||||
- move m_die_range_map and m_deferred_dies to cooked_index_shard, and
|
||||
- move handle_deferred_dies to the cooked_index, where it is called in the
|
||||
constructor, and update it to handle the intra-shard case.
|
||||
|
||||
Handling units from the .debug_info section alongside units from the
|
||||
.debug_types section requires us to extend form_addr to take is_debug_types
|
||||
into account.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
|
||||
PR symtab/30846
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30846
|
||||
---
|
||||
gdb/dwarf2/cooked-index.c | 77 +++++++++++++++++++++++
|
||||
gdb/dwarf2/cooked-index.h | 105 ++++++++++++++++++++++++++++++-
|
||||
gdb/dwarf2/read.c | 128 ++++++++++++++++++++++----------------
|
||||
3 files changed, 254 insertions(+), 56 deletions(-)
|
||||
|
||||
diff --git a/gdb/dwarf2/cooked-index.c b/gdb/dwarf2/cooked-index.c
|
||||
index 58ea541a5c9..3231d25db5a 100644
|
||||
--- a/gdb/dwarf2/cooked-index.c
|
||||
+++ b/gdb/dwarf2/cooked-index.c
|
||||
@@ -228,6 +228,12 @@ cooked_index_entry::write_scope (struct obstack *storage,
|
||||
|
||||
/* See cooked-index.h. */
|
||||
|
||||
+cooked_index_entry parent_map::deferred((sect_offset)0, (dwarf_tag)0,
|
||||
+ (cooked_index_flag)0, nullptr,
|
||||
+ nullptr, nullptr);
|
||||
+
|
||||
+/* See cooked-index.h. */
|
||||
+
|
||||
const cooked_index_entry *
|
||||
cooked_index_shard::add (sect_offset die_offset, enum dwarf_tag tag,
|
||||
cooked_index_flag flags, const char *name,
|
||||
@@ -446,6 +452,8 @@ cooked_index_shard::wait (bool allow_quit) const
|
||||
cooked_index::cooked_index (vec_type &&vec)
|
||||
: m_vector (std::move (vec))
|
||||
{
|
||||
+ handle_deferred_entries ();
|
||||
+
|
||||
for (auto &idx : m_vector)
|
||||
idx->finalize ();
|
||||
|
||||
@@ -649,6 +657,75 @@ cooked_index::maybe_write_index (dwarf2_per_bfd *per_bfd,
|
||||
global_index_cache.store (per_bfd, ctx);
|
||||
}
|
||||
|
||||
+/* See cooked-index.h. */
|
||||
+
|
||||
+const cooked_index_entry *
|
||||
+cooked_index_shard::resolve_deferred_entry
|
||||
+ (const deferred_entry &de, const cooked_index_entry *parent_entry)
|
||||
+{
|
||||
+ reset_parent_deferred (parent_map::form_addr (de.die_offset, de.per_cu_2->is_dwz,
|
||||
+ de.per_cu_2->is_debug_types));
|
||||
+ return add (de.die_offset, de.tag, de.flags, de.name,
|
||||
+ parent_entry, de.per_cu);
|
||||
+}
|
||||
+
|
||||
+/* See cooked-index.h. */
|
||||
+
|
||||
+const cooked_index_entry *
|
||||
+cooked_index::find_parent_deferred_entry
|
||||
+ (const cooked_index_shard::deferred_entry &entry) const
|
||||
+{
|
||||
+ const cooked_index_entry *parent_entry = nullptr;
|
||||
+ for (auto &parent_map_shard : m_vector)
|
||||
+ {
|
||||
+ auto res = parent_map_shard->find_parent (entry.spec_offset);
|
||||
+ if (res != nullptr)
|
||||
+ {
|
||||
+ parent_entry = res;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return parent_entry;
|
||||
+}
|
||||
+
|
||||
+/* See cooked-index.h. */
|
||||
+
|
||||
+void
|
||||
+cooked_index::handle_deferred_entries ()
|
||||
+{
|
||||
+ bool changed;
|
||||
+ bool deferred;
|
||||
+ do
|
||||
+ {
|
||||
+ deferred = false;
|
||||
+ changed = false;
|
||||
+ for (auto &shard : m_vector)
|
||||
+ for (auto it = shard->m_deferred_entries->begin ();
|
||||
+ it != shard->m_deferred_entries->end (); )
|
||||
+ {
|
||||
+ const cooked_index_entry *parent_entry
|
||||
+ = find_parent_deferred_entry (*it);
|
||||
+ if (parent_entry == &parent_map::deferred)
|
||||
+ {
|
||||
+ deferred = true;
|
||||
+ it++;
|
||||
+ continue;
|
||||
+ }
|
||||
+ shard->resolve_deferred_entry (*it, parent_entry);
|
||||
+ it = shard->m_deferred_entries->erase (it);
|
||||
+ changed = true;
|
||||
+ }
|
||||
+ }
|
||||
+ while (changed && deferred);
|
||||
+
|
||||
+ for (auto &shard : m_vector)
|
||||
+ {
|
||||
+ shard->m_die_range_map.reset (nullptr);
|
||||
+ shard->m_deferred_entries.reset (nullptr);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/* Wait for all the index cache entries to be written before gdb
|
||||
exits. */
|
||||
static void
|
||||
diff --git a/gdb/dwarf2/cooked-index.h b/gdb/dwarf2/cooked-index.h
|
||||
index 79fbfe88c03..66424c37f7c 100644
|
||||
--- a/gdb/dwarf2/cooked-index.h
|
||||
+++ b/gdb/dwarf2/cooked-index.h
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "dwarf2/mapped-index.h"
|
||||
#include "dwarf2/tag.h"
|
||||
#include "gdbsupport/range-chain.h"
|
||||
+#include <unordered_set>
|
||||
|
||||
struct dwarf2_per_cu_data;
|
||||
struct dwarf2_per_bfd;
|
||||
@@ -242,19 +243,29 @@ struct cooked_index_entry : public allocate_on_obstack
|
||||
class parent_map
|
||||
{
|
||||
public:
|
||||
+ /* A dummy cooked_index_entry to mark that computing the parent has been
|
||||
+ deferred. */
|
||||
+ static cooked_index_entry deferred;
|
||||
+
|
||||
/* A helper function to turn a section offset into an address that
|
||||
can be used in a parent_map. */
|
||||
- static CORE_ADDR form_addr (sect_offset offset, bool is_dwz)
|
||||
+ static CORE_ADDR form_addr (sect_offset offset, bool is_dwz,
|
||||
+ bool is_debug_types)
|
||||
{
|
||||
CORE_ADDR value = to_underlying (offset);
|
||||
if (is_dwz)
|
||||
value |= ((CORE_ADDR) 1) << (8 * sizeof (CORE_ADDR) - 1);
|
||||
+ if (is_debug_types)
|
||||
+ value |= ((CORE_ADDR) 1) << (8 * sizeof (CORE_ADDR) - 2);
|
||||
return value;
|
||||
}
|
||||
|
||||
/* Find the parent of DIE LOOKUP. */
|
||||
const cooked_index_entry *find_parent (CORE_ADDR lookup) const
|
||||
{
|
||||
+ if (m_deferred.find (lookup) != m_deferred.end ())
|
||||
+ return &parent_map::deferred;
|
||||
+
|
||||
const void *obj = m_parent_map.find (lookup);
|
||||
return static_cast<const cooked_index_entry *> (obj);
|
||||
}
|
||||
@@ -265,12 +276,28 @@ class parent_map
|
||||
{
|
||||
/* Calling set_empty with nullptr is currently not allowed. */
|
||||
if (parent_entry != nullptr)
|
||||
- m_parent_map.set_empty (start, end, (void *)parent_entry);
|
||||
+ {
|
||||
+ gdb_assert (parent_entry != &parent_map::deferred);
|
||||
+ m_parent_map.set_empty (start, end, (void *)parent_entry);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ void set_parent_deferred (CORE_ADDR addr)
|
||||
+ {
|
||||
+ m_deferred.emplace (addr);
|
||||
+ }
|
||||
+
|
||||
+ void reset_parent_deferred (CORE_ADDR addr)
|
||||
+ {
|
||||
+ m_deferred.erase (addr);
|
||||
}
|
||||
|
||||
private:
|
||||
/* An addrmap that maps from section offsets to cooked_index_entry *. */
|
||||
addrmap_mutable m_parent_map;
|
||||
+
|
||||
+ /* DIEs that are deffered. */
|
||||
+ std::unordered_set<CORE_ADDR> m_deferred;
|
||||
};
|
||||
|
||||
class cooked_index;
|
||||
@@ -285,7 +312,12 @@ class cooked_index;
|
||||
class cooked_index_shard
|
||||
{
|
||||
public:
|
||||
- cooked_index_shard () = default;
|
||||
+ cooked_index_shard ()
|
||||
+ {
|
||||
+ m_die_range_map.reset (new parent_map);
|
||||
+ m_deferred_entries.reset (new std::vector<deferred_entry>);
|
||||
+ }
|
||||
+
|
||||
DISABLE_COPY_AND_ASSIGN (cooked_index_shard);
|
||||
|
||||
/* Create a new cooked_index_entry and register it with this object.
|
||||
@@ -329,6 +361,52 @@ class cooked_index_shard
|
||||
for completion, will be returned. */
|
||||
range find (const std::string &name, bool completing) const;
|
||||
|
||||
+ /* Find the parent of DIE LOOKUP. */
|
||||
+ const cooked_index_entry *
|
||||
+ find_parent (CORE_ADDR lookup) const
|
||||
+ {
|
||||
+ return m_die_range_map->find_parent (lookup);
|
||||
+ }
|
||||
+
|
||||
+ /* Set the parent of DIES in range [START, END] to PARENT_ENTRY. */
|
||||
+ void set_parent (CORE_ADDR start, CORE_ADDR end,
|
||||
+ const cooked_index_entry *parent_entry)
|
||||
+ {
|
||||
+ m_die_range_map->set_parent (start, end, parent_entry);
|
||||
+ }
|
||||
+
|
||||
+ void set_parent_deferred (CORE_ADDR addr)
|
||||
+ {
|
||||
+ m_die_range_map->set_parent_deferred (addr);
|
||||
+ }
|
||||
+
|
||||
+ void reset_parent_deferred (CORE_ADDR addr)
|
||||
+ {
|
||||
+ m_die_range_map->reset_parent_deferred (addr);
|
||||
+ }
|
||||
+
|
||||
+ /* A single deferred entry. See m_deferred_entries. */
|
||||
+ struct deferred_entry
|
||||
+ {
|
||||
+ sect_offset die_offset;
|
||||
+ const char *name;
|
||||
+ CORE_ADDR spec_offset;
|
||||
+ dwarf_tag tag;
|
||||
+ cooked_index_flag flags;
|
||||
+ dwarf2_per_cu_data *per_cu;
|
||||
+ dwarf2_per_cu_data *per_cu_2;
|
||||
+ };
|
||||
+
|
||||
+ /* Defer creating a cooked_index_entry corresponding to DEFERRED. */
|
||||
+ void defer_entry (deferred_entry de)
|
||||
+ {
|
||||
+ m_deferred_entries->push_back (de);
|
||||
+ }
|
||||
+
|
||||
+ /* Variant of add that takes a deferred_entry as parameter. */
|
||||
+ const cooked_index_entry *resolve_deferred_entry
|
||||
+ (const deferred_entry &entry, const cooked_index_entry *parent_entry);
|
||||
+
|
||||
private:
|
||||
|
||||
/* Return the entry that is believed to represent the program's
|
||||
@@ -386,6 +464,20 @@ class cooked_index_shard
|
||||
that the 'get' method is never called on this future, only
|
||||
'wait'. */
|
||||
gdb::future<void> m_future;
|
||||
+
|
||||
+ /* An addrmap that maps from section offsets (see the form_addr
|
||||
+ method) to newly-created entries. See m_deferred_entries to
|
||||
+ understand this. */
|
||||
+ std::unique_ptr<parent_map> m_die_range_map;
|
||||
+
|
||||
+ /* The generated DWARF can sometimes have the declaration for a
|
||||
+ method in a class (or perhaps namespace) scope, with the
|
||||
+ definition appearing outside this scope... just one of the many
|
||||
+ bad things about DWARF. In order to handle this situation, we
|
||||
+ defer certain entries until the end of scanning, at which point
|
||||
+ we'll know the containing context of all the DIEs that we might
|
||||
+ have scanned. This vector stores these deferred entries. */
|
||||
+ std::unique_ptr<std::vector<deferred_entry>> m_deferred_entries;
|
||||
};
|
||||
|
||||
/* The main index of DIEs. The parallel DIE indexers create
|
||||
@@ -469,6 +561,13 @@ class cooked_index : public dwarf_scanner_base
|
||||
|
||||
private:
|
||||
|
||||
+ /* Find the parent corresponding to deferred entry ENTRY. */
|
||||
+ const cooked_index_entry *find_parent_deferred_entry
|
||||
+ (const cooked_index_shard::deferred_entry &entry) const;
|
||||
+
|
||||
+ /* Create cooked_index_entries for the deferred entries. */
|
||||
+ void handle_deferred_entries ();
|
||||
+
|
||||
/* Maybe write the index to the index cache. */
|
||||
void maybe_write_index (dwarf2_per_bfd *per_bfd,
|
||||
const index_cache_store_context &);
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index afdf9e870a8..5b7c0969ed7 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -4672,6 +4672,31 @@ class cooked_index_storage
|
||||
return &m_addrmap;
|
||||
}
|
||||
|
||||
+ /* Find the parent of DIE LOOKUP. */
|
||||
+ const cooked_index_entry *find_parent (CORE_ADDR lookup)
|
||||
+ {
|
||||
+ return m_index->find_parent (lookup);
|
||||
+ }
|
||||
+
|
||||
+ /* Set the parent of DIES in range [START, END] to PARENT_ENTRY. */
|
||||
+ void set_parent (CORE_ADDR start, CORE_ADDR end,
|
||||
+ const cooked_index_entry *parent_entry)
|
||||
+ {
|
||||
+ m_index->set_parent (start, end, parent_entry);
|
||||
+ }
|
||||
+
|
||||
+ /* Set the parent of DIE at ADDR as deferred. */
|
||||
+ void set_parent_deferred (CORE_ADDR addr)
|
||||
+ {
|
||||
+ m_index->set_parent_deferred (addr);
|
||||
+ }
|
||||
+
|
||||
+ /* Defer creating a cooked_index_entry corresponding to deferred_entry DE. */
|
||||
+ void defer_entry (cooked_index_shard::deferred_entry de)
|
||||
+ {
|
||||
+ m_index->defer_entry (de);
|
||||
+ }
|
||||
+
|
||||
private:
|
||||
|
||||
/* Hash function for a cutu_reader. */
|
||||
@@ -4794,59 +4819,26 @@ class cooked_indexer
|
||||
/* Find the parent of DIE LOOKUP. */
|
||||
const cooked_index_entry *find_parent (CORE_ADDR lookup) const
|
||||
{
|
||||
- return m_die_range_map.find_parent (lookup);
|
||||
+ return m_index_storage->find_parent (lookup);
|
||||
}
|
||||
|
||||
/* Set the parent of DIES in range [START, END] to PARENT_ENTRY. */
|
||||
void set_parent (CORE_ADDR start, CORE_ADDR end,
|
||||
const cooked_index_entry *parent_entry)
|
||||
{
|
||||
- m_die_range_map.set_parent (start, end, parent_entry);
|
||||
+ m_index_storage->set_parent (start, end, parent_entry);
|
||||
}
|
||||
|
||||
- /* A single deferred entry. */
|
||||
- struct deferred_entry
|
||||
- {
|
||||
- sect_offset die_offset;
|
||||
- const char *name;
|
||||
- CORE_ADDR spec_offset;
|
||||
- dwarf_tag tag;
|
||||
- cooked_index_flag flags;
|
||||
- };
|
||||
-
|
||||
- /* The generated DWARF can sometimes have the declaration for a
|
||||
- method in a class (or perhaps namespace) scope, with the
|
||||
- definition appearing outside this scope... just one of the many
|
||||
- bad things about DWARF. In order to handle this situation, we
|
||||
- defer certain entries until the end of scanning, at which point
|
||||
- we'll know the containing context of all the DIEs that we might
|
||||
- have scanned. This vector stores these deferred entries. */
|
||||
- std::vector<deferred_entry> m_deferred_entries;
|
||||
-
|
||||
- /* Defer creating a cooked_index_entry corresponding to deferred_entry DE. */
|
||||
- void defer_entry (const deferred_entry &de)
|
||||
+ /* Set the parent of DIE at ADDR as deferred. */
|
||||
+ void set_parent_deferred (CORE_ADDR addr)
|
||||
{
|
||||
- m_deferred_entries.push_back (de);
|
||||
+ m_index_storage->set_parent_deferred (addr);
|
||||
}
|
||||
|
||||
- /* Create a cooked_index_entry corresponding to deferred_entry DE with
|
||||
- parent PARENT_ENTRY. */
|
||||
- const cooked_index_entry *resolve_deferred_entry
|
||||
- (const deferred_entry &de, const cooked_index_entry *parent_entry)
|
||||
- {
|
||||
- return m_index_storage->add (de.die_offset, de.tag, de.flags, de.name,
|
||||
- parent_entry, m_per_cu);
|
||||
- }
|
||||
-
|
||||
- /* Create cooked_index_entries for the deferred entries. */
|
||||
- void handle_deferred_entries ()
|
||||
+ /* Defer creating a cooked_index_entry corresponding to deferred_entry DE. */
|
||||
+ void defer_entry (const cooked_index_shard::deferred_entry &de)
|
||||
{
|
||||
- for (const auto &entry : m_deferred_entries)
|
||||
- {
|
||||
- const cooked_index_entry *parent_entry
|
||||
- = find_parent (entry.spec_offset);
|
||||
- resolve_deferred_entry (entry, parent_entry);
|
||||
- }
|
||||
+ m_index_storage->defer_entry (de);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -16441,13 +16433,36 @@ cooked_indexer::scan_attributes (dwarf2_per_cu_data *scanning_per_cu,
|
||||
|
||||
if (*parent_entry == nullptr)
|
||||
{
|
||||
+ gdb_assert (reader->cu->per_cu->is_debug_types
|
||||
+ == new_reader->cu->per_cu->is_debug_types);
|
||||
CORE_ADDR addr
|
||||
- = parent_map::form_addr (origin_offset, origin_is_dwz);
|
||||
- if (new_reader->cu == reader->cu
|
||||
- && new_info_ptr > watermark_ptr)
|
||||
- *maybe_defer = addr;
|
||||
+ = parent_map::form_addr (origin_offset, origin_is_dwz,
|
||||
+ reader->cu->per_cu->is_debug_types);
|
||||
+ if (new_reader->cu == reader->cu)
|
||||
+ {
|
||||
+ /* Intra-CU case. */
|
||||
+ if (new_info_ptr > watermark_ptr)
|
||||
+ {
|
||||
+ /* Defer because origin is not read yet. */
|
||||
+ *maybe_defer = addr;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ auto tmp = find_parent (addr);
|
||||
+ if (tmp == &parent_map::deferred)
|
||||
+ {
|
||||
+ /* Defer because origin is deferred. */
|
||||
+ *maybe_defer = addr;
|
||||
+ }
|
||||
+ else
|
||||
+ *parent_entry = tmp;
|
||||
+ }
|
||||
+ }
|
||||
else
|
||||
- *parent_entry = find_parent (addr);
|
||||
+ {
|
||||
+ /* Inter-CU case. */
|
||||
+ *maybe_defer = addr;
|
||||
+ }
|
||||
}
|
||||
|
||||
unsigned int bytes_read;
|
||||
@@ -16567,10 +16582,12 @@ cooked_indexer::recurse (cutu_reader *reader,
|
||||
limit the range to the children of parent_entry. */
|
||||
CORE_ADDR start
|
||||
= parent_map::form_addr (parent_entry->die_offset + 1,
|
||||
- reader->cu->per_cu->is_dwz);
|
||||
+ reader->cu->per_cu->is_dwz,
|
||||
+ reader->cu->per_cu->is_debug_types);
|
||||
CORE_ADDR end
|
||||
= parent_map::form_addr (sect_offset (info_ptr - 1 - reader->buffer),
|
||||
- reader->cu->per_cu->is_dwz);
|
||||
+ reader->cu->per_cu->is_dwz,
|
||||
+ reader->cu->per_cu->is_debug_types);
|
||||
set_parent (start, end, parent_entry);
|
||||
}
|
||||
|
||||
@@ -16637,9 +16654,16 @@ cooked_indexer::index_dies (cutu_reader *reader,
|
||||
if (name != nullptr)
|
||||
{
|
||||
if (defer != 0)
|
||||
- defer_entry ({
|
||||
- this_die, name, defer, abbrev->tag, flags
|
||||
- });
|
||||
+ {
|
||||
+ CORE_ADDR addr
|
||||
+ = parent_map::form_addr (this_die, reader->cu->per_cu->is_dwz,
|
||||
+ reader->cu->per_cu->is_debug_types);
|
||||
+ set_parent_deferred (addr);
|
||||
+ defer_entry ({
|
||||
+ this_die, name, defer, abbrev->tag, flags, m_per_cu,
|
||||
+ reader->cu->per_cu
|
||||
+ });
|
||||
+ }
|
||||
else
|
||||
this_entry = m_index_storage->add (this_die, abbrev->tag, flags,
|
||||
name, this_parent_entry,
|
||||
@@ -16741,8 +16765,6 @@ cooked_indexer::make_index (cutu_reader *reader)
|
||||
if (!reader->comp_unit_die->has_children)
|
||||
return;
|
||||
index_dies (reader, reader->info_ptr, nullptr, false);
|
||||
-
|
||||
- handle_deferred_entries ();
|
||||
}
|
||||
|
||||
/* An implementation of quick_symbol_functions for the cooked DWARF
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,120 +0,0 @@
|
||||
From 3b2f2b376bb80edadacc582161c362612947e3a6 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Sun, 24 Sep 2023 11:43:24 +0200
|
||||
Subject: [PATCH 09/13] [gdb/symtab] Resolve deferred entries, intra-shard case
|
||||
|
||||
In patch "[gdb/symtab] Resolve deferred entries, inter-shard case" we've
|
||||
solved the generic case of handling deferred entries.
|
||||
|
||||
Now add an optimization that handles deferred entries with an intra-shard
|
||||
dependency in the parallel for.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
---
|
||||
gdb/dwarf2/cooked-index.c | 35 +++++++++++++++++++++++++++++++++++
|
||||
gdb/dwarf2/cooked-index.h | 7 +++++++
|
||||
gdb/dwarf2/read.c | 10 ++++++++++
|
||||
3 files changed, 52 insertions(+)
|
||||
|
||||
diff --git a/gdb/dwarf2/cooked-index.c b/gdb/dwarf2/cooked-index.c
|
||||
index c096da57d62..ebed21d510c 100644
|
||||
--- a/gdb/dwarf2/cooked-index.c
|
||||
+++ b/gdb/dwarf2/cooked-index.c
|
||||
@@ -452,6 +452,7 @@ cooked_index_shard::wait (bool allow_quit) const
|
||||
cooked_index::cooked_index (vec_type &&vec)
|
||||
: m_vector (std::move (vec))
|
||||
{
|
||||
+ /* Handle deferred entries, inter-cu case. */
|
||||
handle_deferred_entries ();
|
||||
|
||||
for (auto &idx : m_vector)
|
||||
@@ -659,6 +660,40 @@ cooked_index::maybe_write_index (dwarf2_per_bfd *per_bfd,
|
||||
|
||||
/* See cooked-index.h. */
|
||||
|
||||
+const cooked_index_entry *
|
||||
+cooked_index_shard::find_parent_deferred_entry
|
||||
+ (const cooked_index_shard::deferred_entry &entry) const
|
||||
+{
|
||||
+ return find_parent (entry.spec_offset);
|
||||
+}
|
||||
+
|
||||
+/* See cooked-index.h. */
|
||||
+
|
||||
+void
|
||||
+cooked_index_shard::handle_deferred_entries ()
|
||||
+{
|
||||
+ for (auto it = m_deferred_entries->begin (); it != m_deferred_entries->end (); )
|
||||
+ {
|
||||
+ const deferred_entry & deferred_entry = *it;
|
||||
+ if (!parent_valid (deferred_entry.spec_offset))
|
||||
+ {
|
||||
+ it++;
|
||||
+ continue;
|
||||
+ }
|
||||
+ const cooked_index_entry *parent_entry
|
||||
+ = find_parent_deferred_entry (deferred_entry);
|
||||
+ if (parent_entry == &parent_map::deferred)
|
||||
+ {
|
||||
+ it++;
|
||||
+ continue;
|
||||
+ }
|
||||
+ resolve_deferred_entry (deferred_entry, parent_entry);
|
||||
+ it = m_deferred_entries->erase (it);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* See cooked-index.h. */
|
||||
+
|
||||
const cooked_index_entry *
|
||||
cooked_index_shard::resolve_deferred_entry
|
||||
(const deferred_entry &de, const cooked_index_entry *parent_entry)
|
||||
diff --git a/gdb/dwarf2/cooked-index.h b/gdb/dwarf2/cooked-index.h
|
||||
index fa895233035..106e3091a90 100644
|
||||
--- a/gdb/dwarf2/cooked-index.h
|
||||
+++ b/gdb/dwarf2/cooked-index.h
|
||||
@@ -408,6 +408,13 @@ class cooked_index_shard
|
||||
const cooked_index_entry *resolve_deferred_entry
|
||||
(const deferred_entry &entry, const cooked_index_entry *parent_entry);
|
||||
|
||||
+ /* Find the parent entry for deferred_entry ENTRY. */
|
||||
+ const cooked_index_entry *find_parent_deferred_entry
|
||||
+ (const cooked_index_shard::deferred_entry &entry) const;
|
||||
+
|
||||
+ /* Create cooked_index_entries for the deferred entries. */
|
||||
+ void handle_deferred_entries ();
|
||||
+
|
||||
/* Mark parents in range [START, END] as valid . */
|
||||
void set_parent_valid (CORE_ADDR start, CORE_ADDR end)
|
||||
{
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index 09598e702bc..a97f738a54e 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -4697,6 +4697,12 @@ class cooked_index_storage
|
||||
m_index->defer_entry (de);
|
||||
}
|
||||
|
||||
+ /* Handle deferred entries, intra-cu case. */
|
||||
+ void handle_deferred_entries ()
|
||||
+ {
|
||||
+ m_index->handle_deferred_entries ();
|
||||
+ }
|
||||
+
|
||||
/* Mark parents in range [START, END] as valid . */
|
||||
void set_parent_valid (CORE_ADDR start, CORE_ADDR end)
|
||||
{
|
||||
@@ -5183,6 +5189,10 @@ dwarf2_build_psymtabs_hard (dwarf2_per_objfile *per_objfile)
|
||||
errors.push_back (std::move (except));
|
||||
}
|
||||
}
|
||||
+
|
||||
+ /* Handle deferred entries, intra-cu case. */
|
||||
+ thread_storage.handle_deferred_entries ();
|
||||
+
|
||||
return result_type (thread_storage.release (), std::move (errors));
|
||||
}, task_size);
|
||||
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,278 +0,0 @@
|
||||
From 1b878333913343630472f89b4bc42f51b1619308 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Wed, 1 Nov 2023 00:33:12 +0100
|
||||
Subject: [PATCH 1/2] [gdb/symtab] Work around gas PR28629
|
||||
|
||||
When running test-case gdb.tui/tui-layout-asm-short-prog.exp on AlmaLinux 9.2
|
||||
ppc64le, I run into:
|
||||
...
|
||||
FAIL: gdb.tui/tui-layout-asm-short-prog.exp: check asm box contents
|
||||
...
|
||||
|
||||
The problem is that we get:
|
||||
...
|
||||
7 [ No Assembly Available ]
|
||||
...
|
||||
because tui_get_begin_asm_address doesn't succeed.
|
||||
|
||||
In more detail, tui_get_begin_asm_address calls:
|
||||
...
|
||||
find_line_pc (sal.symtab, sal.line, &addr);
|
||||
...
|
||||
with:
|
||||
...
|
||||
(gdb) p *sal.symtab
|
||||
$5 = {next = 0x130393c0, m_compunit = 0x130392f0, m_linetable = 0x0,
|
||||
filename = "tui-layout-asm-short-prog.S",
|
||||
filename_for_id = "$gdb/build/gdb/testsuite/tui-layout-asm-short-prog.S",
|
||||
m_language = language_asm, fullname = 0x0}
|
||||
(gdb) p sal.line
|
||||
$6 = 1
|
||||
...
|
||||
|
||||
The problem is the filename_for_id which is the source file prefixed with the
|
||||
compilation dir rather than the source dir.
|
||||
|
||||
This is due to faulty debug info generated by gas, PR28629:
|
||||
...
|
||||
<1a> DW_AT_name : tui-layout-asm-short-prog.S
|
||||
<1e> DW_AT_comp_dir : $gdb/build/gdb/testsuite
|
||||
<22> DW_AT_producer : GNU AS 2.35.2
|
||||
...
|
||||
|
||||
The DW_AT_name is relative, and it's relative to the DW_AT_comp_dir entry,
|
||||
making the effective name $gdb/build/gdb/testsuite/tui-layout-asm-short-prog.S.
|
||||
|
||||
The bug is fixed starting version 2.38, where we get instead:
|
||||
...
|
||||
<1a> DW_AT_name :
|
||||
$gdb/src/gdb/testsuite/gdb.tui/tui-layout-asm-short-prog.S
|
||||
<1e> DW_AT_comp_dir : $gdb/build/gdb/testsuite
|
||||
<22> DW_AT_producer : GNU AS 2.38
|
||||
...
|
||||
|
||||
Work around the faulty debug info by constructing the filename_for_id using
|
||||
the second directory from the directory table in the .debug_line header:
|
||||
...
|
||||
The Directory Table (offset 0x22, lines 2, columns 1):
|
||||
Entry Name
|
||||
0 $gdb/build/gdb/testsuite
|
||||
1 $gdb/src/gdb/testsuite/gdb.tui
|
||||
...
|
||||
|
||||
Note that the used gas contains a backport of commit 3417bfca676 ("GAS:
|
||||
DWARF-5: Ensure that the 0'th entry in the directory table contains the
|
||||
current working directory."), because directory 0 is correct. With the
|
||||
unpatched 2.35.2 release the directory 0 entry is incorrect: it's a copy of
|
||||
entry 1.
|
||||
|
||||
Add a dwarf assembly test-case that reflects the debug info as generated by
|
||||
unpatched gas 2.35.2.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
---
|
||||
gdb/dwarf2/cu.c | 1 +
|
||||
gdb/dwarf2/cu.h | 1 +
|
||||
gdb/dwarf2/read.c | 37 +++++++-
|
||||
.../gdb.dwarf2/dw2-gas-workaround.exp | 92 +++++++++++++++++++
|
||||
4 files changed, 130 insertions(+), 1 deletion(-)
|
||||
create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-gas-workaround.exp
|
||||
|
||||
diff --git a/gdb/dwarf2/cu.c b/gdb/dwarf2/cu.c
|
||||
index a908ec908cd..f9b05dfc709 100644
|
||||
--- a/gdb/dwarf2/cu.c
|
||||
+++ b/gdb/dwarf2/cu.c
|
||||
@@ -40,6 +40,7 @@ dwarf2_cu::dwarf2_cu (dwarf2_per_cu_data *per_cu,
|
||||
producer_is_icc_lt_14 (false),
|
||||
producer_is_codewarrior (false),
|
||||
producer_is_clang (false),
|
||||
+ producer_is_gas_lt_2_38 (false),
|
||||
producer_is_gas_2_39 (false),
|
||||
processing_has_namespace_info (false),
|
||||
load_all_dies (false)
|
||||
diff --git a/gdb/dwarf2/cu.h b/gdb/dwarf2/cu.h
|
||||
index 6c611710503..ef8db480e3f 100644
|
||||
--- a/gdb/dwarf2/cu.h
|
||||
+++ b/gdb/dwarf2/cu.h
|
||||
@@ -265,6 +265,7 @@ struct dwarf2_cu
|
||||
bool producer_is_icc_lt_14 : 1;
|
||||
bool producer_is_codewarrior : 1;
|
||||
bool producer_is_clang : 1;
|
||||
+ bool producer_is_gas_lt_2_38 : 1;
|
||||
bool producer_is_gas_2_39 : 1;
|
||||
|
||||
/* When true, the file that we're processing is known to have
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index fc4667b782f..50fa302b43a 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -147,6 +147,8 @@ static int dwarf2_locexpr_block_index;
|
||||
static int dwarf2_loclist_block_index;
|
||||
static int ada_block_index;
|
||||
|
||||
+static bool producer_is_gas_lt_2_38 (struct dwarf2_cu *cu);
|
||||
+
|
||||
/* Size of .debug_loclists section header for 32-bit DWARF format. */
|
||||
#define LOCLIST_HEADER_SIZE32 12
|
||||
|
||||
@@ -7665,6 +7667,27 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
|
||||
|
||||
file_and_directory &fnd = find_file_and_directory (die, cu);
|
||||
|
||||
+ /* GAS supports generating dwarf-5 info starting version 2.35. Versions
|
||||
+ 2.35-2.37 generate an incorrect CU name attribute: it's relative,
|
||||
+ implicitly prefixing it with the compilation dir. Work around this by
|
||||
+ prefixing it with the source dir instead. */
|
||||
+ if (cu->header.version == 5 && !IS_ABSOLUTE_PATH (fnd.get_name ())
|
||||
+ && producer_is_gas_lt_2_38 (cu))
|
||||
+ {
|
||||
+ attr = dwarf2_attr (die, DW_AT_stmt_list, cu);
|
||||
+ if (attr != nullptr && attr->form_is_unsigned ())
|
||||
+ {
|
||||
+ sect_offset line_offset = (sect_offset) attr->as_unsigned ();
|
||||
+ line_header_up lh = dwarf_decode_line_header (line_offset, cu,
|
||||
+ fnd.get_comp_dir ());
|
||||
+ if (lh->version == 5 && lh->is_valid_file_index (1))
|
||||
+ {
|
||||
+ std::string dir = lh->include_dir_at (1);
|
||||
+ fnd.set_comp_dir (std::move (dir));
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
cu->start_compunit_symtab (fnd.get_name (), fnd.intern_comp_dir (objfile),
|
||||
lowpc);
|
||||
|
||||
@@ -11427,7 +11450,10 @@ check_producer (struct dwarf2_cu *cu)
|
||||
else if (producer_is_clang (cu->producer, &major, &minor))
|
||||
cu->producer_is_clang = true;
|
||||
else if (producer_is_gas (cu->producer, &major, &minor))
|
||||
- cu->producer_is_gas_2_39 = major == 2 && minor == 39;
|
||||
+ {
|
||||
+ cu->producer_is_gas_lt_2_38 = major < 2 || (major == 2 && minor < 38);
|
||||
+ cu->producer_is_gas_2_39 = major == 2 && minor == 39;
|
||||
+ }
|
||||
else
|
||||
{
|
||||
/* For other non-GCC compilers, expect their behavior is DWARF version
|
||||
@@ -11463,6 +11489,15 @@ producer_is_codewarrior (struct dwarf2_cu *cu)
|
||||
return cu->producer_is_codewarrior;
|
||||
}
|
||||
|
||||
+static bool
|
||||
+producer_is_gas_lt_2_38 (struct dwarf2_cu *cu)
|
||||
+{
|
||||
+ if (!cu->checked_producer)
|
||||
+ check_producer (cu);
|
||||
+
|
||||
+ return cu->producer_is_gas_lt_2_38;
|
||||
+}
|
||||
+
|
||||
static bool
|
||||
producer_is_gas_2_39 (struct dwarf2_cu *cu)
|
||||
{
|
||||
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-gas-workaround.exp b/gdb/testsuite/gdb.dwarf2/dw2-gas-workaround.exp
|
||||
new file mode 100644
|
||||
index 00000000000..ca2b10f23b3
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.dwarf2/dw2-gas-workaround.exp
|
||||
@@ -0,0 +1,92 @@
|
||||
+# Copyright 2023 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/>.
|
||||
+
|
||||
+# Test line number information in various configurations.
|
||||
+
|
||||
+load_lib dwarf.exp
|
||||
+
|
||||
+# This test can only be run on targets which support DWARF-2 and use gas.
|
||||
+require dwarf2_support
|
||||
+
|
||||
+standard_testfile dw2-lines.c -dw2.S
|
||||
+
|
||||
+with_shared_gdb {
|
||||
+ set func_info_vars [get_func_info bar]
|
||||
+}
|
||||
+
|
||||
+# Helper function.
|
||||
+proc line_for { l } {
|
||||
+ global srcfile
|
||||
+ set line [gdb_get_line_number "$l:" $srcfile]
|
||||
+ return [expr $line + 1]
|
||||
+}
|
||||
+
|
||||
+set asm_file [standard_output_file $srcfile2]
|
||||
+Dwarf::assemble $asm_file {
|
||||
+ declare_labels Llines
|
||||
+ global srcdir subdir srcfile objdir
|
||||
+ global func_info_vars
|
||||
+ foreach var $func_info_vars {
|
||||
+ global $var
|
||||
+ }
|
||||
+
|
||||
+ cu { version 5 } {
|
||||
+ compile_unit {
|
||||
+ {language @DW_LANG_Mips_Assembler}
|
||||
+ {name $srcfile}
|
||||
+ {comp_dir $objdir}
|
||||
+ {stmt_list $Llines DW_FORM_sec_offset}
|
||||
+ {producer "GNU AS 2.35.2"}
|
||||
+ } {
|
||||
+ subprogram {
|
||||
+ {external 1 flag}
|
||||
+ {name bar}
|
||||
+ {low_pc $bar_start addr}
|
||||
+ {high_pc "$bar_start + $bar_len" addr}
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ lines [list version 5] Llines {
|
||||
+ set diridx1 [include_dir "${srcdir}/${subdir}"]
|
||||
+ set diridx2 [include_dir "${srcdir}/${subdir}"]
|
||||
+ file_name "$srcfile" $diridx1
|
||||
+ file_name "$srcfile" $diridx2
|
||||
+
|
||||
+ program {
|
||||
+ DW_LNE_set_address bar_label
|
||||
+ line [line_for bar_label]
|
||||
+ DW_LNS_copy
|
||||
+
|
||||
+ DW_LNE_set_address bar_label_2
|
||||
+ DW_LNE_end_sequence
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+if { [prepare_for_testing "failed to prepare" ${testfile} \
|
||||
+ [list $srcfile $asm_file] {nodebug}] } {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+gdb_test_no_output "set debug symtab-create 1"
|
||||
+gdb_test_multiple "ptype bar" "" {
|
||||
+ -re -wrap "$objdir.*" {
|
||||
+ fail $gdb_test_name
|
||||
+ }
|
||||
+ -re -wrap "" {
|
||||
+ pass $gdb_test_name
|
||||
+ }
|
||||
+}
|
||||
|
||||
base-commit: d9951c3c9ea2e542d071710e9706ed505046fe36
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,137 +0,0 @@
|
||||
From 582fc35843fdf71b82d645d83d2903e2546cc21a Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Wed, 1 May 2024 15:10:50 +0200
|
||||
Subject: [PATCH 2/2] [gdb/symtab] Work around PR gas/29517, dwarf2 case
|
||||
|
||||
In commit 1d45d90934b ("[gdb/symtab] Work around PR gas/29517") we added a
|
||||
workaround for PR gas/29517.
|
||||
|
||||
The problem is present in gas version 2.39, and fixed in 2.40, so the
|
||||
workaround is only active for gas version == 2.39.
|
||||
|
||||
However, the problem in gas is only fixed for dwarf version >= 3, which
|
||||
supports DW_TAG_unspecified_type.
|
||||
|
||||
Fix this by also activating the workaround for dwarf version == 2.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
|
||||
PR symtab/31689
|
||||
https://sourceware.org/bugzilla/show_bug.cgi?id=31689
|
||||
---
|
||||
gdb/dwarf2/read.c | 5 +++-
|
||||
.../gdb.dwarf2/dw2-unspecified-type-foo.c | 7 ++++++
|
||||
.../gdb.dwarf2/dw2-unspecified-type.c | 3 ++-
|
||||
.../gdb.dwarf2/dw2-unspecified-type.exp | 23 ++++++++++++++++++-
|
||||
4 files changed, 35 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index 761437f6631..fc4667b782f 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -14646,10 +14646,13 @@ read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu)
|
||||
|
||||
type = die_type (die, cu);
|
||||
|
||||
+ /* PR gas/29517 occurs in 2.39, and is fixed in 2.40, but it's only fixed
|
||||
+ for dwarf version >= 3 which supports DW_TAG_unspecified_type. */
|
||||
if (type->code () == TYPE_CODE_VOID
|
||||
&& !type->is_stub ()
|
||||
&& die->child == nullptr
|
||||
- && producer_is_gas_2_39 (cu))
|
||||
+ && (cu->per_cu->version () == 2
|
||||
+ || producer_is_gas_2_39 (cu)))
|
||||
{
|
||||
/* Work around PR gas/29517, pretend we have an DW_TAG_unspecified_type
|
||||
return type. */
|
||||
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type-foo.c b/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type-foo.c
|
||||
index 164e781c9f0..bcf525a4d2e 100644
|
||||
--- a/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type-foo.c
|
||||
+++ b/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type-foo.c
|
||||
@@ -21,3 +21,10 @@ foo (void)
|
||||
asm ("foo_label: .globl foo_label");
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+int
|
||||
+foo2 (void)
|
||||
+{
|
||||
+ asm ("foo2_label: .globl foo2_label");
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type.c b/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type.c
|
||||
index e07d9517ff2..9e600f9dcce 100644
|
||||
--- a/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type.c
|
||||
+++ b/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type.c
|
||||
@@ -16,6 +16,7 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
extern int foo (void);
|
||||
+extern int foo2 (void);
|
||||
|
||||
int
|
||||
bar (void)
|
||||
@@ -27,6 +28,6 @@ bar (void)
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
- int res = foo () + bar ();
|
||||
+ int res = foo () + bar () + foo2 ();
|
||||
return res;
|
||||
}
|
||||
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type.exp b/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type.exp
|
||||
index a6f2a57e33e..947246ba44d 100644
|
||||
--- a/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type.exp
|
||||
+++ b/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type.exp
|
||||
@@ -34,11 +34,19 @@ lassign $bar_res \
|
||||
bar_start bar_len
|
||||
set bar_end "$bar_start + $bar_len"
|
||||
|
||||
+set foo2_res \
|
||||
+ [function_range foo2 \
|
||||
+ [list ${srcdir}/${subdir}/$srcfile ${srcdir}/${subdir}/$srcfile2]]
|
||||
+lassign $foo2_res \
|
||||
+ foo2_start foo2_len
|
||||
+set foo2_end "$foo2_start + $foo2_len"
|
||||
+
|
||||
# Create the DWARF.
|
||||
set asm_file [standard_output_file $srcfile3]
|
||||
Dwarf::assemble $asm_file {
|
||||
global foo_start foo_end
|
||||
global bar_start bar_end
|
||||
+ global foo2_start foo2_end
|
||||
declare_labels unspecified_type_label
|
||||
|
||||
cu {} {
|
||||
@@ -68,6 +76,19 @@ Dwarf::assemble $asm_file {
|
||||
}
|
||||
}
|
||||
}
|
||||
+
|
||||
+ cu { version 2 } {
|
||||
+ compile_unit {
|
||||
+ {language @DW_LANG_Mips_Assembler}
|
||||
+ {producer "GNU AS 2.40.0"}
|
||||
+ } {
|
||||
+ DW_TAG_subprogram {
|
||||
+ {name foo2}
|
||||
+ {low_pc $foo2_start addr}
|
||||
+ {high_pc $foo2_end addr}
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
if [prepare_for_testing "failed to prepare" $testfile \
|
||||
@@ -79,7 +100,7 @@ if ![runto_main] {
|
||||
return -1
|
||||
}
|
||||
|
||||
-foreach f {foo bar} {
|
||||
+foreach f {foo bar foo2} {
|
||||
# Print the function type. Return type should be stub type, which is printed
|
||||
# as void.
|
||||
gdb_test "ptype $f" "type = void \\(void\\)"
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,256 +0,0 @@
|
||||
From 7a2731d9d1c0926d22905b9d07e32a7b63c43b34 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Thu, 28 Sep 2023 13:55:07 +0200
|
||||
Subject: [PATCH 57/65] Work around PR gas/29517
|
||||
|
||||
When using glibc debuginfo generated with gas 2.39, we run into PR gas/29517:
|
||||
...
|
||||
$ gdb -q -batch a.out -ex start -ex "p (char *)strstr (\"haha\", \"ah\")"
|
||||
Temporary breakpoint 1 at 0x40051b: file hello.c, line 6.
|
||||
|
||||
Temporary breakpoint 1, main () at hello.c:6
|
||||
6 printf ("hello\n");
|
||||
Invalid cast.
|
||||
...
|
||||
while without glibc debuginfo installed we get the expected result:
|
||||
...
|
||||
$n = 0x7ffff7daa1b1 "aha"
|
||||
...
|
||||
and likewise with glibc debuginfo generated with gas 2.40.
|
||||
|
||||
The strstr ifunc resolves to __strstr_sse2_unaligned. The problem is that gas
|
||||
generates dwarf that states that the return type is void:
|
||||
...
|
||||
<1><3e1e58>: Abbrev Number: 2 (DW_TAG_subprogram)
|
||||
<3e1e59> DW_AT_name : __strstr_sse2_unaligned
|
||||
<3e1e5d> DW_AT_external : 1
|
||||
<3e1e5e> DW_AT_low_pc : 0xbbd2e
|
||||
<3e1e66> DW_AT_high_pc : 0xbc1c3
|
||||
...
|
||||
while the return type should be a DW_TAG_unspecified_type, as is the case
|
||||
with gas 2.40.
|
||||
|
||||
We can still use the workaround of casting to another function type for both
|
||||
__strstr_sse2_unaligned:
|
||||
...
|
||||
(gdb) p ((char * (*) (const char *, const char *))__strstr_sse2_unaligned) \
|
||||
("haha", "ah")
|
||||
$n = 0x7ffff7daa211 "aha"
|
||||
...
|
||||
and strstr (which requires using *strstr to dereference the ifunc before we
|
||||
cast):
|
||||
...
|
||||
gdb) p ((char * (*) (const char *, const char *))*strstr) ("haha", "ah")
|
||||
$n = 0x7ffff7daa251 "aha"
|
||||
...
|
||||
but that's a bit cumbersome to use.
|
||||
|
||||
Work around this in the dwarf reader, such that we have instead:
|
||||
...
|
||||
(gdb) p (char *)strstr ("haha", "ah")
|
||||
$n = 0x7ffff7daa1b1 "aha"
|
||||
...
|
||||
|
||||
This also requires fixing producer_is_gcc to stop returning true for
|
||||
producer "GNU AS 2.39.0".
|
||||
|
||||
Tested on x86_64-linux.
|
||||
|
||||
PR symtab/30911
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30911
|
||||
---
|
||||
gdb/dwarf2/cu.c | 1 +
|
||||
gdb/dwarf2/cu.h | 1 +
|
||||
gdb/dwarf2/read.c | 23 ++++++++++++
|
||||
gdb/producer.c | 8 ++++-
|
||||
.../gdb.dwarf2/dw2-unspecified-type.c | 9 ++++-
|
||||
.../gdb.dwarf2/dw2-unspecified-type.exp | 36 +++++++++++++++----
|
||||
6 files changed, 69 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/gdb/dwarf2/cu.c b/gdb/dwarf2/cu.c
|
||||
index 89de40daab0..a908ec908cd 100644
|
||||
--- a/gdb/dwarf2/cu.c
|
||||
+++ b/gdb/dwarf2/cu.c
|
||||
@@ -40,6 +40,7 @@ dwarf2_cu::dwarf2_cu (dwarf2_per_cu_data *per_cu,
|
||||
producer_is_icc_lt_14 (false),
|
||||
producer_is_codewarrior (false),
|
||||
producer_is_clang (false),
|
||||
+ producer_is_gas_2_39 (false),
|
||||
processing_has_namespace_info (false),
|
||||
load_all_dies (false)
|
||||
{
|
||||
diff --git a/gdb/dwarf2/cu.h b/gdb/dwarf2/cu.h
|
||||
index 0c15d8b02db..6c611710503 100644
|
||||
--- a/gdb/dwarf2/cu.h
|
||||
+++ b/gdb/dwarf2/cu.h
|
||||
@@ -265,6 +265,7 @@ struct dwarf2_cu
|
||||
bool producer_is_icc_lt_14 : 1;
|
||||
bool producer_is_codewarrior : 1;
|
||||
bool producer_is_clang : 1;
|
||||
+ bool producer_is_gas_2_39 : 1;
|
||||
|
||||
/* When true, the file that we're processing is known to have
|
||||
debugging info for C++ namespaces. GCC 3.3.x did not produce
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index a5c48baa6f8..e5e557c17d3 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -11426,6 +11426,8 @@ check_producer (struct dwarf2_cu *cu)
|
||||
cu->producer_is_codewarrior = true;
|
||||
else if (producer_is_clang (cu->producer, &major, &minor))
|
||||
cu->producer_is_clang = true;
|
||||
+ else if (startswith (cu->producer, "GNU AS 2.39.0"))
|
||||
+ cu->producer_is_gas_2_39 = true;
|
||||
else
|
||||
{
|
||||
/* For other non-GCC compilers, expect their behavior is DWARF version
|
||||
@@ -11461,6 +11463,15 @@ producer_is_codewarrior (struct dwarf2_cu *cu)
|
||||
return cu->producer_is_codewarrior;
|
||||
}
|
||||
|
||||
+static bool
|
||||
+producer_is_gas_2_39 (struct dwarf2_cu *cu)
|
||||
+{
|
||||
+ if (!cu->checked_producer)
|
||||
+ check_producer (cu);
|
||||
+
|
||||
+ return cu->producer_is_gas_2_39;
|
||||
+}
|
||||
+
|
||||
/* Return the accessibility of DIE, as given by DW_AT_accessibility.
|
||||
If that attribute is not available, return the appropriate
|
||||
default. */
|
||||
@@ -14635,6 +14646,18 @@ read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu)
|
||||
|
||||
type = die_type (die, cu);
|
||||
|
||||
+ if (type->code () == TYPE_CODE_VOID
|
||||
+ && !type->is_stub ()
|
||||
+ && die->child == nullptr
|
||||
+ && producer_is_gas_2_39 (cu))
|
||||
+ {
|
||||
+ /* Work around PR gas/29517, pretend we have an DW_TAG_unspecified_type
|
||||
+ return type. */
|
||||
+ type = (type_allocator (cu->per_objfile->objfile, cu->lang ())
|
||||
+ .new_type (TYPE_CODE_VOID, 0, nullptr));
|
||||
+ type->set_is_stub (true);
|
||||
+ }
|
||||
+
|
||||
/* The die_type call above may have already set the type for this DIE. */
|
||||
ftype = get_die_type (die, cu);
|
||||
if (ftype)
|
||||
diff --git a/gdb/producer.c b/gdb/producer.c
|
||||
index 655eb971283..9fcf749e3d4 100644
|
||||
--- a/gdb/producer.c
|
||||
+++ b/gdb/producer.c
|
||||
@@ -54,13 +54,19 @@ producer_is_gcc (const char *producer, int *major, int *minor)
|
||||
if (minor == NULL)
|
||||
minor = &min;
|
||||
|
||||
+ /* Skip GNU. */
|
||||
+ cs = &producer[strlen ("GNU ")];
|
||||
+
|
||||
+ /* Bail out for GNU AS. */
|
||||
+ if (startswith (cs, "AS "))
|
||||
+ return 0;
|
||||
+
|
||||
/* Skip any identifier after "GNU " - such as "C11" "C++" or "Java".
|
||||
A full producer string might look like:
|
||||
"GNU C 4.7.2"
|
||||
"GNU Fortran 4.8.2 20140120 (Red Hat 4.8.2-16) -mtune=generic ..."
|
||||
"GNU C++14 5.0.0 20150123 (experimental)"
|
||||
*/
|
||||
- cs = &producer[strlen ("GNU ")];
|
||||
while (*cs && !isspace (*cs))
|
||||
cs++;
|
||||
if (*cs && isspace (*cs))
|
||||
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type.c b/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type.c
|
||||
index 1df09214d4a..e07d9517ff2 100644
|
||||
--- a/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type.c
|
||||
+++ b/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type.c
|
||||
@@ -17,9 +17,16 @@
|
||||
|
||||
extern int foo (void);
|
||||
|
||||
+int
|
||||
+bar (void)
|
||||
+{
|
||||
+ asm ("bar_label: .globl bar_label");
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
- int res = foo ();
|
||||
+ int res = foo () + bar ();
|
||||
return res;
|
||||
}
|
||||
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type.exp b/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type.exp
|
||||
index 5fa6ee544b2..a6f2a57e33e 100644
|
||||
--- a/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type.exp
|
||||
+++ b/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type.exp
|
||||
@@ -27,10 +27,18 @@ lassign $foo_res \
|
||||
foo_start foo_len
|
||||
set foo_end "$foo_start + $foo_len"
|
||||
|
||||
+set bar_res \
|
||||
+ [function_range bar \
|
||||
+ [list ${srcdir}/${subdir}/$srcfile ${srcdir}/${subdir}/$srcfile2]]
|
||||
+lassign $bar_res \
|
||||
+ bar_start bar_len
|
||||
+set bar_end "$bar_start + $bar_len"
|
||||
+
|
||||
# Create the DWARF.
|
||||
set asm_file [standard_output_file $srcfile3]
|
||||
Dwarf::assemble $asm_file {
|
||||
global foo_start foo_end
|
||||
+ global bar_start bar_end
|
||||
declare_labels unspecified_type_label
|
||||
|
||||
cu {} {
|
||||
@@ -45,7 +53,19 @@ Dwarf::assemble $asm_file {
|
||||
{high_pc $foo_end addr}
|
||||
{type :$unspecified_type_label}
|
||||
}
|
||||
+ }
|
||||
+ }
|
||||
|
||||
+ cu {} {
|
||||
+ compile_unit {
|
||||
+ {language @DW_LANG_Mips_Assembler}
|
||||
+ {producer "GNU AS 2.39.0"}
|
||||
+ } {
|
||||
+ DW_TAG_subprogram {
|
||||
+ {name bar}
|
||||
+ {low_pc $bar_start addr}
|
||||
+ {high_pc $bar_end addr}
|
||||
+ }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -59,12 +79,14 @@ if ![runto_main] {
|
||||
return -1
|
||||
}
|
||||
|
||||
-# Print the function type. Return type should be stub type, which is printed
|
||||
-# as void.
|
||||
-gdb_test "ptype foo" "type = void \\(void\\)"
|
||||
+foreach f {foo bar} {
|
||||
+ # Print the function type. Return type should be stub type, which is printed
|
||||
+ # as void.
|
||||
+ gdb_test "ptype $f" "type = void \\(void\\)"
|
||||
|
||||
-# Call the function, casting the function to the correct function type.
|
||||
-gdb_test "p ((int (*) ()) foo) ()" " = 0"
|
||||
+ # Call the function, casting the function to the correct function type.
|
||||
+ gdb_test "p ((int (*) ()) $f) ()" " = 0"
|
||||
|
||||
-# Call the function, casting the function result to the correct type.
|
||||
-gdb_test "p (int) foo ()" " = 0"
|
||||
+ # Call the function, casting the function result to the correct type.
|
||||
+ gdb_test "p (int) $f ()" " = 0"
|
||||
+}
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,122 +0,0 @@
|
||||
From d25e3f4ed05c3a6c207263d7e532f829860b83f0 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Wed, 20 Mar 2024 09:57:49 +0100
|
||||
Subject: [PATCH 1/7] [gdb/symtab] Workaround PR gas/31115
|
||||
|
||||
On arm-linux, with gas 2.40, I run into:
|
||||
...
|
||||
(gdb) x /i main+8^M
|
||||
0x4e1 <main+7>: vrhadd.u16 d14, d14, d31^M
|
||||
(gdb) FAIL: gdb.arch/pr25124.exp: disassemble thumb instruction (1st try)
|
||||
...
|
||||
|
||||
This is a regression due to PR gas/31115, which makes gas produce a low_pc
|
||||
with the thumb bit set (0x4d8 & 0x1):
|
||||
...
|
||||
<1><24>: Abbrev Number: 2 (DW_TAG_subprogram)
|
||||
<25> DW_AT_name : main
|
||||
<29> DW_AT_external : 1
|
||||
<29> DW_AT_type : <0x2f>
|
||||
<2a> DW_AT_low_pc : 0x4d9
|
||||
<2e> DW_AT_high_pc : 12
|
||||
...
|
||||
|
||||
The regression was introduced in 2.39, and is also present in 2.40 and 2.41,
|
||||
and hasn't been fixed yet.
|
||||
|
||||
Work around this in read_func_scope, by using gdbarch_addr_bits_remove on
|
||||
low_pc and high_pc.
|
||||
|
||||
Tested on arm-linux and x86_64-linux.
|
||||
|
||||
PR tdep/31453
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31453
|
||||
---
|
||||
gdb/dwarf2/cu.c | 1 +
|
||||
gdb/dwarf2/cu.h | 1 +
|
||||
gdb/dwarf2/read.c | 22 ++++++++++++++++++++++
|
||||
3 files changed, 24 insertions(+)
|
||||
|
||||
diff --git a/gdb/dwarf2/cu.c b/gdb/dwarf2/cu.c
|
||||
index f9b05dfc709..7f89500effd 100644
|
||||
--- a/gdb/dwarf2/cu.c
|
||||
+++ b/gdb/dwarf2/cu.c
|
||||
@@ -42,6 +42,7 @@ dwarf2_cu::dwarf2_cu (dwarf2_per_cu_data *per_cu,
|
||||
producer_is_clang (false),
|
||||
producer_is_gas_lt_2_38 (false),
|
||||
producer_is_gas_2_39 (false),
|
||||
+ producer_is_gas_ge_2_40 (false),
|
||||
processing_has_namespace_info (false),
|
||||
load_all_dies (false)
|
||||
{
|
||||
diff --git a/gdb/dwarf2/cu.h b/gdb/dwarf2/cu.h
|
||||
index ef8db480e3f..1b02f89ed2f 100644
|
||||
--- a/gdb/dwarf2/cu.h
|
||||
+++ b/gdb/dwarf2/cu.h
|
||||
@@ -267,6 +267,7 @@ struct dwarf2_cu
|
||||
bool producer_is_clang : 1;
|
||||
bool producer_is_gas_lt_2_38 : 1;
|
||||
bool producer_is_gas_2_39 : 1;
|
||||
+ bool producer_is_gas_ge_2_40 : 1;
|
||||
|
||||
/* When true, the file that we're processing is known to have
|
||||
debugging info for C++ namespaces. GCC 3.3.x did not produce
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index a4f982962ae..8f2d7a34aef 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -148,6 +148,7 @@ static int dwarf2_loclist_block_index;
|
||||
static int ada_block_index;
|
||||
|
||||
static bool producer_is_gas_lt_2_38 (struct dwarf2_cu *cu);
|
||||
+static bool producer_is_gas_ge_2_39 (struct dwarf2_cu *cu);
|
||||
|
||||
/* Size of .debug_loclists section header for 32-bit DWARF format. */
|
||||
#define LOCLIST_HEADER_SIZE32 12
|
||||
@@ -10223,6 +10224,15 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
|
||||
lowpc = per_objfile->relocate (unrel_low);
|
||||
highpc = per_objfile->relocate (unrel_high);
|
||||
|
||||
+ if (gdbarch_bfd_arch_info (gdbarch)->arch == bfd_arch_arm
|
||||
+ && producer_is_gas_ge_2_39 (cu))
|
||||
+ {
|
||||
+ /* Gas version 2.39 produces DWARF for a Thumb subprogram with a low_pc
|
||||
+ attribute with the thumb bit set (PR gas/31115). Work around this. */
|
||||
+ lowpc = gdbarch_addr_bits_remove (gdbarch, lowpc);
|
||||
+ highpc = gdbarch_addr_bits_remove (gdbarch, highpc);
|
||||
+ }
|
||||
+
|
||||
/* If we have any template arguments, then we must allocate a
|
||||
different sort of symbol. */
|
||||
for (child_die = die->child; child_die; child_die = child_die->sibling)
|
||||
@@ -11507,6 +11517,7 @@ check_producer (struct dwarf2_cu *cu)
|
||||
{
|
||||
cu->producer_is_gas_lt_2_38 = major < 2 || (major == 2 && minor < 38);
|
||||
cu->producer_is_gas_2_39 = major == 2 && minor == 39;
|
||||
+ cu->producer_is_gas_ge_2_40 = major > 2 || (major == 2 && minor >= 40);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -11561,6 +11572,17 @@ producer_is_gas_2_39 (struct dwarf2_cu *cu)
|
||||
return cu->producer_is_gas_2_39;
|
||||
}
|
||||
|
||||
+/* Return true if CU is produced by GAS 2.39 or later. */
|
||||
+
|
||||
+static bool
|
||||
+producer_is_gas_ge_2_39 (struct dwarf2_cu *cu)
|
||||
+{
|
||||
+ if (!cu->checked_producer)
|
||||
+ check_producer (cu);
|
||||
+
|
||||
+ return cu->producer_is_gas_2_39 || cu->producer_is_gas_ge_2_40;
|
||||
+}
|
||||
+
|
||||
/* Return the accessibility of DIE, as given by DW_AT_accessibility.
|
||||
If that attribute is not available, return the appropriate
|
||||
default. */
|
||||
|
||||
base-commit: c79ecacd3f75cfb0ec1a3afc49ca3f30b1759009
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,47 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Burgess <aburgess@redhat.com>
|
||||
Date: Thu, 12 Oct 2023 19:42:19 +0100
|
||||
Subject: gdb-sync-coffread-with-elfread.patch
|
||||
|
||||
;; Backport upstream commit 7628a997f27.
|
||||
|
||||
gdb/coffread: bring separate debug file logic into line with elfread.c
|
||||
|
||||
In this commit:
|
||||
|
||||
commit 8a92335bfca80cc9b4cd217505ea0dcbfdefbf07
|
||||
Date: Fri Feb 1 19:39:04 2013 +0000
|
||||
|
||||
the logic for when we try to load a separate debug file in elfread.c
|
||||
was extended. The new code checks that the objfile doesn't already
|
||||
have a separate debug objfile linked to it, and that the objfile isn't
|
||||
itself a separate debug objfile for some other objfile.
|
||||
|
||||
The coffread code wasn't extended at the same time.
|
||||
|
||||
I don't know if it's possible for the coffread code to get into the
|
||||
same state where these checks are needed, but I don't see why having
|
||||
these checks would be a problem. In a later commit I plan to merge
|
||||
this part of the elfread and coffread code, so bringing these two
|
||||
pieces of code into line first makes that job easier.
|
||||
|
||||
I've tested this with a simple test binary compiled with the mingw
|
||||
toolchain on a Linux host. After compiling the binary and splitting
|
||||
out the debug info GDB still finds and loads the separate debug info.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
diff --git a/gdb/coffread.c b/gdb/coffread.c
|
||||
--- a/gdb/coffread.c
|
||||
+++ b/gdb/coffread.c
|
||||
@@ -725,7 +725,9 @@ coff_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
|
||||
}
|
||||
|
||||
/* Try to add separate debug file if no symbols table found. */
|
||||
- if (!objfile->has_partial_symbols ())
|
||||
+ else if (!objfile->has_partial_symbols ()
|
||||
+ && objfile->separate_debug_objfile == NULL
|
||||
+ && objfile->separate_debug_objfile_backlink == NULL)
|
||||
{
|
||||
deferred_warnings warnings;
|
||||
std::string debugfile
|
@@ -1,130 +0,0 @@
|
||||
From e2a2cb30bc4e85f462b817bac5393b3fee1ecf9f Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Tue, 21 Nov 2023 11:44:07 +0100
|
||||
Subject: [PATCH 3/7] [gdb/tdep] Fix catching syscall execve exit for arm
|
||||
|
||||
When running test-case gdb.base/catch-syscall.exp on a pinebook (64-bit
|
||||
aarch64 kernel, 32-bit userland) I run into:
|
||||
...
|
||||
(gdb) PASS: $exp: execve: syscall(s) execve appears in 'info breakpoints'
|
||||
continue^M
|
||||
Continuing.^M
|
||||
^M
|
||||
Catchpoint 18 (call to syscall execve), 0xf7726318 in execve () from \
|
||||
/lib/arm-linux-gnueabihf/libc.so.6^M
|
||||
(gdb) PASS: gdb.base/catch-syscall.exp: execve: program has called execve
|
||||
continue^M
|
||||
Continuing.^M
|
||||
process 32392 is executing new program: catch-syscall^M
|
||||
Cannot access memory at address 0xf77c6a7c^M
|
||||
(gdb) FAIL: $exp: execve: syscall execve has returned
|
||||
...
|
||||
|
||||
The memory error is thrown by arm_linux_get_syscall_number, when doing:
|
||||
...
|
||||
/* PC gets incremented before the syscall-stop, so read the
|
||||
previous instruction. */
|
||||
unsigned long this_instr =
|
||||
read_memory_unsigned_integer (pc - 4, 4, byte_order_for_code);
|
||||
...
|
||||
|
||||
The reason for the error is that we're stopped at the syscall exit of syscall
|
||||
execve, and the pc is at the first insn of the new exec, which also happens to
|
||||
be the first insn in the code segment, so consequently we cannot read the
|
||||
previous insn.
|
||||
|
||||
Fix this by detecting the situation by looking at the register state, similar
|
||||
to what is done in aarch64_linux_get_syscall_number.
|
||||
|
||||
Furthermore, catch the memory error by using safe_read_memory_unsigned_integer
|
||||
and return -1 instead, matching the documented behaviour of
|
||||
arm_linux_get_syscall_number.
|
||||
|
||||
Finally, rather than using a hardcoded constant 11, introduce an ad-hoc
|
||||
arm_sys_execve.
|
||||
|
||||
Tested on pinebook.
|
||||
|
||||
PR tdep/31071
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31071
|
||||
---
|
||||
gdb/arm-linux-tdep.c | 42 ++++++++++++++++++++++++++++++++++++++----
|
||||
1 file changed, 38 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c
|
||||
index 33748731cfd..8116c1368ff 100644
|
||||
--- a/gdb/arm-linux-tdep.c
|
||||
+++ b/gdb/arm-linux-tdep.c
|
||||
@@ -813,6 +813,32 @@ arm_linux_sigreturn_next_pc (struct regcache *regcache,
|
||||
return next_pc;
|
||||
}
|
||||
|
||||
+/* Return true if we're at execve syscall-exit-stop. */
|
||||
+
|
||||
+static bool
|
||||
+is_execve_syscall_exit (struct regcache *regs)
|
||||
+{
|
||||
+ ULONGEST reg = -1;
|
||||
+
|
||||
+ /* Check that lr is 0. */
|
||||
+ regcache_cooked_read_unsigned (regs, ARM_LR_REGNUM, ®);
|
||||
+ if (reg != 0)
|
||||
+ return false;
|
||||
+
|
||||
+ /* Check that r0-r8 is 0. */
|
||||
+ for (int i = 0; i <= 8; ++i)
|
||||
+ {
|
||||
+ reg = -1;
|
||||
+ regcache_cooked_read_unsigned (regs, ARM_A1_REGNUM + i, ®);
|
||||
+ if (reg != 0)
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+#define arm_sys_execve 11
|
||||
+
|
||||
/* At a ptrace syscall-stop, return the syscall number. This either
|
||||
comes from the SWI instruction (OABI) or from r7 (EABI).
|
||||
|
||||
@@ -830,6 +856,9 @@ arm_linux_get_syscall_number (struct gdbarch *gdbarch,
|
||||
int is_thumb;
|
||||
ULONGEST svc_number = -1;
|
||||
|
||||
+ if (is_execve_syscall_exit (regs))
|
||||
+ return arm_sys_execve;
|
||||
+
|
||||
regcache_cooked_read_unsigned (regs, ARM_PC_REGNUM, &pc);
|
||||
regcache_cooked_read_unsigned (regs, ARM_PS_REGNUM, &cpsr);
|
||||
is_thumb = (cpsr & t_bit) != 0;
|
||||
@@ -845,9 +874,14 @@ arm_linux_get_syscall_number (struct gdbarch *gdbarch,
|
||||
|
||||
/* PC gets incremented before the syscall-stop, so read the
|
||||
previous instruction. */
|
||||
- unsigned long this_instr =
|
||||
- read_memory_unsigned_integer (pc - 4, 4, byte_order_for_code);
|
||||
-
|
||||
+ unsigned long this_instr;
|
||||
+ {
|
||||
+ ULONGEST val;
|
||||
+ if (!safe_read_memory_unsigned_integer (pc - 4, 4, byte_order_for_code,
|
||||
+ &val))
|
||||
+ return -1;
|
||||
+ this_instr = val;
|
||||
+ }
|
||||
unsigned long svc_operand = (0x00ffffff & this_instr);
|
||||
|
||||
if (svc_operand)
|
||||
@@ -1265,7 +1299,7 @@ arm_canonicalize_syscall (int syscall)
|
||||
case 8: return gdb_sys_creat;
|
||||
case 9: return gdb_sys_link;
|
||||
case 10: return gdb_sys_unlink;
|
||||
- case 11: return gdb_sys_execve;
|
||||
+ case arm_sys_execve: return gdb_sys_execve;
|
||||
case 12: return gdb_sys_chdir;
|
||||
case 13: return gdb_sys_time;
|
||||
case 14: return gdb_sys_mknod;
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,349 +0,0 @@
|
||||
From 83b2b88c96f87a3649b4440f43a088dc6e292181 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Tue, 12 Mar 2024 17:08:18 +0100
|
||||
Subject: [PATCH 08/48] [gdb/tdep] Fix gdb.base/watch-bitfields.exp on aarch64
|
||||
|
||||
On aarch64-linux, with test-case gdb.base/watch-bitfields.exp I run into:
|
||||
...
|
||||
(gdb) continue^M
|
||||
Continuing.^M
|
||||
^M
|
||||
Hardware watchpoint 2: -location q.a^M
|
||||
^M
|
||||
Old value = 1^M
|
||||
New value = 0^M
|
||||
main () at watch-bitfields.c:42^M
|
||||
42 q.h--;^M
|
||||
(gdb) FAIL: $exp: -location watch against bitfields: q.e: 0->5: continue
|
||||
...
|
||||
|
||||
In a minimal form, if we step past line 37 which sets q.e, and we have a
|
||||
watchpoint set on q.e, it triggers:
|
||||
...
|
||||
$ gdb -q -batch watch-bitfields -ex "b 37" -ex run -ex "watch q.e" -ex step
|
||||
Breakpoint 1 at 0x410204: file watch-bitfields.c, line 37.
|
||||
|
||||
Breakpoint 1, main () at watch-bitfields.c:37
|
||||
37 q.e = 5;
|
||||
Hardware watchpoint 2: q.e
|
||||
|
||||
Hardware watchpoint 2: q.e
|
||||
|
||||
Old value = 0
|
||||
New value = 5
|
||||
main () at /home/vries/gdb/src/gdb/testsuite/gdb.base/watch-bitfields.c:38
|
||||
38 q.f = 6;
|
||||
...
|
||||
|
||||
However, if we set in addition a watchpoint on q.a, the watchpoint on q.e
|
||||
doesn't trigger.
|
||||
|
||||
How does this happen?
|
||||
|
||||
Bitfield q.a is just bit 0 of byte 0, and bitfield q.e is bit 4..7 of byte 1
|
||||
and bit 1 of byte 2. So, watch q.a should watch byte 0, and watch q.e should
|
||||
watch bytes 1 and 2.
|
||||
|
||||
Using "maint set show-debug-regs on" (and some more detailed debug prints) we
|
||||
get:
|
||||
...
|
||||
WP2: addr=0x440028 (orig=0x440029), ctrl=0x000000d5, ref.count=1
|
||||
ctrl: enabled=1, offset=1, len=2
|
||||
WP3: addr=0x440028 (orig=0x440028), ctrl=0x00000035, ref.count=1
|
||||
ctrl: enabled=1, offset=0, len=1
|
||||
...
|
||||
which matches that.
|
||||
|
||||
When executing line 37, a hardware watchpoint trap triggers and we hit
|
||||
aarch64_stopped_data_address with addr_trap == 0x440028:
|
||||
...
|
||||
(gdb) p /x addr_trap
|
||||
$1 = 0x440028
|
||||
....
|
||||
and since the loop in aarch64_stopped_data_address walks backward, we check
|
||||
WP3 first, which matches, and consequently target_stopped_by_watchpoint
|
||||
returns true in watchpoints_triggered.
|
||||
|
||||
Likewise for target_stopped_data_address, which also returns addr == 0x440028.
|
||||
Watchpoints_triggered matches watchpoint q.a to that address, and sets
|
||||
watch_triggered_yes.
|
||||
|
||||
However, subsequently the value of q.a is checked, and it's the same value as
|
||||
before (becase the insn in line 37 didn't change q.a), so the watchpoint
|
||||
hardware trap is not reported to the user.
|
||||
|
||||
The problem originates from that fact that aarch64_stopped_data_address picked
|
||||
WP3 instead of WP2.
|
||||
|
||||
There's something we can do about this. In the example above, both
|
||||
target_stopped_by_watchpoint and target_stopped_data_address returned true.
|
||||
Instead we can return true in target_stopped_by_watchpoint but false in
|
||||
target_stopped_data_address. This lets watchpoints_triggered known that a
|
||||
watchpoint was triggered, but we don't know where, and both watchpoints
|
||||
get set to watch_triggered_unknown.
|
||||
|
||||
Subsequently, the values of both q.a and q.e are checked, and since q.e is not
|
||||
the same value as before, the watchpoint hardware trap is reported to the user.
|
||||
|
||||
Note that this works well for regular (write) watchpoints (watch command), but
|
||||
not for read watchpoints (rwatch command), because for those no value is
|
||||
checked. Likewise for access watchpoints (awatch command).
|
||||
|
||||
So, fix this by:
|
||||
- passing a nullptr in aarch64_fbsd_nat_target::stopped_by_watchpoint and
|
||||
aarch64_linux_nat_target::stopped_by_watchpoint to make clear we're not
|
||||
interested in the stop address,
|
||||
- introducing a two-phase approach in aarch64_stopped_data_address, where:
|
||||
- phase one handles access and read watchpoints, as before, and
|
||||
- phase two handles write watchpoints, where multiple matches cause:
|
||||
- return true if addr_p == null, and
|
||||
- return false if addr_p != null.
|
||||
|
||||
Tested on aarch64-linux.
|
||||
|
||||
Approved-By: Luis Machado <luis.machado@arm.com>
|
||||
|
||||
PR tdep/31214
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31214
|
||||
---
|
||||
gdb/aarch64-fbsd-nat.c | 4 +-
|
||||
gdb/aarch64-linux-nat.c | 4 +-
|
||||
gdb/aarch64-nat.c | 132 ++++++++++++++++++++++++++-----------
|
||||
gdb/nat/aarch64-hw-point.c | 25 +++++++
|
||||
gdb/nat/aarch64-hw-point.h | 2 +
|
||||
5 files changed, 123 insertions(+), 44 deletions(-)
|
||||
|
||||
diff --git a/gdb/aarch64-fbsd-nat.c b/gdb/aarch64-fbsd-nat.c
|
||||
index 38fb093f139..58518248248 100644
|
||||
--- a/gdb/aarch64-fbsd-nat.c
|
||||
+++ b/gdb/aarch64-fbsd-nat.c
|
||||
@@ -164,9 +164,7 @@ aarch64_fbsd_nat_target::stopped_data_address (CORE_ADDR *addr_p)
|
||||
bool
|
||||
aarch64_fbsd_nat_target::stopped_by_watchpoint ()
|
||||
{
|
||||
- CORE_ADDR addr;
|
||||
-
|
||||
- return stopped_data_address (&addr);
|
||||
+ return stopped_data_address (nullptr);
|
||||
}
|
||||
|
||||
/* Implement the "stopped_by_hw_breakpoint" target_ops method. */
|
||||
diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
|
||||
index c1d59b5d77c..768748a20db 100644
|
||||
--- a/gdb/aarch64-linux-nat.c
|
||||
+++ b/gdb/aarch64-linux-nat.c
|
||||
@@ -972,9 +972,7 @@ aarch64_linux_nat_target::stopped_data_address (CORE_ADDR *addr_p)
|
||||
bool
|
||||
aarch64_linux_nat_target::stopped_by_watchpoint ()
|
||||
{
|
||||
- CORE_ADDR addr;
|
||||
-
|
||||
- return stopped_data_address (&addr);
|
||||
+ return stopped_data_address (nullptr);
|
||||
}
|
||||
|
||||
/* Implement the "can_do_single_step" target_ops method. */
|
||||
diff --git a/gdb/aarch64-nat.c b/gdb/aarch64-nat.c
|
||||
index ee8c5a1e21d..89d1ba6acc6 100644
|
||||
--- a/gdb/aarch64-nat.c
|
||||
+++ b/gdb/aarch64-nat.c
|
||||
@@ -231,46 +231,102 @@ bool
|
||||
aarch64_stopped_data_address (const struct aarch64_debug_reg_state *state,
|
||||
CORE_ADDR addr_trap, CORE_ADDR *addr_p)
|
||||
{
|
||||
- int i;
|
||||
-
|
||||
- for (i = aarch64_num_wp_regs - 1; i >= 0; --i)
|
||||
- {
|
||||
- const unsigned int offset
|
||||
- = aarch64_watchpoint_offset (state->dr_ctrl_wp[i]);
|
||||
- const unsigned int len = aarch64_watchpoint_length (state->dr_ctrl_wp[i]);
|
||||
- const CORE_ADDR addr_watch = state->dr_addr_wp[i] + offset;
|
||||
- const CORE_ADDR addr_watch_aligned = align_down (state->dr_addr_wp[i], 8);
|
||||
- const CORE_ADDR addr_orig = state->dr_addr_orig_wp[i];
|
||||
-
|
||||
- if (state->dr_ref_count_wp[i]
|
||||
- && DR_CONTROL_ENABLED (state->dr_ctrl_wp[i])
|
||||
- && addr_trap >= addr_watch_aligned
|
||||
- && addr_trap < addr_watch + len)
|
||||
- {
|
||||
- /* ADDR_TRAP reports the first address of the memory range
|
||||
- accessed by the CPU, regardless of what was the memory
|
||||
- range watched. Thus, a large CPU access that straddles
|
||||
- the ADDR_WATCH..ADDR_WATCH+LEN range may result in an
|
||||
- ADDR_TRAP that is lower than the
|
||||
- ADDR_WATCH..ADDR_WATCH+LEN range. E.g.:
|
||||
-
|
||||
- addr: | 4 | 5 | 6 | 7 | 8 |
|
||||
- |---- range watched ----|
|
||||
- |----------- range accessed ------------|
|
||||
-
|
||||
- In this case, ADDR_TRAP will be 4.
|
||||
-
|
||||
- To match a watchpoint known to GDB core, we must never
|
||||
- report *ADDR_P outside of any ADDR_WATCH..ADDR_WATCH+LEN
|
||||
- range. ADDR_WATCH <= ADDR_TRAP < ADDR_ORIG is a false
|
||||
- positive on kernels older than 4.10. See PR
|
||||
- external/20207. */
|
||||
+ bool found = false;
|
||||
+ for (int phase = 0; phase <= 1; ++phase)
|
||||
+ for (int i = aarch64_num_wp_regs - 1; i >= 0; --i)
|
||||
+ {
|
||||
+ if (!(state->dr_ref_count_wp[i]
|
||||
+ && DR_CONTROL_ENABLED (state->dr_ctrl_wp[i])))
|
||||
+ {
|
||||
+ /* Watchpoint disabled. */
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ const enum target_hw_bp_type type
|
||||
+ = aarch64_watchpoint_type (state->dr_ctrl_wp[i]);
|
||||
+ if (type == hw_execute)
|
||||
+ {
|
||||
+ /* Watchpoint disabled. */
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (phase == 0)
|
||||
+ {
|
||||
+ /* Phase 0: No hw_write. */
|
||||
+ if (type == hw_write)
|
||||
+ continue;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /* Phase 1: Only hw_write. */
|
||||
+ if (type != hw_write)
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ const unsigned int offset
|
||||
+ = aarch64_watchpoint_offset (state->dr_ctrl_wp[i]);
|
||||
+ const unsigned int len
|
||||
+ = aarch64_watchpoint_length (state->dr_ctrl_wp[i]);
|
||||
+ const CORE_ADDR addr_watch = state->dr_addr_wp[i] + offset;
|
||||
+ const CORE_ADDR addr_watch_aligned
|
||||
+ = align_down (state->dr_addr_wp[i], 8);
|
||||
+ const CORE_ADDR addr_orig = state->dr_addr_orig_wp[i];
|
||||
+
|
||||
+ /* ADDR_TRAP reports the first address of the memory range
|
||||
+ accessed by the CPU, regardless of what was the memory
|
||||
+ range watched. Thus, a large CPU access that straddles
|
||||
+ the ADDR_WATCH..ADDR_WATCH+LEN range may result in an
|
||||
+ ADDR_TRAP that is lower than the
|
||||
+ ADDR_WATCH..ADDR_WATCH+LEN range. E.g.:
|
||||
+
|
||||
+ addr: | 4 | 5 | 6 | 7 | 8 |
|
||||
+ |---- range watched ----|
|
||||
+ |----------- range accessed ------------|
|
||||
+
|
||||
+ In this case, ADDR_TRAP will be 4. */
|
||||
+ if (!(addr_trap >= addr_watch_aligned
|
||||
+ && addr_trap < addr_watch + len))
|
||||
+ {
|
||||
+ /* Not a match. */
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* To match a watchpoint known to GDB core, we must never
|
||||
+ report *ADDR_P outside of any ADDR_WATCH..ADDR_WATCH+LEN
|
||||
+ range. ADDR_WATCH <= ADDR_TRAP < ADDR_ORIG is a false
|
||||
+ positive on kernels older than 4.10. See PR
|
||||
+ external/20207. */
|
||||
+ if (addr_p != nullptr)
|
||||
*addr_p = addr_orig;
|
||||
- return true;
|
||||
- }
|
||||
- }
|
||||
|
||||
- return false;
|
||||
+ if (phase == 0)
|
||||
+ {
|
||||
+ /* Phase 0: Return first match. */
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ /* Phase 1. */
|
||||
+ if (addr_p == nullptr)
|
||||
+ {
|
||||
+ /* First match, and we don't need to report an address. No need
|
||||
+ to look for other matches. */
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ if (!found)
|
||||
+ {
|
||||
+ /* First match, and we need to report an address. Look for other
|
||||
+ matches. */
|
||||
+ found = true;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* More than one match, and we need to return an address. No need to
|
||||
+ look for further matches. */
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ return found;
|
||||
}
|
||||
|
||||
/* Define AArch64 maintenance commands. */
|
||||
diff --git a/gdb/nat/aarch64-hw-point.c b/gdb/nat/aarch64-hw-point.c
|
||||
index 6747e61e026..3b8cdcba23b 100644
|
||||
--- a/gdb/nat/aarch64-hw-point.c
|
||||
+++ b/gdb/nat/aarch64-hw-point.c
|
||||
@@ -73,6 +73,31 @@ aarch64_watchpoint_length (unsigned int ctrl)
|
||||
return retval;
|
||||
}
|
||||
|
||||
+/* Utility function that returns the type of a watchpoint according to the
|
||||
+ content of a hardware debug control register CTRL. */
|
||||
+
|
||||
+enum target_hw_bp_type
|
||||
+aarch64_watchpoint_type (unsigned int ctrl)
|
||||
+{
|
||||
+ unsigned int type = DR_CONTROL_TYPE (ctrl);
|
||||
+
|
||||
+ switch (type)
|
||||
+ {
|
||||
+ case 1:
|
||||
+ return hw_read;
|
||||
+ case 2:
|
||||
+ return hw_write;
|
||||
+ case 3:
|
||||
+ return hw_access;
|
||||
+ case 0:
|
||||
+ /* Reserved for a watchpoint. It must behave as if the watchpoint is
|
||||
+ disabled. */
|
||||
+ return hw_execute;
|
||||
+ default:
|
||||
+ gdb_assert_not_reached ("");
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/* Given the hardware breakpoint or watchpoint type TYPE and its
|
||||
length LEN, return the expected encoding for a hardware
|
||||
breakpoint/watchpoint control register. */
|
||||
diff --git a/gdb/nat/aarch64-hw-point.h b/gdb/nat/aarch64-hw-point.h
|
||||
index 2ff9ccb5c1c..71ae2864927 100644
|
||||
--- a/gdb/nat/aarch64-hw-point.h
|
||||
+++ b/gdb/nat/aarch64-hw-point.h
|
||||
@@ -73,6 +73,7 @@
|
||||
|
||||
#define DR_CONTROL_ENABLED(ctrl) (((ctrl) & 0x1) == 1)
|
||||
#define DR_CONTROL_MASK(ctrl) (((ctrl) >> 5) & 0xff)
|
||||
+#define DR_CONTROL_TYPE(ctrl) (((ctrl) >> 3) & 0x3)
|
||||
|
||||
/* Structure for managing the hardware breakpoint/watchpoint resources.
|
||||
DR_ADDR_* stores the address, DR_CTRL_* stores the control register
|
||||
@@ -107,6 +108,7 @@ void aarch64_notify_debug_reg_change (ptid_t ptid, int is_watchpoint,
|
||||
|
||||
unsigned int aarch64_watchpoint_offset (unsigned int ctrl);
|
||||
unsigned int aarch64_watchpoint_length (unsigned int ctrl);
|
||||
+enum target_hw_bp_type aarch64_watchpoint_type (unsigned int ctrl);
|
||||
|
||||
int aarch64_handle_breakpoint (enum target_hw_bp_type type, CORE_ADDR addr,
|
||||
int len, int is_insert, ptid_t ptid,
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,76 +0,0 @@
|
||||
From 1e64a66f72c79874016e78a4672b85cdeb506b9f Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Tue, 4 Jun 2024 09:30:03 +0000
|
||||
Subject: [PATCH] [gdb/tdep] Fix gdb.base/watchpoint-running on
|
||||
{arm,ppc64le}-linux
|
||||
|
||||
When running test-case gdb.base/watchpoint-running on ppc64le-linux, we get:
|
||||
...
|
||||
(gdb) watch global_var^M
|
||||
warning: Error when detecting the debug register interface. \
|
||||
Debug registers will be unavailable.^M
|
||||
Watchpoint 2: global_var^M
|
||||
(gdb) FAIL: $exp: all-stop: hardware: watch global_var
|
||||
FAIL: $exp: all-stop: hardware: watchpoint hit (timeout)
|
||||
...
|
||||
|
||||
The problem is that ppc_linux_dreg_interface::detect fails to detect the
|
||||
hardware watchpoint interface, because the calls to ptrace return with errno
|
||||
set to ESRCH.
|
||||
|
||||
This is a feature of ptrace: if a call is done while the tracee is not
|
||||
ptrace-stopped, it returns ESRCH.
|
||||
|
||||
Indeed, in the test-case "watch global_var" is executed while the inferior is
|
||||
running, and that triggers the first call to ppc_linux_dreg_interface::detect.
|
||||
|
||||
And because the detection failure is cached, subsequent attempts at setting
|
||||
hardware watchpoints will also fail, even if the tracee is ptrace-stopped.
|
||||
|
||||
Fix this by calling target_can_use_hardware_watchpoint from
|
||||
linux_init_ptrace_procfs, which is called from both:
|
||||
- linux_nat_target::post_attach, and
|
||||
- linux_nat_target::post_startup_inferior.
|
||||
|
||||
By fixing this here, we also fix the same problem for arm-linux.
|
||||
|
||||
Tested on ppc64le-linux and arm-linux.
|
||||
|
||||
PR tdep/31834
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31834
|
||||
PR tdep/31705
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31705
|
||||
|
||||
(cherry picked from commit bbc92bfbf25ad42548100e31e491ed3c32fbfa3e)
|
||||
---
|
||||
gdb/linux-nat.c | 12 ++++++++++++
|
||||
1 file changed, 12 insertions(+)
|
||||
|
||||
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
|
||||
index c8991cc3da4..47d74d27e11 100644
|
||||
--- a/gdb/linux-nat.c
|
||||
+++ b/gdb/linux-nat.c
|
||||
@@ -385,6 +385,18 @@ linux_init_ptrace_procfs (pid_t pid, int attached)
|
||||
linux_ptrace_init_warnings ();
|
||||
linux_proc_init_warnings ();
|
||||
proc_mem_file_is_writable ();
|
||||
+
|
||||
+ /* Some targets (for instance ppc and arm) may call ptrace to answer a
|
||||
+ target_can_use_hardware_watchpoint query, and cache the result. However,
|
||||
+ the ptrace call will fail with errno ESRCH if the tracee is not
|
||||
+ ptrace-stopped, making the query fail. And if the caching mechanism does
|
||||
+ not disregard an ESRCH result, all subsequent queries will also fail.
|
||||
+ Call it now, where we known the tracee is ptrace-stopped.
|
||||
+
|
||||
+ Other targets (for instance aarch64) do the relevant ptrace call and
|
||||
+ caching in their implementation of post_attach and post_startup_inferior,
|
||||
+ in which case this call is expected to have no effect. */
|
||||
+ target_can_use_hardware_watchpoint (bp_hardware_watchpoint, 1, 0);
|
||||
}
|
||||
|
||||
linux_nat_target::~linux_nat_target ()
|
||||
|
||||
base-commit: a6800d9c8145f25001dd39afc3571e3350573e81
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,262 +0,0 @@
|
||||
From 3efde6721b362fe0acad348443e4b961d7485717 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Thu, 14 Mar 2024 11:25:10 +0100
|
||||
Subject: [PATCH 09/48] [gdb/tdep] Fix gdb.base/watchpoint-unaligned.exp on
|
||||
aarch64
|
||||
|
||||
On aarch64-linux, with test-case gdb.base/watchpoint-unaligned.exp I run into:
|
||||
...
|
||||
(gdb) watch data.u.size8twice[1]^M
|
||||
Hardware watchpoint 241: data.u.size8twice[1]^M
|
||||
(gdb) PASS: gdb.base/watchpoint-unaligned.exp: watch data.u.size8twice[1]
|
||||
continue^M
|
||||
Continuing.^M
|
||||
FAIL: gdb.base/watchpoint-unaligned.exp: continue (timeout)
|
||||
FAIL: gdb.base/watchpoint-unaligned.exp: size8twice write
|
||||
...
|
||||
|
||||
This happens as follows.
|
||||
|
||||
We start the exec and set an 8-byte hardware watchpoint on
|
||||
data.u.size8twice[1] at address 0x440048:
|
||||
...
|
||||
(gdb) p sizeof (data.u.size8twice[1])
|
||||
$1 = 8
|
||||
(gdb) p &data.u.size8twice[1]
|
||||
$2 = (uint64_t *) 0x440048 <data+16>
|
||||
...
|
||||
|
||||
We continue execution, and a 16-byte write at address 0x440040 triggers the
|
||||
hardware watchpoint:
|
||||
...
|
||||
4101c8: a9000801 stp x1, x2, [x0]
|
||||
...
|
||||
|
||||
When checking whether a watchpoint has triggered in
|
||||
aarch64_stopped_data_address, we check against address 0x440040 (passed in
|
||||
parameter addr_trap). This behaviour is documented:
|
||||
...
|
||||
/* ADDR_TRAP reports the first address of the memory range
|
||||
accessed by the CPU, regardless of what was the memory
|
||||
range watched. ... */
|
||||
...
|
||||
and consequently the matching logic compares against an addr_watch_aligned:
|
||||
...
|
||||
&& addr_trap >= addr_watch_aligned
|
||||
&& addr_trap < addr_watch + len)
|
||||
...
|
||||
|
||||
However, the comparison fails:
|
||||
...
|
||||
(gdb) p /x addr_watch_aligned
|
||||
$3 = 0x440048
|
||||
(gdb) p addr_trap >= addr_watch_aligned
|
||||
$4 = false
|
||||
...
|
||||
|
||||
Consequently, aarch64_stopped_data_address returns false, and
|
||||
stopped_by_watchpoint returns false, and watchpoints_triggered returns 0,
|
||||
which make infrun think it's looking at a delayed hardware
|
||||
breakpoint/watchpoint trap:
|
||||
...
|
||||
[infrun] handle_signal_stop: stop_pc=0x4101c8
|
||||
[infrun] handle_signal_stop: delayed hardware breakpoint/watchpoint trap, ignoring
|
||||
...
|
||||
Infrun then ignores the trap and continues, but runs into the same situation
|
||||
again and again, causing a hang which then causes the test timeout.
|
||||
|
||||
Fix this by allowing a match 8 bytes below addr_watch_aligned. This
|
||||
introduces the possibility for false positives, so we only do this for regular
|
||||
"value changed" watchpoints.
|
||||
|
||||
An earlier version of this patch worked by aligning addr_watch_aligned to 16
|
||||
instead of 8:
|
||||
...
|
||||
- const CORE_ADDR addr_watch_aligned = align_down (state->dr_addr_wp[i], 8);
|
||||
+ const CORE_ADDR addr_watch_aligned = align_down (state->dr_addr_wp[i], 16);
|
||||
...
|
||||
but while that fixed the test-case, it didn't fix the problem completely, so
|
||||
extend the test-case to check more scenarios.
|
||||
|
||||
Tested on aarch64-linux.
|
||||
|
||||
Tested-By: Luis Machado <luis.machado@arm.com>
|
||||
Approved-By: Luis Machado <luis.machado@arm.com>
|
||||
|
||||
PR tdep/29423
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29423
|
||||
---
|
||||
gdb/aarch64-nat.c | 17 +++-
|
||||
gdb/testsuite/gdb.base/watchpoint-unaligned.c | 11 +--
|
||||
.../gdb.base/watchpoint-unaligned.exp | 78 ++++++++++++-------
|
||||
3 files changed, 68 insertions(+), 38 deletions(-)
|
||||
|
||||
diff --git a/gdb/aarch64-nat.c b/gdb/aarch64-nat.c
|
||||
index 89d1ba6acc6..a173e4e18d5 100644
|
||||
--- a/gdb/aarch64-nat.c
|
||||
+++ b/gdb/aarch64-nat.c
|
||||
@@ -269,7 +269,7 @@ aarch64_stopped_data_address (const struct aarch64_debug_reg_state *state,
|
||||
= aarch64_watchpoint_length (state->dr_ctrl_wp[i]);
|
||||
const CORE_ADDR addr_watch = state->dr_addr_wp[i] + offset;
|
||||
const CORE_ADDR addr_watch_aligned
|
||||
- = align_down (state->dr_addr_wp[i], 8);
|
||||
+ = align_down (state->dr_addr_wp[i], AARCH64_HWP_MAX_LEN_PER_REG);
|
||||
const CORE_ADDR addr_orig = state->dr_addr_orig_wp[i];
|
||||
|
||||
/* ADDR_TRAP reports the first address of the memory range
|
||||
@@ -283,8 +283,19 @@ aarch64_stopped_data_address (const struct aarch64_debug_reg_state *state,
|
||||
|---- range watched ----|
|
||||
|----------- range accessed ------------|
|
||||
|
||||
- In this case, ADDR_TRAP will be 4. */
|
||||
- if (!(addr_trap >= addr_watch_aligned
|
||||
+ In this case, ADDR_TRAP will be 4.
|
||||
+
|
||||
+ The access size also can be larger than that of the watchpoint
|
||||
+ itself. For instance, the access size of an stp instruction is 16.
|
||||
+ So, if we use stp to store to address p, and set a watchpoint on
|
||||
+ address p + 8, the reported ADDR_TRAP can be p + 8 (observed on
|
||||
+ RK3399 SOC). But it also can be p (observed on M1 SOC). Checking
|
||||
+ for this situation introduces the possibility of false positives,
|
||||
+ so we only do this for hw_write watchpoints. */
|
||||
+ const CORE_ADDR max_access_size = type == hw_write ? 16 : 8;
|
||||
+ const CORE_ADDR addr_watch_base = addr_watch_aligned -
|
||||
+ (max_access_size - AARCH64_HWP_MAX_LEN_PER_REG);
|
||||
+ if (!(addr_trap >= addr_watch_base
|
||||
&& addr_trap < addr_watch + len))
|
||||
{
|
||||
/* Not a match. */
|
||||
diff --git a/gdb/testsuite/gdb.base/watchpoint-unaligned.c b/gdb/testsuite/gdb.base/watchpoint-unaligned.c
|
||||
index b60025a64f4..d854c376be9 100644
|
||||
--- a/gdb/testsuite/gdb.base/watchpoint-unaligned.c
|
||||
+++ b/gdb/testsuite/gdb.base/watchpoint-unaligned.c
|
||||
@@ -29,7 +29,7 @@ static volatile struct
|
||||
uint32_t size4[2];
|
||||
uint16_t size2[4];
|
||||
uint8_t size1[8];
|
||||
- uint64_t size8twice[2];
|
||||
+ uint64_t size8twice[3];
|
||||
}
|
||||
u;
|
||||
} data;
|
||||
@@ -44,13 +44,14 @@ write_size8twice (void)
|
||||
static const uint64_t second = 2;
|
||||
|
||||
#ifdef __aarch64__
|
||||
+ volatile void *p = &data.u.size8twice[offset];
|
||||
asm volatile ("stp %1, %2, [%0]"
|
||||
: /* output */
|
||||
- : "r" (data.u.size8twice), "r" (first), "r" (second) /* input */
|
||||
+ : "r" (p), "r" (first), "r" (second) /* input */
|
||||
: "memory" /* clobber */);
|
||||
#else
|
||||
- data.u.size8twice[0] = first;
|
||||
- data.u.size8twice[1] = second;
|
||||
+ data.u.size8twice[offset] = first;
|
||||
+ data.u.size8twice[offset + 1] = second;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -59,7 +60,7 @@ main (void)
|
||||
{
|
||||
volatile uint64_t local;
|
||||
|
||||
- assert (sizeof (data) == 8 + 2 * 8);
|
||||
+ assert (sizeof (data) == 8 + 3 * 8);
|
||||
|
||||
write_size8twice ();
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/watchpoint-unaligned.exp b/gdb/testsuite/gdb.base/watchpoint-unaligned.exp
|
||||
index d31a9cdc2c8..c58704d033d 100644
|
||||
--- a/gdb/testsuite/gdb.base/watchpoint-unaligned.exp
|
||||
+++ b/gdb/testsuite/gdb.base/watchpoint-unaligned.exp
|
||||
@@ -151,38 +151,56 @@ foreach wpcount {4 7} {
|
||||
gdb_assert $got_hit $test
|
||||
}
|
||||
|
||||
-if ![runto_main] {
|
||||
- return -1
|
||||
-}
|
||||
-gdb_breakpoint [gdb_get_line_number "final_return"] "Breakpoint $decimal at $hex" "final_return"
|
||||
-set test {watch data.u.size8twice[1]}
|
||||
-set wpnum 0
|
||||
-gdb_test_multiple $test $test {
|
||||
- -re "Hardware watchpoint (\[0-9\]+): .*\r\n$gdb_prompt $" {
|
||||
- set wpnum $expect_out(1,string)
|
||||
- pass $gdb_test_name
|
||||
- }
|
||||
- -re "Watchpoint (\[0-9\]+): .*\r\n$gdb_prompt $" {
|
||||
- if {[istarget "arm*-*-*"]} {
|
||||
- untested $gdb_test_name
|
||||
- } else {
|
||||
- fail $gdb_test_name
|
||||
- }
|
||||
- }
|
||||
-}
|
||||
-if {$wpnum} {
|
||||
- set test "continue"
|
||||
- set got_hit 0
|
||||
- gdb_test_multiple $test $test {
|
||||
- -re "\r\nCould not insert hardware watchpoint .*\r\n$gdb_prompt $" {
|
||||
+# We've got an array with 3 8-byte elements. Do a store of 16 bytes,
|
||||
+# to:
|
||||
+# - elements 0 and 1 (offset == 0), and
|
||||
+# - elements 1 and 2 (offset == 1).
|
||||
+# For each case, check setting a watchpoint at:
|
||||
+# - the first written element (index == 0), and
|
||||
+# - the second element (index == 1).
|
||||
+foreach_with_prefix offset { 0 1 } {
|
||||
+ foreach_with_prefix index { 0 1 } {
|
||||
+
|
||||
+ clean_restart $binfile
|
||||
+
|
||||
+ if ![runto_main] {
|
||||
+ return -1
|
||||
}
|
||||
- -re "Hardware watchpoint $wpnum:.*New value = .*\r\n$gdb_prompt $" {
|
||||
- set got_hit 1
|
||||
- send_gdb "continue\n"
|
||||
- exp_continue
|
||||
+
|
||||
+ gdb_test_no_output "set var offset = $offset"
|
||||
+ gdb_breakpoint [gdb_get_line_number "final_return"] \
|
||||
+ "Breakpoint $decimal at $hex" "final_return"
|
||||
+ set watch_index [expr $offset + $index]
|
||||
+ set test "watch data.u.size8twice\[$watch_index\]"
|
||||
+ set wpnum 0
|
||||
+ gdb_test_multiple $test $test {
|
||||
+ -re "Hardware watchpoint (\[0-9\]+): .*\r\n$gdb_prompt $" {
|
||||
+ set wpnum $expect_out(1,string)
|
||||
+ pass $gdb_test_name
|
||||
+ }
|
||||
+ -re "Watchpoint (\[0-9\]+): .*\r\n$gdb_prompt $" {
|
||||
+ if {[istarget "arm*-*-*"]} {
|
||||
+ untested $gdb_test_name
|
||||
+ } else {
|
||||
+ fail $gdb_test_name
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
- -re " final_return .*\r\n$gdb_prompt $" {
|
||||
+ if {$wpnum} {
|
||||
+ set test "continue"
|
||||
+ set got_hit 0
|
||||
+ gdb_test_multiple $test $test {
|
||||
+ -re "\r\nCould not insert hardware watchpoint .*\r\n$gdb_prompt $" {
|
||||
+ }
|
||||
+ -re "Hardware watchpoint $wpnum:.*New value = .*\r\n$gdb_prompt $" {
|
||||
+ set got_hit 1
|
||||
+ send_gdb "continue\n"
|
||||
+ exp_continue
|
||||
+ }
|
||||
+ -re " final_return .*\r\n$gdb_prompt $" {
|
||||
+ }
|
||||
+ }
|
||||
+ gdb_assert $got_hit "size8twice write"
|
||||
}
|
||||
}
|
||||
- gdb_assert $got_hit "size8twice write"
|
||||
}
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,86 +0,0 @@
|
||||
From 3f0c512dc37dbede372a018732d315726a56d10e Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Wed, 1 Nov 2023 08:07:15 +0100
|
||||
Subject: [PATCH] [gdb/tdep] Fix nr array elements in ppc64_aggregate_candidate
|
||||
|
||||
On AlmaLinux 9.2 powerpc64le I run into:
|
||||
...
|
||||
(gdb) PASS: gdb.ada/array_return.exp: continuing to Create_Small_Float_Vector
|
||||
finish^M
|
||||
Run till exit from #0 pck.create_small_float_vector () at pck.adb:30^M
|
||||
0x00000000100022d4 in p () at p.adb:25^M
|
||||
25 Vector := Create_Small_Float_Vector;^M
|
||||
Value returned is $3 = (2.80259693e-45, 2.80259693e-45)^M
|
||||
(gdb) FAIL: gdb.ada/array_return.exp: value printed by finish of Create_Small_Float_Vector
|
||||
...
|
||||
while this is expected:
|
||||
...
|
||||
Value returned is $3 = (4.25, 4.25)^M
|
||||
...
|
||||
|
||||
The problem is here in ppc64_aggregate_candidate:
|
||||
...
|
||||
if (!get_array_bounds (type, &low_bound, &high_bound))
|
||||
return -1;
|
||||
count *= high_bound - low_bound
|
||||
...
|
||||
|
||||
The array type (containing 2 elements) is:
|
||||
...
|
||||
type Small_Float_Vector is array (1 .. 2) of Float;
|
||||
...
|
||||
so we have:
|
||||
...
|
||||
(gdb) p low_bound
|
||||
$1 = 1
|
||||
(gdb) p high_bound
|
||||
$2 = 2
|
||||
...
|
||||
but we calculate the number of elements in the array using
|
||||
"high_bound - low_bound", which is 1.
|
||||
|
||||
Consequently, gdb fails to correctly classify the type as a ELFv2 homogeneous
|
||||
aggregate.
|
||||
|
||||
Fix this by calculating the number of elements in the array by using
|
||||
"high_bound - low_bound + 1" instead.
|
||||
|
||||
Furthermore, high_bound can (in general, though perhaps not here) be also be
|
||||
smaller than low_bound, so to be safe take that into account as well:
|
||||
...
|
||||
LONGEST nr_array_elements = (low_bound > high_bound
|
||||
? 0
|
||||
: (high_bound - low_bound + 1));
|
||||
count *= nr_array_elements;
|
||||
...
|
||||
|
||||
Tested on powerpc64le-linux.
|
||||
|
||||
PR tdep/31015
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31015
|
||||
---
|
||||
gdb/ppc-sysv-tdep.c | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/ppc-sysv-tdep.c b/gdb/ppc-sysv-tdep.c
|
||||
index 9cea63307e6..dc89201eed2 100644
|
||||
--- a/gdb/ppc-sysv-tdep.c
|
||||
+++ b/gdb/ppc-sysv-tdep.c
|
||||
@@ -1126,7 +1126,11 @@ ppc64_aggregate_candidate (struct type *type,
|
||||
|
||||
if (!get_array_bounds (type, &low_bound, &high_bound))
|
||||
return -1;
|
||||
- count *= high_bound - low_bound;
|
||||
+
|
||||
+ LONGEST nr_array_elements = (low_bound > high_bound
|
||||
+ ? 0
|
||||
+ : (high_bound - low_bound + 1));
|
||||
+ count *= nr_array_elements;
|
||||
|
||||
/* There must be no padding. */
|
||||
if (count == 0)
|
||||
|
||||
base-commit: b1136560e772dd4c74f1fbb41f6ba840b92fb9d6
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,80 +0,0 @@
|
||||
From b8a8f319b30149f94823302d9120d83b9eee01a4 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Tue, 13 Feb 2024 09:10:54 +0100
|
||||
Subject: [PATCH 23/48] [gdb/tdep] Fix reverse execution of LDR(immediate) T4
|
||||
|
||||
When running test-case gdb.reverse/func-map-to-same-line.exp on arm-linux with
|
||||
target board unix/-mthumb, we run into:
|
||||
...
|
||||
(gdb) reverse-step
|
||||
func2 () at func-map-to-same-line.c:26
|
||||
26 {
|
||||
(gdb) FAIL: gdb.reverse/func-map-to-same-line.exp: \
|
||||
column_info_flag=column-info: step-test: reverse-step into func2
|
||||
...
|
||||
|
||||
The FAIL is caused by incorrect recording of this insn:
|
||||
...
|
||||
4f6: f85d 7b04 ldr.w r7, [sp], #4
|
||||
...
|
||||
|
||||
The insn updates the sp, but we don't record this:
|
||||
...
|
||||
$ gdb -q -batch func-map-to-same-line \
|
||||
-ex "b *func2+8" \
|
||||
-ex run \
|
||||
-ex record \
|
||||
-ex "set debug record 2" \
|
||||
-ex stepi
|
||||
Breakpoint 1 at 0x4f6: file func-map-to-same-line.c, line 27.
|
||||
|
||||
Breakpoint 1, 0xaaaaa4f6 in func2 () at func-map-to-same-line.c:27
|
||||
27 } /* END FUNC2 */
|
||||
Process record: arm_process_record addr = 0xaaaaa4f6
|
||||
Process record: add register num = 15 to record list.
|
||||
Process record: record_full_arch_list_add 0xabc6c460.
|
||||
Process record: add register num = 7 to record list.
|
||||
Process record: record_full_arch_list_add 0xabc3b868.
|
||||
Process record: add register num = 25 to record list.
|
||||
...
|
||||
[ Note that sp is r13, and we see here only r15 (pc), r7, and r25 (ps). ]
|
||||
|
||||
The problem is that the specific insn, an LDR(immediate) T4, is not handled in
|
||||
thumb2_record_ld_word.
|
||||
|
||||
Fix this by detecting the insn in thumb2_record_ld_word, and recording the
|
||||
updated base register.
|
||||
|
||||
Tested on arm-linux.
|
||||
|
||||
Reported-By: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
|
||||
Approved-By: Luis Machado <luis.machado@arm.com>
|
||||
|
||||
PR tdep/31278
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31278
|
||||
---
|
||||
gdb/arm-tdep.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
|
||||
index 04392115848..3b1682a2aea 100644
|
||||
--- a/gdb/arm-tdep.c
|
||||
+++ b/gdb/arm-tdep.c
|
||||
@@ -14156,6 +14156,14 @@ thumb2_record_ld_word (arm_insn_decode_record *thumb2_insn_r)
|
||||
record_buf[1] = ARM_PS_REGNUM;
|
||||
thumb2_insn_r->reg_rec_count = 2;
|
||||
|
||||
+ if ((thumb2_insn_r->arm_insn & 0xfff00900) == 0xf8500900)
|
||||
+ {
|
||||
+ /* Detected LDR(immediate), T4, with write-back bit set. Record Rn
|
||||
+ update. */
|
||||
+ record_buf[2] = bits (thumb2_insn_r->arm_insn, 16, 19);
|
||||
+ thumb2_insn_r->reg_rec_count++;
|
||||
+ }
|
||||
+
|
||||
REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count,
|
||||
record_buf);
|
||||
return ARM_RECORD_SUCCESS;
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,128 +0,0 @@
|
||||
From 088088cf78b937cff973c95ec6da2d86ea173b48 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Sun, 24 Sep 2023 12:30:10 +0200
|
||||
Subject: [PATCH 07/13] [gdb/testsuite] Add
|
||||
gdb.dwarf2/backward-spec-inter-cu.exp
|
||||
|
||||
Add another regression test for PR symtab/30846.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30846
|
||||
---
|
||||
.../gdb.dwarf2/backward-spec-inter-cu.exp | 103 ++++++++++++++++++
|
||||
1 file changed, 103 insertions(+)
|
||||
create mode 100644 gdb/testsuite/gdb.dwarf2/backward-spec-inter-cu.exp
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.dwarf2/backward-spec-inter-cu.exp b/gdb/testsuite/gdb.dwarf2/backward-spec-inter-cu.exp
|
||||
new file mode 100644
|
||||
index 00000000000..59b3db50dbb
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.dwarf2/backward-spec-inter-cu.exp
|
||||
@@ -0,0 +1,103 @@
|
||||
+# Copyright 2023 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/>.
|
||||
+
|
||||
+# Check that the DWARF reader works with a a DW_AT_specification that
|
||||
+# refers to an earlier DIE. Inter-cu variant of forward-spec.exp.
|
||||
+
|
||||
+load_lib dwarf.exp
|
||||
+
|
||||
+# This test can only be run on targets which support DWARF-2 and use gas.
|
||||
+require dwarf2_support
|
||||
+
|
||||
+standard_testfile main.c -debug.S
|
||||
+
|
||||
+# Set up the DWARF for the test.
|
||||
+set asm_file [standard_output_file $srcfile2]
|
||||
+Dwarf::assemble $asm_file {
|
||||
+ global srcfile
|
||||
+
|
||||
+ declare_labels spec
|
||||
+
|
||||
+ cu {} {
|
||||
+ DW_TAG_compile_unit {
|
||||
+ {DW_AT_language @DW_LANG_C_plus_plus}
|
||||
+ } {
|
||||
+ declare_labels myint
|
||||
+
|
||||
+ myint: DW_TAG_base_type {
|
||||
+ {DW_AT_byte_size 4 DW_FORM_sdata}
|
||||
+ {DW_AT_encoding @DW_ATE_signed}
|
||||
+ {DW_AT_name myint}
|
||||
+ }
|
||||
+
|
||||
+ DW_TAG_namespace {
|
||||
+ {DW_AT_name ns}
|
||||
+ } {
|
||||
+ spec: DW_TAG_variable {
|
||||
+ {DW_AT_name v}
|
||||
+ {DW_AT_type :$myint}
|
||||
+ {DW_AT_declaration 1 DW_FORM_flag_present}
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ cu {} {
|
||||
+ DW_TAG_compile_unit {
|
||||
+ {DW_AT_language @DW_LANG_C_plus_plus}
|
||||
+ } {
|
||||
+ # The new indexer has special code to compute the full
|
||||
+ # name of an object that uses a specification that appears
|
||||
+ # later in the DWARF.
|
||||
+ DW_TAG_variable {
|
||||
+ {DW_AT_specification %$spec}
|
||||
+ {DW_AT_location {
|
||||
+ DW_OP_const1u 23
|
||||
+ DW_OP_stack_value
|
||||
+ } SPECIAL_expr}
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+if {[build_executable "failed to build executable" ${testfile} \
|
||||
+ [list $srcfile $asm_file] {nodebug}]} {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+set eol "\r\n"
|
||||
+set ws "\[ \t\]"
|
||||
+
|
||||
+set worker_threads_list {}
|
||||
+
|
||||
+# Exercises the intra-shard case.
|
||||
+lappend worker_threads_list 0
|
||||
+
|
||||
+# Might exercise the inter-shard case.
|
||||
+lappend worker_threads_list default
|
||||
+
|
||||
+foreach_with_prefix worker_threads $worker_threads_list {
|
||||
+
|
||||
+ clean_restart
|
||||
+
|
||||
+ if { $worker_threads != "default" } {
|
||||
+ gdb_test_no_output "maint set worker-threads $worker_threads"
|
||||
+ }
|
||||
+
|
||||
+ gdb_load $binfile
|
||||
+
|
||||
+ gdb_test "maint print objfiles" "$eol$ws+qualified:$ws+ns::v$eol.*" \
|
||||
+ "v has parent ns"
|
||||
+}
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,128 +0,0 @@
|
||||
From a022afb07305b50fd6372015bef6c51ae461c6a9 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Sun, 24 Sep 2023 12:33:59 +0200
|
||||
Subject: [PATCH 06/13] [gdb/testsuite] Add
|
||||
gdb.dwarf2/forward-spec-inter-cu.exp
|
||||
|
||||
Add a regression test for PR symtab/30846.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30846
|
||||
---
|
||||
.../gdb.dwarf2/forward-spec-inter-cu.exp | 103 ++++++++++++++++++
|
||||
1 file changed, 103 insertions(+)
|
||||
create mode 100644 gdb/testsuite/gdb.dwarf2/forward-spec-inter-cu.exp
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.dwarf2/forward-spec-inter-cu.exp b/gdb/testsuite/gdb.dwarf2/forward-spec-inter-cu.exp
|
||||
new file mode 100644
|
||||
index 00000000000..d8367b0a162
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.dwarf2/forward-spec-inter-cu.exp
|
||||
@@ -0,0 +1,103 @@
|
||||
+# Copyright 2023 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/>.
|
||||
+
|
||||
+# Check that the DWARF reader works with a a DW_AT_specification that
|
||||
+# refers to a later DIE. Inter-cu variant of forward-spec.exp.
|
||||
+
|
||||
+load_lib dwarf.exp
|
||||
+
|
||||
+# This test can only be run on targets which support DWARF-2 and use gas.
|
||||
+require dwarf2_support
|
||||
+
|
||||
+standard_testfile main.c -debug.S
|
||||
+
|
||||
+# Set up the DWARF for the test.
|
||||
+set asm_file [standard_output_file $srcfile2]
|
||||
+Dwarf::assemble $asm_file {
|
||||
+ global srcfile
|
||||
+
|
||||
+ declare_labels spec
|
||||
+
|
||||
+ cu {} {
|
||||
+ DW_TAG_compile_unit {
|
||||
+ {DW_AT_language @DW_LANG_C_plus_plus}
|
||||
+ } {
|
||||
+ # The new indexer has special code to compute the full
|
||||
+ # name of an object that uses a specification that appears
|
||||
+ # later in the DWARF.
|
||||
+ DW_TAG_variable {
|
||||
+ {DW_AT_specification %$spec}
|
||||
+ {DW_AT_location {
|
||||
+ DW_OP_const1u 23
|
||||
+ DW_OP_stack_value
|
||||
+ } SPECIAL_expr}
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ cu {} {
|
||||
+ DW_TAG_compile_unit {
|
||||
+ {DW_AT_language @DW_LANG_C_plus_plus}
|
||||
+ } {
|
||||
+ declare_labels myint
|
||||
+
|
||||
+ myint: DW_TAG_base_type {
|
||||
+ {DW_AT_byte_size 4 DW_FORM_sdata}
|
||||
+ {DW_AT_encoding @DW_ATE_signed}
|
||||
+ {DW_AT_name myint}
|
||||
+ }
|
||||
+
|
||||
+ DW_TAG_namespace {
|
||||
+ {DW_AT_name ns}
|
||||
+ } {
|
||||
+ spec: DW_TAG_variable {
|
||||
+ {DW_AT_name v}
|
||||
+ {DW_AT_type :$myint}
|
||||
+ {DW_AT_declaration 1 DW_FORM_flag_present}
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+if {[build_executable "failed to build executable" ${testfile} \
|
||||
+ [list $srcfile $asm_file] {nodebug}]} {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+set eol "\r\n"
|
||||
+set ws "\[ \t\]"
|
||||
+
|
||||
+set worker_threads_list {}
|
||||
+
|
||||
+# Exercises the intra-shard case.
|
||||
+lappend worker_threads_list 0
|
||||
+
|
||||
+# Might exercise the inter-shard case.
|
||||
+lappend worker_threads_list default
|
||||
+
|
||||
+foreach_with_prefix worker_threads $worker_threads_list {
|
||||
+
|
||||
+ clean_restart
|
||||
+
|
||||
+ if { $worker_threads != "default" } {
|
||||
+ gdb_test_no_output "maint set worker-threads $worker_threads"
|
||||
+ }
|
||||
+
|
||||
+ gdb_load $binfile
|
||||
+
|
||||
+ gdb_test "maint print objfiles" "$eol$ws+qualified:$ws+ns::v$eol.*" \
|
||||
+ "v has parent ns"
|
||||
+}
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,51 +0,0 @@
|
||||
From 4e9077b7e451bd87e48e9868519079a5a7070106 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Tue, 2 Apr 2024 16:22:46 +0200
|
||||
Subject: [PATCH 29/48] [gdb/testsuite] Add missing include in
|
||||
gdb.base/ctf-ptype.c
|
||||
|
||||
On fedora rawhide, when running test-case gdb.base/ctf-ptype.exp, I get:
|
||||
...
|
||||
gdb compile failed, ctf-ptype.c: In function 'main':
|
||||
ctf-ptype.c:242:29: error: implicit declaration of function 'malloc' \
|
||||
[-Wimplicit-function-declaration]
|
||||
242 | v_char_pointer = (char *) malloc (1);
|
||||
| ^~~~~~
|
||||
ctf-ptype.c:1:1: note: include '<stdlib.h>' or provide a declaration of 'malloc'
|
||||
+++ |+#include <stdlib.h>
|
||||
1 | /* This test program is part of GDB, the GNU debugger.
|
||||
...
|
||||
|
||||
Fix this by adding the missing include.
|
||||
|
||||
Tested on aarch64-linux.
|
||||
---
|
||||
gdb/testsuite/gdb.base/ctf-ptype.c | 5 ++---
|
||||
1 file changed, 2 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/ctf-ptype.c b/gdb/testsuite/gdb.base/ctf-ptype.c
|
||||
index cc4e98a234f..0cea44701b9 100644
|
||||
--- a/gdb/testsuite/gdb.base/ctf-ptype.c
|
||||
+++ b/gdb/testsuite/gdb.base/ctf-ptype.c
|
||||
@@ -24,6 +24,8 @@
|
||||
* First the basic C types.
|
||||
*/
|
||||
|
||||
+#include <stdlib.h>
|
||||
+
|
||||
#if !defined (__STDC__) && !defined (_AIX)
|
||||
#define signed /**/
|
||||
#endif
|
||||
@@ -234,9 +236,6 @@ func_type v_func_type;
|
||||
|
||||
int main ()
|
||||
{
|
||||
- /* Ensure that malloc is a pointer type; avoid use of "void" and any include files. */
|
||||
-/* extern char *malloc();*/
|
||||
-
|
||||
/* Some of the tests in ptype.exp require invoking malloc, so make
|
||||
sure it is linked in to this program. */
|
||||
v_char_pointer = (char *) malloc (1);
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,47 +0,0 @@
|
||||
From a2889f1e3f71589fee9454c0aa772ce1bc540db3 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Thu, 28 Mar 2024 06:51:59 +0100
|
||||
Subject: [PATCH 35/48] [gdb/testsuite] Add missing include in
|
||||
gdb.base/rtld-step.exp
|
||||
|
||||
On fedora rawhide, with test-case gdb.base/rtld-step.exp I get:
|
||||
...
|
||||
static-pie-static-libc.c: In function '_start':^M
|
||||
static-pie-static-libc.c:1:22: error: \
|
||||
implicit declaration of function '_exit' [-Wimplicit-function-declaration]^M
|
||||
1 | void _start (void) { _exit (0); }^M
|
||||
| ^~~~~^M
|
||||
compiler exited with status 1
|
||||
...
|
||||
UNTESTED: gdb.base/rtld-step.exp: failed to compile \
|
||||
(-static-pie not supported or static libc missing)
|
||||
...
|
||||
|
||||
Fix this by adding the missing include.
|
||||
|
||||
Tested on aarch64-linux.
|
||||
|
||||
Approved-by: Kevin Buettner <kevinb@redhat.com>
|
||||
---
|
||||
gdb/testsuite/gdb.base/rtld-step.exp | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/rtld-step.exp b/gdb/testsuite/gdb.base/rtld-step.exp
|
||||
index 9a6c76d191a..bd3f89769b8 100644
|
||||
--- a/gdb/testsuite/gdb.base/rtld-step.exp
|
||||
+++ b/gdb/testsuite/gdb.base/rtld-step.exp
|
||||
@@ -86,7 +86,10 @@ set rtld_flags [list debug additional_flags=[list -static-pie -fPIE \
|
||||
-nostdlib -static -lc]]
|
||||
|
||||
if { ![gdb_can_simple_compile static-pie-static-libc \
|
||||
- "void _start (void) { _exit (0); }" \
|
||||
+ {
|
||||
+ #include <unistd.h>
|
||||
+ void _start (void) { _exit (0); }
|
||||
+ } \
|
||||
executable $rtld_flags] } {
|
||||
set reason "-static-pie not supported or static libc missing"
|
||||
untested "failed to compile ($reason)"
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,60 +0,0 @@
|
||||
From 4a08080ba59f4f66bf062a9015f9e51c765b05b5 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Fri, 29 Mar 2024 07:47:30 +0100
|
||||
Subject: [PATCH 31/48] [gdb/testsuite] Add missing includes in
|
||||
gdb.trace/collection.c
|
||||
|
||||
On fedora rawhide, with test-case gdb.trace/collection.exp, I get:
|
||||
...
|
||||
gdb compile failed, collection.c: In function 'strings_test_func':
|
||||
collection.c:227:13: error: implicit declaration of function 'malloc' \
|
||||
[-Wimplicit-function-declaration]
|
||||
227 | longloc = malloc(500);
|
||||
| ^~~~~~
|
||||
collection.c:1:1: note: \
|
||||
include '<stdlib.h>' or provide a declaration of 'malloc'
|
||||
+++ |+#include <stdlib.h>
|
||||
1 | /* This testcase is part of GDB, the GNU debugger.
|
||||
|
||||
collection.c:228:3: error: implicit declaration of function 'strcpy' \
|
||||
[-Wimplicit-function-declaration]
|
||||
228 | strcpy(longloc, ... );
|
||||
| ^~~~~~
|
||||
collection.c:1:1: note: include '<string.h>' or provide a declaration of \
|
||||
'strcpy'
|
||||
+++ |+#include <string.h>
|
||||
1 | /* This testcase is part of GDB, the GNU debugger.
|
||||
collection.c:230:8: error: implicit declaration of function 'strlen' \
|
||||
[-Wimplicit-function-declaration]
|
||||
230 | i += strlen (locstr);
|
||||
| ^~~~~~
|
||||
collection.c:230:8: note: include '<string.h>' or provide a declaration of \
|
||||
'strlen'
|
||||
...
|
||||
|
||||
Fix this by adding the missing includes.
|
||||
|
||||
Tested on aarch64-linux.
|
||||
|
||||
Approved-By: John Baldwin <jhb@FreeBSD.org>
|
||||
---
|
||||
gdb/testsuite/gdb.trace/collection.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.trace/collection.c b/gdb/testsuite/gdb.trace/collection.c
|
||||
index 3b5484748af..4ef93a3fa33 100644
|
||||
--- a/gdb/testsuite/gdb.trace/collection.c
|
||||
+++ b/gdb/testsuite/gdb.trace/collection.c
|
||||
@@ -19,6 +19,9 @@
|
||||
* Test program for trace collection
|
||||
*/
|
||||
|
||||
+#include <string.h>
|
||||
+#include <stdlib.h>
|
||||
+
|
||||
/*
|
||||
* Typedefs
|
||||
*/
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,45 +0,0 @@
|
||||
From 08ce0d63c343f7db9a504d37de25391a997b46e2 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Mon, 8 Jan 2024 13:01:50 +0100
|
||||
Subject: [PATCH] [gdb/testsuite] Add missing -no-prompt-anchor in
|
||||
gdb.base/vfork-follow-parent.exp
|
||||
|
||||
When running test-case gdb.base/vfork-follow-parent.exp it passes fine, but
|
||||
when running it with "taskset -c 0" I run into:
|
||||
...
|
||||
(gdb) inferior 1^M
|
||||
[Switching to inferior 1 [process 26606] (vfork-follow-parent-exit)]^M
|
||||
[Switching to thread 1.1 (process 26606)]^M
|
||||
(gdb) Reading symbols from vfork-follow-parent-exit...^M
|
||||
FAIL: $exp: exec_file=vfork-follow-parent-exit: target-non-stop=on: \
|
||||
non-stop=off: resolution_method=schedule-multiple: inferior 1 (timeout)
|
||||
...
|
||||
|
||||
Fix this by using -no-prompt-anchor.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
|
||||
PR testsuite/31166
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31166
|
||||
---
|
||||
gdb/testsuite/gdb.base/vfork-follow-parent.exp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/vfork-follow-parent.exp b/gdb/testsuite/gdb.base/vfork-follow-parent.exp
|
||||
index 89c38001dac..ee6f2835d8e 100644
|
||||
--- a/gdb/testsuite/gdb.base/vfork-follow-parent.exp
|
||||
+++ b/gdb/testsuite/gdb.base/vfork-follow-parent.exp
|
||||
@@ -64,7 +64,7 @@ proc do_test { resolution_method } {
|
||||
gdb_test "set schedule-multiple on"
|
||||
gdb_test "continue" "$::inferior_exited_re normally.*" \
|
||||
"continue to end of inferior 2"
|
||||
- gdb_test "inferior 1" ".*Switching to inferior 1.*"
|
||||
+ gdb_test -no-prompt-anchor "inferior 1" ".*Switching to inferior 1.*"
|
||||
gdb_test "print unblock_parent = 1" " = 1"
|
||||
} else {
|
||||
error "invalid resolution method: $resolution_method"
|
||||
|
||||
base-commit: 19185006cfe0901da907da4f09fbc197aba976a2
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,167 +0,0 @@
|
||||
From fb2b155e33f5a21259c52685ee9b24f75ac66e75 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Wed, 20 Mar 2024 19:23:48 +0100
|
||||
Subject: [PATCH 10/48] [gdb/testsuite] Add PR gdb/26967 KFAIL in two more
|
||||
test-cases
|
||||
|
||||
On aarch64-linux (debian 12), when running test-case
|
||||
gdb.base/longjmp-until-in-main.exp, I run into:
|
||||
...
|
||||
(gdb) until 33^M
|
||||
warning: Breakpoint address adjusted from 0x70f727c678928489 to 0xfff727c678928489.^M
|
||||
Warning:^M
|
||||
Cannot insert breakpoint 0.^M
|
||||
Cannot access memory at address 0xfff727c678928489^M
|
||||
^M
|
||||
0x0000fffff7e3a580 in siglongjmp () from /lib/aarch64-linux-gnu/libc.so.6^M
|
||||
(gdb) FAIL: gdb.base/longjmp-until-in-main.exp: until $line, in main
|
||||
...
|
||||
|
||||
This is PR gdb/26967: no longjmp probe is available:
|
||||
...
|
||||
(gdb) info probes stap libc ^longjmp$^M
|
||||
No probes matched.^M
|
||||
...
|
||||
and glibc applies pointer mangling which makes it fairly difficult for gdb to
|
||||
get the longjmp target.
|
||||
|
||||
There's a KFAIL for this in test-case gdb.base/longjmp.exp, added in commit
|
||||
b5e7cd5cd3d ("[gdb/testsuite] Add KFAILs in gdb.base/longjmp.exp").
|
||||
|
||||
Factor out new proc have_longjmp_probe, and use it to add similar KFAIL in
|
||||
this and one more test-case.
|
||||
|
||||
Tested on aarch64-linux.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
---
|
||||
.../gdb.base/longjmp-until-in-main.exp | 24 ++++++++++++++++---
|
||||
gdb/testsuite/gdb.base/longjmp.exp | 11 +--------
|
||||
.../premature-dummy-frame-removal.exp | 22 ++++++++++++++++-
|
||||
gdb/testsuite/lib/gdb.exp | 19 +++++++++++++++
|
||||
4 files changed, 62 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/longjmp-until-in-main.exp b/gdb/testsuite/gdb.base/longjmp-until-in-main.exp
|
||||
index c0635f23345..6167989319a 100644
|
||||
--- a/gdb/testsuite/gdb.base/longjmp-until-in-main.exp
|
||||
+++ b/gdb/testsuite/gdb.base/longjmp-until-in-main.exp
|
||||
@@ -35,10 +35,28 @@ if {![runto_main]} {
|
||||
return
|
||||
}
|
||||
|
||||
+set have_longjmp_probe [have_longjmp_probe]
|
||||
+
|
||||
delete_breakpoints
|
||||
|
||||
set until_to_line [gdb_get_line_number "until to here"]
|
||||
|
||||
-gdb_test "until $until_to_line" \
|
||||
- " until to here .*" \
|
||||
- "until \$line, in main"
|
||||
+set re_cannot_insert_bp \
|
||||
+ [multi_line \
|
||||
+ "Warning:" \
|
||||
+ "Cannot insert breakpoint $::decimal\\." \
|
||||
+ "Cannot access memory at address $::hex"]
|
||||
+
|
||||
+set test "until \$line, in main"
|
||||
+gdb_test_multiple "until $until_to_line" $test {
|
||||
+ -re -wrap "\r\n$re_cannot_insert_bp\r\n.*" {
|
||||
+ if { $have_longjmp_probe } {
|
||||
+ fail $gdb_test_name
|
||||
+ } else {
|
||||
+ kfail gdb/26967 $gdb_test_name
|
||||
+ }
|
||||
+ }
|
||||
+ -re -wrap " until to here .*" {
|
||||
+ pass $gdb_test_name
|
||||
+ }
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.base/longjmp.exp b/gdb/testsuite/gdb.base/longjmp.exp
|
||||
index f74891aa7ca..0420f4df675 100644
|
||||
--- a/gdb/testsuite/gdb.base/longjmp.exp
|
||||
+++ b/gdb/testsuite/gdb.base/longjmp.exp
|
||||
@@ -62,16 +62,7 @@ proc do_test { with_probes } {
|
||||
#
|
||||
# We detect the different failure modes and kfail these.
|
||||
|
||||
- set have_longjmp_probe 0
|
||||
- gdb_test_multiple "info probes stap libc ^longjmp$" "" {
|
||||
- -re -wrap "No probes matched\\." {
|
||||
- pass $gdb_test_name
|
||||
- }
|
||||
- -re -wrap "\r\nstap\[ \t\]+libc\[ \t\]+longjmp\[ \t\]+.*" {
|
||||
- pass $gdb_test_name
|
||||
- set have_longjmp_probe 1
|
||||
- }
|
||||
- }
|
||||
+ set have_longjmp_probe [have_longjmp_probe]
|
||||
|
||||
if { $with_probes } {
|
||||
if { !$have_longjmp_probe } {
|
||||
diff --git a/gdb/testsuite/gdb.base/premature-dummy-frame-removal.exp b/gdb/testsuite/gdb.base/premature-dummy-frame-removal.exp
|
||||
index fe906cefb14..6979345ee45 100644
|
||||
--- a/gdb/testsuite/gdb.base/premature-dummy-frame-removal.exp
|
||||
+++ b/gdb/testsuite/gdb.base/premature-dummy-frame-removal.exp
|
||||
@@ -49,7 +49,27 @@ if {![runto_main]} {
|
||||
set pyfile [gdb_remote_download host ${srcdir}/${subdir}/${testfile}.py]
|
||||
gdb_test_no_output "source ${pyfile}" "load python file"
|
||||
|
||||
-gdb_test "p some_func ()" " = 0"
|
||||
+set have_longjmp_probe [have_longjmp_probe]
|
||||
+
|
||||
+set re_cannot_insert_bp \
|
||||
+ [multi_line \
|
||||
+ "Warning:" \
|
||||
+ "Cannot insert breakpoint $::decimal\\." \
|
||||
+ "Cannot access memory at address $::hex"]
|
||||
+
|
||||
+gdb_test_multiple "p some_func ()" "" {
|
||||
+ -re -wrap "\r\n$re_cannot_insert_bp\r\n.*" {
|
||||
+ if { $have_longjmp_probe } {
|
||||
+ fail $gdb_test_name
|
||||
+ } else {
|
||||
+ kfail gdb/26967 $gdb_test_name
|
||||
+ return 0
|
||||
+ }
|
||||
+ }
|
||||
+ -re -wrap " = 0" {
|
||||
+ pass $gdb_test_name
|
||||
+ }
|
||||
+}
|
||||
|
||||
# When frame debugging is turned on, this test has (previously)
|
||||
# revealed some crashes due to the Python frame unwinder trying to
|
||||
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
|
||||
index 21967550cf6..70c2db4ac84 100644
|
||||
--- a/gdb/testsuite/lib/gdb.exp
|
||||
+++ b/gdb/testsuite/lib/gdb.exp
|
||||
@@ -4615,6 +4615,25 @@ proc skip_libstdcxx_probe_tests {} {
|
||||
return [skip_libstdcxx_probe_tests_prompt "$gdb_prompt $"]
|
||||
}
|
||||
|
||||
+# Return 1 if libc supports the longjmp probe. Note that we're not using
|
||||
+# gdb_caching_proc because the probe may have been disabled.
|
||||
+
|
||||
+proc have_longjmp_probe {} {
|
||||
+ set have_probe -1
|
||||
+ gdb_test_multiple "info probes stap libc ^longjmp$" "" {
|
||||
+ -re -wrap "No probes matched\\." {
|
||||
+ set have_probe 0
|
||||
+ }
|
||||
+ -re -wrap "\r\nstap\[ \t\]+libc\[ \t\]+longjmp\[ \t\]+.*" {
|
||||
+ set have_probe 1
|
||||
+ }
|
||||
+ }
|
||||
+ if { $have_probe == -1 } {
|
||||
+ error "failed to get libc longjmp probe status"
|
||||
+ }
|
||||
+ return $have_probe
|
||||
+}
|
||||
+
|
||||
# Helper for gdb_is_target_* procs. TARGET_NAME is the name of the target
|
||||
# we're looking for (used to build the test name). TARGET_STACK_REGEXP
|
||||
# is a regexp that will match the output of "maint print target-stack" if
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,39 +0,0 @@
|
||||
From dedb6d4ce0478d053b7e786d73f298c8e72f1f99 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Thu, 18 Jan 2024 11:14:19 +0100
|
||||
Subject: [PATCH 44/48] [gdb/testsuite] Call ldd --version in
|
||||
gdb.testsuite/dump-system-info.exp
|
||||
|
||||
Once in a while I'm looking at the gdb.log of an entire testsuite run, and I'm
|
||||
trying to establish what glibc version is used. Sometimes this is possible,
|
||||
sometimes not.
|
||||
|
||||
Make this easy by calling ldd --version in test-case
|
||||
gdb.testsuite/dump-system-info.exp, which for instance on openSUSE Leap 15.4
|
||||
gives:
|
||||
...
|
||||
$ ldd --version
|
||||
ldd (GNU libc) 2.31
|
||||
...
|
||||
$
|
||||
...
|
||||
|
||||
Tested on x86_64-linux.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
---
|
||||
gdb/testsuite/gdb.testsuite/dump-system-info.exp | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.testsuite/dump-system-info.exp b/gdb/testsuite/gdb.testsuite/dump-system-info.exp
|
||||
index 1a28b29b1c7..e3eb9eee73a 100644
|
||||
--- a/gdb/testsuite/gdb.testsuite/dump-system-info.exp
|
||||
+++ b/gdb/testsuite/gdb.testsuite/dump-system-info.exp
|
||||
@@ -36,3 +36,4 @@ proc dump_info {cmd {what ""}} {
|
||||
dump_info "cat /proc/cpuinfo" "Cpuinfo"
|
||||
dump_info "uname -a"
|
||||
dump_info "lsb_release -a"
|
||||
+dump_info "ldd --version"
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,98 +0,0 @@
|
||||
From 2e5c943519de45144a880b8ce0d693dfd13f4650 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Sat, 4 May 2024 10:41:09 +0200
|
||||
Subject: [PATCH 16/48] [gdb/testsuite] Factor out proc get_portnum
|
||||
|
||||
In gdbserver_start, we have some code that determines what port number to use:
|
||||
...
|
||||
# Port id -- either specified in baseboard file, or managed here.
|
||||
if [target_info exists gdb,socketport] {
|
||||
set portnum [target_info gdb,socketport]
|
||||
} else {
|
||||
# Bump the port number to avoid conflicts with hung ports.
|
||||
incr portnum
|
||||
}
|
||||
...
|
||||
|
||||
Factor this out into a new proc get_portnum.
|
||||
|
||||
Tested on aarch64-linux.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
---
|
||||
gdb/testsuite/lib/gdbserver-support.exp | 40 ++++++++++++++++++-------
|
||||
1 file changed, 29 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/gdb/testsuite/lib/gdbserver-support.exp b/gdb/testsuite/lib/gdbserver-support.exp
|
||||
index 30d94fd7eb6..8aaca946b7d 100644
|
||||
--- a/gdb/testsuite/lib/gdbserver-support.exp
|
||||
+++ b/gdb/testsuite/lib/gdbserver-support.exp
|
||||
@@ -129,8 +129,31 @@ proc gdb_target_cmd { args } {
|
||||
return [expr $res == 0 ? 0 : 1]
|
||||
}
|
||||
|
||||
-global portnum
|
||||
-set portnum "2345"
|
||||
+# Return a usable port number.
|
||||
+
|
||||
+proc get_portnum {} {
|
||||
+ if { [target_info exists gdb,socketport] } {
|
||||
+ # Hard-coded in target board.
|
||||
+ return [target_info gdb,socketport]
|
||||
+ }
|
||||
+
|
||||
+ # Not hard-coded in target board. Return increasing port numbers,
|
||||
+ # starting at $initial_portnum, to avoid conflicts with hung ports.
|
||||
+ set initial_portnum 2345
|
||||
+
|
||||
+ # Currently available port number.
|
||||
+ global portnum
|
||||
+
|
||||
+ # Initialize, if necessary.
|
||||
+ if { ![info exists portnum] } {
|
||||
+ set portnum $initial_portnum
|
||||
+ }
|
||||
+
|
||||
+ # Return currently available port number, and update it.
|
||||
+ set res $portnum
|
||||
+ incr portnum
|
||||
+ return $res
|
||||
+}
|
||||
|
||||
# Locate the gdbserver binary. Returns "" if gdbserver could not be found.
|
||||
|
||||
@@ -247,16 +270,10 @@ proc gdbserver_default_get_comm_port { port } {
|
||||
# Returns the target protocol and socket to connect to.
|
||||
|
||||
proc gdbserver_start { options arguments } {
|
||||
- global portnum
|
||||
global GDB_TEST_SOCKETHOST
|
||||
|
||||
# Port id -- either specified in baseboard file, or managed here.
|
||||
- if [target_info exists gdb,socketport] {
|
||||
- set portnum [target_info gdb,socketport]
|
||||
- } else {
|
||||
- # Bump the port number to avoid conflicts with hung ports.
|
||||
- incr portnum
|
||||
- }
|
||||
+ set portnum [get_portnum]
|
||||
|
||||
# Extract the local and remote host ids from the target board struct.
|
||||
if { [info exists GDB_TEST_SOCKETHOST] } {
|
||||
@@ -372,10 +389,11 @@ proc gdbserver_start { options arguments } {
|
||||
-re "Listening on" { }
|
||||
-re "Can't (bind address|listen on socket): Address already in use\\.\r\n" {
|
||||
verbose -log "Port $portnum is already in use."
|
||||
- if ![target_info exists gdb,socketport] {
|
||||
+ set other_portnum [get_portnum]
|
||||
+ if { $other_portnum != $portnum } {
|
||||
# Bump the port number to avoid the conflict.
|
||||
wait -i $expect_out(spawn_id)
|
||||
- incr portnum
|
||||
+ set portnum $other_portnum
|
||||
continue
|
||||
}
|
||||
}
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,63 +0,0 @@
|
||||
From a9cc672af5f81034f4189446aa656c08ea10e2ac Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Sat, 4 May 2024 10:41:09 +0200
|
||||
Subject: [PATCH 19/48] [gdb/testsuite] Factor out proc lock_dir
|
||||
|
||||
In lib/rocm.exp we have:
|
||||
...
|
||||
set gpu_lock_filename $objdir/gpu-parallel.lock
|
||||
...
|
||||
|
||||
This decides both the lock file name and directory.
|
||||
|
||||
Factor out a new proc lock_dir that decides on the directory, leaving just:
|
||||
...
|
||||
set gpu_lock_filename gpu-parallel.lock
|
||||
...
|
||||
|
||||
Tested on aarch64-linux.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
---
|
||||
gdb/testsuite/lib/gdb-utils.exp | 7 +++++++
|
||||
gdb/testsuite/lib/rocm.exp | 2 +-
|
||||
2 files changed, 8 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/testsuite/lib/gdb-utils.exp b/gdb/testsuite/lib/gdb-utils.exp
|
||||
index 3dc4b3a3ebc..63f6b8c3698 100644
|
||||
--- a/gdb/testsuite/lib/gdb-utils.exp
|
||||
+++ b/gdb/testsuite/lib/gdb-utils.exp
|
||||
@@ -177,10 +177,17 @@ proc lock_file_release {info} {
|
||||
}
|
||||
}
|
||||
|
||||
+# Return directory where we keep lock files.
|
||||
+
|
||||
+proc lock_dir {} {
|
||||
+ return $objdir
|
||||
+}
|
||||
+
|
||||
# Run body under lock LOCK_FILE.
|
||||
|
||||
proc with_lock { lock_file body } {
|
||||
if {[info exists ::GDB_PARALLEL]} {
|
||||
+ set lock_file [file join [lock_dir] $lock_file]
|
||||
set lock_rc [lock_file_acquire $lock_file]
|
||||
}
|
||||
|
||||
diff --git a/gdb/testsuite/lib/rocm.exp b/gdb/testsuite/lib/rocm.exp
|
||||
index 86ec29567da..a6608664f24 100644
|
||||
--- a/gdb/testsuite/lib/rocm.exp
|
||||
+++ b/gdb/testsuite/lib/rocm.exp
|
||||
@@ -105,7 +105,7 @@ gdb_caching_proc allow_hipcc_tests {} {
|
||||
|
||||
# The lock file used to ensure that only one GDB has access to the GPU
|
||||
# at a time.
|
||||
-set gpu_lock_filename $objdir/gpu-parallel.lock
|
||||
+set gpu_lock_filename gpu-parallel.lock
|
||||
|
||||
# Run body under the GPU lock. Also calls gdb_exit before releasing
|
||||
# the GPU lock.
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,160 +0,0 @@
|
||||
From d96f9a0ef44eb3a3f41e2a478b817c1d00e6e0a1 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Sat, 4 May 2024 10:41:09 +0200
|
||||
Subject: [PATCH 18/48] [gdb/testsuite] Factor out proc with_lock
|
||||
|
||||
Factor out proc with_lock from with_rocm_gpu_lock, and move required procs
|
||||
lock_file_acquire and lock_file_release to lib/gdb-utils.exp.
|
||||
|
||||
Tested on aarch64-linux.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
---
|
||||
gdb/testsuite/lib/gdb-utils.exp | 59 +++++++++++++++++++++++++++++++++
|
||||
gdb/testsuite/lib/rocm.exp | 55 +-----------------------------
|
||||
2 files changed, 60 insertions(+), 54 deletions(-)
|
||||
|
||||
diff --git a/gdb/testsuite/lib/gdb-utils.exp b/gdb/testsuite/lib/gdb-utils.exp
|
||||
index a010e14fc04..3dc4b3a3ebc 100644
|
||||
--- a/gdb/testsuite/lib/gdb-utils.exp
|
||||
+++ b/gdb/testsuite/lib/gdb-utils.exp
|
||||
@@ -138,3 +138,62 @@ proc version_compare { l1 op l2 } {
|
||||
}
|
||||
return 1
|
||||
}
|
||||
+
|
||||
+# Acquire lock file LOCKFILE. Tries forever until the lock file is
|
||||
+# successfully created.
|
||||
+
|
||||
+proc lock_file_acquire {lockfile} {
|
||||
+ verbose -log "acquiring lock file: $::subdir/${::gdb_test_file_name}.exp"
|
||||
+ while {true} {
|
||||
+ if {![catch {open $lockfile {WRONLY CREAT EXCL}} rc]} {
|
||||
+ set msg "locked by $::subdir/${::gdb_test_file_name}.exp"
|
||||
+ verbose -log "lock file: $msg"
|
||||
+ # For debugging, put info in the lockfile about who owns
|
||||
+ # it.
|
||||
+ puts $rc $msg
|
||||
+ flush $rc
|
||||
+ return [list $rc $lockfile]
|
||||
+ }
|
||||
+ after 10
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+# Release a lock file.
|
||||
+
|
||||
+proc lock_file_release {info} {
|
||||
+ verbose -log "releasing lock file: $::subdir/${::gdb_test_file_name}.exp"
|
||||
+
|
||||
+ if {![catch {fconfigure [lindex $info 0]}]} {
|
||||
+ if {![catch {
|
||||
+ close [lindex $info 0]
|
||||
+ file delete -force [lindex $info 1]
|
||||
+ } rc]} {
|
||||
+ return ""
|
||||
+ } else {
|
||||
+ return -code error "Error releasing lockfile: '$rc'"
|
||||
+ }
|
||||
+ } else {
|
||||
+ error "invalid lock"
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+# Run body under lock LOCK_FILE.
|
||||
+
|
||||
+proc with_lock { lock_file body } {
|
||||
+ if {[info exists ::GDB_PARALLEL]} {
|
||||
+ set lock_rc [lock_file_acquire $lock_file]
|
||||
+ }
|
||||
+
|
||||
+ set code [catch {uplevel 1 $body} result]
|
||||
+
|
||||
+ if {[info exists ::GDB_PARALLEL]} {
|
||||
+ lock_file_release $lock_rc
|
||||
+ }
|
||||
+
|
||||
+ if {$code == 1} {
|
||||
+ global errorInfo errorCode
|
||||
+ return -code $code -errorinfo $errorInfo -errorcode $errorCode $result
|
||||
+ } else {
|
||||
+ return -code $code $result
|
||||
+ }
|
||||
+}
|
||||
diff --git a/gdb/testsuite/lib/rocm.exp b/gdb/testsuite/lib/rocm.exp
|
||||
index fcdf665aef9..86ec29567da 100644
|
||||
--- a/gdb/testsuite/lib/rocm.exp
|
||||
+++ b/gdb/testsuite/lib/rocm.exp
|
||||
@@ -107,68 +107,15 @@ gdb_caching_proc allow_hipcc_tests {} {
|
||||
# at a time.
|
||||
set gpu_lock_filename $objdir/gpu-parallel.lock
|
||||
|
||||
-# Acquire lock file LOCKFILE. Tries forever until the lock file is
|
||||
-# successfully created.
|
||||
-
|
||||
-proc lock_file_acquire {lockfile} {
|
||||
- verbose -log "acquiring lock file: $::subdir/${::gdb_test_file_name}.exp"
|
||||
- while {true} {
|
||||
- if {![catch {open $lockfile {WRONLY CREAT EXCL}} rc]} {
|
||||
- set msg "locked by $::subdir/${::gdb_test_file_name}.exp"
|
||||
- verbose -log "lock file: $msg"
|
||||
- # For debugging, put info in the lockfile about who owns
|
||||
- # it.
|
||||
- puts $rc $msg
|
||||
- flush $rc
|
||||
- return [list $rc $lockfile]
|
||||
- }
|
||||
- after 10
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-# Release a lock file.
|
||||
-
|
||||
-proc lock_file_release {info} {
|
||||
- verbose -log "releasing lock file: $::subdir/${::gdb_test_file_name}.exp"
|
||||
-
|
||||
- if {![catch {fconfigure [lindex $info 0]}]} {
|
||||
- if {![catch {
|
||||
- close [lindex $info 0]
|
||||
- file delete -force [lindex $info 1]
|
||||
- } rc]} {
|
||||
- return ""
|
||||
- } else {
|
||||
- return -code error "Error releasing lockfile: '$rc'"
|
||||
- }
|
||||
- } else {
|
||||
- error "invalid lock"
|
||||
- }
|
||||
-}
|
||||
-
|
||||
# Run body under the GPU lock. Also calls gdb_exit before releasing
|
||||
# the GPU lock.
|
||||
|
||||
proc with_rocm_gpu_lock { body } {
|
||||
- if {[info exists ::GDB_PARALLEL]} {
|
||||
- set lock_rc [lock_file_acquire $::gpu_lock_filename]
|
||||
- }
|
||||
-
|
||||
- set code [catch {uplevel 1 $body} result]
|
||||
+ with_lock $::gpu_lock_filename $body
|
||||
|
||||
# In case BODY returned early due to some testcase failing, and
|
||||
# left GDB running, debugging the GPU.
|
||||
gdb_exit
|
||||
-
|
||||
- if {[info exists ::GDB_PARALLEL]} {
|
||||
- lock_file_release $lock_rc
|
||||
- }
|
||||
-
|
||||
- if {$code == 1} {
|
||||
- global errorInfo errorCode
|
||||
- return -code $code -errorinfo $errorInfo -errorcode $errorCode $result
|
||||
- } else {
|
||||
- return -code $code $result
|
||||
- }
|
||||
}
|
||||
|
||||
# Return true if all the devices support debugging multiple processes
|
||||
--
|
||||
2.35.3
|
||||
|
40
gdb-testsuite-fix-another-regexp-in-gdb.threads-step.patch
Normal file
40
gdb-testsuite-fix-another-regexp-in-gdb.threads-step.patch
Normal file
@@ -0,0 +1,40 @@
|
||||
From 210d0ce41454a56ee39ff97d5353c98b38c8ac5f Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Thu, 29 Aug 2024 11:39:02 +0200
|
||||
Subject: [PATCH 17/37] [gdb/testsuite] Fix another regexp in
|
||||
gdb.threads/stepi-over-clone.exp
|
||||
|
||||
On openSUSE Tumbleweed, I run into:
|
||||
...
|
||||
(gdb) PASS: gdb.threads/stepi-over-clone.exp: catch process syscalls
|
||||
continue^M
|
||||
Continuing.^M
|
||||
^M
|
||||
Catchpoint 2 (call to syscall clone3), __clone3 () at clone3.S:62^M
|
||||
(gdb) FAIL: gdb.threads/stepi-over-clone.exp: continue
|
||||
...
|
||||
|
||||
Fix this by updating another (see commit 8fbf220321d) regexp to also recognize
|
||||
__clone3.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
---
|
||||
gdb/testsuite/gdb.threads/stepi-over-clone.exp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.threads/stepi-over-clone.exp b/gdb/testsuite/gdb.threads/stepi-over-clone.exp
|
||||
index f671fd7b8bd..a9f3cb52fca 100644
|
||||
--- a/gdb/testsuite/gdb.threads/stepi-over-clone.exp
|
||||
+++ b/gdb/testsuite/gdb.threads/stepi-over-clone.exp
|
||||
@@ -50,7 +50,7 @@ gdb_test_multiple "catch syscall group:process" "catch process syscalls" {
|
||||
|
||||
set re_loc1 "$hex in clone\[23\]? \\(\\)"
|
||||
set re_loc2 "$decimal\[ \t\]+in \[^\r\n\]+"
|
||||
-set re_loc3 "clone\[23\]? \\(\\) at \[^:\]+:$decimal"
|
||||
+set re_loc3 "(__)?clone\[23\]? \\(\\) at \[^:\]+:$decimal"
|
||||
|
||||
gdb_test "continue" \
|
||||
"Catchpoint $decimal \\(call to syscall clone\[23\]?\\), ($re_loc1|$re_loc3).*"
|
||||
--
|
||||
2.43.0
|
||||
|
@@ -1,84 +0,0 @@
|
||||
From d9a17115fbeb8d4c1780677bb57edf0fe8448038 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Tue, 2 Apr 2024 16:14:39 +0200
|
||||
Subject: [PATCH 30/48] [gdb/testsuite] Fix gdb.ada/verylong.exp on 32-bit
|
||||
target
|
||||
|
||||
In an aarch32-linux chroot on an aarch64-linux system, I run into:
|
||||
...
|
||||
(gdb) print x^M
|
||||
$1 = 9223372036854775807^M
|
||||
(gdb) FAIL: gdb.ada/verylong.exp: print x
|
||||
...
|
||||
|
||||
A passing version on aarch64-linux looks like:
|
||||
...
|
||||
(gdb) print x^M
|
||||
$1 = 170141183460469231731687303715884105727^M
|
||||
(gdb) PASS: gdb.ada/verylong.exp: print x
|
||||
...
|
||||
|
||||
The difference is caused by the size of the type Long_Long_Long_Integer, which
|
||||
is:
|
||||
- a 128-bit signed on 64-bit targets, and
|
||||
- a 64-bit signed on 32-bit target.
|
||||
|
||||
Fix this by detecting the size of the Long_Long_Long_Integer type, and
|
||||
handling it.
|
||||
|
||||
Tested on aarch64-linux and aarch32-linux.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
PR testsuite/31574
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31574
|
||||
|
||||
[1] https://gcc.gnu.org/onlinedocs/gnat_rm/Implementation-Defined-Characteristics.html
|
||||
---
|
||||
gdb/testsuite/gdb.ada/verylong.exp | 28 +++++++++++++++++++++-------
|
||||
1 file changed, 21 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.ada/verylong.exp b/gdb/testsuite/gdb.ada/verylong.exp
|
||||
index d1fa968015b..4b83e0bd467 100644
|
||||
--- a/gdb/testsuite/gdb.ada/verylong.exp
|
||||
+++ b/gdb/testsuite/gdb.ada/verylong.exp
|
||||
@@ -29,15 +29,29 @@ clean_restart ${testfile}
|
||||
set bp_location [gdb_get_line_number "START" ${testdir}/prog.adb]
|
||||
runto "prog.adb:$bp_location"
|
||||
|
||||
-gdb_test "print x" " = 170141183460469231731687303715884105727"
|
||||
-gdb_test "print x / 2" " = 85070591730234615865843651857942052863"
|
||||
-gdb_test "print (x / 4) * 2" " = 85070591730234615865843651857942052862"
|
||||
+set lll_int_size 0
|
||||
+gdb_test_multiple "ptype Long_Long_Long_Integer" "" {
|
||||
+ -re -wrap "type = <8-byte integer>" {
|
||||
+ set lll_int_size 8
|
||||
+ set max 9223372036854775807
|
||||
+ }
|
||||
+ -re -wrap "type = <16-byte integer>" {
|
||||
+ set lll_int_size 16
|
||||
+ set max 170141183460469231731687303715884105727
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+require {expr $lll_int_size == 8 || $lll_int_size == 16}
|
||||
+
|
||||
+gdb_test "print x" " = $max"
|
||||
+gdb_test "print x / 2" " = [expr $max / 2]"
|
||||
+gdb_test "print (x / 4) * 2" " = [expr ($max / 4) * 2]"
|
||||
gdb_test "print x - x" " = 0"
|
||||
-gdb_test "print x - 99 + 1" " = 170141183460469231731687303715884105629"
|
||||
-gdb_test "print -x" " = -170141183460469231731687303715884105727"
|
||||
-gdb_test "print +x" " = 170141183460469231731687303715884105727"
|
||||
+gdb_test "print x - 99 + 1" " = [expr $max - 99 + 1]"
|
||||
+gdb_test "print -x" " = -$max"
|
||||
+gdb_test "print +x" " = $max"
|
||||
|
||||
gdb_test "print 170141183460469231731687303715884105727" \
|
||||
" = 170141183460469231731687303715884105727"
|
||||
-gdb_test "print x = 170141183460469231731687303715884105727" \
|
||||
+gdb_test "print x = $max" \
|
||||
" = true"
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,80 +0,0 @@
|
||||
From 7ee7b011e0c846a77cb4d1dde3a3c625412f1733 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Thu, 25 Jan 2024 16:25:07 +0100
|
||||
Subject: [PATCH 11/48] [gdb/testsuite] Fix gdb.base/eh_return.exp
|
||||
|
||||
On Fedora rawhide aarch64, I run into:
|
||||
...
|
||||
(gdb) PASS: gdb.base/eh_return.exp: set breakpoint on address
|
||||
run ^M
|
||||
Starting program: eh_return ^M
|
||||
[Thread debugging using libthread_db enabled]^M
|
||||
Using host libthread_db library "/lib64/libthread_db.so.1".^M
|
||||
[Inferior 1 (process 1113051) exited normally]^M
|
||||
(gdb) FAIL: gdb.base/eh_return.exp: hit breakpoint (the program exited)
|
||||
...
|
||||
|
||||
This happens as follows: the test-case sets a breakpoint on the last
|
||||
instruction of function eh2:
|
||||
...
|
||||
(gdb) break *0x00000000004103ec^M
|
||||
...
|
||||
and expects to hit the breakpoint, but instead the "br x6" is taken:
|
||||
...
|
||||
0x00000000004103e0 <+176>: cbz x4, 0x4103ec <eh2+188>^M
|
||||
0x00000000004103e4 <+180>: add sp, sp, x5^M
|
||||
0x00000000004103e8 <+184>: br x6^M
|
||||
0x00000000004103ec <+188>: ret^M
|
||||
...
|
||||
|
||||
In contrast, with fedora f39 we have:
|
||||
...
|
||||
0x00000000004103bc <+156>: ldp x2, x3, [sp, #48]^M
|
||||
0x00000000004103c0 <+160>: ldp x29, x30, [sp, #16]^M
|
||||
0x00000000004103c4 <+164>: add sp, sp, #0x50^M
|
||||
0x00000000004103c8 <+168>: add sp, sp, x4^M
|
||||
0x00000000004103cc <+172>: ret^M
|
||||
|
||||
...
|
||||
and the breakpoint is reached.
|
||||
|
||||
Fix this by detecting that the breakpoint is not hit, and declaring the test
|
||||
unsupported.
|
||||
|
||||
Tested on aarch64-linux.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
PR testsuite/31291
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31291
|
||||
---
|
||||
gdb/testsuite/gdb.base/eh_return.exp | 16 +++++++++++++++-
|
||||
1 file changed, 15 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/eh_return.exp b/gdb/testsuite/gdb.base/eh_return.exp
|
||||
index bced409547b..7d566b1ddc2 100644
|
||||
--- a/gdb/testsuite/gdb.base/eh_return.exp
|
||||
+++ b/gdb/testsuite/gdb.base/eh_return.exp
|
||||
@@ -79,4 +79,18 @@ gdb_assert [gdb_breakpoint "*$address" no-message] "set breakpoint on address"
|
||||
# breakpoint, so instead, run to the breakpoint.
|
||||
gdb_run_cmd
|
||||
|
||||
-gdb_test "" "Breakpoint .*" "hit breakpoint"
|
||||
+set test "hit breakpoint"
|
||||
+gdb_expect {
|
||||
+ -re "Breakpoint .*\r\n$gdb_prompt $" {
|
||||
+ pass $test
|
||||
+ }
|
||||
+ -re "$inferior_exited_re normally.*\r\n$gdb_prompt $" {
|
||||
+ unsupported $test
|
||||
+ }
|
||||
+ -re "\r\n$gdb_prompt $" {
|
||||
+ fail $test
|
||||
+ }
|
||||
+ default {
|
||||
+ fail $test
|
||||
+ }
|
||||
+}
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,58 +0,0 @@
|
||||
From 5f7c4f7a435571d535c2372b999e1017eefb15c4 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Thu, 28 Mar 2024 08:26:31 +0100
|
||||
Subject: [PATCH 33/48] [gdb/testsuite] Fix gdb.base/ending-run.exp on manjaro
|
||||
linux
|
||||
|
||||
On aarch64-linux, using the manjaro linux distro, I run into:
|
||||
...
|
||||
(gdb) next^M
|
||||
32 }^M
|
||||
(gdb) next^M
|
||||
0x0000fffff7d67b80 in ?? () from /usr/lib/libc.so.6^M
|
||||
(gdb) FAIL: gdb.base/ending-run.exp: step out of main
|
||||
...
|
||||
|
||||
What happens here is described in detail in this clause:
|
||||
...
|
||||
-re "0x.*\\?\\? \\(\\) from /lib/powerpc.*$gdb_prompt $" {
|
||||
# This case occurs on Powerpc when gdb steps out of main and the
|
||||
# needed debug info files are not loaded on the system, preventing
|
||||
# GDB to determine which function it reached (__libc_start_call_main).
|
||||
# Ideally, the target system would have the necessary debugging
|
||||
# information, but in its absence, GDB's behavior is as expected.
|
||||
...
|
||||
}
|
||||
...
|
||||
but the clause only matches for powerpc.
|
||||
|
||||
Fix this by:
|
||||
- making the regexp generic enough to also match /usr/lib/libc.so.6, and
|
||||
- updating the comment to not mention powerpc.
|
||||
|
||||
Tested on aarch64-linux.
|
||||
|
||||
PR testsuite/31450
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31450
|
||||
---
|
||||
gdb/testsuite/gdb.base/ending-run.exp | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/ending-run.exp b/gdb/testsuite/gdb.base/ending-run.exp
|
||||
index 070dcc6f190..76701d33e19 100644
|
||||
--- a/gdb/testsuite/gdb.base/ending-run.exp
|
||||
+++ b/gdb/testsuite/gdb.base/ending-run.exp
|
||||
@@ -206,8 +206,8 @@ gdb_test_multiple "next" "step out of main" {
|
||||
# This is what happens on system using uClibc.
|
||||
pass "step out of main"
|
||||
}
|
||||
- -re "0x.*\\?\\? \\(\\) from /lib/powerpc.*$gdb_prompt $" {
|
||||
- # This case occurs on Powerpc when gdb steps out of main and the
|
||||
+ -re -wrap "$hex in \\?\\? \\(\\) from \[^\r\n\]+" {
|
||||
+ # This case occurs when gdb steps out of main and the
|
||||
# needed debug info files are not loaded on the system, preventing
|
||||
# GDB to determine which function it reached (__libc_start_call_main).
|
||||
# Ideally, the target system would have the necessary debugging
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,103 +0,0 @@
|
||||
From 2235f362eba0387f0404620676dd29637ff17738 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Sun, 17 Mar 2024 16:48:43 +0100
|
||||
Subject: [PATCH 39/48] [gdb/testsuite] Fix gdb.base/list-no-debug.exp on
|
||||
debian
|
||||
|
||||
On debian 12, aarch64-linux I run into:
|
||||
...
|
||||
(gdb) list .^M
|
||||
No symbol table is loaded. Use the "file" command.^M
|
||||
(gdb) FAIL: gdb.base/list-nodebug.exp: first 'list .'
|
||||
...
|
||||
|
||||
The test-case expects some debug info, but none for main. Instead, there's no
|
||||
debug info at all.
|
||||
|
||||
Fix this by adding another source file to the test-case, and compiling it with
|
||||
debug info.
|
||||
|
||||
Tested on aarch64-linux.
|
||||
|
||||
Approved-By: Andrew Burgess <aburgess@redhat.com>
|
||||
|
||||
PR testsuite/31290
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31290
|
||||
---
|
||||
gdb/testsuite/gdb.base/list-nodebug-2.c | 24 ++++++++++++++++++++++++
|
||||
gdb/testsuite/gdb.base/list-nodebug.c | 7 +++++--
|
||||
gdb/testsuite/gdb.base/list-nodebug.exp | 9 ++++++---
|
||||
3 files changed, 35 insertions(+), 5 deletions(-)
|
||||
create mode 100644 gdb/testsuite/gdb.base/list-nodebug-2.c
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/list-nodebug-2.c b/gdb/testsuite/gdb.base/list-nodebug-2.c
|
||||
new file mode 100644
|
||||
index 00000000000..861e6149071
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/list-nodebug-2.c
|
||||
@@ -0,0 +1,24 @@
|
||||
+/* This testcase is part of GDB, the GNU debugger.
|
||||
+
|
||||
+ Copyright 2024 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/>. */
|
||||
+
|
||||
+extern int foo (void);
|
||||
+
|
||||
+int
|
||||
+foo (void)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.base/list-nodebug.c b/gdb/testsuite/gdb.base/list-nodebug.c
|
||||
index 078517c011e..d4ae6787310 100644
|
||||
--- a/gdb/testsuite/gdb.base/list-nodebug.c
|
||||
+++ b/gdb/testsuite/gdb.base/list-nodebug.c
|
||||
@@ -15,7 +15,10 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
-int main ()
|
||||
+extern int foo (void);
|
||||
+
|
||||
+int
|
||||
+main (void)
|
||||
{
|
||||
- return 0;
|
||||
+ return foo ();
|
||||
}
|
||||
diff --git a/gdb/testsuite/gdb.base/list-nodebug.exp b/gdb/testsuite/gdb.base/list-nodebug.exp
|
||||
index 08de05423af..942a282083a 100644
|
||||
--- a/gdb/testsuite/gdb.base/list-nodebug.exp
|
||||
+++ b/gdb/testsuite/gdb.base/list-nodebug.exp
|
||||
@@ -16,10 +16,13 @@
|
||||
# Test that using the command "list" in a file with no debug information
|
||||
# will not crash GDB and will give reasonable output.
|
||||
|
||||
-standard_testfile .c
|
||||
+standard_testfile .c -2.c
|
||||
|
||||
-if {[prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \
|
||||
- {nodebug}]} {
|
||||
+if { [prepare_for_testing_full "failed to prepare" \
|
||||
+ [list \
|
||||
+ $testfile {} \
|
||||
+ $srcfile {nodebug} \
|
||||
+ $srcfile2 {debug}]] } {
|
||||
return -1
|
||||
}
|
||||
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,57 +0,0 @@
|
||||
From 818f70aa9a6c17ddc79ac33f80c1a3e4df30ea14 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Sun, 14 Jan 2024 09:36:12 +0100
|
||||
Subject: [PATCH 46/48] [gdb/testsuite] Fix gdb.cp/namespace.exp with read1
|
||||
|
||||
With check-read1 we run into:
|
||||
...
|
||||
(gdb) break DNE>::DNE^M
|
||||
Function "DNE>::DNE" not defined.^M
|
||||
Make breakpoint pending on future shared library load? (y or [n]) y^M
|
||||
Breakpoint 9 (DNE>::DNE) pending.^M
|
||||
n^M
|
||||
(gdb) FAIL: gdb.cp/namespace.exp: br malformed '>' (got interactive prompt)
|
||||
n^M
|
||||
...
|
||||
|
||||
The question is supposed to be handled by the question and response arguments
|
||||
to this gdb_test call:
|
||||
...
|
||||
gdb_test "break DNE>::DNE" "" "br malformed \'>\'" \
|
||||
"Make breakpoint pending on future shared library load?.*" "y"
|
||||
...
|
||||
but both this and the builtin handling in gdb_test_multiple triggers.
|
||||
|
||||
The cause of this is that the question argument regexp is incomplete.
|
||||
|
||||
Fix this by making sure that the entire question is matched in the regexp:
|
||||
...
|
||||
set yn_re [string_to_regexp {(y or [n])}]
|
||||
...
|
||||
"Make breakpoint pending on future shared library load\\? $yn_re " "Y"
|
||||
...
|
||||
|
||||
Tested on x86_64-linux.
|
||||
---
|
||||
gdb/testsuite/gdb.cp/namespace.exp | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.cp/namespace.exp b/gdb/testsuite/gdb.cp/namespace.exp
|
||||
index a9de09f087d..b1c7403f2c6 100644
|
||||
--- a/gdb/testsuite/gdb.cp/namespace.exp
|
||||
+++ b/gdb/testsuite/gdb.cp/namespace.exp
|
||||
@@ -251,8 +251,9 @@ gdb_test "print AAA::ALPHA" "\\$\[0-9\].* = AAA::ALPHA"
|
||||
gdb_test "whatis ::C::CClass::NestedClass" "type = C::CClass::NestedClass"
|
||||
gdb_test "whatis ::C::CClass::NestedClass *" "type = C::CClass::NestedClass \\*"
|
||||
|
||||
+set yn_re [string_to_regexp {(y or [n])}]
|
||||
# Break on functions with a malformed name.
|
||||
gdb_test "break DNE>::DNE" "" "br malformed \'>\'" \
|
||||
- "Make breakpoint pending on future shared library load?.*" "y"
|
||||
+ "Make breakpoint pending on future shared library load\\? $yn_re " "Y"
|
||||
gdb_test "break DNE)::DNE" "" "br malformed \')\'" \
|
||||
- "Make breakpoint pending on future shared library load?.*" "y"
|
||||
+ "Make breakpoint pending on future shared library load\\? $yn_re " "Y"
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,41 +0,0 @@
|
||||
From 254988c36fe592e89af5d92e1d35a6eb4b09cbb0 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Mon, 6 Nov 2023 08:32:54 +0100
|
||||
Subject: [PATCH 2/2] [gdb/testsuite] Fix gdb.dwarf2/dw2-gas-workaround.exp
|
||||
|
||||
Recently added test-case gdb.dwarf2/dw2-gas-workaround.exp:
|
||||
- passes when gdb is configured using $(cd ../src; pwd)/configure, but
|
||||
- fails when using ../src/configure.
|
||||
|
||||
Fix this by making the matching more precise:
|
||||
...
|
||||
- -re -wrap "$objdir.*" {
|
||||
+ -re -wrap "name_for_id = $objdir/$srcfile\r\n.*" {
|
||||
...
|
||||
such that we only fail on the line:
|
||||
...
|
||||
[symtab-create] start_subfile: name = dw2-lines.c, name_for_id = \
|
||||
/data/vries/gdb/leap-15-4/build/gdb/testsuite/dw2-lines.c^M
|
||||
...
|
||||
|
||||
Reported-By: Carl Love <cel@us.ibm.com>
|
||||
---
|
||||
gdb/testsuite/gdb.dwarf2/dw2-gas-workaround.exp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-gas-workaround.exp b/gdb/testsuite/gdb.dwarf2/dw2-gas-workaround.exp
|
||||
index ca2b10f23b3..7d5375a920a 100644
|
||||
--- a/gdb/testsuite/gdb.dwarf2/dw2-gas-workaround.exp
|
||||
+++ b/gdb/testsuite/gdb.dwarf2/dw2-gas-workaround.exp
|
||||
@@ -83,7 +83,7 @@ if { [prepare_for_testing "failed to prepare" ${testfile} \
|
||||
|
||||
gdb_test_no_output "set debug symtab-create 1"
|
||||
gdb_test_multiple "ptype bar" "" {
|
||||
- -re -wrap "$objdir.*" {
|
||||
+ -re -wrap "name_for_id = $objdir/$srcfile\r\n.*" {
|
||||
fail $gdb_test_name
|
||||
}
|
||||
-re -wrap "" {
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,72 +0,0 @@
|
||||
From 80b0afed39702c7a25d68f6b28427f92c5db6d80 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Sun, 14 Jan 2024 10:21:46 +0100
|
||||
Subject: [PATCH 45/48] [gdb/testsuite] Fix gdb.mi/mi-dprintf.exp with read1
|
||||
|
||||
When running test-case gdb.mi/mi-dprintf.exp with check-read1, I run into:
|
||||
...
|
||||
(gdb) ^M
|
||||
PASS: gdb.mi/mi-dprintf.exp: gdb: mi 2nd dprintf stop
|
||||
-data-evaluate-expression stderr^M
|
||||
^done,value="0x7ffff7e4a420 <_IO_2_1_stderr_>"^M
|
||||
(gdb) FAIL: gdb.mi/mi-dprintf.exp: stderr symbol check
|
||||
...
|
||||
|
||||
The problem is in proc mi_gdb_is_stderr_available:
|
||||
...
|
||||
proc mi_gdb_is_stderr_available {} {
|
||||
set has_stderr_symbol false
|
||||
gdb_test_multiple "-data-evaluate-expression stderr" "stderr symbol check" {
|
||||
-re "\\^error,msg=\"'stderr' has unknown type; cast it to its declared type\"\r\n$::mi_gdb_prompt$" {
|
||||
}
|
||||
-re "$::mi_gdb_prompt$" {
|
||||
set has_stderr_symbol true
|
||||
}
|
||||
}
|
||||
...
|
||||
which uses a gdb_test_multiple that is supposed to use the mi prompt, but
|
||||
doesn't use -prompt to indicate this. Consequently, the default patterns use
|
||||
the regular gdb prompt, which trigger earlier than the two custom patterns
|
||||
which use "$::mi_gdb_prompt$".
|
||||
|
||||
Fix this by adding the missing -prompt "$::mi_gdb_prompt$" arguments.
|
||||
|
||||
While we're at it, make the gdb_test_multiple call a bit more readable by
|
||||
using variables, and by using -wrap.
|
||||
|
||||
Tested on x86_64-linux, with:
|
||||
- gcc and clang (to trigger both the has_stderr_symbol true and false cases)
|
||||
- make check and make check-read1.
|
||||
---
|
||||
gdb/testsuite/lib/mi-support.exp | 11 ++++++++---
|
||||
1 file changed, 8 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/gdb/testsuite/lib/mi-support.exp b/gdb/testsuite/lib/mi-support.exp
|
||||
index 540eb3371c6..1b702e8a3bb 100644
|
||||
--- a/gdb/testsuite/lib/mi-support.exp
|
||||
+++ b/gdb/testsuite/lib/mi-support.exp
|
||||
@@ -2956,13 +2956,18 @@ proc foreach_mi_ui_mode { var_name body } {
|
||||
# Check if GDB has information about the stderr symbol.
|
||||
proc mi_gdb_is_stderr_available {} {
|
||||
set has_stderr_symbol false
|
||||
- gdb_test_multiple "-data-evaluate-expression stderr" "stderr symbol check" {
|
||||
- -re "\\^error,msg=\"'stderr' has unknown type; cast it to its declared type\"\r\n$::mi_gdb_prompt$" {
|
||||
+
|
||||
+ set cmd "-data-evaluate-expression stderr"
|
||||
+ set test "stderr symbol check"
|
||||
+ set msg_re {"'stderr' has unknown type; cast it to its declared type"}
|
||||
+ gdb_test_multiple $cmd $test -prompt "$::mi_gdb_prompt$" {
|
||||
+ -re -wrap "\\^error,msg=$msg_re" {
|
||||
# Default value of false is fine.
|
||||
}
|
||||
- -re "$::mi_gdb_prompt$" {
|
||||
+ -re -wrap "" {
|
||||
set has_stderr_symbol true
|
||||
}
|
||||
}
|
||||
+
|
||||
return $has_stderr_symbol
|
||||
}
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,74 +0,0 @@
|
||||
From 237a0ec8a20cc5e233d630a43d9cacd2774a564d Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Wed, 20 Mar 2024 19:31:24 +0100
|
||||
Subject: [PATCH 37/48] [gdb/testsuite] Fix gdb.server/server-connect.exp for
|
||||
missing ipv6
|
||||
|
||||
On a system without ipv6 support enabled, when running test-case
|
||||
gdb.server/server-connect.exp, it takes about 4 minutes, and I get:
|
||||
...
|
||||
builtin_spawn gdbserver --once ::1:2347 server-connect^M
|
||||
Can't open socket: Address family not supported by protocol.^M
|
||||
Exiting^M
|
||||
PASS: gdb.server/server-connect.exp: tcp6: start gdbserver
|
||||
target remote tcp6:::1:2347^M
|
||||
A program is being debugged already. Kill it? (y or n) y^M
|
||||
could not connect: Address family not supported by protocol.^M
|
||||
(gdb) FAIL: gdb.server/server-connect.exp: tcp6: connect to gdbserver using tcp6:::1
|
||||
...
|
||||
|
||||
Fix this by:
|
||||
- recognizing the error message in gdbserver_start, and returning an empty list
|
||||
to signal unsupported, and
|
||||
- handling the unsupported response in the test-case.
|
||||
|
||||
This brings testing time down to 2 seconds, and gets me:
|
||||
...
|
||||
UNSUPPORTED: gdb.server/server-connect.exp: tcp6: start gdbserver
|
||||
UNSUPPORTED: gdb.server/server-connect.exp: tcp6-with-brackets: start gdbserver
|
||||
UNSUPPORTED: gdb.server/server-connect.exp: udp6: start gdbserver
|
||||
UNSUPPORTED: gdb.server/server-connect.exp: udp6-with-brackets: start gdbserver
|
||||
...
|
||||
|
||||
Tested on aarch64-linux.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
PR testsuite/31502
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31502
|
||||
---
|
||||
gdb/testsuite/gdb.server/server-connect.exp | 3 +++
|
||||
gdb/testsuite/lib/gdbserver-support.exp | 3 +++
|
||||
2 files changed, 6 insertions(+)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.server/server-connect.exp b/gdb/testsuite/gdb.server/server-connect.exp
|
||||
index 1f5b9a27cf4..ffdfaa89154 100644
|
||||
--- a/gdb/testsuite/gdb.server/server-connect.exp
|
||||
+++ b/gdb/testsuite/gdb.server/server-connect.exp
|
||||
@@ -88,6 +88,9 @@ save_vars { GDB_TEST_SOCKETHOST } {
|
||||
} else {
|
||||
if { $gdbserver_should_fail } {
|
||||
fail "$test: gdbserver should fail but did not"
|
||||
+ } elseif { [llength $res] == 0 } {
|
||||
+ unsupported $test
|
||||
+ continue
|
||||
} else {
|
||||
pass "$test"
|
||||
}
|
||||
diff --git a/gdb/testsuite/lib/gdbserver-support.exp b/gdb/testsuite/lib/gdbserver-support.exp
|
||||
index a3cccf54a72..d065fb36764 100644
|
||||
--- a/gdb/testsuite/lib/gdbserver-support.exp
|
||||
+++ b/gdb/testsuite/lib/gdbserver-support.exp
|
||||
@@ -429,6 +429,9 @@ proc gdbserver_start { options arguments } {
|
||||
-re ".*: cannot resolve name: .*\r\n" {
|
||||
error "gdbserver cannot resolve name."
|
||||
}
|
||||
+ -re "Can't open socket: Address family not supported by protocol." {
|
||||
+ return {}
|
||||
+ }
|
||||
timeout {
|
||||
error "Timeout waiting for gdbserver response."
|
||||
}
|
||||
--
|
||||
2.35.3
|
||||
|
39
gdb-testsuite-fix-gdb_py_module_available-for-python.patch
Normal file
39
gdb-testsuite-fix-gdb_py_module_available-for-python.patch
Normal file
@@ -0,0 +1,39 @@
|
||||
From 7992b582e5a55bf2fd64f2f94b854d335c36c6a5 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Tue, 28 Jan 2025 17:44:42 +0100
|
||||
Subject: [PATCH] [gdb/testsuite] Fix gdb_py_module_available for python 3.4
|
||||
|
||||
On SLE-12, I run into:
|
||||
...
|
||||
(gdb) python import pygments
|
||||
Python Exception <class 'ImportError'>: No module named 'pygments'
|
||||
Error occurred in Python: No module named 'pygments'
|
||||
(gdb) FAIL: gdb.base/style.exp: python import pygments
|
||||
...
|
||||
|
||||
Fix this by handling the output string in gdb_py_module_available.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
---
|
||||
gdb/testsuite/lib/gdb-python.exp | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/gdb/testsuite/lib/gdb-python.exp b/gdb/testsuite/lib/gdb-python.exp
|
||||
index e27d5c17769..f8141193596 100644
|
||||
--- a/gdb/testsuite/lib/gdb-python.exp
|
||||
+++ b/gdb/testsuite/lib/gdb-python.exp
|
||||
@@ -64,6 +64,9 @@ proc gdb_py_module_available { name } {
|
||||
-re -wrap "ImportError: No module named '?${name}'?.*" {
|
||||
set available false
|
||||
}
|
||||
+ -re -wrap "Python Exception <class 'ImportError'>: No module named '?${name}'?.*" {
|
||||
+ set available false
|
||||
+ }
|
||||
-re -wrap "python import ${name}" {
|
||||
set available true
|
||||
}
|
||||
|
||||
base-commit: 94df6741bbabaa9a51960446b2af4c0bed01b54b
|
||||
--
|
||||
2.43.0
|
||||
|
@@ -1,117 +0,0 @@
|
||||
From 7357f73483cfe8f3e8ec2dd9ca2fb3d52206055a Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Wed, 17 Apr 2024 11:45:02 +0200
|
||||
Subject: [PATCH 28/48] [gdb/testsuite] Fix gdbserver pid in
|
||||
gdb.server/server-kill-python.exp
|
||||
|
||||
The commit ed32754a8c7 ("[gdb/testsuite] Fix gdb.server/multi-ui-errors.exp for
|
||||
remote target") intended to addresss the problem that this command:
|
||||
...
|
||||
set gdbserver_pid [exp_pid -i $server_spawn_id]
|
||||
...
|
||||
does not return the pid of the gdbserver for remote target, but rather the one
|
||||
of the ssh client session.
|
||||
|
||||
To fix this, it added another way of getting the gdbserver_pid.
|
||||
|
||||
For the trivial case of non-remote target, the PID found by either method
|
||||
should be identical, but if we compare those by adding
|
||||
"puts [exec ps -p $gdbserver_pid]" we get:
|
||||
...
|
||||
PID TTY TIME CMD
|
||||
31711 pts/8 00:00:00 gdbserver
|
||||
PID TTY TIME CMD
|
||||
31718 pts/8 00:00:00 server-kill-pyt
|
||||
...
|
||||
|
||||
The problem is that while the gdbserver PID is supposed to be read from the
|
||||
result of "gdb.execute ('p server_pid')" in the python script, instead it's
|
||||
taken from:
|
||||
...
|
||||
Process server-kill-python created; pid = 31718^M
|
||||
...
|
||||
|
||||
Fix this by moving the printing of the gdbserver PID out of the python script.
|
||||
|
||||
Also double-check the two methods against each other, in the cases that they
|
||||
should match.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
|
||||
PR testsuite/31633
|
||||
https://sourceware.org/bugzilla/show_bug.cgi?id=31633
|
||||
---
|
||||
.../gdb.server/server-kill-python.exp | 37 +++++++++++--------
|
||||
1 file changed, 21 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.server/server-kill-python.exp b/gdb/testsuite/gdb.server/server-kill-python.exp
|
||||
index dcb6eddd6eb..778880984ec 100644
|
||||
--- a/gdb/testsuite/gdb.server/server-kill-python.exp
|
||||
+++ b/gdb/testsuite/gdb.server/server-kill-python.exp
|
||||
@@ -37,7 +37,7 @@ set host_binfile [gdb_remote_download host $binfile]
|
||||
set res [gdbserver_spawn "${target_binfile}"]
|
||||
set gdbserver_protocol [lindex $res 0]
|
||||
set gdbserver_gdbport [lindex $res 1]
|
||||
-set gdbserver_pid [exp_pid -i $server_spawn_id]
|
||||
+set gdbserver_pid_check [exp_pid -i $server_spawn_id]
|
||||
|
||||
set break_linenr [gdb_get_line_number "@@XX@@ Inferior Starting @@XX@@"]
|
||||
|
||||
@@ -48,9 +48,6 @@ puts $fd \
|
||||
"import gdb
|
||||
|
||||
def do_gdb_stuff ():
|
||||
- gdb.execute ('break $srcfile:$break_linenr')
|
||||
- gdb.execute ('continue')
|
||||
- gdb.execute ('p server_pid')
|
||||
gdb.execute ('continue')
|
||||
|
||||
do_gdb_stuff()"
|
||||
@@ -68,24 +65,32 @@ if {[gdb_spawn_with_cmdline_opts \
|
||||
|
||||
gdb_load $binfile
|
||||
gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport
|
||||
-send_gdb "source $host_file1\n"
|
||||
+
|
||||
+gdb_test "break $srcfile:$break_linenr"
|
||||
|
||||
# Get the gdbserver PID.
|
||||
set gdbserver_pid 0
|
||||
-
|
||||
-# Wait for the inferior to start up.
|
||||
-with_spawn_id $server_spawn_id {
|
||||
- gdb_test_multiple "" "get gdbserver PID" {
|
||||
- -re " = ($decimal)\r\n" {
|
||||
- set gdbserver_pid $expect_out(1,string)
|
||||
- pass $gdb_test_name
|
||||
- }
|
||||
+gdb_test "continue"
|
||||
+gdb_test_multiple "print server_pid" "get gdbserver PID" {
|
||||
+ -re -wrap " = ($decimal)" {
|
||||
+ set gdbserver_pid $expect_out(1,string)
|
||||
+ pass $gdb_test_name
|
||||
}
|
||||
+}
|
||||
|
||||
- if { $gdbserver_pid == 0 } {
|
||||
- return
|
||||
- }
|
||||
+if { $gdbserver_pid == 0 } {
|
||||
+ return
|
||||
+}
|
||||
+
|
||||
+if { ![is_remote target] && $gdbserver_pid != $gdbserver_pid_check } {
|
||||
+ error "Failed to get correct gdbserver pid"
|
||||
+}
|
||||
|
||||
+send_gdb "source $host_file1\n"
|
||||
+
|
||||
+
|
||||
+# Wait for the inferior to start up.
|
||||
+with_spawn_id $server_spawn_id {
|
||||
gdb_test_multiple "" "ensure inferior is running" {
|
||||
-re "@@XX@@ Inferior Starting @@XX@@" {
|
||||
pass $gdb_test_name
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,49 +0,0 @@
|
||||
From 5b840a3cb41ada4cee1456d16993809abeb30eda Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Thu, 22 Feb 2024 12:09:14 +0100
|
||||
Subject: [PATCH 43/48] [gdb/testsuite] Fix license text in
|
||||
gdb.reverse/map-to-same-line.{c,exp}
|
||||
|
||||
I noticed in gdb.reverse/map-to-same-line.{c,exp} that the license urls are
|
||||
using some kind of indirection via urldefense.proofpoint.com.
|
||||
|
||||
Fix this by removing this indirection.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
|
||||
PR testsuite/31358
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31358
|
||||
---
|
||||
gdb/testsuite/gdb.reverse/map-to-same-line.c | 2 +-
|
||||
gdb/testsuite/gdb.reverse/map-to-same-line.exp | 2 +-
|
||||
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.reverse/map-to-same-line.c b/gdb/testsuite/gdb.reverse/map-to-same-line.c
|
||||
index 3086e849231..f6b4f10dbf7 100644
|
||||
--- a/gdb/testsuite/gdb.reverse/map-to-same-line.c
|
||||
+++ b/gdb/testsuite/gdb.reverse/map-to-same-line.c
|
||||
@@ -11,7 +11,7 @@
|
||||
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 <https://urldefense.proofpoint.com/v2/url?u=http-3A__www.gnu.org_licenses_&d=DwIDAg&c=jf_iaSHvJObTbx-siA1ZOg&r=RFEmMkZAk--_wFGN5tkM_A&m=hvslrRyYSFfiB2uOFjd7I62ZBKNJkGFWTdsHWVjwDIkK3MWESdWS4tI89FoblXn9&s=Ety3VhMg8aZcBncPPcPCS5XzUde9hjKVulkt8r7mD2k&e= >. */
|
||||
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* The purpose of this test is to create a DWARF line table that contains two
|
||||
or more entries for the same line. When stepping (forwards or backwards),
|
||||
diff --git a/gdb/testsuite/gdb.reverse/map-to-same-line.exp b/gdb/testsuite/gdb.reverse/map-to-same-line.exp
|
||||
index 63f8c9c76b3..1510cf98d0c 100644
|
||||
--- a/gdb/testsuite/gdb.reverse/map-to-same-line.exp
|
||||
+++ b/gdb/testsuite/gdb.reverse/map-to-same-line.exp
|
||||
@@ -11,7 +11,7 @@
|
||||
# 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 <https://urldefense.proofpoint.com/v2/url?u=http-3A__www.gnu.org_licenses_&d=DwIDAg&c=jf_iaSHvJObTbx-siA1ZOg&r=RFEmMkZAk--_wFGN5tkM_A&m=hvslrRyYSFfiB2uOFjd7I62ZBKNJkGFWTdsHWVjwDIkK3MWESdWS4tI89FoblXn9&s=Ety3VhMg8aZcBncPPcPCS5XzUde9hjKVulkt8r7mD2k&e= >.
|
||||
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# When stepping (forwards or backwards), GDB should step over the entire line
|
||||
# and not just a particular entry in the line table. This test was added to
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,40 +0,0 @@
|
||||
From 3e4d764ebb264f0c9153c6fd3727f67d4454ae9b Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Fri, 29 Mar 2024 07:47:30 +0100
|
||||
Subject: [PATCH 32/48] [gdb/testsuite] Fix missing return type in
|
||||
gdb.linespec/break-asm-file.c
|
||||
|
||||
On fedora rawhide, when running test-case gdb.linespec/break-asm-file.exp, I
|
||||
get:
|
||||
...
|
||||
gdb compile failed, break-asm-file.c:21:8: error: \
|
||||
return type defaults to 'int' [-Wimplicit-int]
|
||||
21 | static func()
|
||||
| ^~~~
|
||||
...
|
||||
|
||||
Fix this by adding the missing return type.
|
||||
|
||||
Tested on aarch64-linux.
|
||||
|
||||
Approved-By: John Baldwin <jhb@FreeBSD.org>
|
||||
---
|
||||
gdb/testsuite/gdb.linespec/break-asm-file.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.linespec/break-asm-file.c b/gdb/testsuite/gdb.linespec/break-asm-file.c
|
||||
index 41f0904fc84..e7bdc26b1ec 100644
|
||||
--- a/gdb/testsuite/gdb.linespec/break-asm-file.c
|
||||
+++ b/gdb/testsuite/gdb.linespec/break-asm-file.c
|
||||
@@ -18,7 +18,7 @@
|
||||
void func3();
|
||||
void func2();
|
||||
|
||||
-static func()
|
||||
+static void func()
|
||||
{
|
||||
}
|
||||
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,66 +0,0 @@
|
||||
From acc30323a8bc8aa04d404356e96b003a9a30543f Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Thu, 25 Jan 2024 16:36:09 +0100
|
||||
Subject: [PATCH 06/48] [gdb/testsuite] Fix regexp in vgdb_start
|
||||
|
||||
On Fedora 39 aarch64 I run into:
|
||||
...
|
||||
(gdb) target remote | vgdb --wait=2 --max-invoke-ms=2500 --pid=2114437^M
|
||||
Remote debugging using | vgdb --wait=2 --max-invoke-ms=2500 --pid=2114437^M
|
||||
relaying data between gdb and process 2114437^M
|
||||
warning: remote target does not support file transfer, \
|
||||
attempting to access files from local filesystem.^M
|
||||
Reading symbols from /lib/ld-linux-aarch64.so.1...^M
|
||||
_start () at ../sysdeps/aarch64/dl-start.S:22^M
|
||||
warning: 22 ../sysdeps/aarch64/dl-start.S: No such file or directory^M
|
||||
(gdb) FAIL: gdb.base/valgrind-infcall.exp: target remote for vgdb
|
||||
...
|
||||
|
||||
For contrast, on openSUSE Leap 15.4 x86_64 I have:
|
||||
...
|
||||
(gdb) target remote | vgdb --wait=2 --max-invoke-ms=2500 --pid=18797^M
|
||||
Remote debugging using | vgdb --wait=2 --max-invoke-ms=2500 --pid=18797^M
|
||||
relaying data between gdb and process 18797^M
|
||||
warning: remote target does not support file transfer, \
|
||||
attempting to access files from local filesystem.^M
|
||||
Reading symbols from /lib64/ld-linux-x86-64.so.2...^M
|
||||
(No debugging symbols found in /lib64/ld-linux-x86-64.so.2)^M
|
||||
0x0000000004002550 in _start () from /lib64/ld-linux-x86-64.so.2^M
|
||||
(gdb) PASS: gdb.base/valgrind-infcall.exp: target remote for vgdb
|
||||
...
|
||||
|
||||
The fail happens in vgdb_start because the regexp only matches the
|
||||
"in _start ()" variant, not the "_start () at":
|
||||
...
|
||||
gdb_test "$vgdbcmd" " in \\.?_start .*" "target remote for vgdb"
|
||||
...
|
||||
Which variant you get is determined by presence of debug info.
|
||||
|
||||
Fix this by also matching the "_start () at" variant.
|
||||
|
||||
Tested aarch64-linux and x86_64-linux.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
---
|
||||
gdb/testsuite/lib/valgrind.exp | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/testsuite/lib/valgrind.exp b/gdb/testsuite/lib/valgrind.exp
|
||||
index a1cd85a7b09..f9096663509 100644
|
||||
--- a/gdb/testsuite/lib/valgrind.exp
|
||||
+++ b/gdb/testsuite/lib/valgrind.exp
|
||||
@@ -92,7 +92,10 @@ proc vgdb_start { {active_at_startup 1} } {
|
||||
set vgdbcmd "target remote | vgdb --wait=2 --max-invoke-ms=2500 --pid=$vgdbpid"
|
||||
|
||||
if { $active_at_startup } {
|
||||
- gdb_test "$vgdbcmd" " in \\.?_start .*" "target remote for vgdb"
|
||||
+ set start_re1 " in \\.?_start "
|
||||
+ set start_re2 "\\.?_start \\(\\) at "
|
||||
+ gdb_test "$vgdbcmd" "($start_re1|$start_re2).*" \
|
||||
+ "target remote for vgdb"
|
||||
} else {
|
||||
# Let $binfile run a bit before attaching. This is a bit of a hack,
|
||||
# in that it lets test-case valgrind-infcall-2.exp run to the point of
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,221 +0,0 @@
|
||||
From 8bf7fdfc16f5d5fd9a94c233c0c41d307ba86cd2 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Tue, 21 Nov 2023 13:15:29 +0100
|
||||
Subject: [PATCH 04/48] [gdb/testsuite] Fix spurious FAILs with
|
||||
examine-backward.exp, again
|
||||
|
||||
Commit 59a561480d5 ("Fix spurious FAILs with examine-backward.exp") describes
|
||||
the problem that:
|
||||
...
|
||||
The test case examine-backward.exp issues the command "x/-s" after the end
|
||||
of the first string in TestStrings, but without making sure that this
|
||||
string is preceded by a string terminator. Thus GDB may spuriously print
|
||||
some random characters from before that string, and then the test fails.
|
||||
...
|
||||
|
||||
The commit fixes the problem by adding a Barrier variable before the TestStrings
|
||||
variable:
|
||||
...
|
||||
+const char Barrier[] = { 0x0 };
|
||||
const char TestStrings[] = {
|
||||
...
|
||||
|
||||
There is however no guarantee that Barrier is placed immediately before
|
||||
TestStrings.
|
||||
|
||||
Before recent commit 169fe7ab54b ("Change gdb.base/examine-backwards.exp for
|
||||
AIX.") on x86_64-linux, I see:
|
||||
...
|
||||
0000000000400660 R Barrier
|
||||
0000000000400680 R TestStrings
|
||||
...
|
||||
|
||||
So while the Barrier variable is the first before the TestStrings variable,
|
||||
it's not immediately preceding TestStrings.
|
||||
|
||||
After commit 169fe7ab54b:
|
||||
...
|
||||
0000000000402259 B Barrier
|
||||
0000000000402020 D TestStrings
|
||||
...
|
||||
they're not even in the same section anymore.
|
||||
|
||||
Fix this reliably by adding the zero in the array itself:
|
||||
...
|
||||
char TestStringsBase[] = {
|
||||
0x0,
|
||||
...
|
||||
};
|
||||
char *TestStrings = &TestStringsBase[1];
|
||||
...
|
||||
and do likewise for TestStringsH and TestStringsW.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
|
||||
PR testsuite/31064
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31064
|
||||
---
|
||||
gdb/testsuite/gdb.base/examine-backward.c | 35 ++++++++++++++-------
|
||||
gdb/testsuite/gdb.base/examine-backward.exp | 18 +++++------
|
||||
2 files changed, 33 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/examine-backward.c b/gdb/testsuite/gdb.base/examine-backward.c
|
||||
index 354c2e2f323..5549cc20a4a 100644
|
||||
--- a/gdb/testsuite/gdb.base/examine-backward.c
|
||||
+++ b/gdb/testsuite/gdb.base/examine-backward.c
|
||||
@@ -32,15 +32,12 @@ literals. The content of each array is the same as followings:
|
||||
};
|
||||
*/
|
||||
|
||||
-/* This is here just to ensure we have a null character before
|
||||
- TestStrings, to avoid showing garbage when we look for strings
|
||||
- backwards from TestStrings. */
|
||||
+unsigned char TestStringsBase[] = {
|
||||
+ /* This is here just to ensure we have a null character before
|
||||
+ TestStrings, to avoid showing garbage when we look for strings
|
||||
+ backwards from TestStrings. */
|
||||
+ 0x0,
|
||||
|
||||
-unsigned char Barrier[] = {
|
||||
- 0x00,
|
||||
-};
|
||||
-
|
||||
-unsigned char TestStrings[] = {
|
||||
0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
|
||||
0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
|
||||
0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
|
||||
@@ -54,7 +51,14 @@ unsigned char TestStrings[] = {
|
||||
0x00
|
||||
};
|
||||
|
||||
-short TestStringsH[] = {
|
||||
+unsigned char *TestStrings = &TestStringsBase[1];
|
||||
+
|
||||
+short TestStringsHBase[] = {
|
||||
+ /* This is here just to ensure we have a null character before
|
||||
+ TestStringsH, to avoid showing garbage when we look for strings
|
||||
+ backwards from TestStringsH. */
|
||||
+ 0x0,
|
||||
+
|
||||
0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048,
|
||||
0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
|
||||
0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
|
||||
@@ -67,7 +71,14 @@ short TestStringsH[] = {
|
||||
0x0000
|
||||
};
|
||||
|
||||
-int TestStringsW[] = {
|
||||
+short *TestStringsH = &TestStringsHBase[1];
|
||||
+
|
||||
+int TestStringsWBase[] = {
|
||||
+ /* This is here just to ensure we have a null character before
|
||||
+ TestStringsW, to avoid showing garbage when we look for strings
|
||||
+ backwards from TestStringsW. */
|
||||
+ 0x0,
|
||||
+
|
||||
0x00000041, 0x00000042, 0x00000043, 0x00000044,
|
||||
0x00000045, 0x00000046, 0x00000047, 0x00000048,
|
||||
0x00000049, 0x0000004a, 0x0000004b, 0x0000004c,
|
||||
@@ -89,11 +100,13 @@ int TestStringsW[] = {
|
||||
0x00000000
|
||||
};
|
||||
|
||||
+int *TestStringsW = &TestStringsWBase[1];
|
||||
+
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
/* Clang++ eliminates the variables if nothing references them. */
|
||||
- int dummy = Barrier[0] + TestStrings[0] + TestStringsH[0] + TestStringsW[0];
|
||||
+ int dummy = TestStrings[0] + TestStringsH[0] + TestStringsW[0];
|
||||
|
||||
/* Backward disassemble test requires at least 20 instructions in
|
||||
this function. Adding a simple bubble sort. */
|
||||
diff --git a/gdb/testsuite/gdb.base/examine-backward.exp b/gdb/testsuite/gdb.base/examine-backward.exp
|
||||
index 7c8a08c0726..4e197d7d725 100644
|
||||
--- a/gdb/testsuite/gdb.base/examine-backward.exp
|
||||
+++ b/gdb/testsuite/gdb.base/examine-backward.exp
|
||||
@@ -145,7 +145,7 @@ gdb_test_no_output "set charset ASCII"
|
||||
|
||||
with_test_prefix "char-width=1, print-max=20" {
|
||||
gdb_test_no_output "set print elements 20"
|
||||
- gdb_test_sequence "x/6s &TestStrings" "take 6 strings forward" {
|
||||
+ gdb_test_sequence "x/6s TestStrings" "take 6 strings forward" {
|
||||
"\"ABCDEFGHIJKLMNOPQRST\"\.\.\."
|
||||
"\"UVWXYZ\""
|
||||
"\"\""
|
||||
@@ -162,7 +162,7 @@ with_test_prefix "char-width=1, print-max=20" {
|
||||
"\"[^\"]+\""
|
||||
"\"01234567890123456789\"\.\.\."
|
||||
}
|
||||
- gdb_test_sequence "x/6s &TestStrings" "take 6 strings forward again" {
|
||||
+ gdb_test_sequence "x/6s TestStrings" "take 6 strings forward again" {
|
||||
"\"ABCDEFGHIJKLMNOPQRST\"\.\.\."
|
||||
"\"UVWXYZ\""
|
||||
"\"\""
|
||||
@@ -187,7 +187,7 @@ with_test_prefix "char-width=1, print-max=20" {
|
||||
|
||||
with_test_prefix "char-width=2, print-max=20" {
|
||||
gdb_test_no_output "set print elements 20"
|
||||
- gdb_test_sequence "x/6sh &TestStringsH" "take 6 strings forward" {
|
||||
+ gdb_test_sequence "x/6sh TestStringsH" "take 6 strings forward" {
|
||||
"u\"ABCDEFGHIJKLMNOPQRST\"\.\.\."
|
||||
"u\"UVWXYZ\""
|
||||
"u\"\""
|
||||
@@ -204,7 +204,7 @@ with_test_prefix "char-width=2, print-max=20" {
|
||||
"u\"[^\"]+\""
|
||||
"u\"01234567890123456789\"\.\.\."
|
||||
}
|
||||
- gdb_test_sequence "x/6sh &TestStringsH" "take 6 strings forward again" {
|
||||
+ gdb_test_sequence "x/6sh TestStringsH" "take 6 strings forward again" {
|
||||
"u\"ABCDEFGHIJKLMNOPQRST\"\.\.\."
|
||||
"u\"UVWXYZ\""
|
||||
"u\"\""
|
||||
@@ -229,7 +229,7 @@ with_test_prefix "char-width=2, print-max=20" {
|
||||
|
||||
with_test_prefix "char-width=4, print-max=20" {
|
||||
gdb_test_no_output "set print elements 20"
|
||||
- gdb_test_sequence "x/6sw &TestStringsW" "take 6 strings forward" {
|
||||
+ gdb_test_sequence "x/6sw TestStringsW" "take 6 strings forward" {
|
||||
"U\"ABCDEFGHIJKLMNOPQRST\"\.\.\."
|
||||
"U\"UVWXYZ\""
|
||||
"U\"\""
|
||||
@@ -246,7 +246,7 @@ with_test_prefix "char-width=4, print-max=20" {
|
||||
"U\"[^\"]+\""
|
||||
"U\"01234567890123456789\"\.\.\."
|
||||
}
|
||||
- gdb_test_sequence "x/6sw &TestStringsW" "take 6 strings forward again" {
|
||||
+ gdb_test_sequence "x/6sw TestStringsW" "take 6 strings forward again" {
|
||||
"U\"ABCDEFGHIJKLMNOPQRST\"\.\.\."
|
||||
"U\"UVWXYZ\""
|
||||
"U\"\""
|
||||
@@ -271,7 +271,7 @@ with_test_prefix "char-width=4, print-max=20" {
|
||||
|
||||
with_test_prefix "char-width=2, print-max=0" {
|
||||
gdb_test_no_output "set print elements 0"
|
||||
- gdb_test_sequence "x/6sh &TestStringsH" "take 6 strings forward" {
|
||||
+ gdb_test_sequence "x/6sh TestStringsH" "take 6 strings forward" {
|
||||
"u\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\""
|
||||
"u\"\""
|
||||
"u\"\""
|
||||
@@ -289,7 +289,7 @@ with_test_prefix "char-width=2, print-max=0" {
|
||||
"u\"012345678901234567890123456789\""
|
||||
"u\"!!!!!!\""
|
||||
}
|
||||
- gdb_test_sequence "x/6sh &TestStringsH" "take 6 strings forward again" {
|
||||
+ gdb_test_sequence "x/6sh TestStringsH" "take 6 strings forward again" {
|
||||
"u\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\""
|
||||
"u\"\""
|
||||
"u\"\""
|
||||
@@ -314,7 +314,7 @@ with_test_prefix "char-width=2, print-max=0" {
|
||||
|
||||
with_test_prefix "char-width=1, print-max=4" {
|
||||
gdb_test_no_output "set print elements 4"
|
||||
- gdb_test_sequence "x/9s &TestStrings" "take 9 strings forward" {
|
||||
+ gdb_test_sequence "x/9s TestStrings" "take 9 strings forward" {
|
||||
"\"ABCD\"\.\.\."
|
||||
"\"EFGH\"\.\.\."
|
||||
"\"IJKL\"\.\.\."
|
||||
--
|
||||
2.35.3
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user