- Maintenance script qa.sh:
* Add PR29770 xfail (glibc). * Add PR31229 kfail. OBS-URL: https://build.opensuse.org/package/show/devel:gcc/gdb?expand=0&rev=403
This commit is contained in:
commit
4ba6c6a136
23
.gitattributes
vendored
Normal file
23
.gitattributes
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
## Default LFS
|
||||
*.7z filter=lfs diff=lfs merge=lfs -text
|
||||
*.bsp filter=lfs diff=lfs merge=lfs -text
|
||||
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
||||
*.gem filter=lfs diff=lfs merge=lfs -text
|
||||
*.gz filter=lfs diff=lfs merge=lfs -text
|
||||
*.jar filter=lfs diff=lfs merge=lfs -text
|
||||
*.lz filter=lfs diff=lfs merge=lfs -text
|
||||
*.lzma filter=lfs diff=lfs merge=lfs -text
|
||||
*.obscpio filter=lfs diff=lfs merge=lfs -text
|
||||
*.oxt filter=lfs diff=lfs merge=lfs -text
|
||||
*.pdf filter=lfs diff=lfs merge=lfs -text
|
||||
*.png filter=lfs diff=lfs merge=lfs -text
|
||||
*.rpm filter=lfs diff=lfs merge=lfs -text
|
||||
*.tbz filter=lfs diff=lfs merge=lfs -text
|
||||
*.tbz2 filter=lfs diff=lfs merge=lfs -text
|
||||
*.tgz filter=lfs diff=lfs merge=lfs -text
|
||||
*.ttf filter=lfs diff=lfs merge=lfs -text
|
||||
*.txz filter=lfs diff=lfs merge=lfs -text
|
||||
*.whl filter=lfs diff=lfs merge=lfs -text
|
||||
*.xz filter=lfs diff=lfs merge=lfs -text
|
||||
*.zip filter=lfs diff=lfs merge=lfs -text
|
||||
*.zst filter=lfs diff=lfs merge=lfs -text
|
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
.osc
|
117
README.qa
Normal file
117
README.qa
Normal file
@ -0,0 +1,117 @@
|
||||
I. LOCAL QA.
|
||||
|
||||
|
||||
0. Notes.
|
||||
|
||||
Note that the configs are hardcoded in the script. F.i. atm SLE-11 is not
|
||||
included, because the config is unresolvable on devel:gcc/gdb. Also Leap
|
||||
15.2 is not included because of 'remote error: unknown repository type
|
||||
UNDEFINED"'.
|
||||
|
||||
The script tries to keep disk usage low by removing the buildroot after each
|
||||
build, but that requires sudo rights, so the first thing the script does is
|
||||
ask for sudo authentication.
|
||||
|
||||
|
||||
1. Cleanup.
|
||||
|
||||
Do:
|
||||
...
|
||||
$ bash qa-local.sh 1
|
||||
...
|
||||
|
||||
|
||||
2. Build.
|
||||
|
||||
Do:
|
||||
...
|
||||
$ bash qa-local.sh 2
|
||||
...
|
||||
|
||||
This builds gdb for each x86_64 config, without running the testsuite.
|
||||
|
||||
I did a timing run on my laptop (with 6 configs) and got:
|
||||
...
|
||||
real 66m17.689s
|
||||
user 149m31.925s
|
||||
sys 12m25.359s
|
||||
...
|
||||
so for a dual-core/4-SMT CPU, it's ~1h5m.
|
||||
|
||||
|
||||
3. Build & test.
|
||||
|
||||
Do:
|
||||
...
|
||||
$ bash qa-local.sh 3
|
||||
...
|
||||
|
||||
This builds gdb and produces test results for each x86_64 config.
|
||||
|
||||
I did a timing run on my laptop (with 6 configs) and got:
|
||||
...
|
||||
real 285m9.679s
|
||||
user 683m16.769s
|
||||
sys 133m58.287s
|
||||
...
|
||||
so for a dual-core/4-SMT CPU, it's ~4h45m.
|
||||
|
||||
The resulting testlogs (with 6 configs) is 1.4GB.
|
||||
|
||||
|
||||
4. Verify.
|
||||
|
||||
Do:
|
||||
...
|
||||
$ bash qa-local.sh 4
|
||||
...
|
||||
|
||||
This verifies the test results for each x86_64 config, using the qa.sh script.
|
||||
|
||||
|
||||
5. Cleanup.
|
||||
|
||||
Do:
|
||||
...
|
||||
$ rm -Rf tmp-qa-local
|
||||
...
|
||||
l
|
||||
|
||||
|
||||
I. REMOTE QA.
|
||||
|
||||
|
||||
1. Cleanup.
|
||||
|
||||
Do:
|
||||
...
|
||||
$ bash qa-remote.sh 1
|
||||
...
|
||||
|
||||
|
||||
2. Get test results.
|
||||
|
||||
Do:
|
||||
...
|
||||
$ bash qa-remote.sh 2
|
||||
...
|
||||
|
||||
This downloads the remote test results.
|
||||
|
||||
|
||||
3. Verify.
|
||||
|
||||
Do:
|
||||
...
|
||||
$ bash qa-remote.sh 3 <m>
|
||||
...
|
||||
with m running from 1 to 5.
|
||||
|
||||
This verifies the test results, using the qa.sh script.
|
||||
|
||||
4. Cleanup.
|
||||
|
||||
Do:
|
||||
...
|
||||
$ rm -Rf tmp-qa-remote
|
||||
...
|
24
_constraints
Normal file
24
_constraints
Normal file
@ -0,0 +1,24 @@
|
||||
<constraints>
|
||||
<overwrite>
|
||||
<conditions>
|
||||
<arch>ppc64</arch>
|
||||
<arch>ppc64le</arch>
|
||||
</conditions>
|
||||
<hardware>
|
||||
<disk>
|
||||
<size unit="G">4</size>
|
||||
</disk>
|
||||
</hardware>
|
||||
</overwrite>
|
||||
<overwrite>
|
||||
<conditions>
|
||||
<arch>x86_64</arch>
|
||||
</conditions>
|
||||
<hardware>
|
||||
<disk>
|
||||
<size unit="G">8</size>
|
||||
</disk>
|
||||
</hardware>
|
||||
</overwrite>
|
||||
</constraints>
|
||||
|
3
_multibuild
Normal file
3
_multibuild
Normal file
@ -0,0 +1,3 @@
|
||||
<multibuild>
|
||||
<package>testsuite</package>
|
||||
</multibuild>
|
11
baselibs.conf
Normal file
11
baselibs.conf
Normal file
@ -0,0 +1,11 @@
|
||||
gdb
|
||||
+/usr/bin/gdb -> /usr/bin/gdb<extension>
|
||||
# kill package for i586 32bit
|
||||
targetarch x86_64 block!
|
||||
prereq -glibc-x86
|
||||
gdbserver
|
||||
+/usr/bin/gdbserver -> /usr/bin/gdbserver<extension>
|
||||
provides "gdb-<targettype>:/usr/bin/gdbserver<extension>"
|
||||
# kill package for i586 32bit
|
||||
targetarch x86_64 block!
|
||||
prereq -glibc-x86
|
53
change-gdb.base-examine-backwards.exp-for-aix.patch
Normal file
53
change-gdb.base-examine-backwards.exp-for-aix.patch
Normal file
@ -0,0 +1,53 @@
|
||||
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
|
||||
|
46
clean.sh
Normal file
46
clean.sh
Normal file
@ -0,0 +1,46 @@
|
||||
#!/bin/sh
|
||||
|
||||
dryrun=false
|
||||
while [ $# -gt 0 ]; do
|
||||
case $1 in
|
||||
-dryrun|--dryrun|-dry-run|--dry-run)
|
||||
dryrun=true
|
||||
;;
|
||||
*)
|
||||
echo "Don't know how to handle arg: $1"
|
||||
exit 1
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
first=true
|
||||
for f in *.patch; do
|
||||
if grep -q "^Patch.*[ \t]$f" gdb.spec; then
|
||||
continue
|
||||
fi
|
||||
|
||||
if $dryrun; then
|
||||
if $first; then
|
||||
echo "Patches not mentioned in gdb.spec:"
|
||||
fi
|
||||
first=false
|
||||
|
||||
echo "$f"
|
||||
|
||||
continue
|
||||
fi
|
||||
|
||||
( set -x; osc remove -f "$f" )
|
||||
done
|
||||
|
||||
files=$(echo ./*~)
|
||||
if [ "$files" != "./*~" ]; then
|
||||
if $dryrun; then
|
||||
echo "Backup files:"
|
||||
echo "$files"
|
||||
else
|
||||
for f in $files; do
|
||||
( set -x; rm -f "$f" )
|
||||
done
|
||||
fi
|
||||
fi
|
23
fix-gdb.mi-new-ui-mi-sync.exp.patch
Normal file
23
fix-gdb.mi-new-ui-mi-sync.exp.patch
Normal file
@ -0,0 +1,23 @@
|
||||
Fix gdb.mi/new-ui-mi-sync.exp
|
||||
|
||||
---
|
||||
gdb/testsuite/gdb.mi/new-ui-mi-sync.exp | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.mi/new-ui-mi-sync.exp b/gdb/testsuite/gdb.mi/new-ui-mi-sync.exp
|
||||
index 887bd60abcd..18072d4e668 100644
|
||||
--- a/gdb/testsuite/gdb.mi/new-ui-mi-sync.exp
|
||||
+++ b/gdb/testsuite/gdb.mi/new-ui-mi-sync.exp
|
||||
@@ -83,7 +83,11 @@ proc do_test {sync_command} {
|
||||
# in the separate MI UI. Note the "run" variant usually triggers
|
||||
# =thread-group-started/=thread-created/=library-loaded as well.
|
||||
with_spawn_id $gdb_main_spawn_id {
|
||||
- gdb_test "add-inferior" "Added inferior 2 on connection .*"
|
||||
+ gdb_test_multiple "add-inferior" "" {
|
||||
+ -re "\r\nAdded inferior 2 on connection .*\[\r\n\]+$gdb_prompt " {
|
||||
+ pass $gdb_test_name
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
# Interrupt the program.
|
366
fix-regression-on-aarch64-linux-gdbserver.patch
Normal file
366
fix-regression-on-aarch64-linux-gdbserver.patch
Normal file
@ -0,0 +1,366 @@
|
||||
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
|
||||
|
80
fix-the-gdb.ada-inline-section-gc.exp-test.patch
Normal file
80
fix-the-gdb.ada-inline-section-gc.exp-test.patch
Normal file
@ -0,0 +1,80 @@
|
||||
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
|
||||
|
30
fixup-gdb-6.3-attach-see-vdso-test.patch
Normal file
30
fixup-gdb-6.3-attach-see-vdso-test.patch
Normal file
@ -0,0 +1,30 @@
|
||||
From 19dc95258888a9e110ad54fa25a613611956a13f Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Tue, 13 Jun 2023 15:04:32 +0200
|
||||
Subject: [PATCH 5/6] fixup gdb-6.3-attach-see-vdso-test.patch
|
||||
|
||||
---
|
||||
gdb/testsuite/gdb.base/attach-see-vdso.exp | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/attach-see-vdso.exp b/gdb/testsuite/gdb.base/attach-see-vdso.exp
|
||||
index 5457ec4129d..35c49731f0b 100644
|
||||
--- a/gdb/testsuite/gdb.base/attach-see-vdso.exp
|
||||
+++ b/gdb/testsuite/gdb.base/attach-see-vdso.exp
|
||||
@@ -34,10 +34,11 @@ set escapedbinfile [string_to_regexp [standard_output_file ${testfile}]]
|
||||
# The kernel VDSO is used for the syscalls returns only on i386 (not x86_64).
|
||||
#
|
||||
if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-m32}] != "" } {
|
||||
- gdb_suppress_entire_file "Testcase nonthraded compile failed, so all tests in this file will automatically fail."
|
||||
+ unsupported "Testcase nonthreaded compile failed, so all tests in this file will automatically fail."
|
||||
+ return
|
||||
}
|
||||
|
||||
-if [get_compiler_info ${binfile}] {
|
||||
+if [get_compiler_info] {
|
||||
return -1
|
||||
}
|
||||
|
||||
--
|
||||
2.35.3
|
||||
|
25
fixup-gdb-6.3-gstack-20050411.patch
Normal file
25
fixup-gdb-6.3-gstack-20050411.patch
Normal file
@ -0,0 +1,25 @@
|
||||
From 8c0ae8c3c6fa34f046131f76871db13bc392a440 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Tue, 13 Jun 2023 14:56:55 +0200
|
||||
Subject: [PATCH 4/6] fixup gdb-6.3-gstack-20050411.patch
|
||||
|
||||
---
|
||||
gdb/testsuite/gdb.base/gstack.exp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/gstack.exp b/gdb/testsuite/gdb.base/gstack.exp
|
||||
index 089407ec04a..a5dacd582ff 100644
|
||||
--- a/gdb/testsuite/gdb.base/gstack.exp
|
||||
+++ b/gdb/testsuite/gdb.base/gstack.exp
|
||||
@@ -52,7 +52,7 @@ gdb_expect {
|
||||
# exiting the function. Still we could retry the gstack command if we fail.
|
||||
|
||||
set test "spawn gstack"
|
||||
-set command "sh -c GDB=$GDB\\ GDBARGS=-data-directory\\\\\\ $BUILD_DATA_DIRECTORY\\ sh\\ ${srcdir}/../gstack.sh\\ $pid\\;echo\\ GSTACK-END"
|
||||
+set command "sh -c GDB=$GDB\\ GDBARGS=-data-directory\\\\\\ $GDB_DATA_DIRECTORY\\ sh\\ ${srcdir}/../gstack.sh\\ $pid\\;echo\\ GSTACK-END"
|
||||
set res [remote_spawn host $command];
|
||||
if { $res < 0 || $res == "" } {
|
||||
perror "Spawning $command failed."
|
||||
--
|
||||
2.35.3
|
||||
|
35
fixup-gdb-6.5-bz243845-stale-testing-zombie-test.patch
Normal file
35
fixup-gdb-6.5-bz243845-stale-testing-zombie-test.patch
Normal file
@ -0,0 +1,35 @@
|
||||
Fixup gdb.base/tracefork-zombie.exp
|
||||
|
||||
Fix ERROR:
|
||||
...
|
||||
PASS: gdb.base/tracefork-zombie.exp: attach
|
||||
ERROR: tcl error sourcing gdb/testsuite/gdb.base/tracefork-zombie.exp.
|
||||
ERROR: tcl error code POSIX ESRCH {no such process}
|
||||
ERROR: error reading "file12": no such process
|
||||
while executing
|
||||
"read $statusfi"
|
||||
("foreach" body line 5)
|
||||
invoked from within
|
||||
...
|
||||
|
||||
---
|
||||
gdb/testsuite/gdb.base/tracefork-zombie.exp | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/tracefork-zombie.exp b/gdb/testsuite/gdb.base/tracefork-zombie.exp
|
||||
index 03f790d4c5d..3e2e5517d46 100644
|
||||
--- a/gdb/testsuite/gdb.base/tracefork-zombie.exp
|
||||
+++ b/gdb/testsuite/gdb.base/tracefork-zombie.exp
|
||||
@@ -58,8 +58,10 @@ foreach procpid [glob -directory /proc -type d {[0-9]*}] {
|
||||
if {[catch {open $procpid/status} statusfi]} {
|
||||
continue
|
||||
}
|
||||
- set status [read $statusfi]
|
||||
- close $statusfi
|
||||
+ if {[catch {read $statusfi} status]} {
|
||||
+ continue
|
||||
+ }
|
||||
+ catch {close $statusfi}
|
||||
if {1
|
||||
&& [regexp -line {^Name:\tgdb$} $status]
|
||||
&& [regexp -line {^PPid:\t1$} $status]
|
22
fixup-gdb-bz634108-solib_address.patch
Normal file
22
fixup-gdb-bz634108-solib_address.patch
Normal file
@ -0,0 +1,22 @@
|
||||
From 023314feb400836eb377a5bc9151850fcdd81b11 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Tue, 6 Jun 2023 09:43:36 +0200
|
||||
Subject: [PATCH 3/4] Fixup gdb-bz634108-solib_address.patch
|
||||
|
||||
---
|
||||
gdb/testsuite/gdb.python/rh634108-solib_address.exp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.python/rh634108-solib_address.exp b/gdb/testsuite/gdb.python/rh634108-solib_address.exp
|
||||
index 99e6aaba831..ebf00babc34 100644
|
||||
--- a/gdb/testsuite/gdb.python/rh634108-solib_address.exp
|
||||
+++ b/gdb/testsuite/gdb.python/rh634108-solib_address.exp
|
||||
@@ -21,4 +21,4 @@ gdb_start
|
||||
# Skip all tests if Python scripting is not enabled.
|
||||
if { [skip_python_tests] } { continue }
|
||||
|
||||
-gdb_test "python print (gdb.solib_name(-1))" "None" "gdb.solib_name exists"
|
||||
+gdb_test "python print (gdb.solib_name(0))" "None" "gdb.solib_name exists"
|
||||
--
|
||||
2.35.3
|
||||
|
19
fixup-gdb-glibc-strstr-workaround.patch
Normal file
19
fixup-gdb-glibc-strstr-workaround.patch
Normal file
@ -0,0 +1,19 @@
|
||||
fixup-gdb-glibc-strstr-workaround.patch
|
||||
|
||||
---
|
||||
gdb/testsuite/gdb.base/gnu-ifunc-strstr-workaround.exp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/gnu-ifunc-strstr-workaround.exp b/gdb/testsuite/gdb.base/gnu-ifunc-strstr-workaround.exp
|
||||
index 889f8c6f584..052bd84d420 100644
|
||||
--- a/gdb/testsuite/gdb.base/gnu-ifunc-strstr-workaround.exp
|
||||
+++ b/gdb/testsuite/gdb.base/gnu-ifunc-strstr-workaround.exp
|
||||
@@ -68,7 +68,7 @@ gdb_test_multiple $test $test {
|
||||
set addr $expect_out(1,string)
|
||||
pass "$test (fixed glibc)"
|
||||
}
|
||||
- -re " = {char \\*\\(const char \\*, const char \\*\\)} 0x\[0-9a-f\]+ <strstr>\r\n$gdb_prompt $" {
|
||||
+ -re " = {char \\*\\(const char \\*, const char \\*\\)} 0x\[0-9a-f\]+ <(__GI_)?strstr>\r\n$gdb_prompt $" {
|
||||
untested "$test (gnu-ifunc not in use by glibc)"
|
||||
return 0
|
||||
}
|
40
fixup-gdb-linux_perf-bundle.patch
Normal file
40
fixup-gdb-linux_perf-bundle.patch
Normal file
@ -0,0 +1,40 @@
|
||||
From af4a87e2b3c2ac5acae1e6f4405fc59e1218de74 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Thu, 18 Apr 2024 14:26:58 +0200
|
||||
Subject: [PATCH] fixup-gdb-linux_perf-bundle
|
||||
|
||||
---
|
||||
gdb/gdb.c | 8 --------
|
||||
1 file changed, 8 deletions(-)
|
||||
|
||||
diff --git a/gdb/gdb.c b/gdb/gdb.c
|
||||
index 41a9b70c222..6e3ff0755ab 100644
|
||||
--- a/gdb/gdb.c
|
||||
+++ b/gdb/gdb.c
|
||||
@@ -21,10 +21,6 @@
|
||||
#include "interps.h"
|
||||
#include "run-on-main-thread.h"
|
||||
|
||||
-#ifdef PERF_ATTR_SIZE_VER5_BUNDLE
|
||||
-extern "C" void __libipt_init(void);
|
||||
-#endif
|
||||
-
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
@@ -36,10 +32,6 @@ main (int argc, char **argv)
|
||||
|
||||
struct captured_main_args args;
|
||||
|
||||
-#ifdef PERF_ATTR_SIZE_VER5_BUNDLE
|
||||
- __libipt_init();
|
||||
-#endif
|
||||
-
|
||||
memset (&args, 0, sizeof args);
|
||||
args.argc = argc;
|
||||
args.argv = argv;
|
||||
|
||||
base-commit: 254988c36fe592e89af5d92e1d35a6eb4b09cbb0
|
||||
--
|
||||
2.35.3
|
||||
|
43
fixup-gdb-rhbz1261564-aarch64-hw-watchpoint-test.pat.patch
Normal file
43
fixup-gdb-rhbz1261564-aarch64-hw-watchpoint-test.pat.patch
Normal file
@ -0,0 +1,43 @@
|
||||
From e452307ba07f5d798edad73631182e137265da7d Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Tue, 13 Jun 2023 17:58:42 +0200
|
||||
Subject: [PATCH 9/9] fixup gdb-rhbz1261564-aarch64-hw-watchpoint-test.patch
|
||||
|
||||
---
|
||||
.../rhbz1261564-aarch64-watchpoint.exp | 18 ++++++++++++++----
|
||||
1 file changed, 14 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/rhbz1261564-aarch64-watchpoint.exp b/gdb/testsuite/gdb.base/rhbz1261564-aarch64-watchpoint.exp
|
||||
index b1cf7115663..42ebc25cc49 100644
|
||||
--- a/gdb/testsuite/gdb.base/rhbz1261564-aarch64-watchpoint.exp
|
||||
+++ b/gdb/testsuite/gdb.base/rhbz1261564-aarch64-watchpoint.exp
|
||||
@@ -20,12 +20,22 @@ if { [prepare_for_testing rhbz1261564-aarch64-watchpoint.exp "rhbz1261564-aarch6
|
||||
if { ! [ runto main ] } then { return 0 }
|
||||
|
||||
set test "rwatch aligned.var4"
|
||||
-if [istarget "s390*-*-*"] {
|
||||
- gdb_test $test {Target does not support this type of hardware watchpoint\.}
|
||||
- untested "s390* does not support hw read watchpoint"
|
||||
+
|
||||
+set supported 1
|
||||
+gdb_test_multiple $test "" {
|
||||
+ -re -wrap "Hardware read watchpoint \[0-9\]+: aligned.var4" {
|
||||
+ pass $gdb_test_name
|
||||
+ }
|
||||
+ -re -wrap "Target does not support this type of hardware watchpoint\\." {
|
||||
+ set supported 0
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+if { !$supported } {
|
||||
+ unsupported $test
|
||||
return
|
||||
}
|
||||
-gdb_test $test "Hardware read watchpoint \[0-9\]+: aligned.var4"
|
||||
+
|
||||
|
||||
proc checkvar { address } {
|
||||
global gdb_prompt
|
||||
--
|
||||
2.35.3
|
||||
|
38
fixup-gdb-test-bt-cfi-without-die.patch
Normal file
38
fixup-gdb-test-bt-cfi-without-die.patch
Normal file
@ -0,0 +1,38 @@
|
||||
fixup-gdb-test-bt-cfi-without-die.patch
|
||||
|
||||
---
|
||||
gdb/testsuite/gdb.base/cfi-without-die.exp | 13 ++++++++-----
|
||||
1 file changed, 8 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/cfi-without-die.exp b/gdb/testsuite/gdb.base/cfi-without-die.exp
|
||||
index 5880d46f6d2..db1726646f8 100644
|
||||
--- a/gdb/testsuite/gdb.base/cfi-without-die.exp
|
||||
+++ b/gdb/testsuite/gdb.base/cfi-without-die.exp
|
||||
@@ -37,19 +37,22 @@ if ![runto callback] then {
|
||||
fail "verify unwinding: Can't run to callback"
|
||||
return 0
|
||||
}
|
||||
-set test "verify unwinding breaks without CFI"
|
||||
-gdb_test_multiple "bt" $test {
|
||||
+
|
||||
+set as_expected 1
|
||||
+gdb_test_multiple "bt" "" {
|
||||
-re " in \[?\]\[?\] .*\r\n$gdb_prompt $" {
|
||||
# It may backtrace through some random frames even to main().
|
||||
- pass $test
|
||||
}
|
||||
-re " in main .*\r\n$gdb_prompt $" {
|
||||
- fail $test
|
||||
+ set as_expected 0
|
||||
}
|
||||
-re "\r\n$gdb_prompt $" {
|
||||
- pass $test
|
||||
}
|
||||
}
|
||||
+if { ! $as_expected } {
|
||||
+ untested ${testfile}.exp
|
||||
+ return -1
|
||||
+}
|
||||
|
||||
if { [gdb_compile "${srcdir}/${subdir}/${srccallerfile}" ${objcallerfile} \
|
||||
object [list {additional_flags=-fomit-frame-pointer -funwind-tables -fasynchronous-unwind-tables}]] != ""
|
21
fixup-gdb-test-dw2-aranges.patch
Normal file
21
fixup-gdb-test-dw2-aranges.patch
Normal file
@ -0,0 +1,21 @@
|
||||
From 81a7585502092b3c133534ac6ecb34fd56d05337 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Thu, 16 Feb 2023 12:56:41 +0100
|
||||
Subject: [PATCH 09/11] fixup gdb-test-dw2-aranges.patch
|
||||
|
||||
---
|
||||
gdb/testsuite/gdb.dwarf2/dw2-aranges.S | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-aranges.S b/gdb/testsuite/gdb.dwarf2/dw2-aranges.S
|
||||
index d5b9ca5a3c6..b811f6644cb 100644
|
||||
--- a/gdb/testsuite/gdb.dwarf2/dw2-aranges.S
|
||||
+++ b/gdb/testsuite/gdb.dwarf2/dw2-aranges.S
|
||||
@@ -138,3 +138,4 @@ main:
|
||||
.byte 0 /* aranges segment_size */
|
||||
|
||||
.Laranges_end:
|
||||
+ .section .note.GNU-stack,"",@progbits
|
||||
--
|
||||
2.35.3
|
||||
|
70
fixup-powerpc-and-aarch64-fix-reverse-stepping-failu.patch
Normal file
70
fixup-powerpc-and-aarch64-fix-reverse-stepping-failu.patch
Normal file
@ -0,0 +1,70 @@
|
||||
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
|
||||
|
101
fixup-skip-tests.patch
Normal file
101
fixup-skip-tests.patch
Normal file
@ -0,0 +1,101 @@
|
||||
From c1da0d6449415cc1fe6f863526735e4325b0b3ac Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Wed, 1 May 2024 12:43:41 +0200
|
||||
Subject: [PATCH 1/2] fixup-skip-tests
|
||||
|
||||
---
|
||||
gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib.exp | 4 +---
|
||||
gdb/testsuite/gdb.base/gnu-ifunc-strstr-workaround.exp | 4 +---
|
||||
gdb/testsuite/gdb.cp/cxxexec.exp | 2 +-
|
||||
.../py-gdb-rhbz1007614-memleak-infpy_read_memory.exp | 4 ++--
|
||||
gdb/testsuite/gdb.python/rh634108-solib_address.exp | 6 +++---
|
||||
5 files changed, 8 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib.exp b/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib.exp
|
||||
index 0c46489f315..5879319f27c 100644
|
||||
--- a/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib.exp
|
||||
+++ b/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib.exp
|
||||
@@ -13,9 +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/>.
|
||||
|
||||
-if {[skip_shlib_tests]} {
|
||||
- return 0
|
||||
-}
|
||||
+require allow_shlib_tests
|
||||
|
||||
set testfile "gcore-buildid-exec-but-not-solib"
|
||||
set srcmainfile ${testfile}-main.c
|
||||
diff --git a/gdb/testsuite/gdb.base/gnu-ifunc-strstr-workaround.exp b/gdb/testsuite/gdb.base/gnu-ifunc-strstr-workaround.exp
|
||||
index 052bd84d420..73a9bb64903 100644
|
||||
--- a/gdb/testsuite/gdb.base/gnu-ifunc-strstr-workaround.exp
|
||||
+++ b/gdb/testsuite/gdb.base/gnu-ifunc-strstr-workaround.exp
|
||||
@@ -17,9 +17,7 @@
|
||||
# invalid IFUNC DW_AT_linkage_name: memmove strstr time
|
||||
# http://sourceware.org/bugzilla/show_bug.cgi?id=14166
|
||||
|
||||
-if {[skip_shlib_tests]} {
|
||||
- return 0
|
||||
-}
|
||||
+require allow_shlib_tests
|
||||
|
||||
set testfile "gnu-ifunc-strstr-workaround"
|
||||
set executable ${testfile}
|
||||
diff --git a/gdb/testsuite/gdb.cp/cxxexec.exp b/gdb/testsuite/gdb.cp/cxxexec.exp
|
||||
index 77c85587407..089a679a1a9 100644
|
||||
--- a/gdb/testsuite/gdb.cp/cxxexec.exp
|
||||
+++ b/gdb/testsuite/gdb.cp/cxxexec.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/>.
|
||||
|
||||
-if { [skip_cplus_tests] } { continue }
|
||||
+require allow_cplus_tests
|
||||
|
||||
set testfile cxxexec
|
||||
if { [prepare_for_testing ${testfile}.exp ${testfile} ${testfile}.cc {c++ debug}] } {
|
||||
diff --git a/gdb/testsuite/gdb.python/py-gdb-rhbz1007614-memleak-infpy_read_memory.exp b/gdb/testsuite/gdb.python/py-gdb-rhbz1007614-memleak-infpy_read_memory.exp
|
||||
index 2e6786d499a..d2693cfef1d 100644
|
||||
--- a/gdb/testsuite/gdb.python/py-gdb-rhbz1007614-memleak-infpy_read_memory.exp
|
||||
+++ b/gdb/testsuite/gdb.python/py-gdb-rhbz1007614-memleak-infpy_read_memory.exp
|
||||
@@ -13,6 +13,8 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
+require allow_python_tests
|
||||
+
|
||||
set testfile py-gdb-rhbz1007614-memleak-infpy_read_memory
|
||||
set srcfile ${testfile}.c
|
||||
set binfile [standard_output_file ${testfile}]
|
||||
@@ -21,8 +23,6 @@ if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } {
|
||||
return -1
|
||||
}
|
||||
|
||||
-if { [skip_python_tests] } { continue }
|
||||
-
|
||||
set pid_of_gdb [exp_pid -i [board_info host fileid]]
|
||||
|
||||
proc memory_v_pages_get {} {
|
||||
diff --git a/gdb/testsuite/gdb.python/rh634108-solib_address.exp b/gdb/testsuite/gdb.python/rh634108-solib_address.exp
|
||||
index ebf00babc34..2d950b79951 100644
|
||||
--- a/gdb/testsuite/gdb.python/rh634108-solib_address.exp
|
||||
+++ b/gdb/testsuite/gdb.python/rh634108-solib_address.exp
|
||||
@@ -15,10 +15,10 @@
|
||||
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=634108
|
||||
|
||||
+# Skip all tests if Python scripting is not enabled.
|
||||
+require allow_python_tests
|
||||
+
|
||||
gdb_exit
|
||||
gdb_start
|
||||
|
||||
-# Skip all tests if Python scripting is not enabled.
|
||||
-if { [skip_python_tests] } { continue }
|
||||
-
|
||||
gdb_test "python print (gdb.solib_name(0))" "None" "gdb.solib_name exists"
|
||||
|
||||
base-commit: 50ee7556c2430effed45ca542852f36368336dce
|
||||
--
|
||||
2.35.3
|
||||
|
BIN
gdb-14.2.tar.bz2
(Stored with Git LFS)
Normal file
BIN
gdb-14.2.tar.bz2
(Stored with Git LFS)
Normal file
Binary file not shown.
120
gdb-6.3-attach-see-vdso-test.patch
Normal file
120
gdb-6.3-attach-see-vdso-test.patch
Normal file
@ -0,0 +1,120 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Fedora GDB patches <invalid@email.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-6.3-attach-see-vdso-test.patch
|
||||
|
||||
;; Test kernel VDSO decoding while attaching to an i386 process.
|
||||
;;=fedoratest
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/attach-see-vdso.c b/gdb/testsuite/gdb.base/attach-see-vdso.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/attach-see-vdso.c
|
||||
@@ -0,0 +1,25 @@
|
||||
+/* This testcase is part of GDB, the GNU debugger.
|
||||
+
|
||||
+ Copyright 2007 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 2 of the License, or
|
||||
+ (at your option) any later version.
|
||||
+
|
||||
+ This program is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ GNU General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU General Public License
|
||||
+ along with this program; if not, write to the Free Software
|
||||
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
+
|
||||
+#include <unistd.h>
|
||||
+
|
||||
+int main ()
|
||||
+{
|
||||
+ pause ();
|
||||
+ return 1;
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.base/attach-see-vdso.exp b/gdb/testsuite/gdb.base/attach-see-vdso.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/attach-see-vdso.exp
|
||||
@@ -0,0 +1,77 @@
|
||||
+# Copyright 2007
|
||||
+
|
||||
+# This program is free software; you can redistribute it and/or modify
|
||||
+# it under the terms of the GNU General Public License as published by
|
||||
+# the Free Software Foundation; either version 2 of the License, or
|
||||
+# (at your option) any later version.
|
||||
+#
|
||||
+# This program is distributed in the hope that it will be useful,
|
||||
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+# GNU General Public License for more details.
|
||||
+#
|
||||
+# You should have received a copy of the GNU General Public License
|
||||
+# along with this program; if not, write to the Free Software
|
||||
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
+
|
||||
+# This file was created by Jan Kratochvil <jan.kratochvil@redhat.com>.
|
||||
+
|
||||
+# This test only works on Linux
|
||||
+if { ![istarget "*-*-linux-gnu*"] } {
|
||||
+ return 0
|
||||
+}
|
||||
+
|
||||
+if {[use_gdb_stub]} {
|
||||
+ untested "skipping test because of use_gdb_stub"
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+set testfile "attach-see-vdso"
|
||||
+set srcfile ${testfile}.c
|
||||
+set binfile [standard_output_file ${testfile}]
|
||||
+set escapedbinfile [string_to_regexp [standard_output_file ${testfile}]]
|
||||
+
|
||||
+# The kernel VDSO is used for the syscalls returns only on i386 (not x86_64).
|
||||
+#
|
||||
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-m32}] != "" } {
|
||||
+ gdb_suppress_entire_file "Testcase nonthraded compile failed, so all tests in this file will automatically fail."
|
||||
+}
|
||||
+
|
||||
+if [get_compiler_info ${binfile}] {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+# Start the program running and then wait for a bit, to be sure
|
||||
+# that it can be attached to.
|
||||
+
|
||||
+set testpid [eval exec $binfile &]
|
||||
+
|
||||
+# Avoid some race:
|
||||
+sleep 2
|
||||
+
|
||||
+# Start with clean gdb
|
||||
+gdb_exit
|
||||
+gdb_start
|
||||
+gdb_reinitialize_dir $srcdir/$subdir
|
||||
+# Never call: gdb_load ${binfile}
|
||||
+# as the former problem would not reproduce otherwise.
|
||||
+
|
||||
+set test "attach"
|
||||
+gdb_test_multiple "attach $testpid" "$test" {
|
||||
+ -re "Attaching to process $testpid\r?\n.*$gdb_prompt $" {
|
||||
+ pass "$test"
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+gdb_test "bt" "#0 *0x\[0-9a-f\]* in \[^?\].*" "backtrace decodes VDSO"
|
||||
+
|
||||
+# Exit and detach the process.
|
||||
+
|
||||
+gdb_exit
|
||||
+
|
||||
+# Make sure we don't leave a process around to confuse
|
||||
+# the next test run (and prevent the compile by keeping
|
||||
+# the text file busy), in case the "set should_exit" didn't
|
||||
+# work.
|
||||
+
|
||||
+remote_exec build "kill -9 ${testpid}"
|
258
gdb-6.3-gstack-20050411.patch
Normal file
258
gdb-6.3-gstack-20050411.patch
Normal file
@ -0,0 +1,258 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Cagney <cagney@gnu.org>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-6.3-gstack-20050411.patch
|
||||
|
||||
;; Add a wrapper script to GDB that implements pstack using the
|
||||
;; --readnever option.
|
||||
;;=push
|
||||
|
||||
2004-11-23 Andrew Cagney <cagney@redhat.com>
|
||||
|
||||
* Makefile.in (uninstall-gstack, install-gstack): New rules, add
|
||||
to install and uninstall.
|
||||
* gstack.sh, gstack.1: New files.
|
||||
|
||||
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
|
||||
install: all
|
||||
@$(MAKE) $(FLAGS_TO_PASS) install-only
|
||||
|
||||
-install-only: $(CONFIG_INSTALL)
|
||||
+install-only: install-gstack $(CONFIG_INSTALL)
|
||||
transformed_name=`t='$(program_transform_name)'; \
|
||||
echo gdb | sed -e "$$t"` ; \
|
||||
if test "x$$transformed_name" = x; then \
|
||||
@@ -2085,7 +2085,25 @@ install-guile:
|
||||
install-python:
|
||||
$(SHELL) $(srcdir)/../mkinstalldirs $(DESTDIR)$(GDB_DATADIR)/python/gdb
|
||||
|
||||
-uninstall: force $(CONFIG_UNINSTALL)
|
||||
+GSTACK=gstack
|
||||
+.PHONY: install-gstack
|
||||
+install-gstack:
|
||||
+ transformed_name=`t='$(program_transform_name)'; \
|
||||
+ echo $(GSTACK) | sed -e "$$t"` ; \
|
||||
+ if test "x$$transformed_name" = x; then \
|
||||
+ transformed_name=$(GSTACK) ; \
|
||||
+ else \
|
||||
+ true ; \
|
||||
+ fi ; \
|
||||
+ $(SHELL) $(srcdir)/../mkinstalldirs $(DESTDIR)$(bindir) ; \
|
||||
+ $(INSTALL_PROGRAM) $(srcdir)/$(GSTACK).sh \
|
||||
+ $(DESTDIR)$(bindir)/$$transformed_name$(EXEEXT) ; \
|
||||
+ : $(SHELL) $(srcdir)/../mkinstalldirs \
|
||||
+ $(DESTDIR)$(man1dir) ; \
|
||||
+ : $(INSTALL_DATA) $(srcdir)/gstack.1 \
|
||||
+ $(DESTDIR)$(man1dir)/$$transformed_name.1
|
||||
+
|
||||
+uninstall: force uninstall-gstack $(CONFIG_UNINSTALL)
|
||||
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)
|
||||
rm -f $(DESTDIR)$(bindir)/$$transformed_name
|
||||
@$(MAKE) DO=uninstall "DODIRS=$(SUBDIRS)" $(FLAGS_TO_PASS) subdir_do
|
||||
|
||||
+.PHONY: uninstall-gstack
|
||||
+uninstall-gstack:
|
||||
+ transformed_name=`t='$(program_transform_name)'; \
|
||||
+ echo $(GSTACK) | sed -e $$t` ; \
|
||||
+ if test "x$$transformed_name" = x; then \
|
||||
+ transformed_name=$(GSTACK) ; \
|
||||
+ else \
|
||||
+ true ; \
|
||||
+ fi ; \
|
||||
+ 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
|
||||
diff --git a/gdb/gstack.sh b/gdb/gstack.sh
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/gstack.sh
|
||||
@@ -0,0 +1,43 @@
|
||||
+#!/bin/sh
|
||||
+
|
||||
+if test $# -ne 1; then
|
||||
+ echo "Usage: `basename $0 .sh` <process-id>" 1>&2
|
||||
+ exit 1
|
||||
+fi
|
||||
+
|
||||
+if test ! -r /proc/$1; then
|
||||
+ echo "Process $1 not found." 1>&2
|
||||
+ exit 1
|
||||
+fi
|
||||
+
|
||||
+# GDB doesn't allow "thread apply all bt" when the process isn't
|
||||
+# threaded; need to peek at the process to determine if that or the
|
||||
+# simpler "bt" should be used.
|
||||
+
|
||||
+backtrace="bt"
|
||||
+if test -d /proc/$1/task ; then
|
||||
+ # Newer kernel; has a task/ directory.
|
||||
+ if test `/bin/ls /proc/$1/task | /usr/bin/wc -l` -gt 1 2>/dev/null ; then
|
||||
+ backtrace="thread apply all bt"
|
||||
+ fi
|
||||
+elif test -f /proc/$1/maps ; then
|
||||
+ # Older kernel; go by it loading libpthread.
|
||||
+ if /bin/grep -e libpthread /proc/$1/maps > /dev/null 2>&1 ; then
|
||||
+ backtrace="thread apply all bt"
|
||||
+ fi
|
||||
+fi
|
||||
+
|
||||
+GDB=${GDB:-gdb}
|
||||
+
|
||||
+# Run GDB, strip out unwanted noise.
|
||||
+# --readnever is no longer used since .gdb_index is now in use.
|
||||
+$GDB --quiet -nx $GDBARGS /proc/$1/exe $1 <<EOF 2>&1 |
|
||||
+set width 0
|
||||
+set height 0
|
||||
+set pagination no
|
||||
+$backtrace
|
||||
+EOF
|
||||
+/bin/sed -n \
|
||||
+ -e 's/^\((gdb) \)*//' \
|
||||
+ -e '/^#/p' \
|
||||
+ -e '/^Thread/p'
|
||||
diff --git a/gdb/testsuite/gdb.base/gstack.c b/gdb/testsuite/gdb.base/gstack.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/gstack.c
|
||||
@@ -0,0 +1,43 @@
|
||||
+/* This testcase is part of GDB, the GNU debugger.
|
||||
+
|
||||
+ Copyright 2005, 2007, 2008, 2009 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/>. */
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+#include <unistd.h>
|
||||
+#include <string.h>
|
||||
+
|
||||
+void
|
||||
+func (void)
|
||||
+{
|
||||
+ const char msg[] = "looping\n";
|
||||
+
|
||||
+ /* Use the most simple notification not to get caught by attach on exiting
|
||||
+ the function. */
|
||||
+ write (1, msg, strlen (msg));
|
||||
+
|
||||
+ for (;;);
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+main (void)
|
||||
+{
|
||||
+ alarm (60);
|
||||
+ nice (100);
|
||||
+
|
||||
+ func ();
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.base/gstack.exp b/gdb/testsuite/gdb.base/gstack.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/gstack.exp
|
||||
@@ -0,0 +1,84 @@
|
||||
+# Copyright (C) 2012 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/>.
|
||||
+
|
||||
+set testfile gstack
|
||||
+set executable ${testfile}
|
||||
+set binfile [standard_output_file $executable]
|
||||
+if {[build_executable ${testfile} ${executable} "" {debug}] == -1} {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+set test "spawn inferior"
|
||||
+set command "${binfile}"
|
||||
+set res [remote_spawn host $command];
|
||||
+if { $res < 0 || $res == "" } {
|
||||
+ perror "Spawning $command failed."
|
||||
+ fail $test
|
||||
+ return
|
||||
+}
|
||||
+
|
||||
+# The spawn id of the test inferior.
|
||||
+set test_spawn_id $res
|
||||
+
|
||||
+set use_gdb_stub 1
|
||||
+set pid [exp_pid -i $res]
|
||||
+gdb_expect {
|
||||
+ -re "looping\r\n" {
|
||||
+ pass $test
|
||||
+ }
|
||||
+ eof {
|
||||
+ fail "$test (eof)"
|
||||
+ return
|
||||
+ }
|
||||
+ timeout {
|
||||
+ fail "$test (timeout)"
|
||||
+ return
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+# Testcase uses the most simple notification not to get caught by attach on
|
||||
+# exiting the function. Still we could retry the gstack command if we fail.
|
||||
+
|
||||
+set test "spawn gstack"
|
||||
+set command "sh -c GDB=$GDB\\ GDBARGS=-data-directory\\\\\\ $BUILD_DATA_DIRECTORY\\ sh\\ ${srcdir}/../gstack.sh\\ $pid\\;echo\\ GSTACK-END"
|
||||
+set res [remote_spawn host $command];
|
||||
+if { $res < 0 || $res == "" } {
|
||||
+ perror "Spawning $command failed."
|
||||
+ fail $test
|
||||
+}
|
||||
+
|
||||
+set gdb_spawn_id $res
|
||||
+
|
||||
+gdb_test_multiple "" $test {
|
||||
+ -re "^#0 +(0x\[0-9a-f\]+ in )?\\.?func \\(\\) at \[^\r\n\]*\r\n#1 +0x\[0-9a-f\]+ in \\.?main \\(\\) at \[^\r\n\]*\r\nGSTACK-END\r\n\$" {
|
||||
+ pass $test
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+gdb_test_multiple "" "gstack exits" {
|
||||
+ eof {
|
||||
+ set result [wait -i $gdb_spawn_id]
|
||||
+ verbose $result
|
||||
+
|
||||
+ gdb_assert { [lindex $result 2] == 0 } "gstack exits with no error"
|
||||
+ gdb_assert { [lindex $result 3] == 0 } "gstack's exit status is 0"
|
||||
+
|
||||
+ remote_close host
|
||||
+ clear_gdb_spawn_id
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+# Kill the test inferior.
|
||||
+kill_wait_spawned_process $test_spawn_id
|
247
gdb-6.3-mapping-zero-inode-test.patch
Normal file
247
gdb-6.3-mapping-zero-inode-test.patch
Normal file
@ -0,0 +1,247 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Fedora GDB patches <invalid@email.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-6.3-mapping-zero-inode-test.patch
|
||||
|
||||
;; Test GCORE for shmid 0 shared memory mappings.
|
||||
;;=fedoratest: But it is broken anyway, sometimes the case being tested is not reproducible.
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/gcore-shmid0.c b/gdb/testsuite/gdb.base/gcore-shmid0.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/gcore-shmid0.c
|
||||
@@ -0,0 +1,128 @@
|
||||
+/* Copyright 2007, 2009 Free Software Foundation, Inc.
|
||||
+
|
||||
+ This file is part of GDB.
|
||||
+
|
||||
+ This program is free software; you can redistribute it and/or modify
|
||||
+ it under the terms of the GNU General Public License as published by
|
||||
+ the Free Software Foundation; either version 2 of the License, or (at
|
||||
+ your option) any later version.
|
||||
+
|
||||
+ This program is distributed in the hope that it will be useful, but
|
||||
+ WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU General Public License
|
||||
+ along with this program; if not, write to the Free Software
|
||||
+ Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
+ Boston, MA 02111-1307, USA. */
|
||||
+
|
||||
+/*
|
||||
+ * Test GDB's handling of gcore for mapping with a name but zero inode.
|
||||
+ */
|
||||
+
|
||||
+#include <sys/ipc.h>
|
||||
+#include <sys/shm.h>
|
||||
+#include <stdio.h>
|
||||
+#include <errno.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <unistd.h>
|
||||
+#include <assert.h>
|
||||
+#include <time.h>
|
||||
+
|
||||
+/* The same test running in a parallel testsuite may steal us the zero SID,
|
||||
+ even if we never get any EEXIST. Just try a while. */
|
||||
+
|
||||
+#define TIMEOUT_SEC 10
|
||||
+
|
||||
+static volatile int v;
|
||||
+
|
||||
+static void
|
||||
+initialized (void)
|
||||
+{
|
||||
+ v++;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+unresolved (void)
|
||||
+{
|
||||
+ v++;
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+main (void)
|
||||
+{
|
||||
+ int sid;
|
||||
+ unsigned int *addr = (void *) -1L;
|
||||
+ int attempt, round = 0;
|
||||
+ time_t ts_start, ts;
|
||||
+
|
||||
+ if (time (&ts_start) == (time_t) -1)
|
||||
+ {
|
||||
+ printf ("time (): %m\n");
|
||||
+ exit (1);
|
||||
+ }
|
||||
+
|
||||
+ /* The generated SID will cycle with an increment of 32768, attempt until it
|
||||
+ * wraps to 0. */
|
||||
+
|
||||
+ for (attempt = 0; addr == (void *) -1L; attempt++)
|
||||
+ {
|
||||
+ /* kernel-2.6.25-8.fc9.x86_64 just never returns the value 0 by
|
||||
+ shmget(2). shmget returns SID range 0..1<<31 in steps of 32768,
|
||||
+ 0x1000 should be enough but wrap the range it to be sure. */
|
||||
+
|
||||
+ if (attempt > 0x21000)
|
||||
+ {
|
||||
+ if (time (&ts) == (time_t) -1)
|
||||
+ {
|
||||
+ printf ("time (): %m\n");
|
||||
+ exit (1);
|
||||
+ }
|
||||
+
|
||||
+ if (ts >= ts_start && ts < ts_start + TIMEOUT_SEC)
|
||||
+ {
|
||||
+ attempt = 0;
|
||||
+ round++;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ printf ("Problem is not reproducible on this kernel (attempt %d, "
|
||||
+ "round %d)\n", attempt, round);
|
||||
+ unresolved ();
|
||||
+ exit (1);
|
||||
+ }
|
||||
+
|
||||
+ sid = shmget ((key_t) rand (), 0x1000, IPC_CREAT | IPC_EXCL | 0777);
|
||||
+ if (sid == -1)
|
||||
+ {
|
||||
+ if (errno == EEXIST)
|
||||
+ continue;
|
||||
+
|
||||
+ printf ("shmget (%d, 0x1000, IPC_CREAT): errno %d\n", 0, errno);
|
||||
+ exit (1);
|
||||
+ }
|
||||
+
|
||||
+ /* Use SID only if it is 0, retry it otherwise. */
|
||||
+
|
||||
+ if (sid == 0)
|
||||
+ {
|
||||
+ addr = shmat (sid, NULL, SHM_RND);
|
||||
+ if (addr == (void *) -1L)
|
||||
+ {
|
||||
+ printf ("shmat (%d, NULL, SHM_RND): errno %d\n", sid,
|
||||
+ errno);
|
||||
+ exit (1);
|
||||
+ }
|
||||
+ }
|
||||
+ if (shmctl (sid, IPC_RMID, NULL) != 0)
|
||||
+ {
|
||||
+ printf ("shmctl (%d, IPC_RMID, NULL): errno %d\n", sid, errno);
|
||||
+ exit (1);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ initialized ();
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.base/gcore-shmid0.exp b/gdb/testsuite/gdb.base/gcore-shmid0.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/gcore-shmid0.exp
|
||||
@@ -0,0 +1,101 @@
|
||||
+# Copyright 2007, 2009 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 2 of the License, or
|
||||
+# (at your option) any later version.
|
||||
+#
|
||||
+# This program is distributed in the hope that it will be useful,
|
||||
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+# GNU General Public License for more details.
|
||||
+#
|
||||
+# You should have received a copy of the GNU General Public License
|
||||
+# along with this program; if not, write to the Free Software
|
||||
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
+
|
||||
+# Test GDB's handling of gcore for mapping with a name but zero inode.
|
||||
+
|
||||
+if { [prepare_for_testing gcore-shmid0.exp gcore-shmid0] } {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+# Does this gdb support gcore?
|
||||
+set test "help gcore"
|
||||
+gdb_test_multiple $test $test {
|
||||
+ -re "Undefined command: .gcore.*$gdb_prompt $" {
|
||||
+ # gcore command not supported -- nothing to test here.
|
||||
+ unsupported "gdb does not support gcore on this target"
|
||||
+ return -1;
|
||||
+ }
|
||||
+ -re "Save a core file .*$gdb_prompt $" {
|
||||
+ pass $test
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+if { ! [ runto_main ] } then {
|
||||
+ untested gcore-shmid0.exp
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+gdb_breakpoint "initialized"
|
||||
+gdb_breakpoint "unresolved"
|
||||
+
|
||||
+set oldtimeout $timeout
|
||||
+set timeout [expr $oldtimeout + 120]
|
||||
+
|
||||
+set test "Continue to initialized."
|
||||
+gdb_test_multiple "continue" $test {
|
||||
+ -re "Breakpoint .*, initialized .* at .*\r\n$gdb_prompt $" {
|
||||
+ pass $test
|
||||
+ }
|
||||
+ -re "Breakpoint .*, unresolved .* at .*\r\n$gdb_prompt $" {
|
||||
+ set timeout $oldtimeout
|
||||
+ unsupported $test
|
||||
+ return -1
|
||||
+ }
|
||||
+}
|
||||
+set timeout $oldtimeout
|
||||
+
|
||||
+set escapedfilename [string_to_regexp [standard_output_file gcore-shmid0.test]]
|
||||
+
|
||||
+set test "save a corefile"
|
||||
+gdb_test_multiple "gcore [standard_output_file gcore-shmid0.test]" $test {
|
||||
+ -re "Saved corefile ${escapedfilename}\[\r\n\]+$gdb_prompt $" {
|
||||
+ pass $test
|
||||
+ }
|
||||
+ -re "Can't create a corefile\[\r\n\]+$gdb_prompt $" {
|
||||
+ unsupported $test
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+# Be sure to remove the handle first.
|
||||
+# But it would get removed even on a kill by GDB as the handle is already
|
||||
+# deleted, just it is still attached.
|
||||
+gdb_continue_to_end "finish"
|
||||
+
|
||||
+set test "core-file command"
|
||||
+gdb_test_multiple "core-file [standard_output_file gcore-shmid0.test]" $test {
|
||||
+ -re ".* program is being debugged already.*y or n. $" {
|
||||
+ # gdb_load may connect us to a gdbserver.
|
||||
+ send_gdb "y\n"
|
||||
+ exp_continue;
|
||||
+ }
|
||||
+ -re "Core was generated by .*\r\n\#0 .*\\\(\\\).*\r\n$gdb_prompt $" {
|
||||
+ # The filename does not fit there anyway so do not check it.
|
||||
+ pass $test
|
||||
+ }
|
||||
+ -re ".*registers from core file: File in wrong format.* $" {
|
||||
+ fail "core-file command (could not read registers from core file)"
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+set test "backtrace"
|
||||
+gdb_test_multiple "bt" $test {
|
||||
+ -re "#0 *initialized \\\(\\\) at .*#1 .* main \\\(.*$gdb_prompt $" {
|
||||
+ pass $test
|
||||
+ }
|
||||
+ -re "#0 *initialized \\\(\\\) at .*Cannot access memory at address .*$gdb_prompt $" {
|
||||
+ fail $test
|
||||
+ }
|
||||
+}
|
265
gdb-6.5-bz185337-resolve-tls-without-debuginfo-v2.patch
Normal file
265
gdb-6.5-bz185337-resolve-tls-without-debuginfo-v2.patch
Normal file
@ -0,0 +1,265 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-6.5-bz185337-resolve-tls-without-debuginfo-v2.patch
|
||||
|
||||
;; Support TLS symbols (+`errno' suggestion if no pthread is found) (BZ 185337).
|
||||
;;=push+jan: It should be replaced by Infinity project.
|
||||
|
||||
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=185337
|
||||
|
||||
2008-02-24 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
|
||||
Port to GDB-6.8pre.
|
||||
|
||||
currently for trivial nonthreaded helloworld with no debug info up to -ggdb2 you
|
||||
will get:
|
||||
(gdb) p errno
|
||||
[some error]
|
||||
|
||||
* with -ggdb2 and less "errno" in fact does not exist anywhere as it was
|
||||
compiled to "(*__errno_location ())" and the macro definition is not present.
|
||||
Unfortunately gdb will find the TLS symbol and it will try to access it but
|
||||
as the program has been compiled without -lpthread the TLS base register
|
||||
(%gs on i386) is not setup and it will result in:
|
||||
Cannot access memory at address 0x8
|
||||
|
||||
Attached suggestion patch how to deal with the most common "errno" symbol
|
||||
for the most common under-ggdb3 compiled programs.
|
||||
|
||||
Original patch hooked into target_translate_tls_address. But its inferior
|
||||
call invalidates `struct frame *' in the callers - RH BZ 690908.
|
||||
|
||||
https://bugzilla.redhat.com/show_bug.cgi?id=1166549
|
||||
|
||||
2007-11-03 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
|
||||
* ./gdb/dwarf2read.c (read_partial_die, dwarf2_linkage_name): Prefer
|
||||
DW_AT_MIPS_linkage_name over DW_AT_name now only for non-C.
|
||||
|
||||
glibc-debuginfo-2.7-2.x86_64: /usr/lib/debug/lib64/libc.so.6.debug:
|
||||
<81a2> DW_AT_name : (indirect string, offset: 0x280e): __errno_location
|
||||
<81a8> DW_AT_MIPS_linkage_name: (indirect string, offset: 0x2808): *__GI___errno_location
|
||||
|
||||
diff --git a/gdb/printcmd.c b/gdb/printcmd.c
|
||||
--- a/gdb/printcmd.c
|
||||
+++ b/gdb/printcmd.c
|
||||
@@ -1308,6 +1308,11 @@ process_print_command_args (const char *args, value_print_options *print_opts,
|
||||
|
||||
if (exp != nullptr && *exp)
|
||||
{
|
||||
+ /* '*((int *(*) (void)) __errno_location) ()' is incompatible with
|
||||
+ function descriptors. */
|
||||
+ if (target_has_execution () && strcmp (exp, "errno") == 0)
|
||||
+ exp = "*(*(int *(*)(void)) __errno_location) ()";
|
||||
+
|
||||
/* This setting allows large arrays to be printed by limiting the
|
||||
number of elements that are loaded into GDB's memory; we only
|
||||
need to load as many array elements as we plan to print. */
|
||||
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-errno.c b/gdb/testsuite/gdb.dwarf2/dw2-errno.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.dwarf2/dw2-errno.c
|
||||
@@ -0,0 +1,28 @@
|
||||
+/* This testcase is part of GDB, the GNU debugger.
|
||||
+
|
||||
+ Copyright 2005, 2007 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/>.
|
||||
+
|
||||
+ Please email any bugs, comments, and/or additions to this file to:
|
||||
+ bug-gdb@prep.ai.mit.edu */
|
||||
+
|
||||
+#include <errno.h>
|
||||
+
|
||||
+int main()
|
||||
+{
|
||||
+ errno = 42;
|
||||
+
|
||||
+ return 0; /* breakpoint */
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-errno.exp b/gdb/testsuite/gdb.dwarf2/dw2-errno.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.dwarf2/dw2-errno.exp
|
||||
@@ -0,0 +1,60 @@
|
||||
+# Copyright 2007 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/>.
|
||||
+
|
||||
+set testfile dw2-errno
|
||||
+set srcfile ${testfile}.c
|
||||
+set binfile [standard_output_file ${testfile}]
|
||||
+
|
||||
+proc prep {} {
|
||||
+ global srcdir subdir binfile
|
||||
+ gdb_exit
|
||||
+ gdb_start
|
||||
+ gdb_reinitialize_dir $srcdir/$subdir
|
||||
+ gdb_load ${binfile}
|
||||
+
|
||||
+ runto_main
|
||||
+
|
||||
+ gdb_breakpoint [gdb_get_line_number "breakpoint"]
|
||||
+ gdb_continue_to_breakpoint "breakpoint"
|
||||
+}
|
||||
+
|
||||
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable "additional_flags=-g2"] != "" } {
|
||||
+ untested "Couldn't compile test program"
|
||||
+ return -1
|
||||
+}
|
||||
+prep
|
||||
+gdb_test "print errno" ".* = 42" "errno with macros=N threads=N"
|
||||
+
|
||||
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable "additional_flags=-g3"] != "" } {
|
||||
+ untested "Couldn't compile test program"
|
||||
+ return -1
|
||||
+}
|
||||
+prep
|
||||
+gdb_test "print errno" ".* = 42" "errno with macros=Y threads=N"
|
||||
+
|
||||
+if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable "additional_flags=-g2"] != "" } {
|
||||
+ return -1
|
||||
+}
|
||||
+prep
|
||||
+gdb_test "print errno" ".* = 42" "errno with macros=N threads=Y"
|
||||
+
|
||||
+if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable "additional_flags=-g3"] != "" } {
|
||||
+ return -1
|
||||
+}
|
||||
+prep
|
||||
+gdb_test "print errno" ".* = 42" "errno with macros=Y threads=Y"
|
||||
+
|
||||
+# TODO: Test the error on resolving ERRNO with only libc loaded.
|
||||
+# Just how to find the current libc filename?
|
||||
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-errno2.c b/gdb/testsuite/gdb.dwarf2/dw2-errno2.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.dwarf2/dw2-errno2.c
|
||||
@@ -0,0 +1,28 @@
|
||||
+/* This testcase is part of GDB, the GNU debugger.
|
||||
+
|
||||
+ Copyright 2005, 2007 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/>.
|
||||
+
|
||||
+ Please email any bugs, comments, and/or additions to this file to:
|
||||
+ bug-gdb@prep.ai.mit.edu */
|
||||
+
|
||||
+#include <errno.h>
|
||||
+
|
||||
+int main()
|
||||
+{
|
||||
+ errno = 42;
|
||||
+
|
||||
+ return 0; /* breakpoint */
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-errno2.exp b/gdb/testsuite/gdb.dwarf2/dw2-errno2.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.dwarf2/dw2-errno2.exp
|
||||
@@ -0,0 +1,71 @@
|
||||
+# Copyright 2007 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/>.
|
||||
+
|
||||
+set testfile dw2-errno2
|
||||
+set srcfile ${testfile}.c
|
||||
+set binfile [standard_output_file ${testfile}]
|
||||
+
|
||||
+proc prep { message {do_xfail 0} } { with_test_prefix $message {
|
||||
+ global srcdir subdir binfile variant
|
||||
+ gdb_exit
|
||||
+ gdb_start
|
||||
+ gdb_reinitialize_dir $srcdir/$subdir
|
||||
+ gdb_load ${binfile}${variant}
|
||||
+
|
||||
+ runto_main
|
||||
+
|
||||
+ gdb_breakpoint [gdb_get_line_number "breakpoint"]
|
||||
+ gdb_continue_to_breakpoint "breakpoint"
|
||||
+
|
||||
+ gdb_test "gcore ${binfile}${variant}.core" "\r\nSaved corefile .*" "gcore $variant"
|
||||
+
|
||||
+ gdb_test "print errno" ".* = 42"
|
||||
+
|
||||
+ gdb_test "kill" ".*" "kill" {Kill the program being debugged\? \(y or n\) } "y"
|
||||
+ gdb_test "core-file ${binfile}${variant}.core" "\r\nCore was generated by .*" "core-file"
|
||||
+ if $do_xfail {
|
||||
+ setup_xfail "*-*-*"
|
||||
+ }
|
||||
+ gdb_test "print (int) errno" ".* = 42" "print errno for core"
|
||||
+}}
|
||||
+
|
||||
+set variant g2thrN
|
||||
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}${variant}" executable "additional_flags=-g2"] != "" } {
|
||||
+ untested "Couldn't compile test program"
|
||||
+ return -1
|
||||
+}
|
||||
+prep "macros=N threads=N" 1
|
||||
+
|
||||
+set variant g3thrN
|
||||
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}${variant}" executable "additional_flags=-g3"] != "" } {
|
||||
+ untested "Couldn't compile test program"
|
||||
+ return -1
|
||||
+}
|
||||
+prep "macros=Y threads=N" 1
|
||||
+
|
||||
+set variant g2thrY
|
||||
+if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}${variant}" executable "additional_flags=-g2"] != "" } {
|
||||
+ return -1
|
||||
+}
|
||||
+prep "macros=N threads=Y"
|
||||
+
|
||||
+set variant g3thrY
|
||||
+if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}${variant}" executable "additional_flags=-g3"] != "" } {
|
||||
+ return -1
|
||||
+}
|
||||
+prep "macros=Y threads=Y" 1
|
||||
+
|
||||
+# TODO: Test the error on resolving ERRNO with only libc loaded.
|
||||
+# Just how to find the current libc filename?
|
107
gdb-6.5-bz218379-ppc-solib-trampoline-test.patch
Normal file
107
gdb-6.5-bz218379-ppc-solib-trampoline-test.patch
Normal file
@ -0,0 +1,107 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Fedora GDB patches <invalid@email.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-6.5-bz218379-ppc-solib-trampoline-test.patch
|
||||
|
||||
;; Test sideeffects of skipping ppc .so libs trampolines (BZ 218379).
|
||||
;;=fedoratest
|
||||
|
||||
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=218379
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/step-over-trampoline.c b/gdb/testsuite/gdb.base/step-over-trampoline.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/step-over-trampoline.c
|
||||
@@ -0,0 +1,28 @@
|
||||
+/* This testcase is part of GDB, the GNU debugger.
|
||||
+
|
||||
+ Copyright 2006 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 2 of the License, or
|
||||
+ (at your option) any later version.
|
||||
+
|
||||
+ This program is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ GNU General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU General Public License
|
||||
+ along with this program; if not, write to the Free Software
|
||||
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
+
|
||||
+ Please email any bugs, comments, and/or additions to this file to:
|
||||
+ bug-gdb@prep.ai.mit.edu */
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+
|
||||
+int main (void)
|
||||
+{
|
||||
+ puts ("hello world");
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.base/step-over-trampoline.exp b/gdb/testsuite/gdb.base/step-over-trampoline.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/step-over-trampoline.exp
|
||||
@@ -0,0 +1,59 @@
|
||||
+# Copyright 2006 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 2 of the License, or
|
||||
+# (at your option) any later version.
|
||||
+#
|
||||
+# This program is distributed in the hope that it will be useful,
|
||||
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+# GNU General Public License for more details.
|
||||
+#
|
||||
+# You should have received a copy of the GNU General Public License
|
||||
+# along with this program; if not, write to the Free Software
|
||||
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
+
|
||||
+if {[use_gdb_stub]} {
|
||||
+ untested "skipping test because of use_gdb_stub"
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+if $tracelevel then {
|
||||
+ strace $tracelevel
|
||||
+}
|
||||
+
|
||||
+set testfile step-over-trampoline
|
||||
+set srcfile ${testfile}.c
|
||||
+set binfile [standard_output_file ${testfile}]
|
||||
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
|
||||
+ untested "Couldn't compile test program"
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+# Get things started.
|
||||
+
|
||||
+gdb_exit
|
||||
+gdb_start
|
||||
+gdb_reinitialize_dir $srcdir/$subdir
|
||||
+gdb_load ${binfile}
|
||||
+
|
||||
+# For C programs, "start" should stop in main().
|
||||
+
|
||||
+gdb_test "start" \
|
||||
+ "main \\(\\) at .*$srcfile.*" \
|
||||
+ "start"
|
||||
+
|
||||
+# main () at hello2.c:5
|
||||
+# 5 puts("hello world\n");
|
||||
+# (gdb) next
|
||||
+# 0x100007e0 in call___do_global_ctors_aux ()
|
||||
+
|
||||
+gdb_test_multiple "next" "invalid `next' output" {
|
||||
+ -re "\nhello world.*return 0;.*" {
|
||||
+ pass "stepped over"
|
||||
+ }
|
||||
+ -re " in call___do_global_ctors_aux \\(\\).*" {
|
||||
+ fail "stepped into trampoline"
|
||||
+ }
|
||||
+}
|
89
gdb-6.5-bz243845-stale-testing-zombie-test.patch
Normal file
89
gdb-6.5-bz243845-stale-testing-zombie-test.patch
Normal file
@ -0,0 +1,89 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Fedora GDB patches <invalid@email.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-6.5-bz243845-stale-testing-zombie-test.patch
|
||||
|
||||
;; Test leftover zombie process (BZ 243845).
|
||||
;;=fedoratest
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/tracefork-zombie.exp b/gdb/testsuite/gdb.base/tracefork-zombie.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/tracefork-zombie.exp
|
||||
@@ -0,0 +1,76 @@
|
||||
+# Copyright 2007 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 2 of the License, or
|
||||
+# (at your option) any later version.
|
||||
+#
|
||||
+# This program is distributed in the hope that it will be useful,
|
||||
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+# GNU General Public License for more details.
|
||||
+#
|
||||
+# You should have received a copy of the GNU General Public License
|
||||
+# along with this program; if not, write to the Free Software
|
||||
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
+
|
||||
+# are we on a target board
|
||||
+if {[use_gdb_stub]} {
|
||||
+ untested "skipping test because of use_gdb_stub"
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+# Start the program running and then wait for a bit, to be sure
|
||||
+# that it can be attached to.
|
||||
+
|
||||
+gdb_exit
|
||||
+gdb_start
|
||||
+gdb_load sleep
|
||||
+
|
||||
+set gdb_pid [exp_pid -i [board_info host fileid]]
|
||||
+set test "identified the child GDB"
|
||||
+if {$gdb_pid != "" && $gdb_pid > 0} {
|
||||
+ pass $test
|
||||
+ verbose -log "Child GDB PID $gdb_pid"
|
||||
+} else {
|
||||
+ fail $test
|
||||
+}
|
||||
+
|
||||
+set testpid [eval exec sleep 10 &]
|
||||
+exec sleep 2
|
||||
+
|
||||
+set test "attach"
|
||||
+gdb_test_multiple "attach $testpid" "$test" {
|
||||
+ -re "Attaching to program.*`?.*'?, process $testpid..*$gdb_prompt $" {
|
||||
+ pass "$test"
|
||||
+ }
|
||||
+ -re "Attaching to program.*`?.*\.exe'?, process $testpid.*\[Switching to thread $testpid\..*\].*$gdb_prompt $" {
|
||||
+ # Response expected on Cygwin
|
||||
+ pass "$test"
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+# Some time to let GDB spawn its testing child.
|
||||
+exec sleep 2
|
||||
+
|
||||
+set found none
|
||||
+foreach procpid [glob -directory /proc -type d {[0-9]*}] {
|
||||
+ if {[catch {open $procpid/status} statusfi]} {
|
||||
+ continue
|
||||
+ }
|
||||
+ set status [read $statusfi]
|
||||
+ close $statusfi
|
||||
+ if {1
|
||||
+ && [regexp -line {^Name:\tgdb$} $status]
|
||||
+ && [regexp -line {^PPid:\t1$} $status]
|
||||
+ && [regexp -line "^TracerPid:\t$gdb_pid$" $status]} {
|
||||
+ set found $procpid
|
||||
+ verbose -log "Found linux_test_for_tracefork zombie PID $procpid"
|
||||
+ }
|
||||
+}
|
||||
+set test "linux_test_for_tracefork leaves no zombie"
|
||||
+if {$found eq {none}} {
|
||||
+ pass $test
|
||||
+} else {
|
||||
+ fail $test
|
||||
+}
|
154
gdb-6.5-gcore-buffer-limit-test.patch
Normal file
154
gdb-6.5-gcore-buffer-limit-test.patch
Normal file
@ -0,0 +1,154 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Fedora GDB patches <invalid@email.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-6.5-gcore-buffer-limit-test.patch
|
||||
|
||||
;; Test gcore memory and time requirements for large inferiors.
|
||||
;;=fedoratest
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/gcore-excessive-memory.c b/gdb/testsuite/gdb.base/gcore-excessive-memory.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/gcore-excessive-memory.c
|
||||
@@ -0,0 +1,37 @@
|
||||
+/* This testcase is part of GDB, the GNU debugger.
|
||||
+
|
||||
+ Copyright 2008 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 2 of the License, or
|
||||
+ (at your option) any later version.
|
||||
+
|
||||
+ This program is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ GNU General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU General Public License
|
||||
+ along with this program; if not, write to the Free Software
|
||||
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
+
|
||||
+ Please email any bugs, comments, and/or additions to this file to:
|
||||
+ bug-gdb@prep.ai.mit.edu */
|
||||
+
|
||||
+#include <unistd.h>
|
||||
+#include <stdlib.h>
|
||||
+
|
||||
+#define MEGS 64
|
||||
+
|
||||
+int main()
|
||||
+{
|
||||
+ void *mem;
|
||||
+
|
||||
+ mem = malloc (MEGS * 1024ULL * 1024ULL);
|
||||
+
|
||||
+ for (;;)
|
||||
+ sleep (1);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.base/gcore-excessive-memory.exp b/gdb/testsuite/gdb.base/gcore-excessive-memory.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/gcore-excessive-memory.exp
|
||||
@@ -0,0 +1,99 @@
|
||||
+# Copyright 2008 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 2 of the License, or
|
||||
+# (at your option) any later version.
|
||||
+#
|
||||
+# This program is distributed in the hope that it will be useful,
|
||||
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+# GNU General Public License for more details.
|
||||
+#
|
||||
+# You should have received a copy of the GNU General Public License
|
||||
+# along with this program; if not, write to the Free Software
|
||||
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
+
|
||||
+if {[use_gdb_stub]} {
|
||||
+ untested "skipping test because of use_gdb_stub"
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+set testfile gcore-excessive-memory
|
||||
+set srcfile ${testfile}.c
|
||||
+set shfile [standard_output_file ${testfile}-gdb.sh]
|
||||
+set corefile [standard_output_file ${testfile}.core]
|
||||
+set binfile [standard_output_file ${testfile}]
|
||||
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
|
||||
+ untested "Couldn't compile test program"
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+set f [open "|getconf PAGESIZE" "r"]
|
||||
+gets $f pagesize
|
||||
+close $f
|
||||
+
|
||||
+set pid_of_bin [eval exec $binfile &]
|
||||
+sleep 2
|
||||
+
|
||||
+# Get things started.
|
||||
+
|
||||
+gdb_exit
|
||||
+gdb_start
|
||||
+gdb_reinitialize_dir $srcdir/$subdir
|
||||
+gdb_load ${binfile}
|
||||
+
|
||||
+set pid_of_gdb [exp_pid -i [board_info host fileid]]
|
||||
+
|
||||
+gdb_test "attach $pid_of_bin" "Attaching to .*" "attach"
|
||||
+gdb_test "up 99" "in main .*" "verify we can get to main"
|
||||
+
|
||||
+proc memory_v_pages_get {} {
|
||||
+ global pid_of_gdb pagesize
|
||||
+ set fd [open "/proc/$pid_of_gdb/statm"]
|
||||
+ gets $fd line
|
||||
+ close $fd
|
||||
+ # number of pages of virtual memory
|
||||
+ scan $line "%d" drs
|
||||
+ return $drs
|
||||
+}
|
||||
+
|
||||
+set pages_found [memory_v_pages_get]
|
||||
+
|
||||
+# It must be definitely less than `MEGS' of `gcore-excessive-memory.c'.
|
||||
+set mb_gcore_reserve 4
|
||||
+verbose -log "pages_found = $pages_found, mb_gcore_reserve = $mb_gcore_reserve"
|
||||
+set kb_found [expr $pages_found * $pagesize / 1024]
|
||||
+set kb_permit [expr $kb_found + 1 * 1024 + $mb_gcore_reserve * 1024]
|
||||
+verbose -log "kb_found = $kb_found, kb_permit = $kb_permit"
|
||||
+
|
||||
+# Create the ulimit wrapper.
|
||||
+set f [open $shfile "w"]
|
||||
+puts $f "#! /bin/sh"
|
||||
+puts $f "ulimit -v $kb_permit"
|
||||
+puts $f "exec $GDB \"\$@\""
|
||||
+close $f
|
||||
+remote_exec host "chmod +x $shfile"
|
||||
+
|
||||
+gdb_exit
|
||||
+set GDBold $GDB
|
||||
+set GDB "$shfile"
|
||||
+gdb_start
|
||||
+set GDB $GDBold
|
||||
+
|
||||
+gdb_reinitialize_dir $srcdir/$subdir
|
||||
+gdb_load ${binfile}
|
||||
+
|
||||
+set pid_of_gdb [exp_pid -i [board_info host fileid]]
|
||||
+
|
||||
+gdb_test "attach $pid_of_bin" "Attaching to .*" "attach"
|
||||
+gdb_test "up 99" "in main .*" "verify we can get to main"
|
||||
+
|
||||
+verbose -log "kb_found before gcore = [expr [memory_v_pages_get] * $pagesize / 1024]"
|
||||
+
|
||||
+gdb_test "gcore $corefile" "Saved corefile \[^\n\r\]*" "Save the core file"
|
||||
+
|
||||
+verbose -log "kb_found after gcore = [expr [memory_v_pages_get] * $pagesize / 1024]"
|
||||
+
|
||||
+# Cleanup.
|
||||
+exec kill -9 $pid_of_bin
|
127
gdb-6.5-section-num-fixup-test.patch
Normal file
127
gdb-6.5-section-num-fixup-test.patch
Normal file
@ -0,0 +1,127 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Fedora GDB patches <invalid@email.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-6.5-section-num-fixup-test.patch
|
||||
|
||||
;; Test a crash on libraries missing the .text section.
|
||||
;;=fedoratest
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/datalib-lib.c b/gdb/testsuite/gdb.base/datalib-lib.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/datalib-lib.c
|
||||
@@ -0,0 +1,22 @@
|
||||
+/* This testcase is part of GDB, the GNU debugger.
|
||||
+
|
||||
+ Copyright 2008 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 2 of the License, or
|
||||
+ (at your option) any later version.
|
||||
+
|
||||
+ This program is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ GNU General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU General Public License
|
||||
+ along with this program; if not, write to the Free Software
|
||||
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
+
|
||||
+ Please email any bugs, comments, and/or additions to this file to:
|
||||
+ bug-gdb@prep.ai.mit.edu */
|
||||
+
|
||||
+int var;
|
||||
diff --git a/gdb/testsuite/gdb.base/datalib-main.c b/gdb/testsuite/gdb.base/datalib-main.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/datalib-main.c
|
||||
@@ -0,0 +1,26 @@
|
||||
+/* This testcase is part of GDB, the GNU debugger.
|
||||
+
|
||||
+ Copyright 2008 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 2 of the License, or
|
||||
+ (at your option) any later version.
|
||||
+
|
||||
+ This program is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ GNU General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU General Public License
|
||||
+ along with this program; if not, write to the Free Software
|
||||
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
+
|
||||
+ Please email any bugs, comments, and/or additions to this file to:
|
||||
+ bug-gdb@prep.ai.mit.edu */
|
||||
+
|
||||
+int
|
||||
+main (void)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.base/datalib.exp b/gdb/testsuite/gdb.base/datalib.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/datalib.exp
|
||||
@@ -0,0 +1,56 @@
|
||||
+# Copyright 2008 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 2 of the License, or
|
||||
+# (at your option) any later version.
|
||||
+#
|
||||
+# This program is distributed in the hope that it will be useful,
|
||||
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+# GNU General Public License for more details.
|
||||
+#
|
||||
+# You should have received a copy of the GNU General Public License
|
||||
+# along with this program; if not, write to the Free Software
|
||||
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
+
|
||||
+if {[use_gdb_stub]} {
|
||||
+ untested "skipping test because of use_gdb_stub"
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+set testfile datalib
|
||||
+set srcfilemain ${testfile}-main.c
|
||||
+set srcfilelib ${testfile}-lib.c
|
||||
+set libfile [standard_output_file ${testfile}-lib.so]
|
||||
+set binfile [standard_output_file ${testfile}-main]
|
||||
+if { [gdb_compile "${srcdir}/${subdir}/${srcfilelib}" "${libfile}" executable [list debug {additional_flags=-shared -nostdlib}]] != "" } {
|
||||
+ untested "Couldn't compile test program"
|
||||
+ return -1
|
||||
+}
|
||||
+if { [gdb_compile "${srcdir}/${subdir}/${srcfilemain}" "${binfile} ${libfile}" executable {debug}] != "" } {
|
||||
+ untested "Couldn't compile test program"
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+# Get things started.
|
||||
+
|
||||
+gdb_exit
|
||||
+gdb_start
|
||||
+gdb_reinitialize_dir $srcdir/$subdir
|
||||
+gdb_load ${binfile}
|
||||
+
|
||||
+# We must use a separate library as the main executable is compiled to the
|
||||
+# address 0 by default and it would get fixed up already at the end of
|
||||
+# INIT_OBJFILE_SECT_INDICES. We also cannot PRELINK it as PRELINK is missing
|
||||
+# on ia64. The library must be NOSTDLIB as otherwise some stub code would
|
||||
+# create the `.text' section there. Also DEBUG option is useful as some of
|
||||
+# the crashes occur in dwarf2read.c.
|
||||
+
|
||||
+# FAIL case:
|
||||
+# ../../gdb/ia64-tdep.c:2838: internal-error: sect_index_text not initialized
|
||||
+# A problem internal to GDB has been detected,
|
||||
+
|
||||
+gdb_test "start" \
|
||||
+ "main \\(\\) at .*${srcfilemain}.*" \
|
||||
+ "start"
|
19
gdb-6.6-buildid-locate-rpm-librpm-workaround.patch
Normal file
19
gdb-6.6-buildid-locate-rpm-librpm-workaround.patch
Normal file
@ -0,0 +1,19 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Fedora GDB patches <invalid@email.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-6.6-buildid-locate-rpm-librpm-workaround.patch
|
||||
|
||||
;; Workaround librpm BZ 643031 due to its unexpected exit() calls (BZ 642879).
|
||||
;;=push+jan
|
||||
|
||||
diff --git a/gdb/proc-service.list b/gdb/proc-service.list
|
||||
--- a/gdb/proc-service.list
|
||||
+++ b/gdb/proc-service.list
|
||||
@@ -37,4 +37,7 @@
|
||||
ps_pstop;
|
||||
ps_ptread;
|
||||
ps_ptwrite;
|
||||
+
|
||||
+ /* gdb-6.6-buildid-locate-rpm.patch */
|
||||
+ rpmsqEnable;
|
||||
};
|
123
gdb-6.6-buildid-locate-rpm-suse.patch
Normal file
123
gdb-6.6-buildid-locate-rpm-suse.patch
Normal file
@ -0,0 +1,123 @@
|
||||
diff --git a/gdb/build-id.c b/gdb/build-id.c
|
||||
index 059a72fc050..58d73e70bad 100644
|
||||
--- a/gdb/build-id.c
|
||||
+++ b/gdb/build-id.c
|
||||
@@ -863,10 +863,8 @@ missing_rpm_enlist_1 (const char *filename, int verify_vendor)
|
||||
#endif
|
||||
{
|
||||
Header h;
|
||||
- char *debuginfo, **slot, *s, *s2;
|
||||
+ char *debuginfo, **slot;
|
||||
errmsg_t err;
|
||||
- size_t srcrpmlen = sizeof (".src.rpm") - 1;
|
||||
- size_t debuginfolen = sizeof ("-debuginfo") - 1;
|
||||
rpmdbMatchIterator mi_debuginfo;
|
||||
|
||||
h = rpmdbNextIterator_p (mi);
|
||||
@@ -875,7 +873,9 @@ missing_rpm_enlist_1 (const char *filename, int verify_vendor)
|
||||
|
||||
/* Verify the debuginfo file is not already installed. */
|
||||
|
||||
- debuginfo = headerFormat_p (h, "%{sourcerpm}-debuginfo.%{arch}",
|
||||
+ /* The allocated memory gets utilized below for MISSING_RPM_HASH. */
|
||||
+ debuginfo = headerFormat_p (h,
|
||||
+ "%{name}-debuginfo-%{version}-%{release}.%{arch}",
|
||||
&err);
|
||||
if (!debuginfo)
|
||||
{
|
||||
@@ -883,60 +883,19 @@ missing_rpm_enlist_1 (const char *filename, int verify_vendor)
|
||||
err);
|
||||
continue;
|
||||
}
|
||||
- /* s = `.src.rpm-debuginfo.%{arch}' */
|
||||
- s = strrchr (debuginfo, '-') - srcrpmlen;
|
||||
- s2 = NULL;
|
||||
- if (s > debuginfo && memcmp (s, ".src.rpm", srcrpmlen) == 0)
|
||||
- {
|
||||
- /* s2 = `-%{release}.src.rpm-debuginfo.%{arch}' */
|
||||
- s2 = (char *) memrchr (debuginfo, '-', s - debuginfo);
|
||||
- }
|
||||
- if (s2)
|
||||
- {
|
||||
- /* s2 = `-%{version}-%{release}.src.rpm-debuginfo.%{arch}' */
|
||||
- s2 = (char *) memrchr (debuginfo, '-', s2 - debuginfo);
|
||||
- }
|
||||
- if (!s2)
|
||||
- {
|
||||
- warning (_("Error querying the rpm file `%s': %s"), filename,
|
||||
- debuginfo);
|
||||
- xfree (debuginfo);
|
||||
- continue;
|
||||
- }
|
||||
- /* s = `.src.rpm-debuginfo.%{arch}' */
|
||||
- /* s2 = `-%{version}-%{release}.src.rpm-debuginfo.%{arch}' */
|
||||
- memmove (s2 + debuginfolen, s2, s - s2);
|
||||
- memcpy (s2, "-debuginfo", debuginfolen);
|
||||
- /* s = `XXXX.%{arch}' */
|
||||
- /* strlen ("XXXX") == srcrpmlen + debuginfolen */
|
||||
- /* s2 = `-debuginfo-%{version}-%{release}XX.%{arch}' */
|
||||
- /* strlen ("XX") == srcrpmlen */
|
||||
- memmove (s + debuginfolen, s + srcrpmlen + debuginfolen,
|
||||
- strlen (s + srcrpmlen + debuginfolen) + 1);
|
||||
- /* s = `-debuginfo-%{version}-%{release}.%{arch}' */
|
||||
|
||||
+ /* Verify the debuginfo file is not already installed. */
|
||||
/* RPMDBI_PACKAGES requires keylen == sizeof (int). */
|
||||
/* RPMDBI_LABEL is an interface for NVR-based dbiFindByLabel(). */
|
||||
mi_debuginfo = rpmtsInitIterator_p (ts, (rpmDbiTagVal) RPMDBI_LABEL, debuginfo, 0);
|
||||
- xfree (debuginfo);
|
||||
if (mi_debuginfo)
|
||||
{
|
||||
+ xfree (debuginfo);
|
||||
rpmdbFreeIterator_p (mi_debuginfo);
|
||||
count = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
- /* The allocated memory gets utilized below for MISSING_RPM_HASH. */
|
||||
- debuginfo = headerFormat_p (h,
|
||||
- "%{name}-%{version}-%{release}.%{arch}",
|
||||
- &err);
|
||||
- if (!debuginfo)
|
||||
- {
|
||||
- warning (_("Error querying the rpm file `%s': %s"), filename,
|
||||
- err);
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
/* Base package name for `debuginfo-install'. We do not use the
|
||||
`yum' command directly as the line
|
||||
yum --enablerepo='*debug*' install NAME-debuginfo.ARCH
|
||||
@@ -1085,10 +1044,7 @@ missing_rpm_list_print (void)
|
||||
missing_rpm_list_entries = 0;
|
||||
|
||||
gdb_printf (_("Missing separate debuginfos, use: %s"),
|
||||
-#ifdef DNF_DEBUGINFO_INSTALL
|
||||
- "dnf "
|
||||
-#endif
|
||||
- "debuginfo-install");
|
||||
+ "zypper install");
|
||||
for (const char *el : array)
|
||||
{
|
||||
gdb_printf (" %s", el);
|
||||
@@ -1296,14 +1252,15 @@ debug_print_missing (const char *binary, const char *debug)
|
||||
_("Missing separate debuginfo for %s.\n"), binary);
|
||||
if (debug != NULL)
|
||||
{
|
||||
+#ifdef HAVE_LIBRPM
|
||||
if (access (debug, F_OK) == 0) {
|
||||
- gdb_printf (gdb_stdlog, _("Try: %s %s\n"),
|
||||
-#ifdef DNF_DEBUGINFO_INSTALL
|
||||
- "dnf"
|
||||
#else
|
||||
- "yum"
|
||||
+ if (1) {
|
||||
#endif
|
||||
- " --enablerepo='*debug*' install", debug);
|
||||
+ const char *p = strrchr (debug, '/');
|
||||
+ gdb_printf (gdb_stdlog, _("Try: %s%.2s%.38s\"\n"),
|
||||
+ "zypper install -C \"debuginfo(build-id)=",
|
||||
+ p - 2, p + 1);
|
||||
} else
|
||||
gdb_printf (gdb_stdlog, _("The debuginfo package for this file is probably broken.\n"));
|
||||
}
|
1084
gdb-6.6-buildid-locate-rpm.patch
Normal file
1084
gdb-6.6-buildid-locate-rpm.patch
Normal file
File diff suppressed because it is too large
Load Diff
238
gdb-6.6-buildid-locate-solib-missing-ids.patch
Normal file
238
gdb-6.6-buildid-locate-solib-missing-ids.patch
Normal file
@ -0,0 +1,238 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Fedora GDB patches <invalid@email.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-6.6-buildid-locate-solib-missing-ids.patch
|
||||
|
||||
;; Fix loading of core files without build-ids but with build-ids in executables.
|
||||
;; Load strictly build-id-checked core files only if no executable is specified
|
||||
;; (Jan Kratochvil, RH BZ 1339862).
|
||||
;;=push+jan
|
||||
|
||||
gdb returns an incorrect back trace when applying a debuginfo
|
||||
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,
|
||||
}
|
||||
|
||||
{
|
||||
- struct bfd_build_id *build_id;
|
||||
+ struct bfd_build_id *build_id = NULL;
|
||||
|
||||
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.
|
||||
+
|
||||
+ 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 (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);
|
||||
|
||||
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
|
||||
+++ b/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib-lib.c
|
||||
@@ -0,0 +1,21 @@
|
||||
+/* Copyright 2010 Free Software Foundation, Inc.
|
||||
+
|
||||
+ This file is part of GDB.
|
||||
+
|
||||
+ This program is free software; you can redistribute it and/or modify
|
||||
+ it under the terms of the GNU General Public License as published by
|
||||
+ the Free Software Foundation; either version 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/>. */
|
||||
+
|
||||
+void
|
||||
+lib (void)
|
||||
+{
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib-main.c b/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib-main.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib-main.c
|
||||
@@ -0,0 +1,25 @@
|
||||
+/* Copyright 2010 Free Software Foundation, Inc.
|
||||
+
|
||||
+ This file is part of GDB.
|
||||
+
|
||||
+ This program is free software; you can redistribute it and/or modify
|
||||
+ it under the terms of the GNU General Public License as published by
|
||||
+ the Free Software Foundation; either version 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 void lib (void);
|
||||
+
|
||||
+int
|
||||
+main (void)
|
||||
+{
|
||||
+ lib ();
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib.exp b/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib.exp
|
||||
@@ -0,0 +1,105 @@
|
||||
+# Copyright 2016 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/>.
|
||||
+
|
||||
+if {[skip_shlib_tests]} {
|
||||
+ return 0
|
||||
+}
|
||||
+
|
||||
+set testfile "gcore-buildid-exec-but-not-solib"
|
||||
+set srcmainfile ${testfile}-main.c
|
||||
+set srclibfile ${testfile}-lib.c
|
||||
+set libfile [standard_output_file ${testfile}-lib.so]
|
||||
+set objfile [standard_output_file ${testfile}-main.o]
|
||||
+set executable ${testfile}-main
|
||||
+set binfile [standard_output_file ${executable}]
|
||||
+set gcorefile [standard_output_file ${executable}.gcore]
|
||||
+set outdir [file dirname $binfile]
|
||||
+
|
||||
+if { [gdb_compile_shlib ${srcdir}/${subdir}/${srclibfile} ${libfile} "debug additional_flags=-Wl,--build-id"] != ""
|
||||
+ || [gdb_compile ${srcdir}/${subdir}/${srcmainfile} ${objfile} object {debug}] != "" } {
|
||||
+ unsupported "-Wl,--build-id compilation failed"
|
||||
+ return -1
|
||||
+}
|
||||
+set opts [list debug shlib=${libfile} "additional_flags=-Wl,--build-id"]
|
||||
+if { [gdb_compile ${objfile} ${binfile} executable $opts] != "" } {
|
||||
+ unsupported "-Wl,--build-id compilation failed"
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+clean_restart $executable
|
||||
+gdb_load_shlib $libfile
|
||||
+
|
||||
+# Does this gdb support gcore?
|
||||
+set test "help gcore"
|
||||
+gdb_test_multiple $test $test {
|
||||
+ -re "Undefined command: .gcore.*\r\n$gdb_prompt $" {
|
||||
+ # gcore command not supported -- nothing to test here.
|
||||
+ unsupported "gdb does not support gcore on this target"
|
||||
+ return -1;
|
||||
+ }
|
||||
+ -re "Save a core file .*\r\n$gdb_prompt $" {
|
||||
+ pass $test
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+if { ![runto lib] } then {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+set escapedfilename [string_to_regexp ${gcorefile}]
|
||||
+
|
||||
+set test "save a corefile"
|
||||
+gdb_test_multiple "gcore ${gcorefile}" $test {
|
||||
+ -re "Saved corefile ${escapedfilename}\r\n$gdb_prompt $" {
|
||||
+ pass $test
|
||||
+ }
|
||||
+ -re "Can't create a corefile\r\n$gdb_prompt $" {
|
||||
+ unsupported $test
|
||||
+ return -1
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+# Now restart gdb and load the corefile.
|
||||
+
|
||||
+clean_restart $executable
|
||||
+gdb_load_shlib $libfile
|
||||
+
|
||||
+set buildid [build_id_debug_filename_get $libfile]
|
||||
+
|
||||
+regsub {\.debug$} $buildid {} buildid
|
||||
+
|
||||
+set debugdir [standard_output_file ${testfile}-debugdir]
|
||||
+file delete -force -- $debugdir
|
||||
+
|
||||
+file mkdir $debugdir/[file dirname $libfile]
|
||||
+file copy $libfile $debugdir/${libfile}
|
||||
+
|
||||
+file mkdir $debugdir/[file dirname $buildid]
|
||||
+file copy $libfile $debugdir/${buildid}
|
||||
+
|
||||
+remote_exec build "ln -s /lib ${debugdir}/"
|
||||
+remote_exec build "ln -s /lib64 ${debugdir}/"
|
||||
+# /usr is not needed, all the libs are in /lib64: libm.so.6 libc.so.6 ld-linux-x86-64.so.2
|
||||
+
|
||||
+gdb_test "set solib-absolute-prefix $debugdir"
|
||||
+
|
||||
+gdb_test_no_output "set debug-file-directory $debugdir" "set debug-file-directory"
|
||||
+
|
||||
+gdb_test "core ${gcorefile}" "Core was generated by .*" "re-load generated corefile"
|
||||
+
|
||||
+gdb_test "frame" "#0 \[^\r\n\]* lib .*" "library got loaded"
|
||||
+
|
||||
+gdb_test "bt"
|
||||
+gdb_test "info shared"
|
1925
gdb-6.6-buildid-locate.patch
Normal file
1925
gdb-6.6-buildid-locate.patch
Normal file
File diff suppressed because it is too large
Load Diff
188
gdb-6.6-bz229517-gcore-without-terminal.patch
Normal file
188
gdb-6.6-bz229517-gcore-without-terminal.patch
Normal file
@ -0,0 +1,188 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-6.6-bz229517-gcore-without-terminal.patch
|
||||
|
||||
;; Allow running `/usr/bin/gcore' with provided but inaccessible tty (BZ 229517).
|
||||
;;=fedoratest
|
||||
|
||||
2007-04-22 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
|
||||
* gdb_gcore.sh: Redirect GDB from `</dev/null'.
|
||||
|
||||
2007-04-22 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
|
||||
* gdb.base/gcorebg.exp, gdb.base/gcorebg.c: New files.
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/gcorebg.c b/gdb/testsuite/gdb.base/gcorebg.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/gcorebg.c
|
||||
@@ -0,0 +1,49 @@
|
||||
+#include <stdio.h>
|
||||
+#include <sys/types.h>
|
||||
+#include <unistd.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <signal.h>
|
||||
+#include <string.h>
|
||||
+#include <assert.h>
|
||||
+
|
||||
+int main (int argc, char **argv)
|
||||
+{
|
||||
+ pid_t pid = 0;
|
||||
+ pid_t ppid;
|
||||
+ char buf[1024*2 + 500];
|
||||
+ int gotint;
|
||||
+
|
||||
+ if (argc != 4)
|
||||
+ {
|
||||
+ fprintf (stderr, "Syntax: %s {standard|detached} <gcore command> <core output file>\n",
|
||||
+ argv[0]);
|
||||
+ exit (1);
|
||||
+ }
|
||||
+
|
||||
+ pid = fork ();
|
||||
+
|
||||
+ switch (pid)
|
||||
+ {
|
||||
+ case 0:
|
||||
+ if (strcmp (argv[1], "detached") == 0)
|
||||
+ setpgrp ();
|
||||
+ ppid = getppid ();
|
||||
+ gotint = snprintf (buf, sizeof (buf), "sh %s -o %s %d", argv[2], argv[3], (int) ppid);
|
||||
+ assert (gotint < sizeof (buf));
|
||||
+ system (buf);
|
||||
+ fprintf (stderr, "Killing parent PID %d\n", ppid);
|
||||
+ kill (ppid, SIGTERM);
|
||||
+ break;
|
||||
+
|
||||
+ case -1:
|
||||
+ perror ("fork err\n");
|
||||
+ exit (1);
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ fprintf (stderr,"Sleeping as PID %d\n", getpid ());
|
||||
+ sleep (60);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.base/gcorebg.exp b/gdb/testsuite/gdb.base/gcorebg.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/gcorebg.exp
|
||||
@@ -0,0 +1,113 @@
|
||||
+# Copyright 2007 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 2 of the License, or
|
||||
+# (at your option) any later version.
|
||||
+#
|
||||
+# This program is distributed in the hope that it will be useful,
|
||||
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+# GNU General Public License for more details.
|
||||
+#
|
||||
+# You should have received a copy of the GNU General Public License
|
||||
+# along with this program; if not, write to the Free Software
|
||||
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
+
|
||||
+# Please email any bugs, comments, and/or additions to this file to:
|
||||
+# bug-gdb@prep.ai.mit.edu
|
||||
+
|
||||
+# This file was written by Jan Kratochvil <jan.kratochvil@redhat.com>.
|
||||
+# This is a test for `gdb_gcore.sh' functionality.
|
||||
+# It also tests a regression with `gdb_gcore.sh' being run without its
|
||||
+# accessible terminal.
|
||||
+
|
||||
+if ![info exists GCORE] {
|
||||
+ set GCORE "[standard_output_file ../../../../gcore]"
|
||||
+}
|
||||
+verbose "using GCORE = $GCORE" 2
|
||||
+
|
||||
+set testfile "gcorebg"
|
||||
+set srcfile ${testfile}.c
|
||||
+set binfile [standard_output_file ${testfile}]
|
||||
+set corefile [standard_output_file ${testfile}.test]
|
||||
+
|
||||
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
|
||||
+ untested gcorebg.exp
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+# Cleanup.
|
||||
+
|
||||
+proc core_clean {} {
|
||||
+ global corefile
|
||||
+
|
||||
+ foreach file [glob -nocomplain [join [list $corefile *] ""]] {
|
||||
+ verbose "Delete file $file" 1
|
||||
+ remote_file target delete $file
|
||||
+ }
|
||||
+}
|
||||
+core_clean
|
||||
+remote_file target delete "./gdb"
|
||||
+
|
||||
+# Generate the core file.
|
||||
+
|
||||
+# Provide `./gdb' for `gdb_gcore.sh' running it as a bare `gdb' command.
|
||||
+# Setup also `$PATH' appropriately.
|
||||
+# If GDB was not found let `gdb_gcore.sh' to find the system GDB by `$PATH'.
|
||||
+if {$GDB != "gdb"} {
|
||||
+ file link ./gdb $GDB
|
||||
+}
|
||||
+global env
|
||||
+set oldpath $env(PATH)
|
||||
+set env(PATH) [join [list . $env(PATH)] ":"]
|
||||
+verbose "PATH = $env(PATH)" 2
|
||||
+
|
||||
+# Test file body.
|
||||
+# $detached == "standard" || $detached == "detached"
|
||||
+
|
||||
+proc test_body { detached } {
|
||||
+ global binfile
|
||||
+ global GCORE
|
||||
+ global corefile
|
||||
+
|
||||
+ set res [remote_spawn target "$binfile $detached $GCORE $corefile"]
|
||||
+ if { $res < 0 || $res == "" } {
|
||||
+ fail "Spawning $detached gcore"
|
||||
+ return 1
|
||||
+ }
|
||||
+ pass "Spawning $detached gcore"
|
||||
+ remote_expect target 20 {
|
||||
+ timeout {
|
||||
+ fail "Spawned $detached gcore finished (timeout)"
|
||||
+ remote_exec target "kill -9 -[exp_pid -i $res]"
|
||||
+ return 1
|
||||
+ }
|
||||
+ "Saved corefile .*\r\nKilling parent PID " {
|
||||
+ pass "Spawned $detached gcore finished"
|
||||
+ remote_wait target 20
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if {1 == [llength [glob -nocomplain [join [list $corefile *] ""]]]} {
|
||||
+ pass "Core file generated by $detached gcore"
|
||||
+ } else {
|
||||
+ fail "Core file generated by $detached gcore"
|
||||
+ }
|
||||
+ core_clean
|
||||
+}
|
||||
+
|
||||
+# First a general `gdb_gcore.sh' spawn with its controlling terminal available.
|
||||
+
|
||||
+test_body standard
|
||||
+
|
||||
+# And now `gdb_gcore.sh' spawn without its controlling terminal available.
|
||||
+# It is spawned through `gcorebg.c' using setpgrp ().
|
||||
+
|
||||
+test_body detached
|
||||
+
|
||||
+
|
||||
+# Cleanup.
|
||||
+
|
||||
+set env(PATH) $oldpath
|
||||
+remote_file target delete "./gdb"
|
278
gdb-6.6-bz237572-ppc-atomic-sequence-test.patch
Normal file
278
gdb-6.6-bz237572-ppc-atomic-sequence-test.patch
Normal file
@ -0,0 +1,278 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-6.6-bz237572-ppc-atomic-sequence-test.patch
|
||||
|
||||
;; Support for stepping over PPC atomic instruction sequences (BZ 237572).
|
||||
;;=fedoratest
|
||||
|
||||
2007-06-25 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
|
||||
* gdb.threads/atomic-seq-threaded.c,
|
||||
gdb.threads/atomic-seq-threaded.exp: New files.
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.threads/atomic-seq-threaded.c b/gdb/testsuite/gdb.threads/atomic-seq-threaded.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.threads/atomic-seq-threaded.c
|
||||
@@ -0,0 +1,171 @@
|
||||
+/* This testcase is part of GDB, the GNU debugger.
|
||||
+
|
||||
+ Copyright 2007 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 2 of the License, or
|
||||
+ (at your option) any later version.
|
||||
+
|
||||
+ This program is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ GNU General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU General Public License
|
||||
+ along with this program; if not, write to the Free Software
|
||||
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
+ MA 02110-1301, USA. */
|
||||
+
|
||||
+/* Test stepping over RISC atomic sequences.
|
||||
+ This variant testcases the code for stepping another thread while skipping
|
||||
+ over the atomic sequence in the former thread
|
||||
+ (STEPPING_PAST_SINGLESTEP_BREAKPOINT).
|
||||
+ Code comes from gcc/testsuite/gcc.dg/sync-2.c */
|
||||
+
|
||||
+/* { dg-options "-march=i486" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */
|
||||
+/* { dg-options "-mcpu=v9" { target sparc*-*-* } } */
|
||||
+
|
||||
+/* Test functionality of the intrinsics for 'short' and 'char'. */
|
||||
+
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <pthread.h>
|
||||
+#include <assert.h>
|
||||
+#include <unistd.h>
|
||||
+
|
||||
+#define LOOPS 2
|
||||
+
|
||||
+static int unused;
|
||||
+
|
||||
+static char AI[18];
|
||||
+static char init_qi[18] = { 3,5,7,9,0,0,0,0,-1,0,0,0,0,0,-1,0,0,0 };
|
||||
+static char test_qi[18] = { 3,5,7,9,1,4,22,-12,7,8,9,7,1,-12,7,8,9,7 };
|
||||
+
|
||||
+static void
|
||||
+do_qi (void)
|
||||
+{
|
||||
+ if (__sync_fetch_and_add(AI+4, 1) != 0)
|
||||
+ abort ();
|
||||
+ if (__sync_fetch_and_add(AI+5, 4) != 0)
|
||||
+ abort ();
|
||||
+ if (__sync_fetch_and_add(AI+6, 22) != 0)
|
||||
+ abort ();
|
||||
+ if (__sync_fetch_and_sub(AI+7, 12) != 0)
|
||||
+ abort ();
|
||||
+ if (__sync_fetch_and_and(AI+8, 7) != (char)-1)
|
||||
+ abort ();
|
||||
+ if (__sync_fetch_and_or(AI+9, 8) != 0)
|
||||
+ abort ();
|
||||
+ if (__sync_fetch_and_xor(AI+10, 9) != 0)
|
||||
+ abort ();
|
||||
+ if (__sync_fetch_and_nand(AI+11, 7) != 0)
|
||||
+ abort ();
|
||||
+
|
||||
+ if (__sync_add_and_fetch(AI+12, 1) != 1)
|
||||
+ abort ();
|
||||
+ if (__sync_sub_and_fetch(AI+13, 12) != (char)-12)
|
||||
+ abort ();
|
||||
+ if (__sync_and_and_fetch(AI+14, 7) != 7)
|
||||
+ abort ();
|
||||
+ if (__sync_or_and_fetch(AI+15, 8) != 8)
|
||||
+ abort ();
|
||||
+ if (__sync_xor_and_fetch(AI+16, 9) != 9)
|
||||
+ abort ();
|
||||
+ if (__sync_nand_and_fetch(AI+17, 7) != 7)
|
||||
+ abort ();
|
||||
+}
|
||||
+
|
||||
+static short AL[18];
|
||||
+static short init_hi[18] = { 3,5,7,9,0,0,0,0,-1,0,0,0,0,0,-1,0,0,0 };
|
||||
+static short test_hi[18] = { 3,5,7,9,1,4,22,-12,7,8,9,7,1,-12,7,8,9,7 };
|
||||
+
|
||||
+static void
|
||||
+do_hi (void)
|
||||
+{
|
||||
+ if (__sync_fetch_and_add(AL+4, 1) != 0)
|
||||
+ abort ();
|
||||
+ if (__sync_fetch_and_add(AL+5, 4) != 0)
|
||||
+ abort ();
|
||||
+ if (__sync_fetch_and_add(AL+6, 22) != 0)
|
||||
+ abort ();
|
||||
+ if (__sync_fetch_and_sub(AL+7, 12) != 0)
|
||||
+ abort ();
|
||||
+ if (__sync_fetch_and_and(AL+8, 7) != -1)
|
||||
+ abort ();
|
||||
+ if (__sync_fetch_and_or(AL+9, 8) != 0)
|
||||
+ abort ();
|
||||
+ if (__sync_fetch_and_xor(AL+10, 9) != 0)
|
||||
+ abort ();
|
||||
+ if (__sync_fetch_and_nand(AL+11, 7) != 0)
|
||||
+ abort ();
|
||||
+
|
||||
+ if (__sync_add_and_fetch(AL+12, 1) != 1)
|
||||
+ abort ();
|
||||
+ if (__sync_sub_and_fetch(AL+13, 12) != -12)
|
||||
+ abort ();
|
||||
+ if (__sync_and_and_fetch(AL+14, 7) != 7)
|
||||
+ abort ();
|
||||
+ if (__sync_or_and_fetch(AL+15, 8) != 8)
|
||||
+ abort ();
|
||||
+ if (__sync_xor_and_fetch(AL+16, 9) != 9)
|
||||
+ abort ();
|
||||
+ if (__sync_nand_and_fetch(AL+17, 7) != 7)
|
||||
+ abort ();
|
||||
+}
|
||||
+
|
||||
+static void *
|
||||
+start1 (void *arg)
|
||||
+{
|
||||
+ unsigned loop;
|
||||
+ sleep(1);
|
||||
+
|
||||
+ for (loop = 0; loop < LOOPS; loop++)
|
||||
+ {
|
||||
+ memcpy(AI, init_qi, sizeof(init_qi));
|
||||
+
|
||||
+ do_qi ();
|
||||
+
|
||||
+ if (memcmp (AI, test_qi, sizeof(test_qi)))
|
||||
+ abort ();
|
||||
+ }
|
||||
+
|
||||
+ return arg; /* _delete1_ */
|
||||
+}
|
||||
+
|
||||
+static void *
|
||||
+start2 (void *arg)
|
||||
+{
|
||||
+ unsigned loop;
|
||||
+
|
||||
+ for (loop = 0; loop < LOOPS; loop++)
|
||||
+ {
|
||||
+ memcpy(AL, init_hi, sizeof(init_hi));
|
||||
+
|
||||
+ do_hi ();
|
||||
+
|
||||
+ if (memcmp (AL, test_hi, sizeof(test_hi)))
|
||||
+ abort ();
|
||||
+ }
|
||||
+
|
||||
+ return arg; /* _delete2_ */
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+main (int argc, char **argv)
|
||||
+{
|
||||
+ pthread_t thread;
|
||||
+ int i;
|
||||
+
|
||||
+ i = pthread_create (&thread, NULL, start1, NULL); /* _create_ */
|
||||
+ assert (i == 0); /* _create_after_ */
|
||||
+
|
||||
+ sleep (1);
|
||||
+
|
||||
+ start2 (NULL);
|
||||
+
|
||||
+ i = pthread_join (thread, NULL); /* _delete_ */
|
||||
+ assert (i == 0);
|
||||
+
|
||||
+ return 0; /* _exit_ */
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.threads/atomic-seq-threaded.exp b/gdb/testsuite/gdb.threads/atomic-seq-threaded.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.threads/atomic-seq-threaded.exp
|
||||
@@ -0,0 +1,84 @@
|
||||
+# atomic-seq-threaded.exp -- Test case for stepping over RISC atomic code seqs.
|
||||
+# This variant testcases the code for stepping another thread while skipping
|
||||
+# over the atomic sequence in the former thread
|
||||
+# (STEPPING_PAST_SINGLESTEP_BREAKPOINT).
|
||||
+# Copyright (C) 2007 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 2 of the License, or
|
||||
+# (at your option) any later version.
|
||||
+#
|
||||
+# This program is distributed in the hope that it will be useful,
|
||||
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+# GNU General Public License for more details.
|
||||
+#
|
||||
+# You should have received a copy of the GNU General Public License
|
||||
+# along with this program; if not, write to the Free Software
|
||||
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
+
|
||||
+# Please email any bugs, comments, and/or additions to this file to:
|
||||
+# bug-gdb@prep.ai.mit.edu
|
||||
+
|
||||
+set testfile atomic-seq-threaded
|
||||
+set srcfile ${testfile}.c
|
||||
+set binfile [standard_output_file ${testfile}]
|
||||
+
|
||||
+foreach opts {{} {compiler=gcc4} {FAIL}} {
|
||||
+ if {$opts eq "FAIL"} {
|
||||
+ return -1
|
||||
+ }
|
||||
+ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug $opts]] eq "" } {
|
||||
+ break
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+gdb_exit
|
||||
+gdb_start
|
||||
+gdb_reinitialize_dir $srcdir/$subdir
|
||||
+
|
||||
+gdb_load ${binfile}
|
||||
+if ![runto_main] then {
|
||||
+ fail "Can't run to main"
|
||||
+ return 0
|
||||
+}
|
||||
+
|
||||
+# pthread_create () will not pass even on x86_64 with software watchpoint.
|
||||
+# Pass after pthread_create () without any watchpoint active.
|
||||
+set line [gdb_get_line_number "_create_after_"]
|
||||
+gdb_test "tbreak $line" \
|
||||
+ "reakpoint (\[0-9\]+) at .*$srcfile, line $line\..*" \
|
||||
+ "set breakpoint after pthread_create ()"
|
||||
+gdb_test "c" \
|
||||
+ ".*/\\* _create_after_ \\*/.*" \
|
||||
+ "run till after pthread_create ()"
|
||||
+
|
||||
+# Without a watchpoint being software no single-stepping would be used.
|
||||
+set test "Start (software) watchpoint"
|
||||
+gdb_test_multiple "watch unused" $test {
|
||||
+ -re "Watchpoint \[0-9\]+: unused.*$gdb_prompt $" {
|
||||
+ pass $test
|
||||
+ }
|
||||
+ -re "Hardware watchpoint \[0-9\]+: unused.*$gdb_prompt $" {
|
||||
+ # We do not test the goal but still the whole testcase should pass.
|
||||
+ unsupported $test
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+# More thorough testing of the scheduling logic.
|
||||
+gdb_test "set scheduler-locking step" ""
|
||||
+
|
||||
+# Critical code path is stepped through at this point.
|
||||
+set line [gdb_get_line_number "_exit_"]
|
||||
+gdb_test "tbreak $line" \
|
||||
+ "reakpoint \[0-9\]+ at .*$srcfile, line $line\..*" \
|
||||
+ "set breakpoint at _exit_"
|
||||
+gdb_test "c" \
|
||||
+ ".*/\\* _exit_ \\*/.*" \
|
||||
+ "run till _exit_"
|
||||
+
|
||||
+# Just a nonproblematic program exit.
|
||||
+gdb_test "c" \
|
||||
+ ".*Program exited normally\\..*" \
|
||||
+ "run till program exit"
|
32
gdb-6.6-testsuite-timeouts.patch
Normal file
32
gdb-6.6-testsuite-timeouts.patch
Normal file
@ -0,0 +1,32 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Fedora GDB patches <invalid@email.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-6.6-testsuite-timeouts.patch
|
||||
|
||||
;; Avoid too long timeouts on failing cases of "annota1.exp annota3.exp".
|
||||
;;=fedoratest
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/annota1.exp b/gdb/testsuite/gdb.base/annota1.exp
|
||||
--- a/gdb/testsuite/gdb.base/annota1.exp
|
||||
+++ b/gdb/testsuite/gdb.base/annota1.exp
|
||||
@@ -37,6 +37,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
|
||||
|
||||
clean_restart ${binfile}
|
||||
|
||||
+gdb_test "set breakpoint pending off" "" "Avoid lockup on nonexisting functions"
|
||||
+
|
||||
# The commands we test here produce many lines of output; disable "press
|
||||
# <return> to continue" prompts.
|
||||
gdb_test_no_output "set height 0"
|
||||
diff --git a/gdb/testsuite/gdb.base/annota3.exp b/gdb/testsuite/gdb.base/annota3.exp
|
||||
--- a/gdb/testsuite/gdb.base/annota3.exp
|
||||
+++ b/gdb/testsuite/gdb.base/annota3.exp
|
||||
@@ -36,6 +36,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
|
||||
|
||||
clean_restart ${binfile}
|
||||
|
||||
+gdb_test "set breakpoint pending off" "" "Avoid lockup on nonexisting functions"
|
||||
+
|
||||
# The commands we test here produce many lines of output; disable "press
|
||||
# <return> to continue" prompts.
|
||||
gdb_test_no_output "set height 0"
|
21
gdb-add-index.sh-fix-bashism.patch
Normal file
21
gdb-add-index.sh-fix-bashism.patch
Normal file
@ -0,0 +1,21 @@
|
||||
[gdb-add-index.sh] Fix bashism
|
||||
|
||||
---
|
||||
gdb/contrib/gdb-add-index.sh | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/contrib/gdb-add-index.sh b/gdb/contrib/gdb-add-index.sh
|
||||
index 734110caa3b..00d3ae8b0ae 100755
|
||||
--- a/gdb/contrib/gdb-add-index.sh
|
||||
+++ b/gdb/contrib/gdb-add-index.sh
|
||||
@@ -38,7 +38,9 @@ fi
|
||||
file="$1"
|
||||
|
||||
if test -L "$file"; then
|
||||
- if ! command -v readlink >/dev/null 2>&1; then
|
||||
+ target=$(readlink "$file")
|
||||
+ st=$?
|
||||
+ if [ $st -eq 127 ]; then
|
||||
echo "$myname: 'readlink' missing. Failed to follow symlink $1." 1>&2
|
||||
exit 1
|
||||
fi
|
88
gdb-archer-next-over-throw-cxx-exec.patch
Normal file
88
gdb-archer-next-over-throw-cxx-exec.patch
Normal file
@ -0,0 +1,88 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Fedora GDB patches <invalid@email.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-archer-next-over-throw-cxx-exec.patch
|
||||
|
||||
;; Fix follow-exec for C++ programs (bugreported by Martin Stransky).
|
||||
;;=fedoratest
|
||||
|
||||
Archer-upstreamed:
|
||||
http://sourceware.org/ml/archer/2010-q2/msg00031.html
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.cp/cxxexec.cc b/gdb/testsuite/gdb.cp/cxxexec.cc
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.cp/cxxexec.cc
|
||||
@@ -0,0 +1,25 @@
|
||||
+/* This test script is part of GDB, the GNU debugger.
|
||||
+
|
||||
+ Copyright 2010 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/>. */
|
||||
+
|
||||
+#include <unistd.h>
|
||||
+
|
||||
+int
|
||||
+main()
|
||||
+{
|
||||
+ execlp ("true", "true", NULL);
|
||||
+ return 1;
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.cp/cxxexec.exp b/gdb/testsuite/gdb.cp/cxxexec.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.cp/cxxexec.exp
|
||||
@@ -0,0 +1,42 @@
|
||||
+# Copyright 2010 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/>.
|
||||
+
|
||||
+if { [skip_cplus_tests] } { continue }
|
||||
+
|
||||
+set testfile cxxexec
|
||||
+if { [prepare_for_testing ${testfile}.exp ${testfile} ${testfile}.cc {c++ debug}] } {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+runto_main
|
||||
+
|
||||
+# We could stop after `continue' again at `main'.
|
||||
+delete_breakpoints
|
||||
+
|
||||
+set test "p _Unwind_DebugHook"
|
||||
+gdb_test_multiple $test $test {
|
||||
+ -re " = .* 0x\[0-9a-f\].*\r\n$gdb_prompt $" {
|
||||
+ pass $test
|
||||
+ }
|
||||
+ -re "\r\nNo symbol .*\r\n$gdb_prompt $" {
|
||||
+ xfail $test
|
||||
+ untested ${testfile}.exp
|
||||
+ return -1
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+# Run to end. The buggy GDB failed instead with:
|
||||
+# Cannot access memory at address ADDR.
|
||||
+gdb_continue_to_end "" "continue" 1
|
47
gdb-arm-fix-epilogue-frame-id.patch
Normal file
47
gdb-arm-fix-epilogue-frame-id.patch
Normal file
@ -0,0 +1,47 @@
|
||||
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
|
||||
|
77
gdb-arm-remove-thumb-bit-in-arm_adjust_breakpoint_ad.patch
Normal file
77
gdb-arm-remove-thumb-bit-in-arm_adjust_breakpoint_ad.patch
Normal file
@ -0,0 +1,77 @@
|
||||
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
|
||||
|
219
gdb-arm-remove-tpidruro-register-from-non-freebsd-ta.patch
Normal file
219
gdb-arm-remove-tpidruro-register-from-non-freebsd-ta.patch
Normal file
@ -0,0 +1,219 @@
|
||||
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
|
||||
|
41
gdb-build-fix-gdbserver-linux-aarch64-low.cc-build.patch
Normal file
41
gdb-build-fix-gdbserver-linux-aarch64-low.cc-build.patch
Normal file
@ -0,0 +1,41 @@
|
||||
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
|
||||
|
41
gdb-bz634108-solib_address.patch
Normal file
41
gdb-bz634108-solib_address.patch
Normal file
@ -0,0 +1,41 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Fedora GDB patches <invalid@email.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-bz634108-solib_address.patch
|
||||
|
||||
;; Verify GDB Python built-in function gdb.solib_address exists (BZ # 634108).
|
||||
;;=fedoratest
|
||||
|
||||
Fix gdb.solib_address (fix by Phil Muldoon).
|
||||
|
||||
s/solib_address/solib_name/ during upstreaming.
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.python/rh634108-solib_address.exp b/gdb/testsuite/gdb.python/rh634108-solib_address.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.python/rh634108-solib_address.exp
|
||||
@@ -0,0 +1,24 @@
|
||||
+# Copyright (C) 2008, 2009, 2010 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/>.
|
||||
+
|
||||
+# https://bugzilla.redhat.com/show_bug.cgi?id=634108
|
||||
+
|
||||
+gdb_exit
|
||||
+gdb_start
|
||||
+
|
||||
+# Skip all tests if Python scripting is not enabled.
|
||||
+if { [skip_python_tests] } { continue }
|
||||
+
|
||||
+gdb_test "python print (gdb.solib_name(-1))" "None" "gdb.solib_name exists"
|
201
gdb-cli-add-ignore-errors-command.patch
Normal file
201
gdb-cli-add-ignore-errors-command.patch
Normal file
@ -0,0 +1,201 @@
|
||||
From 0bb6f49bb9ad577667075550ca2ad4cb49931078 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 2/2] gdb-cli-add-ignore-errors-command
|
||||
|
||||
[gdb/cli] Add ignore-errors command
|
||||
|
||||
While trying to reproduce a failing test-case from the testsuite on the
|
||||
command line using a gdb command script, I ran into the problem that a command
|
||||
failed which stopped script execution.
|
||||
|
||||
I could work around this by splitting the script at each error, but I realized
|
||||
it would be nice if I could tell gdb to ignore the error.
|
||||
|
||||
A python workaround ignore-errors exists, mentioned here (
|
||||
https://sourceware.org/legacy-ml/gdb/2010-06/msg00100.html ), which is
|
||||
already supplied by distros like Fedora and openSUSE.
|
||||
|
||||
FTR, a more elaborate try-catch solution was posted here (
|
||||
https://sourceware.org/bugzilla/show_bug.cgi?id=8487 ).
|
||||
|
||||
This patch adds native ignore-errors support (so no python needed).
|
||||
|
||||
So with this script:
|
||||
...
|
||||
$ cat script.gdb
|
||||
ignore-errors run
|
||||
echo here
|
||||
...
|
||||
we have:
|
||||
...
|
||||
$ gdb -q -batch -x script.gdb
|
||||
No executable file specified.
|
||||
Use the "file" or "exec-file" command.
|
||||
here$
|
||||
...
|
||||
|
||||
Note that quit is not caught:
|
||||
...
|
||||
$ gdb -q
|
||||
(gdb) ignore-errors quit
|
||||
$
|
||||
...
|
||||
which is the same behaviour as with the python implementation.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
|
||||
gdb/ChangeLog:
|
||||
|
||||
2021-05-18 Tom de Vries <tdevries@suse.de>
|
||||
|
||||
* cli/cli-cmds.c (ignore_errors_command_completer)
|
||||
(ignore_errors_command): New function.
|
||||
(_initialize_cli_cmds): Add "ignore-errors" cmd.
|
||||
|
||||
gdb/doc/ChangeLog:
|
||||
|
||||
2021-05-18 Tom de Vries <tdevries@suse.de>
|
||||
|
||||
* gdb.texinfo (Command Files): Document command ignore-errors.
|
||||
|
||||
gdb/testsuite/ChangeLog:
|
||||
|
||||
2021-05-18 Tom de Vries <tdevries@suse.de>
|
||||
|
||||
* gdb.base/ignore-errors.exp: New test.
|
||||
* gdb.base/ignore-errors.gdb: New command file.
|
||||
---
|
||||
gdb/cli/cli-cmds.c | 35 ++++++++++++++++++++++++
|
||||
gdb/doc/gdb.texinfo | 8 +++++-
|
||||
gdb/testsuite/gdb.base/ignore-errors.exp | 24 ++++++++++++++++
|
||||
gdb/testsuite/gdb.base/ignore-errors.gdb | 2 ++
|
||||
4 files changed, 68 insertions(+), 1 deletion(-)
|
||||
create mode 100644 gdb/testsuite/gdb.base/ignore-errors.exp
|
||||
create mode 100644 gdb/testsuite/gdb.base/ignore-errors.gdb
|
||||
|
||||
diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
|
||||
index cfe7b71b0b7..0ae5530c558 100644
|
||||
--- a/gdb/cli/cli-cmds.c
|
||||
+++ b/gdb/cli/cli-cmds.c
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "location.h"
|
||||
#include "block.h"
|
||||
#include "valprint.h"
|
||||
+#include "event-top.h"
|
||||
|
||||
#include "ui-out.h"
|
||||
#include "interps.h"
|
||||
@@ -2544,6 +2545,34 @@ shell_internal_fn (struct gdbarch *gdbarch,
|
||||
return value::allocate_optimized_out (int_type);
|
||||
}
|
||||
|
||||
+/* Completer for "ignore-errors". */
|
||||
+
|
||||
+static void
|
||||
+ignore_errors_command_completer (cmd_list_element *ignore,
|
||||
+ completion_tracker &tracker,
|
||||
+ const char *text, const char * /*word*/)
|
||||
+{
|
||||
+ complete_nested_command_line (tracker, text);
|
||||
+}
|
||||
+
|
||||
+/* Implementation of the ignore-errors command. */
|
||||
+
|
||||
+static void
|
||||
+ignore_errors_command (const char *args, int from_tty)
|
||||
+{
|
||||
+ try
|
||||
+ {
|
||||
+ execute_command (args, from_tty);
|
||||
+ }
|
||||
+ catch (const gdb_exception_error &ex)
|
||||
+ {
|
||||
+ exception_print (gdb_stderr, ex);
|
||||
+
|
||||
+ /* See also execute_gdb_command. */
|
||||
+ async_enable_stdin ();
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
void _initialize_cli_cmds ();
|
||||
void
|
||||
_initialize_cli_cmds ()
|
||||
@@ -2942,4 +2971,10 @@ when GDB is started."), GDBINIT).release ();
|
||||
c = add_cmd ("source", class_support, source_command,
|
||||
source_help_text, &cmdlist);
|
||||
set_cmd_completer (c, filename_completer);
|
||||
+
|
||||
+ c = add_cmd ("ignore-errors", class_support, ignore_errors_command,
|
||||
+ _("Execute a single command, ignoring all errors.\n"
|
||||
+ "Only one-line commands are supported.\n"
|
||||
+ "This is primarily useful in scripts."), &cmdlist);
|
||||
+ set_cmd_completer (c, ignore_errors_command_completer);
|
||||
}
|
||||
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
|
||||
index 1abf91c4470..c277c16297c 100644
|
||||
--- a/gdb/doc/gdb.texinfo
|
||||
+++ b/gdb/doc/gdb.texinfo
|
||||
@@ -29250,7 +29250,8 @@ The lines in a command file are generally executed sequentially,
|
||||
unless the order of execution is changed by one of the
|
||||
@emph{flow-control commands} described below. The commands are not
|
||||
printed as they are executed. An error in any command terminates
|
||||
-execution of the command file and control is returned to the console.
|
||||
+execution of the command file and control is returned to the console,
|
||||
+unless the line is prefixed with the @code{ignore-errors} command.
|
||||
|
||||
@value{GDBN} first searches for @var{filename} in the current directory.
|
||||
If the file is not found there, and @var{filename} does not specify a
|
||||
@@ -29345,6 +29346,11 @@ the controlling expression.
|
||||
@item end
|
||||
Terminate the block of commands that are the body of @code{if},
|
||||
@code{else}, or @code{while} flow-control commands.
|
||||
+
|
||||
+@kindex ignore-errors
|
||||
+@item ignore-errors
|
||||
+This command executes the command specified by its arguments, but
|
||||
+doesn't stop execution of the script if the command fails.
|
||||
@end table
|
||||
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/ignore-errors.exp b/gdb/testsuite/gdb.base/ignore-errors.exp
|
||||
new file mode 100644
|
||||
index 00000000000..30dac7a94e2
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/ignore-errors.exp
|
||||
@@ -0,0 +1,24 @@
|
||||
+# Copyright 2021 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 command ignore-errors.
|
||||
+
|
||||
+clean_restart
|
||||
+
|
||||
+gdb_test "source ignore-errors.gdb" \
|
||||
+ [multi_line \
|
||||
+ "No executable file specified\\." \
|
||||
+ "Use the \"file\" or \"exec-file\" command\\." \
|
||||
+ "here"]
|
||||
diff --git a/gdb/testsuite/gdb.base/ignore-errors.gdb b/gdb/testsuite/gdb.base/ignore-errors.gdb
|
||||
new file mode 100644
|
||||
index 00000000000..5962ff49b11
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/ignore-errors.gdb
|
||||
@@ -0,0 +1,2 @@
|
||||
+ignore-errors run
|
||||
+echo here\n
|
||||
--
|
||||
2.35.3
|
||||
|
58
gdb-core-open-vdso-warning.patch
Normal file
58
gdb-core-open-vdso-warning.patch
Normal file
@ -0,0 +1,58 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Fedora GDB patches <invalid@email.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-core-open-vdso-warning.patch
|
||||
|
||||
;; Fix GNU/Linux core open: Can't read pathname for load map: Input/output error.
|
||||
;; Fix regression of undisplayed missing shared libraries caused by a fix for.
|
||||
;;=fedoratest: It should be in glibc: libc-alpha: <20091004161706.GA27450@.*>
|
||||
|
||||
http://sourceware.org/ml/gdb-patches/2009-10/msg00142.html
|
||||
Subject: [patch] Fix GNU/Linux core open: Can't read pathname for load map: Input/output error.
|
||||
|
||||
[ New patch variant. ]
|
||||
|
||||
commit 7d760051ffb8a23cdc51342d4e6243fbc462f73f
|
||||
Author: Ulrich Weigand <uweigand@de.ibm.com>
|
||||
Date: Wed Sep 25 11:52:50 2013 +0000
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/solib-symbol.exp b/gdb/testsuite/gdb.base/solib-symbol.exp
|
||||
--- a/gdb/testsuite/gdb.base/solib-symbol.exp
|
||||
+++ b/gdb/testsuite/gdb.base/solib-symbol.exp
|
||||
@@ -27,6 +27,7 @@ set testfile "solib-symbol-main"
|
||||
set srcfile ${srcdir}/${subdir}/${testfile}.c
|
||||
set binfile [standard_output_file ${testfile}]
|
||||
set bin_flags [list debug shlib=${binfile_lib}]
|
||||
+set executable ${testfile}
|
||||
|
||||
if { [gdb_compile_shlib ${srcfile_lib} ${binfile_lib} $lib_flags] != ""
|
||||
|| [gdb_compile ${srcfile} ${binfile} executable $bin_flags] != "" } {
|
||||
@@ -61,4 +62,28 @@ gdb_test "br foo2" \
|
||||
"Breakpoint.*: foo2. .2 locations..*" \
|
||||
"foo2 in mdlib"
|
||||
|
||||
+# Test GDB warns for shared libraris which have not been found.
|
||||
+
|
||||
+gdb_test "info sharedlibrary" "/${libname}.*"
|
||||
+
|
||||
+clean_restart ${executable}
|
||||
+gdb_breakpoint "main"
|
||||
+gdb_run_cmd
|
||||
+set test "no warning for missing libraries"
|
||||
+gdb_test_multiple "" $test {
|
||||
+ -re "warning: Could not load shared library symbols for \[0-9\]+ libraries,.*\r\n$gdb_prompt $" {
|
||||
+ fail $test
|
||||
+ }
|
||||
+ -re "Breakpoint \[0-9\]+, main .*\r\n$gdb_prompt $" {
|
||||
+ pass $test
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+clean_restart ${executable}
|
||||
+gdb_test_no_output "set solib-absolute-prefix /doESnotEXIST"
|
||||
+gdb_breakpoint "main"
|
||||
+gdb_run_cmd
|
||||
+gdb_test "" "warning: Could not load shared library symbols for \[0-9\]+ libraries,.*\r\nBreakpoint \[0-9\]+, main .*" \
|
||||
+ "warning for missing libraries"
|
||||
+
|
||||
gdb_exit
|
150
gdb-exp-fix-cast-handling-for-indirection.patch
Normal file
150
gdb-exp-fix-cast-handling-for-indirection.patch
Normal file
@ -0,0 +1,150 @@
|
||||
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
|
||||
|
365
gdb-exp-fix-printing-of-out-of-bounds-struct-members.patch
Normal file
365
gdb-exp-fix-printing-of-out-of-bounds-struct-members.patch
Normal file
@ -0,0 +1,365 @@
|
||||
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
|
||||
|
86
gdb-exp-redo-cast-handling-for-indirection.patch
Normal file
86
gdb-exp-redo-cast-handling-for-indirection.patch
Normal file
@ -0,0 +1,86 @@
|
||||
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
|
||||
|
333
gdb-fedora-libncursesw.patch
Normal file
333
gdb-fedora-libncursesw.patch
Normal file
@ -0,0 +1,333 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Fedora GDB patches <invalid@email.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-fedora-libncursesw.patch
|
||||
|
||||
;; Force libncursesw over libncurses to match the includes (RH BZ 1270534).
|
||||
;;=push+jan
|
||||
|
||||
Fedora: Force libncursesw over libncurses to match the includes.
|
||||
https://bugzilla.redhat.com/show_bug.cgi?id=1270534
|
||||
|
||||
diff --git a/gdb/configure b/gdb/configure
|
||||
--- a/gdb/configure
|
||||
+++ b/gdb/configure
|
||||
@@ -780,9 +780,6 @@ ENABLE_BFD_64_BIT_TRUE
|
||||
subdirs
|
||||
RPM_LIBS
|
||||
RPM_CFLAGS
|
||||
-PKG_CONFIG_LIBDIR
|
||||
-PKG_CONFIG_PATH
|
||||
-PKG_CONFIG
|
||||
GDB_DATADIR
|
||||
DEBUGDIR
|
||||
MAKEINFO_EXTRA_FLAGS
|
||||
@@ -990,12 +987,12 @@ PKG_CONFIG_PATH
|
||||
PKG_CONFIG_LIBDIR
|
||||
MAKEINFO
|
||||
MAKEINFOFLAGS
|
||||
+RPM_CFLAGS
|
||||
+RPM_LIBS
|
||||
AMD_DBGAPI_CFLAGS
|
||||
AMD_DBGAPI_LIBS
|
||||
DEBUGINFOD_CFLAGS
|
||||
DEBUGINFOD_LIBS
|
||||
-RPM_CFLAGS
|
||||
-RPM_LIBS
|
||||
YACC
|
||||
YFLAGS
|
||||
ZSTD_CFLAGS
|
||||
@@ -1684,11 +1681,11 @@ Optional Packages:
|
||||
[--with-auto-load-dir]
|
||||
--without-auto-load-safe-path
|
||||
do not restrict auto-loaded files locations
|
||||
+ --with-rpm query rpm database for missing debuginfos (yes/no,
|
||||
+ def. auto=librpm.so)
|
||||
--with-amd-dbgapi support for the amd-dbgapi target (yes / no / auto)
|
||||
--with-debuginfod Enable debuginfo lookups with debuginfod
|
||||
(auto/yes/no)
|
||||
- --with-rpm query rpm database for missing debuginfos (yes/no,
|
||||
- def. auto=librpm.so)
|
||||
--with-libunwind-ia64 use libunwind frame unwinding for ia64 targets
|
||||
--with-curses use the curses library instead of the termcap
|
||||
library
|
||||
@@ -1761,6 +1758,8 @@ Some influential environment variables:
|
||||
MAKEINFO Parent configure detects if it is of sufficient version.
|
||||
MAKEINFOFLAGS
|
||||
Parameters for MAKEINFO.
|
||||
+ RPM_CFLAGS C compiler flags for RPM, overriding pkg-config
|
||||
+ RPM_LIBS linker flags for RPM, overriding pkg-config
|
||||
AMD_DBGAPI_CFLAGS
|
||||
C compiler flags for AMD_DBGAPI, overriding pkg-config
|
||||
AMD_DBGAPI_LIBS
|
||||
@@ -1769,8 +1768,6 @@ Some influential environment variables:
|
||||
C compiler flags for DEBUGINFOD, overriding pkg-config
|
||||
DEBUGINFOD_LIBS
|
||||
linker flags for DEBUGINFOD, overriding pkg-config
|
||||
- RPM_CFLAGS C compiler flags for RPM, overriding pkg-config
|
||||
- RPM_LIBS linker flags for RPM, overriding pkg-config
|
||||
YACC The `Yet Another Compiler Compiler' implementation to use.
|
||||
Defaults to the first program found out of: `bison -y', `byacc',
|
||||
`yacc'.
|
||||
@@ -11495,7 +11492,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<_LT_EOF
|
||||
-#line 11486 "configure"
|
||||
+#line 11495 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@@ -11601,7 +11598,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<_LT_EOF
|
||||
-#line 11592 "configure"
|
||||
+#line 11601 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@@ -18102,8 +18099,8 @@ $as_echo_n "checking specific librpm version... " >&6; }
|
||||
if test "$cross_compiling" = yes; then :
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
|
||||
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
|
||||
-as_fn_error "cannot run test program while cross compiling
|
||||
-See \`config.log' for more details." "$LINENO" 5; }
|
||||
+as_fn_error $? "cannot run test program while cross compiling
|
||||
+See \`config.log' for more details" "$LINENO" 5; }
|
||||
else
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
@@ -18275,132 +18272,12 @@ $as_echo "#define HAVE_LIBRPM 1" >>confdefs.h
|
||||
$as_echo "no" >&6; }
|
||||
LIBS="$save_LIBS"
|
||||
if $DLOPEN_REQUIRE; then
|
||||
- as_fn_error "Specific name $LIBRPM was requested but it could not be opened." "$LINENO" 5
|
||||
+ as_fn_error $? "Specific name $LIBRPM was requested but it could not be opened." "$LINENO" 5
|
||||
fi
|
||||
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
|
||||
- if test -n "$ac_tool_prefix"; then
|
||||
- # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
|
||||
-set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
|
||||
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
-$as_echo_n "checking for $ac_word... " >&6; }
|
||||
-if test "${ac_cv_path_PKG_CONFIG+set}" = set; then :
|
||||
- $as_echo_n "(cached) " >&6
|
||||
-else
|
||||
- case $PKG_CONFIG in
|
||||
- [\\/]* | ?:[\\/]*)
|
||||
- ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
|
||||
- ;;
|
||||
- *)
|
||||
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
-for as_dir in $PATH
|
||||
-do
|
||||
- IFS=$as_save_IFS
|
||||
- test -z "$as_dir" && as_dir=.
|
||||
- for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
- ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
|
||||
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
- break 2
|
||||
- fi
|
||||
-done
|
||||
- done
|
||||
-IFS=$as_save_IFS
|
||||
-
|
||||
- ;;
|
||||
-esac
|
||||
-fi
|
||||
-PKG_CONFIG=$ac_cv_path_PKG_CONFIG
|
||||
-if test -n "$PKG_CONFIG"; then
|
||||
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
|
||||
-$as_echo "$PKG_CONFIG" >&6; }
|
||||
-else
|
||||
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
-$as_echo "no" >&6; }
|
||||
-fi
|
||||
-
|
||||
-
|
||||
-fi
|
||||
-if test -z "$ac_cv_path_PKG_CONFIG"; then
|
||||
- ac_pt_PKG_CONFIG=$PKG_CONFIG
|
||||
- # Extract the first word of "pkg-config", so it can be a program name with args.
|
||||
-set dummy pkg-config; ac_word=$2
|
||||
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
-$as_echo_n "checking for $ac_word... " >&6; }
|
||||
-if test "${ac_cv_path_ac_pt_PKG_CONFIG+set}" = set; then :
|
||||
- $as_echo_n "(cached) " >&6
|
||||
-else
|
||||
- case $ac_pt_PKG_CONFIG in
|
||||
- [\\/]* | ?:[\\/]*)
|
||||
- ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path.
|
||||
- ;;
|
||||
- *)
|
||||
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
-for as_dir in $PATH
|
||||
-do
|
||||
- IFS=$as_save_IFS
|
||||
- test -z "$as_dir" && as_dir=.
|
||||
- for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
- ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
|
||||
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
- break 2
|
||||
- fi
|
||||
-done
|
||||
- done
|
||||
-IFS=$as_save_IFS
|
||||
-
|
||||
- ;;
|
||||
-esac
|
||||
-fi
|
||||
-ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG
|
||||
-if test -n "$ac_pt_PKG_CONFIG"; then
|
||||
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5
|
||||
-$as_echo "$ac_pt_PKG_CONFIG" >&6; }
|
||||
-else
|
||||
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
-$as_echo "no" >&6; }
|
||||
-fi
|
||||
-
|
||||
- if test "x$ac_pt_PKG_CONFIG" = x; then
|
||||
- PKG_CONFIG=""
|
||||
- else
|
||||
- case $cross_compiling:$ac_tool_warned in
|
||||
-yes:)
|
||||
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
|
||||
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
|
||||
-ac_tool_warned=yes ;;
|
||||
-esac
|
||||
- PKG_CONFIG=$ac_pt_PKG_CONFIG
|
||||
- fi
|
||||
-else
|
||||
- PKG_CONFIG="$ac_cv_path_PKG_CONFIG"
|
||||
-fi
|
||||
-
|
||||
-fi
|
||||
-if test -n "$PKG_CONFIG"; then
|
||||
- _pkg_min_version=0.9.0
|
||||
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5
|
||||
-$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; }
|
||||
- if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
|
||||
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
-$as_echo "yes" >&6; }
|
||||
- else
|
||||
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
-$as_echo "no" >&6; }
|
||||
- PKG_CONFIG=""
|
||||
- fi
|
||||
-fi
|
||||
-
|
||||
pkg_failed=no
|
||||
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for RPM" >&5
|
||||
-$as_echo_n "checking for RPM... " >&6; }
|
||||
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for rpm" >&5
|
||||
+$as_echo_n "checking for rpm... " >&6; }
|
||||
|
||||
if test -n "$RPM_CFLAGS"; then
|
||||
pkg_cv_RPM_CFLAGS="$RPM_CFLAGS"
|
||||
@@ -18437,6 +18314,30 @@ fi
|
||||
pkg_failed=untried
|
||||
fi
|
||||
|
||||
+if test $pkg_failed = no; then
|
||||
+ pkg_save_LDFLAGS="$LDFLAGS"
|
||||
+ LDFLAGS="$LDFLAGS $pkg_cv_RPM_LIBS"
|
||||
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
+/* end confdefs.h. */
|
||||
+
|
||||
+int
|
||||
+main ()
|
||||
+{
|
||||
+
|
||||
+ ;
|
||||
+ return 0;
|
||||
+}
|
||||
+_ACEOF
|
||||
+if ac_fn_c_try_link "$LINENO"; then :
|
||||
+
|
||||
+else
|
||||
+ pkg_failed=yes
|
||||
+fi
|
||||
+rm -f core conftest.err conftest.$ac_objext \
|
||||
+ conftest$ac_exeext conftest.$ac_ext
|
||||
+ LDFLAGS=$pkg_save_LDFLAGS
|
||||
+fi
|
||||
+
|
||||
|
||||
|
||||
if test $pkg_failed = yes; then
|
||||
@@ -18531,7 +18432,7 @@ $as_echo "#define HAVE_LIBRPM 1" >>confdefs.h
|
||||
LIBS="$LIBS $RPM_LIBS"
|
||||
else
|
||||
if $RPM_REQUIRE; then
|
||||
- as_fn_error "$RPM_PKG_ERRORS" "$LINENO" 5
|
||||
+ as_fn_error $? "$RPM_PKG_ERRORS" "$LINENO" 5
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $RPM_PKG_ERRORS" >&5
|
||||
$as_echo "$as_me: WARNING: $RPM_PKG_ERRORS" >&2;}
|
||||
@@ -21164,6 +21065,7 @@ if test x"$prefer_curses" = xyes; then
|
||||
# search /usr/local/include, if ncurses is installed in /usr/local. A
|
||||
# default installation of ncurses on alpha*-dec-osf* will lead to such
|
||||
# a situation.
|
||||
+ # Fedora: Force libncursesw over libncurses to match the includes.
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing waddstr" >&5
|
||||
$as_echo_n "checking for library containing waddstr... " >&6; }
|
||||
if ${ac_cv_search_waddstr+:} false; then :
|
||||
@@ -21188,7 +21090,7 @@ return waddstr ();
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
-for ac_lib in '' ncursesw ncurses cursesX curses; do
|
||||
+for ac_lib in '' ncursesw; do
|
||||
if test -z "$ac_lib"; then
|
||||
ac_res="none required"
|
||||
else
|
||||
@@ -21260,6 +21162,7 @@ case $host_os in
|
||||
esac
|
||||
|
||||
# These are the libraries checked by Readline.
|
||||
+# Fedora: Force libncursesw over libncurses to match the includes.
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing tgetent" >&5
|
||||
$as_echo_n "checking for library containing tgetent... " >&6; }
|
||||
if ${ac_cv_search_tgetent+:} false; then :
|
||||
@@ -21284,7 +21187,7 @@ return tgetent ();
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
-for ac_lib in '' termcap tinfow tinfo curses ncursesw ncurses; do
|
||||
+for ac_lib in '' ncursesw; do
|
||||
if test -z "$ac_lib"; then
|
||||
ac_res="none required"
|
||||
else
|
||||
diff --git a/gdb/configure.ac b/gdb/configure.ac
|
||||
--- a/gdb/configure.ac
|
||||
+++ b/gdb/configure.ac
|
||||
@@ -749,7 +749,8 @@ if test x"$prefer_curses" = xyes; then
|
||||
# search /usr/local/include, if ncurses is installed in /usr/local. A
|
||||
# default installation of ncurses on alpha*-dec-osf* will lead to such
|
||||
# a situation.
|
||||
- AC_SEARCH_LIBS(waddstr, [ncursesw ncurses cursesX curses],
|
||||
+ # Fedora: Force libncursesw over libncurses to match the includes.
|
||||
+ AC_SEARCH_LIBS(waddstr, [ncursesw],
|
||||
[curses_found=yes
|
||||
AC_DEFINE([HAVE_LIBCURSES], [1],
|
||||
[Define to 1 if curses is enabled.])
|
||||
@@ -789,7 +790,8 @@ case $host_os in
|
||||
esac
|
||||
|
||||
# These are the libraries checked by Readline.
|
||||
-AC_SEARCH_LIBS(tgetent, [termcap tinfow tinfo curses ncursesw ncurses])
|
||||
+# Fedora: Force libncursesw over libncurses to match the includes.
|
||||
+AC_SEARCH_LIBS(tgetent, [ncursesw])
|
||||
|
||||
if test "$ac_cv_search_tgetent" = no; then
|
||||
CONFIG_OBS="$CONFIG_OBS stub-termcap.o"
|
144
gdb-fix-heap-use-after-free-in-select_event_lwp.patch
Normal file
144
gdb-fix-heap-use-after-free-in-select_event_lwp.patch
Normal file
@ -0,0 +1,144 @@
|
||||
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
|
||||
|
636
gdb-fix-segfault-in-for_each_block-part-1.patch
Normal file
636
gdb-fix-segfault-in-for_each_block-part-1.patch
Normal file
@ -0,0 +1,636 @@
|
||||
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
|
||||
|
168
gdb-fix-segfault-in-for_each_block-part-2.patch
Normal file
168
gdb-fix-segfault-in-for_each_block-part-2.patch
Normal file
@ -0,0 +1,168 @@
|
||||
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
|
||||
|
42
gdb-ftbs-swapped-calloc-args.patch
Normal file
42
gdb-ftbs-swapped-calloc-args.patch
Normal file
@ -0,0 +1,42 @@
|
||||
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;
|
10
gdb-gcore-bash.patch
Normal file
10
gdb-gcore-bash.patch
Normal file
@ -0,0 +1,10 @@
|
||||
diff --git a/gdb/gcore.in b/gdb/gcore.in
|
||||
index b9770ea415..3149f6e1fe 100644
|
||||
--- a/gdb/gcore.in
|
||||
+++ b/gdb/gcore.in
|
||||
@@ -1,4 +1,4 @@
|
||||
-#!/usr/bin/env bash
|
||||
+#!/bin/bash
|
||||
|
||||
# Copyright (C) 2003-2023 Free Software Foundation, Inc.
|
||||
|
132
gdb-glibc-strstr-workaround.patch
Normal file
132
gdb-glibc-strstr-workaround.patch
Normal file
@ -0,0 +1,132 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Fedora GDB patches <invalid@email.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-glibc-strstr-workaround.patch
|
||||
|
||||
;; Workaround PR libc/14166 for inferior calls of strstr.
|
||||
;;=fedoratest: Compatibility with RHELs (unchecked which ones).
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/gnu-ifunc-strstr-workaround.exp b/gdb/testsuite/gdb.base/gnu-ifunc-strstr-workaround.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/gnu-ifunc-strstr-workaround.exp
|
||||
@@ -0,0 +1,119 @@
|
||||
+# Copyright (C) 2012 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/>.
|
||||
+
|
||||
+# Workaround for:
|
||||
+# invalid IFUNC DW_AT_linkage_name: memmove strstr time
|
||||
+# http://sourceware.org/bugzilla/show_bug.cgi?id=14166
|
||||
+
|
||||
+if {[skip_shlib_tests]} {
|
||||
+ return 0
|
||||
+}
|
||||
+
|
||||
+set testfile "gnu-ifunc-strstr-workaround"
|
||||
+set executable ${testfile}
|
||||
+set srcfile start.c
|
||||
+set binfile [standard_output_file ${executable}]
|
||||
+
|
||||
+if [prepare_for_testing ${testfile}.exp $executable $srcfile] {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+if ![runto_main] {
|
||||
+ return 0
|
||||
+}
|
||||
+
|
||||
+set test "ptype atoi"
|
||||
+gdb_test_multiple $test $test {
|
||||
+ -re "type = int \\(const char \\*\\)\r\n$gdb_prompt $" {
|
||||
+ pass $test
|
||||
+ }
|
||||
+ -re "type = int \\(\\)\r\n$gdb_prompt $" {
|
||||
+ untested "$test (no DWARF)"
|
||||
+ return 0
|
||||
+ }
|
||||
+ -re "type = <unknown return type> \\(\\)\r\n$gdb_prompt $" {
|
||||
+ untested "$test (no DWARF)"
|
||||
+ return 0
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+set addr ""
|
||||
+set test "print strstr"
|
||||
+gdb_test_multiple $test $test {
|
||||
+ -re " = {<text gnu-indirect-function variable, no debug info>} (0x\[0-9a-f\]+) <strstr>\r\n$gdb_prompt $" {
|
||||
+ set addr $expect_out(1,string)
|
||||
+ pass $test
|
||||
+ }
|
||||
+ -re " = {<text gnu-indirect-function variable, no debug info>} (0x\[0-9a-f\]+) <__strstr>\r\n$gdb_prompt $" {
|
||||
+ set addr $expect_out(1,string)
|
||||
+ pass "$test (GDB workaround)"
|
||||
+ }
|
||||
+ -re " = {<text gnu-indirect-function variable, no debug info>} (0x\[0-9a-f\]+) <__libc_strstr>\r\n$gdb_prompt $" {
|
||||
+ set addr $expect_out(1,string)
|
||||
+ pass "$test (fixed glibc)"
|
||||
+ }
|
||||
+ -re " = {<text gnu-indirect-function variable, no debug info>} (0x\[0-9a-f\]+) <__libc_strstr_ifunc>\r\n$gdb_prompt $" {
|
||||
+ set addr $expect_out(1,string)
|
||||
+ pass "$test (fixed glibc)"
|
||||
+ }
|
||||
+ -re " = {char \\*\\(const char \\*, const char \\*\\)} 0x\[0-9a-f\]+ <strstr>\r\n$gdb_prompt $" {
|
||||
+ untested "$test (gnu-ifunc not in use by glibc)"
|
||||
+ return 0
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+set test "info sym"
|
||||
+gdb_test_multiple "info sym $addr" $test {
|
||||
+ -re "strstr in section \\.text of /lib\[^/\]*/libc.so.6\r\n$gdb_prompt $" {
|
||||
+ pass $test
|
||||
+ }
|
||||
+ -re " = {char \\*\\(const char \\*, const char \\*\\)} 0x\[0-9a-f\]+ <strstr>\r\n$gdb_prompt $" {
|
||||
+ # unexpected
|
||||
+ xfail "$test (not in libc.so.6)"
|
||||
+ return 0
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+set test "info addr strstr"
|
||||
+gdb_test_multiple $test $test {
|
||||
+ -re "Symbol \"strstr\" is a function at address $addr\\.\r\n$gdb_prompt $" {
|
||||
+ fail "$test (DWARF for strstr)"
|
||||
+ }
|
||||
+ -re "Symbol \"strstr\" is at $addr in a file compiled without debugging\\.\r\n$gdb_prompt $" {
|
||||
+ pass "$test"
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+set test "print strstr second time"
|
||||
+gdb_test_multiple "print strstr" $test {
|
||||
+ -re " = {<text gnu-indirect-function variable, no debug info>} $addr <strstr>\r\n$gdb_prompt $" {
|
||||
+ pass $test
|
||||
+ }
|
||||
+ -re " = {<text gnu-indirect-function variable, no debug info>} $addr <__strstr>\r\n$gdb_prompt $" {
|
||||
+ pass "$test (GDB workaround)"
|
||||
+ }
|
||||
+ -re " = {<text gnu-indirect-function variable, no debug info>} $addr <__libc_strstr>\r\n$gdb_prompt $" {
|
||||
+ pass "$test (fixed glibc)"
|
||||
+ }
|
||||
+ -re " = {<text gnu-indirect-function variable, no debug info>} $addr <__libc_strstr_ifunc>\r\n$gdb_prompt $" {
|
||||
+ pass "$test (fixed glibc)"
|
||||
+ }
|
||||
+ -re " = {void \\*\\(void\\)} 0x\[0-9a-f\]+ <strstr>\r\n$gdb_prompt $" {
|
||||
+ fail $test
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+gdb_test {print (char *)strstr("abc","b")} { = 0x[0-9a-f]+ "bc"}
|
||||
+gdb_test {print (char *)strstr("def","e")} { = 0x[0-9a-f]+ "ef"}
|
48
gdb-gstack.man
Normal file
48
gdb-gstack.man
Normal file
@ -0,0 +1,48 @@
|
||||
.\"
|
||||
.\" gstack manual page.
|
||||
.\" Copyright (c) 1999 Ross Thompson
|
||||
.\" Copyright (c) 2001, 2002, 2004, 2008 Red Hat, Inc.
|
||||
.\"
|
||||
.\" Original author: Ross Thompson <ross@whatsis.com>
|
||||
.\"
|
||||
.\" This program is free software; you can redistribute it and/or modify
|
||||
.\" it under the terms of the GNU General Public License as published by
|
||||
.\" the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
.\" the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
.\" Boston, MA 02111-1307, USA.
|
||||
.\"
|
||||
.TH GSTACK 1 "Feb 15 2008" "Red Hat Linux" "Linux Programmer's Manual"
|
||||
|
||||
.SH NAME
|
||||
gstack \- print a stack trace of a running process
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B gstack
|
||||
pid
|
||||
|
||||
.SH DESCRIPTION
|
||||
|
||||
\f3gstack\f1 attaches to the active process named by the \f3pid\f1 on
|
||||
the command line, and prints out an execution stack trace. If ELF
|
||||
symbols exist in the binary (usually the case unless you have run
|
||||
strip(1)), then symbolic addresses are printed as well.
|
||||
|
||||
If the process is part of a thread group, then \f3gstack\f1 will print
|
||||
out a stack trace for each of the threads in the group.
|
||||
|
||||
.SH SEE ALSO
|
||||
nm(1), ptrace(2), gdb(1)
|
||||
|
||||
.SH AUTHORS
|
||||
Ross Thompson <ross@whatsis.com>
|
||||
|
||||
Red Hat, Inc. <http://bugzilla.redhat.com/bugzilla>
|
226
gdb-linux_perf-bundle.patch
Normal file
226
gdb-linux_perf-bundle.patch
Normal file
@ -0,0 +1,226 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Fedora GDB patches <invalid@email.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-linux_perf-bundle.patch
|
||||
|
||||
;; [dts+el7] [x86*] Bundle linux_perf.h for libipt (RH BZ 1256513).
|
||||
;;=fedora
|
||||
|
||||
diff --git a/gdb/gdb.c b/gdb/gdb.c
|
||||
--- a/gdb/gdb.c
|
||||
+++ b/gdb/gdb.c
|
||||
@@ -21,6 +21,10 @@
|
||||
#include "interps.h"
|
||||
#include "run-on-main-thread.h"
|
||||
|
||||
+#ifdef PERF_ATTR_SIZE_VER5_BUNDLE
|
||||
+extern "C" void __libipt_init(void);
|
||||
+#endif
|
||||
+
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
@@ -32,6 +36,10 @@ main (int argc, char **argv)
|
||||
|
||||
struct captured_main_args args;
|
||||
|
||||
+#ifdef PERF_ATTR_SIZE_VER5_BUNDLE
|
||||
+ __libipt_init();
|
||||
+#endif
|
||||
+
|
||||
memset (&args, 0, sizeof args);
|
||||
args.argc = argc;
|
||||
args.argv = argv;
|
||||
diff --git a/gdb/nat/linux-btrace.h b/gdb/nat/linux-btrace.h
|
||||
--- a/gdb/nat/linux-btrace.h
|
||||
+++ b/gdb/nat/linux-btrace.h
|
||||
@@ -28,6 +28,177 @@
|
||||
# include <linux/perf_event.h>
|
||||
#endif
|
||||
|
||||
+#ifdef PERF_ATTR_SIZE_VER5_BUNDLE
|
||||
+#ifndef HAVE_LINUX_PERF_EVENT_H
|
||||
+# error "PERF_ATTR_SIZE_VER5_BUNDLE && !HAVE_LINUX_PERF_EVENT_H"
|
||||
+#endif
|
||||
+#ifndef PERF_ATTR_SIZE_VER5
|
||||
+#define PERF_ATTR_SIZE_VER5
|
||||
+#define perf_event_mmap_page perf_event_mmap_page_bundle
|
||||
+// kernel-headers-3.10.0-493.el7.x86_64/usr/include/linux/perf_event.h
|
||||
+/*
|
||||
+ * Structure of the page that can be mapped via mmap
|
||||
+ */
|
||||
+struct perf_event_mmap_page {
|
||||
+ __u32 version; /* version number of this structure */
|
||||
+ __u32 compat_version; /* lowest version this is compat with */
|
||||
+
|
||||
+ /*
|
||||
+ * Bits needed to read the hw events in user-space.
|
||||
+ *
|
||||
+ * u32 seq, time_mult, time_shift, index, width;
|
||||
+ * u64 count, enabled, running;
|
||||
+ * u64 cyc, time_offset;
|
||||
+ * s64 pmc = 0;
|
||||
+ *
|
||||
+ * do {
|
||||
+ * seq = pc->lock;
|
||||
+ * barrier()
|
||||
+ *
|
||||
+ * enabled = pc->time_enabled;
|
||||
+ * running = pc->time_running;
|
||||
+ *
|
||||
+ * if (pc->cap_usr_time && enabled != running) {
|
||||
+ * cyc = rdtsc();
|
||||
+ * time_offset = pc->time_offset;
|
||||
+ * time_mult = pc->time_mult;
|
||||
+ * time_shift = pc->time_shift;
|
||||
+ * }
|
||||
+ *
|
||||
+ * index = pc->index;
|
||||
+ * count = pc->offset;
|
||||
+ * if (pc->cap_user_rdpmc && index) {
|
||||
+ * width = pc->pmc_width;
|
||||
+ * pmc = rdpmc(index - 1);
|
||||
+ * }
|
||||
+ *
|
||||
+ * barrier();
|
||||
+ * } while (pc->lock != seq);
|
||||
+ *
|
||||
+ * NOTE: for obvious reason this only works on self-monitoring
|
||||
+ * processes.
|
||||
+ */
|
||||
+ __u32 lock; /* seqlock for synchronization */
|
||||
+ __u32 index; /* hardware event identifier */
|
||||
+ __s64 offset; /* add to hardware event value */
|
||||
+ __u64 time_enabled; /* time event active */
|
||||
+ __u64 time_running; /* time event on cpu */
|
||||
+ union {
|
||||
+ __u64 capabilities;
|
||||
+ struct {
|
||||
+ __u64 cap_bit0 : 1, /* Always 0, deprecated, see commit 860f085b74e9 */
|
||||
+ cap_bit0_is_deprecated : 1, /* Always 1, signals that bit 0 is zero */
|
||||
+
|
||||
+ cap_user_rdpmc : 1, /* The RDPMC instruction can be used to read counts */
|
||||
+ cap_user_time : 1, /* The time_* fields are used */
|
||||
+ cap_user_time_zero : 1, /* The time_zero field is used */
|
||||
+ cap_____res : 59;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ /*
|
||||
+ * If cap_user_rdpmc this field provides the bit-width of the value
|
||||
+ * read using the rdpmc() or equivalent instruction. This can be used
|
||||
+ * to sign extend the result like:
|
||||
+ *
|
||||
+ * pmc <<= 64 - width;
|
||||
+ * pmc >>= 64 - width; // signed shift right
|
||||
+ * count += pmc;
|
||||
+ */
|
||||
+ __u16 pmc_width;
|
||||
+
|
||||
+ /*
|
||||
+ * If cap_usr_time the below fields can be used to compute the time
|
||||
+ * delta since time_enabled (in ns) using rdtsc or similar.
|
||||
+ *
|
||||
+ * u64 quot, rem;
|
||||
+ * u64 delta;
|
||||
+ *
|
||||
+ * quot = (cyc >> time_shift);
|
||||
+ * rem = cyc & (((u64)1 << time_shift) - 1);
|
||||
+ * delta = time_offset + quot * time_mult +
|
||||
+ * ((rem * time_mult) >> time_shift);
|
||||
+ *
|
||||
+ * Where time_offset,time_mult,time_shift and cyc are read in the
|
||||
+ * seqcount loop described above. This delta can then be added to
|
||||
+ * enabled and possible running (if index), improving the scaling:
|
||||
+ *
|
||||
+ * enabled += delta;
|
||||
+ * if (index)
|
||||
+ * running += delta;
|
||||
+ *
|
||||
+ * quot = count / running;
|
||||
+ * rem = count % running;
|
||||
+ * count = quot * enabled + (rem * enabled) / running;
|
||||
+ */
|
||||
+ __u16 time_shift;
|
||||
+ __u32 time_mult;
|
||||
+ __u64 time_offset;
|
||||
+ /*
|
||||
+ * If cap_usr_time_zero, the hardware clock (e.g. TSC) can be calculated
|
||||
+ * from sample timestamps.
|
||||
+ *
|
||||
+ * time = timestamp - time_zero;
|
||||
+ * quot = time / time_mult;
|
||||
+ * rem = time % time_mult;
|
||||
+ * cyc = (quot << time_shift) + (rem << time_shift) / time_mult;
|
||||
+ *
|
||||
+ * And vice versa:
|
||||
+ *
|
||||
+ * quot = cyc >> time_shift;
|
||||
+ * rem = cyc & (((u64)1 << time_shift) - 1);
|
||||
+ * timestamp = time_zero + quot * time_mult +
|
||||
+ * ((rem * time_mult) >> time_shift);
|
||||
+ */
|
||||
+ __u64 time_zero;
|
||||
+ __u32 size; /* Header size up to __reserved[] fields. */
|
||||
+
|
||||
+ /*
|
||||
+ * Hole for extension of the self monitor capabilities
|
||||
+ */
|
||||
+
|
||||
+ __u8 __reserved[118*8+4]; /* align to 1k. */
|
||||
+
|
||||
+ /*
|
||||
+ * Control data for the mmap() data buffer.
|
||||
+ *
|
||||
+ * User-space reading the @data_head value should issue an smp_rmb(),
|
||||
+ * after reading this value.
|
||||
+ *
|
||||
+ * When the mapping is PROT_WRITE the @data_tail value should be
|
||||
+ * written by userspace to reflect the last read data, after issueing
|
||||
+ * an smp_mb() to separate the data read from the ->data_tail store.
|
||||
+ * In this case the kernel will not over-write unread data.
|
||||
+ *
|
||||
+ * See perf_output_put_handle() for the data ordering.
|
||||
+ *
|
||||
+ * data_{offset,size} indicate the location and size of the perf record
|
||||
+ * buffer within the mmapped area.
|
||||
+ */
|
||||
+ __u64 data_head; /* head in the data section */
|
||||
+ __u64 data_tail; /* user-space written tail */
|
||||
+ __u64 data_offset; /* where the buffer starts */
|
||||
+ __u64 data_size; /* data buffer size */
|
||||
+
|
||||
+ /*
|
||||
+ * AUX area is defined by aux_{offset,size} fields that should be set
|
||||
+ * by the userspace, so that
|
||||
+ *
|
||||
+ * aux_offset >= data_offset + data_size
|
||||
+ *
|
||||
+ * prior to mmap()ing it. Size of the mmap()ed area should be aux_size.
|
||||
+ *
|
||||
+ * Ring buffer pointers aux_{head,tail} have the same semantics as
|
||||
+ * data_{head,tail} and same ordering rules apply.
|
||||
+ */
|
||||
+ __u64 aux_head;
|
||||
+ __u64 aux_tail;
|
||||
+ __u64 aux_offset;
|
||||
+ __u64 aux_size;
|
||||
+};
|
||||
+#endif // PERF_ATTR_SIZE_VER5
|
||||
+#endif // PERF_ATTR_SIZE_VER5_BUNDLE
|
||||
+
|
||||
struct target_ops;
|
||||
|
||||
#if HAVE_LINUX_PERF_EVENT_H
|
||||
diff --git a/gdbsupport/common.m4 b/gdbsupport/common.m4
|
||||
--- a/gdbsupport/common.m4
|
||||
+++ b/gdbsupport/common.m4
|
||||
@@ -168,7 +168,7 @@ AC_DEFUN([GDB_AC_COMMON], [
|
||||
AC_PREPROC_IFELSE([AC_LANG_SOURCE([[
|
||||
#include <linux/perf_event.h>
|
||||
#ifndef PERF_ATTR_SIZE_VER5
|
||||
- # error
|
||||
+ // error // PERF_ATTR_SIZE_VER5_BUNDLE is not available here - Fedora+RHEL
|
||||
#endif
|
||||
]])], [perf_event=yes], [perf_event=no])
|
||||
if test "$perf_event" != yes; then
|
752
gdb-orphanripper.c
Normal file
752
gdb-orphanripper.c
Normal file
@ -0,0 +1,752 @@
|
||||
/*
|
||||
* Copyright 2006-2007 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 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Reap any leftover children possibly holding file descriptors.
|
||||
* Children are identified by the stale file descriptor or PGID / SID.
|
||||
* Both can be missed but only the stale file descriptors are important for us.
|
||||
* PGID / SID may be set by the children on their own.
|
||||
* If we fine a candidate we kill it will all its process tree (grandchildren).
|
||||
* The child process is run with `2>&1' redirection (due to forkpty(3)).
|
||||
* 2007-07-10 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
*/
|
||||
|
||||
/* For getpgid(2). */
|
||||
#define _GNU_SOURCE 1
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
#include <pty.h>
|
||||
#include <poll.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#define LENGTH(x) (sizeof (x) / sizeof (*(x)))
|
||||
|
||||
static const char *progname;
|
||||
|
||||
static volatile pid_t child;
|
||||
|
||||
static void signal_chld (int signo)
|
||||
{
|
||||
}
|
||||
|
||||
static volatile int signal_alrm_hit = 0;
|
||||
|
||||
static void signal_alrm (int signo)
|
||||
{
|
||||
signal_alrm_hit = 1;
|
||||
}
|
||||
|
||||
static char childptyname[LINE_MAX];
|
||||
|
||||
static void print_child_error (const char *reason, char **argv)
|
||||
{
|
||||
char **sp;
|
||||
|
||||
fprintf (stderr, "%s: %d %s:", progname, (int) child, reason);
|
||||
for (sp = argv; *sp != NULL; sp++)
|
||||
{
|
||||
fputc (' ', stderr);
|
||||
fputs (*sp, stderr);
|
||||
}
|
||||
fputc ('\n', stderr);
|
||||
}
|
||||
|
||||
static int read_out (int amaster)
|
||||
{
|
||||
char buf[LINE_MAX];
|
||||
ssize_t buf_got;
|
||||
|
||||
buf_got = read (amaster, buf, sizeof buf);
|
||||
if (buf_got == 0)
|
||||
return 0;
|
||||
/* Weird but at least after POLLHUP we get EIO instead of just EOF. */
|
||||
if (buf_got == -1 && errno == EIO)
|
||||
return 0;
|
||||
if (buf_got == -1 && errno == EAGAIN)
|
||||
return 0;
|
||||
if (buf_got < 0)
|
||||
{
|
||||
perror ("read (amaster)");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
if (write (STDOUT_FILENO, buf, buf_got) != buf_got)
|
||||
{
|
||||
perror ("write(2)");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* kill (child, 0) == 0 sometimes even when CHILD's state is already "Z". */
|
||||
|
||||
static int child_exited (void)
|
||||
{
|
||||
char buf[200];
|
||||
int fd, i, retval;
|
||||
ssize_t got;
|
||||
char state[3];
|
||||
|
||||
snprintf (buf, sizeof (buf), "/proc/%ld/stat", (long) child);
|
||||
fd = open (buf, O_RDONLY);
|
||||
if (fd == -1)
|
||||
{
|
||||
perror ("open (/proc/CHILD/stat)");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
got = read (fd, buf, sizeof(buf));
|
||||
if (got <= 0)
|
||||
{
|
||||
perror ("read (/proc/CHILD/stat)");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
if (close (fd) != 0)
|
||||
{
|
||||
perror ("close (/proc/CHILD/stat)");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
/* RHEL-5 does not support %ms. */
|
||||
i = sscanf (buf, "%*d%*s%2s", state);
|
||||
if (i != 1)
|
||||
{
|
||||
perror ("sscanf (/proc/CHILD/stat)");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
retval = strcmp (state, "Z") == 0;
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int spawn (char **argv, int timeout)
|
||||
{
|
||||
pid_t child_got;
|
||||
int status, amaster, i, rc;
|
||||
struct sigaction act;
|
||||
sigset_t set;
|
||||
struct termios termios;
|
||||
unsigned alarm_orig;
|
||||
|
||||
/* We do not use signal(2) to be sure we do not have SA_RESTART. */
|
||||
memset (&act, 0, sizeof (act));
|
||||
act.sa_handler = signal_chld;
|
||||
i = sigemptyset (&act.sa_mask);
|
||||
assert (i == 0);
|
||||
act.sa_flags = 0; /* !SA_RESTART */
|
||||
i = sigaction (SIGCHLD, &act, NULL);
|
||||
assert (i == 0);
|
||||
|
||||
i = sigemptyset (&set);
|
||||
assert (i == 0);
|
||||
i = sigaddset (&set, SIGCHLD);
|
||||
assert (i == 0);
|
||||
i = sigprocmask (SIG_SETMASK, &set, NULL);
|
||||
assert (i == 0);
|
||||
|
||||
/* With TERMP passed as NULL we get "\n" -> "\r\n". */
|
||||
termios.c_iflag = IGNBRK | IGNPAR;
|
||||
termios.c_oflag = 0;
|
||||
termios.c_cflag = CS8 | CREAD | CLOCAL | HUPCL | B9600;
|
||||
termios.c_lflag = IEXTEN | NOFLSH;
|
||||
memset (termios.c_cc, _POSIX_VDISABLE, sizeof (termios.c_cc));
|
||||
termios.c_cc[VTIME] = 0;
|
||||
termios.c_cc[VMIN ] = 1;
|
||||
cfmakeraw (&termios);
|
||||
#ifdef FLUSHO
|
||||
/* Workaround a readline deadlock bug in _get_tty_settings(). */
|
||||
termios.c_lflag &= ~FLUSHO;
|
||||
#endif
|
||||
child = forkpty (&amaster, childptyname, &termios, NULL);
|
||||
switch (child)
|
||||
{
|
||||
case -1:
|
||||
perror ("forkpty(3)");
|
||||
exit (EXIT_FAILURE);
|
||||
case 0:
|
||||
/* Do not replace STDIN as inferiors query its termios. */
|
||||
#if 0
|
||||
i = close (STDIN_FILENO);
|
||||
assert (i == 0);
|
||||
i = open ("/dev/null", O_RDONLY);
|
||||
assert (i == STDIN_FILENO);
|
||||
#endif
|
||||
|
||||
i = sigemptyset (&set);
|
||||
assert (i == 0);
|
||||
i = sigprocmask (SIG_SETMASK, &set, NULL);
|
||||
assert (i == 0);
|
||||
|
||||
/* Do not setpgrp(2) in the parent process as the process-group
|
||||
is shared for the whole sh(1) pipeline we could be a part
|
||||
of. The process-group is set according to PID of the first
|
||||
command in the pipeline.
|
||||
We would rip even vi(1) in the case of:
|
||||
./orphanripper sh -c 'sleep 1&' | vi -
|
||||
*/
|
||||
/* Do not setpgrp(2) as our pty would not be ours and we would
|
||||
get `SIGSTOP' later, particularly after spawning gdb(1).
|
||||
setsid(3) was already executed by forkpty(3) and it would fail if
|
||||
executed again. */
|
||||
if (getpid() != getpgrp ())
|
||||
{
|
||||
perror ("getpgrp(2)");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
execvp (argv[0], argv);
|
||||
perror ("execvp(2)");
|
||||
exit (EXIT_FAILURE);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
i = fcntl (amaster, F_SETFL, O_RDWR | O_NONBLOCK);
|
||||
if (i != 0)
|
||||
{
|
||||
perror ("fcntl (amaster, F_SETFL, O_NONBLOCK)");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* We do not use signal(2) to be sure we do not have SA_RESTART. */
|
||||
act.sa_handler = signal_alrm;
|
||||
i = sigaction (SIGALRM, &act, NULL);
|
||||
assert (i == 0);
|
||||
|
||||
alarm_orig = alarm (timeout);
|
||||
assert (alarm_orig == 0);
|
||||
|
||||
i = sigemptyset (&set);
|
||||
assert (i == 0);
|
||||
|
||||
while (!signal_alrm_hit)
|
||||
{
|
||||
struct pollfd pollfd;
|
||||
|
||||
pollfd.fd = amaster;
|
||||
pollfd.events = POLLIN;
|
||||
i = ppoll (&pollfd, 1, NULL, &set);
|
||||
if (i == -1 && errno == EINTR)
|
||||
{
|
||||
if (child_exited ())
|
||||
break;
|
||||
/* Non-CHILD child may have exited. */
|
||||
continue;
|
||||
}
|
||||
assert (i == 1);
|
||||
/* Data available? Process it first. */
|
||||
if (pollfd.revents & POLLIN)
|
||||
{
|
||||
if (!read_out (amaster))
|
||||
{
|
||||
fprintf (stderr, "%s: Unexpected EOF\n", progname);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
if (pollfd.revents & POLLHUP)
|
||||
break;
|
||||
if ((pollfd.revents &= ~POLLIN) != 0)
|
||||
{
|
||||
fprintf (stderr, "%s: ppoll(2): revents 0x%x\n", progname,
|
||||
(unsigned) pollfd.revents);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
/* Child exited? */
|
||||
if (child_exited ())
|
||||
break;
|
||||
}
|
||||
|
||||
if (signal_alrm_hit)
|
||||
{
|
||||
i = kill (child, SIGKILL);
|
||||
assert (i == 0);
|
||||
}
|
||||
else
|
||||
alarm (0);
|
||||
|
||||
/* WNOHANG still could fail. */
|
||||
child_got = waitpid (child, &status, 0);
|
||||
if (child != child_got)
|
||||
{
|
||||
fprintf (stderr, "waitpid (%d) = %d: %m\n", (int) child, (int) child_got);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
if (signal_alrm_hit)
|
||||
{
|
||||
char *buf;
|
||||
|
||||
if (asprintf (&buf, "Timed out after %d seconds", timeout) != -1)
|
||||
{
|
||||
print_child_error (buf, argv);
|
||||
free (buf);
|
||||
}
|
||||
rc = 128 + SIGALRM;
|
||||
}
|
||||
else if (WIFEXITED (status))
|
||||
rc = WEXITSTATUS (status);
|
||||
else if (WIFSIGNALED (status))
|
||||
{
|
||||
print_child_error (strsignal (WTERMSIG (status)), argv);
|
||||
rc = 128 + WTERMSIG (status);
|
||||
}
|
||||
else if (WIFSTOPPED (status))
|
||||
{
|
||||
fprintf (stderr, "waitpid (%d): WIFSTOPPED - WSTOPSIG is %d\n",
|
||||
(int) child, WSTOPSIG (status));
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "waitpid (%d): !WIFEXITED (%d)\n", (int) child, status);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Not used in fact. */
|
||||
i = sigprocmask (SIG_SETMASK, &set, NULL);
|
||||
assert (i == 0);
|
||||
|
||||
/* Do not unset O_NONBLOCK as a stale child (the whole purpose of this
|
||||
program) having open its output pty would block us in read_out. */
|
||||
#if 0
|
||||
i = fcntl (amaster, F_SETFL, O_RDONLY /* !O_NONBLOCK */);
|
||||
if (i != 0)
|
||||
{
|
||||
perror ("fcntl (amaster, F_SETFL, O_RDONLY /* !O_NONBLOCK */)");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
while (read_out (amaster));
|
||||
|
||||
/* Do not close the master FD as the child would have `/dev/pts/23 (deleted)'
|
||||
entries which are not expected (and expecting ` (deleted)' would be
|
||||
a race. */
|
||||
#if 0
|
||||
i = close (amaster);
|
||||
if (i != 0)
|
||||
{
|
||||
perror ("close (forkpty ()'s amaster)");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Detected commandline may look weird due to a race:
|
||||
Original command:
|
||||
./orphanripper sh -c 'sleep 1&' &
|
||||
Correct output:
|
||||
[1] 29610
|
||||
./orphanripper: Killed -9 orphan PID 29612 (PGID 29611): sleep 1
|
||||
Raced output (sh(1) child still did not update its argv[]):
|
||||
[1] 29613
|
||||
./orphanripper: Killed -9 orphan PID 29615 (PGID 29614): sh -c sleep 1&
|
||||
We could delay a bit before ripping the children. */
|
||||
static const char *read_cmdline (pid_t pid)
|
||||
{
|
||||
char cmdline_fname[32];
|
||||
static char cmdline[LINE_MAX];
|
||||
int fd;
|
||||
ssize_t got;
|
||||
char *s;
|
||||
|
||||
if (snprintf (cmdline_fname, sizeof cmdline_fname, "/proc/%d/cmdline",
|
||||
(int) pid) < 0)
|
||||
return NULL;
|
||||
fd = open (cmdline_fname, O_RDONLY);
|
||||
if (fd == -1)
|
||||
{
|
||||
/* It may have already exited - ENOENT. */
|
||||
#if 0
|
||||
fprintf (stderr, "%s: open (\"%s\"): %m\n", progname, cmdline_fname);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
got = read (fd, cmdline, sizeof (cmdline) - 1);
|
||||
if (got == -1)
|
||||
fprintf (stderr, "%s: read (\"%s\"): %m\n", progname,
|
||||
cmdline_fname);
|
||||
if (close (fd) != 0)
|
||||
fprintf (stderr, "%s: close (\"%s\"): %m\n", progname,
|
||||
cmdline_fname);
|
||||
if (got < 0)
|
||||
return NULL;
|
||||
/* Convert '\0' argument delimiters to spaces. */
|
||||
for (s = cmdline; s < cmdline + got; s++)
|
||||
if (!*s)
|
||||
*s = ' ';
|
||||
/* Trim the trailing spaces (typically single '\0'->' '). */
|
||||
while (s > cmdline && isspace (s[-1]))
|
||||
s--;
|
||||
*s = 0;
|
||||
return cmdline;
|
||||
}
|
||||
|
||||
static int dir_scan (const char *dirname,
|
||||
int (*callback) (struct dirent *dirent, const char *pathname))
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *dirent;
|
||||
int rc = 0;
|
||||
|
||||
dir = opendir (dirname);
|
||||
if (dir == NULL)
|
||||
{
|
||||
if (errno == EACCES || errno == ENOENT)
|
||||
return rc;
|
||||
fprintf (stderr, "%s: opendir (\"%s\"): %m\n", progname, dirname);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
while ((errno = 0, dirent = readdir (dir)))
|
||||
{
|
||||
char pathname[LINE_MAX];
|
||||
int pathname_len;
|
||||
|
||||
pathname_len = snprintf (pathname, sizeof pathname, "%s/%s",
|
||||
dirname, dirent->d_name);
|
||||
if (pathname_len <= 0 || pathname_len >= (int) sizeof pathname)
|
||||
{
|
||||
fprintf (stderr, "entry file name too long: `%s' / `%s'\n",
|
||||
dirname, dirent->d_name);
|
||||
continue;
|
||||
}
|
||||
/* RHEL-4.5 on s390x never fills in D_TYPE. */
|
||||
if (dirent->d_type == DT_UNKNOWN)
|
||||
{
|
||||
struct stat statbuf;
|
||||
int i;
|
||||
|
||||
/* We are not interested in the /proc/PID/fd/ links targets. */
|
||||
i = lstat (pathname, &statbuf);
|
||||
if (i == -1)
|
||||
{
|
||||
if (errno == EACCES || errno == ENOENT)
|
||||
continue;
|
||||
fprintf (stderr, "%s: stat (\"%s\"): %m\n", progname, pathname);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
if (S_ISDIR (statbuf.st_mode))
|
||||
dirent->d_type = DT_DIR;
|
||||
if (S_ISLNK (statbuf.st_mode))
|
||||
dirent->d_type = DT_LNK;
|
||||
/* No other D_TYPE types used in this code. */
|
||||
}
|
||||
rc = (*callback) (dirent, pathname);
|
||||
if (rc != 0)
|
||||
{
|
||||
errno = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (errno != 0)
|
||||
{
|
||||
fprintf (stderr, "%s: readdir (\"%s\"): %m\n", progname, dirname);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
if (closedir (dir) != 0)
|
||||
{
|
||||
fprintf (stderr, "%s: closedir (\"%s\"): %m\n", progname, dirname);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int fd_fs_scan (pid_t pid, int (*func) (pid_t pid, const char *link))
|
||||
{
|
||||
char dirname[64];
|
||||
|
||||
if (snprintf (dirname, sizeof dirname, "/proc/%d/fd", (int) pid) < 0)
|
||||
{
|
||||
perror ("snprintf(3)");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int callback (struct dirent *dirent, const char *pathname)
|
||||
{
|
||||
char buf[LINE_MAX];
|
||||
ssize_t buf_len;
|
||||
|
||||
if ((dirent->d_type != DT_DIR && dirent->d_type != DT_LNK)
|
||||
|| (dirent->d_type == DT_DIR && strcmp (dirent->d_name, ".") != 0
|
||||
&& strcmp (dirent->d_name, "..") != 0)
|
||||
|| (dirent->d_type == DT_LNK && strspn (dirent->d_name, "0123456789")
|
||||
!= strlen (dirent->d_name)))
|
||||
{
|
||||
fprintf (stderr, "Unexpected entry \"%s\" (d_type %u)"
|
||||
" on readdir (\"%s\"): %m\n",
|
||||
dirent->d_name, (unsigned) dirent->d_type, dirname);
|
||||
return 0;
|
||||
}
|
||||
if (dirent->d_type == DT_DIR)
|
||||
return 0;
|
||||
buf_len = readlink (pathname, buf, sizeof buf - 1);
|
||||
if (buf_len <= 0 || buf_len >= (ssize_t) sizeof buf - 1)
|
||||
{
|
||||
if (errno != ENOENT && errno != EACCES)
|
||||
fprintf (stderr, "Error reading link \"%s\": %m\n", pathname);
|
||||
return 0;
|
||||
}
|
||||
buf[buf_len] = 0;
|
||||
return (*func) (pid, buf);
|
||||
}
|
||||
|
||||
return dir_scan (dirname, callback);
|
||||
}
|
||||
|
||||
static void pid_fs_scan (void (*func) (pid_t pid, void *data), void *data)
|
||||
{
|
||||
int callback (struct dirent *dirent, const char *pathname)
|
||||
{
|
||||
if (dirent->d_type != DT_DIR
|
||||
|| strspn (dirent->d_name, "0123456789") != strlen (dirent->d_name))
|
||||
return 0;
|
||||
(*func) (atoi (dirent->d_name), data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dir_scan ("/proc", callback);
|
||||
}
|
||||
|
||||
static int rip_check_ptyname (pid_t pid, const char *link)
|
||||
{
|
||||
assert (pid != getpid ());
|
||||
|
||||
return strcmp (link, childptyname) == 0;
|
||||
}
|
||||
|
||||
struct pid
|
||||
{
|
||||
struct pid *next;
|
||||
pid_t pid;
|
||||
};
|
||||
static struct pid *pid_list;
|
||||
|
||||
static int pid_found (pid_t pid)
|
||||
{
|
||||
struct pid *entry;
|
||||
|
||||
for (entry = pid_list; entry != NULL; entry = entry->next)
|
||||
if (entry->pid == pid)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Single pass is not enough, a (multithreaded) process was seen to survive.
|
||||
Repeated killing of the same process is not enough, zombies can be killed.
|
||||
*/
|
||||
static int cleanup_acted;
|
||||
|
||||
static void pid_record (pid_t pid)
|
||||
{
|
||||
struct pid *entry;
|
||||
|
||||
if (pid_found (pid))
|
||||
return;
|
||||
cleanup_acted = 1;
|
||||
|
||||
entry = malloc (sizeof (*entry));
|
||||
if (entry == NULL)
|
||||
{
|
||||
fprintf (stderr, "%s: malloc: %m\n", progname);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
entry->pid = pid;
|
||||
entry->next = pid_list;
|
||||
pid_list = entry;
|
||||
}
|
||||
|
||||
static void pid_forall (void (*func) (pid_t pid))
|
||||
{
|
||||
struct pid *entry;
|
||||
|
||||
for (entry = pid_list; entry != NULL; entry = entry->next)
|
||||
(*func) (entry->pid);
|
||||
}
|
||||
|
||||
/* Returns 0 on failure. */
|
||||
static pid_t pid_get_parent (pid_t pid)
|
||||
{
|
||||
char fname[64];
|
||||
FILE *f;
|
||||
char line[LINE_MAX];
|
||||
pid_t retval = 0;
|
||||
|
||||
if (snprintf (fname, sizeof fname, "/proc/%d/status", (int) pid) < 0)
|
||||
{
|
||||
perror ("snprintf(3)");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
f = fopen (fname, "r");
|
||||
if (f == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
while (errno = 0, fgets (line, sizeof line, f) == line)
|
||||
{
|
||||
if (strncmp (line, "PPid:\t", sizeof "PPid:\t" - 1) != 0)
|
||||
continue;
|
||||
retval = atoi (line + sizeof "PPid:\t" - 1);
|
||||
errno = 0;
|
||||
break;
|
||||
}
|
||||
if (errno != 0)
|
||||
{
|
||||
fprintf (stderr, "%s: fgets (\"%s\"): %m\n", progname, fname);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
if (fclose (f) != 0)
|
||||
{
|
||||
fprintf (stderr, "%s: fclose (\"%s\"): %m\n", progname, fname);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void killtree (pid_t pid);
|
||||
|
||||
static void killtree_pid_fs_scan (pid_t pid, void *data)
|
||||
{
|
||||
pid_t parent_pid = *(pid_t *) data;
|
||||
|
||||
/* Do not optimize it as we could miss some newly spawned processes.
|
||||
Always traverse all the leaves. */
|
||||
#if 0
|
||||
/* Optimization. */
|
||||
if (pid_found (pid))
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (pid_get_parent (pid) != parent_pid)
|
||||
return;
|
||||
|
||||
killtree (pid);
|
||||
}
|
||||
|
||||
static void killtree (pid_t pid)
|
||||
{
|
||||
pid_record (pid);
|
||||
pid_fs_scan (killtree_pid_fs_scan, &pid);
|
||||
}
|
||||
|
||||
static void rip_pid_fs_scan (pid_t pid, void *data)
|
||||
{
|
||||
pid_t pgid;
|
||||
|
||||
/* Shouldn't happen. */
|
||||
if (pid == getpid ())
|
||||
return;
|
||||
|
||||
/* Check both PGID and the stale file descriptors. */
|
||||
pgid = getpgid (pid);
|
||||
if (pgid == child
|
||||
|| fd_fs_scan (pid, rip_check_ptyname) != 0)
|
||||
killtree (pid);
|
||||
}
|
||||
|
||||
static void killproc (pid_t pid)
|
||||
{
|
||||
const char *cmdline;
|
||||
|
||||
cmdline = read_cmdline (pid);
|
||||
/* Avoid printing the message for already gone processes. */
|
||||
if (kill (pid, 0) != 0 && errno == ESRCH)
|
||||
return;
|
||||
if (cmdline == NULL)
|
||||
cmdline = "<error>";
|
||||
fprintf (stderr, "%s: Killed -9 orphan PID %d: %s\n", progname, (int) pid, cmdline);
|
||||
if (kill (pid, SIGKILL) == 0)
|
||||
cleanup_acted = 1;
|
||||
else if (errno != ESRCH)
|
||||
fprintf (stderr, "%s: kill (%d, SIGKILL): %m\n", progname, (int) pid);
|
||||
/* RHEL-3 kernels cannot SIGKILL a `T (stopped)' process. */
|
||||
kill (pid, SIGCONT);
|
||||
/* Do not waitpid(2) as it cannot be our direct descendant and it gets
|
||||
cleaned up by init(8). */
|
||||
#if 0
|
||||
pid_t pid_got;
|
||||
pid_got = waitpid (pid, NULL, 0);
|
||||
if (pid != pid_got)
|
||||
{
|
||||
fprintf (stderr, "%s: waitpid (%d) != %d: %m\n", progname,
|
||||
(int) pid, (int) pid_got);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void rip (void)
|
||||
{
|
||||
cleanup_acted = 0;
|
||||
do
|
||||
{
|
||||
if (cleanup_acted)
|
||||
usleep (1000000 / 10);
|
||||
cleanup_acted = 0;
|
||||
pid_fs_scan (rip_pid_fs_scan, NULL);
|
||||
pid_forall (killproc);
|
||||
}
|
||||
while (cleanup_acted);
|
||||
}
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
int timeout = 0;
|
||||
int rc;
|
||||
|
||||
progname = *argv++;
|
||||
argc--;
|
||||
|
||||
if (argc < 1 || strcmp (*argv, "-h") == 0
|
||||
|| strcmp (*argv, "--help") == 0)
|
||||
{
|
||||
puts ("Syntax: orphanripper [-t <seconds>] <execvp(3) commandline>");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
if ((*argv)[0] == '-' && (*argv)[1] == 't')
|
||||
{
|
||||
char *timeout_s = NULL;
|
||||
|
||||
if ((*argv)[2] == 0)
|
||||
timeout_s = *++argv;
|
||||
else if (isdigit ((*argv)[2]))
|
||||
timeout_s = (*argv) + 2;
|
||||
if (timeout_s != NULL)
|
||||
{
|
||||
long l;
|
||||
char *endptr;
|
||||
|
||||
argv++;
|
||||
l = strtol (timeout_s, &endptr, 0);
|
||||
timeout = l;
|
||||
if ((endptr != NULL && *endptr != 0) || timeout < 0 || timeout != l)
|
||||
{
|
||||
fprintf (stderr, "%s: Invalid timeout value: %s\n", progname,
|
||||
timeout_s);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rc = spawn (argv, timeout);
|
||||
rip ();
|
||||
return rc;
|
||||
}
|
447
gdb-python-finishbreakpoint-update.patch
Normal file
447
gdb-python-finishbreakpoint-update.patch
Normal file
@ -0,0 +1,447 @@
|
||||
From adfcabe4cc43766996a61bdf08ce1e9db7f18dcc 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
|
||||
|
||||
[gdb/python] FinishBreakPoint update
|
||||
|
||||
I.
|
||||
|
||||
Consider the python gdb.FinishBreakpoint class, an extension of the
|
||||
gdb.Breakpoint class.
|
||||
|
||||
It sets a temporary breakpoint on the return address of a frame.
|
||||
|
||||
This type of breakpoints is thread-specific.
|
||||
|
||||
II.
|
||||
|
||||
If the FinishBreakpoint is hit, it is deleted, and the method return_value
|
||||
can be used to get the value returned by the function.
|
||||
|
||||
Let's demonstrate this:
|
||||
...
|
||||
$ cat -n test.c
|
||||
1 int foo (int a) { return a + 2; }
|
||||
2 int main () { return foo (1); }
|
||||
$ gcc -g test.c
|
||||
$ gdb -q -batch a.out -ex "set trace-commands on" -ex "tbreak foo" -ex run \
|
||||
-ex "python bp = gdb.FinishBreakpoint()" -ex "info breakpoints" \
|
||||
-ex continue -ex "info breakpoints" -ex "python print (bp.return_value)"
|
||||
+tbreak foo
|
||||
Temporary breakpoint 1 at 0x40049e: file test.c, line 1.
|
||||
+run
|
||||
|
||||
Temporary breakpoint 1, foo (a=1) at test.c:1
|
||||
1 int foo (int a) { return a + 2; }
|
||||
+python bp = gdb.FinishBreakpoint()
|
||||
Temporary breakpoint 2 at 0x4004b4: file test.c, line 2.
|
||||
+info breakpoints
|
||||
Num Type Disp Enb Address What
|
||||
2 breakpoint del y 0x004004b4 in main at test.c:2 thread 1
|
||||
stop only in thread 1
|
||||
+continue
|
||||
|
||||
Temporary breakpoint 2, 0x004004b4 in main () at test.c:2
|
||||
2 int main () { return foo (1); }
|
||||
+info breakpoints
|
||||
No breakpoints or watchpoints.
|
||||
+python print (bp.return_value)
|
||||
3
|
||||
...
|
||||
|
||||
III.
|
||||
|
||||
Another possibility is that the FinishBreakpoint is not hit, because the
|
||||
function did not terminate, f.i. because of longjmp, C++ exceptions, or GDB
|
||||
return command.
|
||||
|
||||
Let's demonstrate this, using C++ exceptions:
|
||||
...
|
||||
$ cat -n test.c
|
||||
1 int foo (int a) { throw 1; return a + 2; }
|
||||
2 int main () {
|
||||
3 try { return foo (1); } catch (...) {};
|
||||
4 return 1;
|
||||
5 }
|
||||
$ g++ -g test.c
|
||||
$ gdb -q -batch a.out -ex "set trace-commands on" -ex "tbreak foo" -ex run \
|
||||
-ex "python bp = gdb.FinishBreakpoint()" -ex "info breakpoints" \
|
||||
-ex continue -ex "info breakpoints" -ex "python print (bp.return_value)"
|
||||
+tbreak foo
|
||||
Temporary breakpoint 1 at 0x400712: file test.c, line 1.
|
||||
+run
|
||||
|
||||
Temporary breakpoint 1, foo (a=1) at test.c:1
|
||||
1 int foo (int a) { throw 1; return a + 2; }
|
||||
+python bp = gdb.FinishBreakpoint()
|
||||
Temporary breakpoint 2 at 0x400742: file test.c, line 3.
|
||||
+info breakpoints
|
||||
Num Type Disp Enb Address What
|
||||
2 breakpoint del y 0x00400742 in main() at test.c:3 thread 1
|
||||
stop only in thread 1
|
||||
+continue
|
||||
[Inferior 1 (process 25269) exited with code 01]
|
||||
Thread-specific breakpoint 2 deleted - thread 1 no longer in the thread list.
|
||||
+info breakpoints
|
||||
No breakpoints or watchpoints.
|
||||
+python print (bp.return_value)
|
||||
None
|
||||
...
|
||||
|
||||
Indeed, we do not hit the FinishBreakpoint. Instead, it's deleted when the
|
||||
thread disappears, like any other thread-specific breakpoint.
|
||||
|
||||
I think this is a bug: the deletion is meant to be handled by FinishBreakpoint
|
||||
itself.
|
||||
|
||||
IV.
|
||||
|
||||
Fix aforementioned bug by:
|
||||
- adding an observer of the thread_exit event in FinishBreakpoint
|
||||
- making sure that this observer is called before the
|
||||
remove_threaded_breakpoints observer of that same event.
|
||||
|
||||
This changes the behaviour to:
|
||||
...
|
||||
+continue
|
||||
[Inferior 1 (process 30256) exited with code 01]
|
||||
+info breakpoints
|
||||
No breakpoints or watchpoints.
|
||||
+python print (bp.return_value)
|
||||
None
|
||||
...
|
||||
|
||||
V.
|
||||
|
||||
An out_of_scope callback can be defined to make this more verbose:
|
||||
...
|
||||
$ cat fbp.py
|
||||
class FBP(gdb.FinishBreakpoint):
|
||||
def __init__(self):
|
||||
gdb.FinishBreakpoint.__init__(self)
|
||||
|
||||
def out_of_scope(self):
|
||||
try:
|
||||
frame = gdb.selected_frame ()
|
||||
sal = frame.find_sal ()
|
||||
print ("out_of_scope triggered at %s:%s"
|
||||
% (sal.symtab.fullname(), sal.line))
|
||||
except gdb.error as e:
|
||||
print ("out_of_scope triggered at thread/inferior exit")
|
||||
...
|
||||
and using that gets us:
|
||||
...
|
||||
+continue
|
||||
[Inferior 1 (process 30742) exited with code 01]
|
||||
out_of_scope triggered at thread/inferior exit
|
||||
+info breakpoints
|
||||
No breakpoints or watchpoints.
|
||||
+python print (bp.return_value)
|
||||
None
|
||||
...
|
||||
|
||||
VI.
|
||||
|
||||
This out_of_scope event can be triggered earlier than inferior/thread exit.
|
||||
|
||||
Let's demonstrate this:
|
||||
...
|
||||
$ cat -n test.c
|
||||
1 int bar (int a) { throw 1; return a + 2; }
|
||||
2 int foo (int a) {
|
||||
3 int res = a;
|
||||
4 try
|
||||
5 {
|
||||
6 res += bar (1);
|
||||
7 }
|
||||
8 catch (...)
|
||||
9 {
|
||||
10 }
|
||||
11 return res;
|
||||
12 }
|
||||
13 int main () {
|
||||
14 int res = 0;
|
||||
15 res += foo (1);
|
||||
16 res += 2;
|
||||
17 return res * 2;
|
||||
18 }
|
||||
$ g++ -g test.c
|
||||
$ gdb -q -batch -ex "source fbp.py" a.out -ex "set trace-commands on" \
|
||||
-ex "tbreak bar" -ex run -ex "python bp = FBP()" -ex "info breakpoints" \
|
||||
-ex "tbreak 16" -ex continue -ex "info breakpoints" \
|
||||
-ex "python print (bp.return_value)"
|
||||
+tbreak bar
|
||||
Temporary breakpoint 1 at 0x400712: file test.c, line 1.
|
||||
+run
|
||||
|
||||
Temporary breakpoint 1, bar (a=1) at test.c:1
|
||||
1 int bar (int a) { throw 1; return a + 2; }
|
||||
+python bp = FBP()
|
||||
Temporary breakpoint 2 at 0x40074f: file test.c, line 6.
|
||||
+info breakpoints
|
||||
Num Type Disp Enb Address What
|
||||
2 breakpoint del y 0x0040074f in foo(int) at test.c:6 thread 1
|
||||
stop only in thread 1
|
||||
+tbreak 16
|
||||
Temporary breakpoint 3 at 0x400784: file test.c, line 16.
|
||||
+continue
|
||||
|
||||
Temporary breakpoint 3, main () at test.c:16
|
||||
16 res += 2;
|
||||
out_of_scope triggered at /home/vries/gdb_versions/devel/test.c:16
|
||||
+info breakpoints
|
||||
No breakpoints or watchpoints.
|
||||
+python print (bp.return_value)
|
||||
None
|
||||
...
|
||||
|
||||
Note that the out_of_scope event triggers at the breakpoint we set at
|
||||
test.c:16. If we'd set that breakpoint at line 17, the out_of_scope event
|
||||
would trigger at line 17 instead.
|
||||
|
||||
Also note that it can't be triggered earlier, say by setting the breakpoint in
|
||||
foo at line 11. We would get instead "out_of_scope triggered at
|
||||
thread/inferior exit".
|
||||
|
||||
VII.
|
||||
|
||||
Now consider a reduced version of
|
||||
src/gdb/testsuite/gdb.python/py-finish-breakpoint2.cc:
|
||||
...
|
||||
$ cat -n test.c
|
||||
1 #include <iostream>
|
||||
2
|
||||
3 void
|
||||
4 throw_exception_1 (int e)
|
||||
5 {
|
||||
6 throw new int (e);
|
||||
7 }
|
||||
8
|
||||
9 int
|
||||
10 main (void)
|
||||
11 {
|
||||
12 int i;
|
||||
13 try
|
||||
14 {
|
||||
15 throw_exception_1 (10);
|
||||
16 }
|
||||
17 catch (const int *e)
|
||||
18 {
|
||||
19 std::cerr << "Exception #" << *e << std::endl;
|
||||
20 }
|
||||
21 i += 1;
|
||||
22
|
||||
23 return i;
|
||||
24 }
|
||||
$ g++ -g test.c
|
||||
...
|
||||
|
||||
Now let's try to see if the FinishBreakPoint triggers:
|
||||
...
|
||||
$ gdb -q -batch -ex "source fbp.py" a.out -ex "set trace-commands on" \
|
||||
-ex "tbreak throw_exception_1" -ex run -ex "python bp = FBP()" \
|
||||
-ex "info breakpoints" -ex continue -ex "info breakpoints" \
|
||||
-ex "python print (bp.return_value)"
|
||||
+tbreak throw_exception_1
|
||||
Temporary breakpoint 1 at 0x400bd5: file test.c, line 6.
|
||||
+run
|
||||
|
||||
Temporary breakpoint 1, throw_exception_1 (e=10) at test.c:6
|
||||
6 throw new int (e);
|
||||
+python bp = FBP()
|
||||
Temporary breakpoint 2 at 0x400c2f: file test.c, line 21.
|
||||
+info breakpoints
|
||||
Num Type Disp Enb Address What
|
||||
2 breakpoint del y 0x00400c2f in main() at test.c:21 thread 1
|
||||
stop only in thread 1
|
||||
+continue
|
||||
Exception #10
|
||||
|
||||
Temporary breakpoint 2, main () at test.c:21
|
||||
21 i += 1;
|
||||
+info breakpoints
|
||||
No breakpoints or watchpoints.
|
||||
+python print (bp.return_value)
|
||||
None
|
||||
...
|
||||
|
||||
Surprisingly, it did. The explanation is that FinishBreakPoint is really a
|
||||
frame-return-address breakpoint, and that address happens to be at line 21,
|
||||
which is still executed after the throw in throw_exception_1.
|
||||
|
||||
Interestingly, with -m32 the FinishBreakPoint doesn't trigger, because the
|
||||
frame-return-address happens to be an instruction which is part of line 15.
|
||||
|
||||
VIII.
|
||||
|
||||
In conclusion, the FinishBreakpoint is a frame-return-address breakpoint.
|
||||
|
||||
After being set, either:
|
||||
- it triggers, or
|
||||
- an out-of-scope event will be generated.
|
||||
|
||||
If an out-of-scope event is generated, it will be due to incomplete function
|
||||
termination.
|
||||
|
||||
OTOH, incomplete function termination does not guarantee an out-of-scope event
|
||||
instead of hitting the breakpoint.
|
||||
|
||||
IX.
|
||||
|
||||
The documentation states that 'A finish breakpoint is a temporary breakpoint
|
||||
set at the return address of a frame, based on the finish command'.
|
||||
|
||||
It's indeed somewhat similar to the finish command, at least in the sense that
|
||||
both may stop at the frame-return-address.
|
||||
|
||||
But the finish command can accurately detect function termination.
|
||||
|
||||
And the finish command will stop at any other address that is the first
|
||||
address not in the original function.
|
||||
|
||||
The documentation needs updating to accurately describe what it does.
|
||||
|
||||
X.
|
||||
|
||||
A better implementation of a finish breakpoint would be one that borrows from
|
||||
the finish command implementation. That one:
|
||||
- installs a thread_fsm, and
|
||||
- continues
|
||||
|
||||
A finish breakpoint would do the same minus the continue, but it requires gdb
|
||||
to handle multiple thread_fsms at a time (because other commands may wish to
|
||||
install their own thread_fsm), which AFAICT is not supported yet.
|
||||
|
||||
XI.
|
||||
|
||||
This patch repairs a minor part of the functionality, and updates
|
||||
documentation and test-cases to match actual behaviour.
|
||||
|
||||
The question remains how useful the functionality is, as it is now
|
||||
( see f.i. discussion at
|
||||
https://sourceware.org/pipermail/gdb-patches/2021-January/175290.html ).
|
||||
Perhaps it would be better to deprecate this in a follow-up patch in some form
|
||||
or another, say by disabling it by default and introducing a maintenance
|
||||
command that switches it on, with the warning that it is deprecated.
|
||||
|
||||
Tested on x86_64-linux with native and target board unix/-m32, by rebuilding
|
||||
and running the test-cases:
|
||||
- gdb.python/py-finish-breakpoint.exp
|
||||
- gdb.python/py-finish-breakpoint2.exp
|
||||
---
|
||||
gdb/breakpoint.c | 10 ++++++++++
|
||||
gdb/doc/python.texi | 6 ++++--
|
||||
gdb/python/py-finishbreakpoint.c | 20 +++++++++++++++++++
|
||||
.../gdb.python/py-finish-breakpoint2.exp | 1 +
|
||||
4 files changed, 35 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
|
||||
index db7d2e6a8e5..01f187ca4fe 100644
|
||||
--- a/gdb/breakpoint.c
|
||||
+++ b/gdb/breakpoint.c
|
||||
@@ -14683,6 +14683,10 @@ breakpoint_free_objfile (struct objfile *objfile)
|
||||
|
||||
static struct cmd_list_element *enablebreaklist = NULL;
|
||||
|
||||
+#if HAVE_PYTHON
|
||||
+extern gdb::observers::token bpfinishpy_handle_thread_exit_observer_token;
|
||||
+#endif
|
||||
+
|
||||
/* See breakpoint.h. */
|
||||
|
||||
cmd_list_element *commands_cmd_element = nullptr;
|
||||
@@ -15243,8 +15247,14 @@ This is useful for formatted output in user-defined commands."));
|
||||
|
||||
gdb::observers::about_to_proceed.attach (breakpoint_about_to_proceed,
|
||||
"breakpoint");
|
||||
+#if HAVE_PYTHON
|
||||
+ gdb::observers::thread_exit.attach
|
||||
+ (remove_threaded_breakpoints, "breakpoint",
|
||||
+ { &bpfinishpy_handle_thread_exit_observer_token });
|
||||
+#else
|
||||
gdb::observers::thread_exit.attach (remove_threaded_breakpoints,
|
||||
"breakpoint");
|
||||
+#endif
|
||||
gdb::observers::inferior_removed.attach (remove_inferior_breakpoints,
|
||||
"breakpoint");
|
||||
}
|
||||
diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
|
||||
index 99670cca025..ba414b4e2c3 100644
|
||||
--- a/gdb/doc/python.texi
|
||||
+++ b/gdb/doc/python.texi
|
||||
@@ -6648,7 +6648,7 @@ is not writable.
|
||||
@tindex gdb.FinishBreakpoint
|
||||
|
||||
A finish breakpoint is a temporary breakpoint set at the return address of
|
||||
-a frame, based on the @code{finish} command. @code{gdb.FinishBreakpoint}
|
||||
+a frame. @code{gdb.FinishBreakpoint}
|
||||
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.
|
||||
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
|
||||
-situation, the @code{out_of_scope} callback will be triggered.
|
||||
+situation, the @code{out_of_scope} callback will be triggered. Note
|
||||
+though that improper function termination does not guarantee that the
|
||||
+finish breakpoint is not hit.
|
||||
|
||||
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
|
||||
--- a/gdb/python/py-finishbreakpoint.c
|
||||
+++ b/gdb/python/py-finishbreakpoint.c
|
||||
@@ -433,6 +433,24 @@ bpfinishpy_handle_exit (struct inferior *inf)
|
||||
bpfinishpy_detect_out_scope_cb (&bp, nullptr, true);
|
||||
}
|
||||
|
||||
+/* Attached to `thread_exit' notifications, triggers all the necessary out of
|
||||
+ scope notifications. */
|
||||
+
|
||||
+static void
|
||||
+bpfinishpy_handle_thread_exit (struct thread_info *tp, gdb::optional<ULONGEST>, bool)
|
||||
+{
|
||||
+ gdbpy_enter enter_py (target_gdbarch (), current_language);
|
||||
+
|
||||
+ for (breakpoint &bp : all_breakpoints_safe ())
|
||||
+ {
|
||||
+ if (tp->global_num == bp.thread)
|
||||
+ bpfinishpy_detect_out_scope_cb (&bp, nullptr, true);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+extern gdb::observers::token bpfinishpy_handle_thread_exit_observer_token;
|
||||
+gdb::observers::token bpfinishpy_handle_thread_exit_observer_token;
|
||||
+
|
||||
/* Initialize the Python finish breakpoint code. */
|
||||
|
||||
static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
|
||||
@@ -452,6 +470,8 @@ gdbpy_initialize_finishbreakpoints (void)
|
||||
"py-finishbreakpoint");
|
||||
gdb::observers::inferior_exit.attach (bpfinishpy_handle_exit,
|
||||
"py-finishbreakpoint");
|
||||
+ gdb::observers::thread_exit.attach
|
||||
+ (bpfinishpy_handle_thread_exit, "py-finishbreakpoint");
|
||||
|
||||
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
|
||||
--- 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 } {
|
||||
gdb_test "continue" ".*Breakpoint.* throw_exception_1.*" \
|
||||
"continue to second exception"
|
||||
}
|
||||
+
|
||||
gdb_test "python ExceptionFinishBreakpoint(gdb.newest_frame())" \
|
||||
"init ExceptionFinishBreakpoint" "set FinishBP after the exception again"
|
||||
|
||||
|
||||
base-commit: 6de9111c512de99fd8cb3ea89f9890b1d72f6ef0
|
||||
--
|
||||
2.35.3
|
||||
|
125
gdb-python-fix-gdb.python-py-disasm.exp-on-arm-linux.patch
Normal file
125
gdb-python-fix-gdb.python-py-disasm.exp-on-arm-linux.patch
Normal file
@ -0,0 +1,125 @@
|
||||
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
|
||||
|
@ -0,0 +1,70 @@
|
||||
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
|
||||
|
61
gdb-python-make-gdb.unwindinfo.add_saved_register-mo.patch
Normal file
61
gdb-python-make-gdb.unwindinfo.add_saved_register-mo.patch
Normal file
@ -0,0 +1,61 @@
|
||||
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
|
||||
|
229
gdb-remote-fix-abort-on-remote_close_error.patch
Normal file
229
gdb-remote-fix-abort-on-remote_close_error.patch
Normal file
@ -0,0 +1,229 @@
|
||||
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
|
||||
|
264
gdb-rhbz-2232086-cpp-ify-mapped-symtab.patch
Normal file
264
gdb-rhbz-2232086-cpp-ify-mapped-symtab.patch
Normal file
@ -0,0 +1,264 @@
|
||||
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);
|
||||
|
101
gdb-rhbz-2232086-generate-dwarf-5-index-consistently.patch
Normal file
101
gdb-rhbz-2232086-generate-dwarf-5-index-consistently.patch
Normal file
@ -0,0 +1,101 @@
|
||||
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}\""]
|
230
gdb-rhbz-2232086-generate-gdb-index-consistently.patch
Normal file
230
gdb-rhbz-2232086-generate-gdb-index-consistently.patch
Normal file
@ -0,0 +1,230 @@
|
||||
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.
|
||||
#
|
222
gdb-rhbz-2232086-reduce-size-of-gdb-index.patch
Normal file
222
gdb-rhbz-2232086-reduce-size-of-gdb-index.patch
Normal file
@ -0,0 +1,222 @@
|
||||
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"
|
83
gdb-rhbz-818343-set-solib-absolute-prefix-testcase.patch
Normal file
83
gdb-rhbz-818343-set-solib-absolute-prefix-testcase.patch
Normal file
@ -0,0 +1,83 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Fedora GDB patches <invalid@email.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-rhbz-818343-set-solib-absolute-prefix-testcase.patch
|
||||
|
||||
;; Testcase for `Setting solib-absolute-prefix breaks vDSO' (BZ 818343).
|
||||
;;=fedoratest
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/set-solib-absolute-prefix.c b/gdb/testsuite/gdb.base/set-solib-absolute-prefix.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/set-solib-absolute-prefix.c
|
||||
@@ -0,0 +1,26 @@
|
||||
+/* Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
+
|
||||
+ This file is part of GDB.
|
||||
+
|
||||
+ This program is free software; you can redistribute it and/or modify
|
||||
+ it under the terms of the GNU General Public License as published by
|
||||
+ the Free Software Foundation; either version 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/>. */
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+
|
||||
+int
|
||||
+main (int argc, char *argv[])
|
||||
+{
|
||||
+ printf ("Hello, World.\n");
|
||||
+ abort ();
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.base/set-solib-absolute-prefix.exp b/gdb/testsuite/gdb.base/set-solib-absolute-prefix.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/set-solib-absolute-prefix.exp
|
||||
@@ -0,0 +1,39 @@
|
||||
+# Copyright 2012 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/>.
|
||||
+
|
||||
+set testfile "set-solib-absolute-prefix"
|
||||
+set srcfile ${testfile}.c
|
||||
+
|
||||
+# It is necessary to verify if the binary is 32-bit, so that the system
|
||||
+# call `__kernel_vsyscall' originates from vDSO.
|
||||
+
|
||||
+if { ![is_ilp32_target] } {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+if { [prepare_for_testing $testfile.exp $testfile $srcfile] } {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+if { ![runto_main] } {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+gdb_test "continue" "Program received signal SIGABRT, Aborted.*" \
|
||||
+ "continue until abort"
|
||||
+gdb_test "set solib-absolute-prefix /BOGUS_DIRECT" \
|
||||
+ ".*warning: Unable to find dynamic linker breakpoint function.*" \
|
||||
+ "set solib-absolute-prefix"
|
||||
+gdb_test "bt" "__kernel_vsyscall.*" "backtrace with __kernel_vsyscall"
|
170
gdb-rhbz1007614-memleak-infpy_read_memory-test.patch
Normal file
170
gdb-rhbz1007614-memleak-infpy_read_memory-test.patch
Normal file
@ -0,0 +1,170 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Fedora GDB patches <invalid@email.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-rhbz1007614-memleak-infpy_read_memory-test.patch
|
||||
|
||||
;; Fix 'memory leak in infpy_read_memory()' (RH BZ 1007614)
|
||||
;;=fedoratest
|
||||
|
||||
Original message by Tom Tromey:
|
||||
|
||||
<https://sourceware.org/ml/gdb-patches/2012-03/msg00955.html>
|
||||
Message-ID: <871uoc1va3.fsf@fleche.redhat.com>
|
||||
|
||||
Comment from Sergio Durigan Junior:
|
||||
|
||||
In order to correctly test this patch, I wrote a testcase based on Jan
|
||||
Kratochvil's <gdb/testsuite/gdb.base/gcore-excessive-memory.exp>. The
|
||||
testcase, which can be seen below, tests GDB in order to see if the
|
||||
amount of memory being leaked is minimal, as requested in the bugzilla.
|
||||
It is hard to define what "minimum" is, so I ran the testcase on all
|
||||
supported RHEL architectures and came up with an average.
|
||||
|
||||
commit cc0265cdda9dc7e8665e8bfcf5b4477489daf27c
|
||||
Author: Tom Tromey <tromey@redhat.com>
|
||||
Date: Wed Mar 28 17:38:08 2012 +0000
|
||||
|
||||
* python/py-inferior.c (infpy_read_memory): Remove cleanups and
|
||||
explicitly free 'buffer' on exit paths. Decref 'membuf_object'
|
||||
before returning.
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.python/py-gdb-rhbz1007614-memleak-infpy_read_memory.c b/gdb/testsuite/gdb.python/py-gdb-rhbz1007614-memleak-infpy_read_memory.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.python/py-gdb-rhbz1007614-memleak-infpy_read_memory.c
|
||||
@@ -0,0 +1,27 @@
|
||||
+/* This testcase is part of GDB, the GNU debugger.
|
||||
+
|
||||
+ Copyright 2014 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/>. */
|
||||
+
|
||||
+static struct x
|
||||
+ {
|
||||
+ char unsigned u[4096];
|
||||
+ } x, *px = &x;
|
||||
+
|
||||
+int
|
||||
+main (int argc, char *argv[])
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.python/py-gdb-rhbz1007614-memleak-infpy_read_memory.exp b/gdb/testsuite/gdb.python/py-gdb-rhbz1007614-memleak-infpy_read_memory.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.python/py-gdb-rhbz1007614-memleak-infpy_read_memory.exp
|
||||
@@ -0,0 +1,68 @@
|
||||
+# Copyright 2014 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/>.
|
||||
+
|
||||
+set testfile py-gdb-rhbz1007614-memleak-infpy_read_memory
|
||||
+set srcfile ${testfile}.c
|
||||
+set binfile [standard_output_file ${testfile}]
|
||||
+
|
||||
+if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+if { [skip_python_tests] } { continue }
|
||||
+
|
||||
+set pid_of_gdb [exp_pid -i [board_info host fileid]]
|
||||
+
|
||||
+proc memory_v_pages_get {} {
|
||||
+ global pid_of_gdb
|
||||
+ set fd [open "/proc/$pid_of_gdb/statm"]
|
||||
+ gets $fd line
|
||||
+ close $fd
|
||||
+ # number of pages of virtual memory
|
||||
+ scan $line "%d" drs
|
||||
+ return $drs
|
||||
+}
|
||||
+
|
||||
+if { ![runto_main] } {
|
||||
+ untested $testfile.exp
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+set remote_python_file [remote_download host ${srcdir}/${subdir}/${testfile}.py]
|
||||
+
|
||||
+gdb_test "source ${remote_python_file}" ""
|
||||
+
|
||||
+gdb_test "hello-world" ""
|
||||
+
|
||||
+set kbytes_before [memory_v_pages_get]
|
||||
+verbose -log "kbytes_before = $kbytes_before"
|
||||
+
|
||||
+gdb_test "hello-world" ""
|
||||
+
|
||||
+set kbytes_after [memory_v_pages_get]
|
||||
+verbose -log "kbytes_after = $kbytes_after"
|
||||
+
|
||||
+set kbytes_diff [expr $kbytes_after - $kbytes_before]
|
||||
+verbose -log "kbytes_diff = $kbytes_diff"
|
||||
+
|
||||
+# The value "1000" was calculated by running a few GDB sessions with this
|
||||
+# testcase, and seeing how much (in average) the memory consumption
|
||||
+# increased after the "hello-world" command issued above. The average
|
||||
+# was around 500 bytes, so I chose 1000 as a high estimate.
|
||||
+if { $kbytes_diff > 1000 } {
|
||||
+ fail "there is a memory leak on GDB (RHBZ 1007614)"
|
||||
+} else {
|
||||
+ pass "there is not a memory leak on GDB (RHBZ 1007614)"
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.python/py-gdb-rhbz1007614-memleak-infpy_read_memory.py b/gdb/testsuite/gdb.python/py-gdb-rhbz1007614-memleak-infpy_read_memory.py
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.python/py-gdb-rhbz1007614-memleak-infpy_read_memory.py
|
||||
@@ -0,0 +1,30 @@
|
||||
+# Copyright (C) 2014 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/>.
|
||||
+
|
||||
+class HelloWorld (gdb.Command):
|
||||
+ """Greet the whole world."""
|
||||
+
|
||||
+ def __init__ (self):
|
||||
+ super (HelloWorld, self).__init__ ("hello-world",
|
||||
+ gdb.COMMAND_OBSCURE)
|
||||
+
|
||||
+ def invoke (self, arg, from_tty):
|
||||
+ px = gdb.parse_and_eval("px")
|
||||
+ core = gdb.inferiors()[0]
|
||||
+ for i in range(256 * 1024):
|
||||
+ chunk = core.read_memory(px, 4096)
|
||||
+ print "Hello, World!"
|
||||
+
|
||||
+HelloWorld ()
|
235
gdb-rhbz1084404-ppc64-s390x-wrong-prologue-skip-O2-g-3of3.patch
Normal file
235
gdb-rhbz1084404-ppc64-s390x-wrong-prologue-skip-O2-g-3of3.patch
Normal file
@ -0,0 +1,235 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Fedora GDB patches <invalid@email.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-rhbz1084404-ppc64-s390x-wrong-prologue-skip-O2-g-3of3.patch
|
||||
|
||||
;; Fix '[ppc64] and [s390x] wrong prologue skip on -O2 -g code' (Jan
|
||||
;; Kratochvil, RH BZ 1084404).
|
||||
;;=fedoratest
|
||||
|
||||
These testcases have been created by compiling glibc-2.17-78 on
|
||||
RHEL-7.1 s390x/ppc64 boxes, and then taking the "select.o" file
|
||||
present at $builddir/misc/select.o.
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.arch/ppc64-prologue-skip.exp b/gdb/testsuite/gdb.arch/ppc64-prologue-skip.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.arch/ppc64-prologue-skip.exp
|
||||
@@ -0,0 +1,34 @@
|
||||
+# Copyright 2015 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/>.
|
||||
+
|
||||
+if { ![istarget powerpc64-*linux-*] || ![is_lp64_target] } {
|
||||
+ verbose "Skipping ppc64-prologue-skip.exp"
|
||||
+ return
|
||||
+}
|
||||
+
|
||||
+set testfile "ppc64-prologue-skip"
|
||||
+set uufile "${srcdir}/${subdir}/${testfile}.o.uu"
|
||||
+set ofile "${srcdir}/${subdir}/${testfile}.o"
|
||||
+
|
||||
+if { [catch "system \"uudecode -o ${ofile} ${uufile}\"" ] != 0 } {
|
||||
+ untested "failed uudecode"
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+gdb_exit
|
||||
+gdb_start
|
||||
+gdb_load $ofile
|
||||
+
|
||||
+gdb_test "break ___newselect_nocancel" "Breakpoint $decimal at 0xc: file ../sysdeps/unix/syscall-template.S, line 81." "breakpoint on ___newselect_nocancel"
|
||||
diff --git a/gdb/testsuite/gdb.arch/ppc64-prologue-skip.o.uu b/gdb/testsuite/gdb.arch/ppc64-prologue-skip.o.uu
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.arch/ppc64-prologue-skip.o.uu
|
||||
@@ -0,0 +1,70 @@
|
||||
+begin 644 ppc64-skip-prologue.o.uu
|
||||
+M?T5,1@("`0`````````````!`!4````!````````````````````````````
|
||||
+M``-(``````!```````!``!0`$8%-B-`L"@``0,(`-#@``(Y$```"3.,`('P(
|
||||
+M`J;X`0`0^"'_D4@```%@````Z`$`@#@A`'!\"`.F3H``(/@A_X%]*`*F^2$`
|
||||
+MD/CA`-#XP0#(^*$`P/B!`+CX80"P2````6````#X80!PZ.$`T.C!`,CHH0#`
|
||||
+MZ($`N.AA`+`X``".1````GP``";X80!X^`$`B.AA`'!(```!8````.DA`)#H
|
||||
+M`0"(Z&$`>'TH`Z9\#_$@."$`@$SC`"!+__]@```````,($``````````O``(
|
||||
+M7U]S96QE8W0```````````````````````````!6``(````Y!`'[#@T``0$!
|
||||
+M`0````$```$N+B]S>7-D97!S+W5N:7@``'-Y<V-A;&PM=&5M<&QA=&4N4P`!
|
||||
+M``````D"```````````#T``!`BT3`@D``0$```"/``(`````"`$`````````
|
||||
+M`````````````````"XN+W-Y<V1E<',O=6YI>"]S>7-C86QL+71E;7!L871E
|
||||
+M+E,`+W)O;W0O9VQI8F,O9VQI8F,M,BXQ-RTW."YE;#<N<W)C+V=L:6)C+3(N
|
||||
+M,3<M8S<U.&$V.#8O;6ES8P!'3E4@05,@,BXR,RXU,BXP+C$`@`$!$0`0!A$!
|
||||
+M$@$#"!L()0@3!0`````````````````L``(`````"```````````````````
|
||||
+M````````V``````````````````````````0``````%Z4@`$>$$!&PP!````
|
||||
+M`#`````8`````````+P`20YP$4%^1`X`009!0@Z``4(107Y2$49_20X`!D$&
|
||||
+M1@``````+G-Y;71A8@`N<W1R=&%B`"YS:'-T<G1A8@`N<F5L82YT97AT`"YD
|
||||
+M871A`"YB<W,`+G)E;&$N;W!D`"YN;W1E+D=.52US=&%C:P`N<F5L82YD96)U
|
||||
+M9U]L:6YE`"YR96QA+F1E8G5G7VEN9F\`+F1E8G5G7V%B8G)E=@`N<F5L82YD
|
||||
+M96)U9U]A<F%N9V5S`"YR96QA+F5H7V9R86UE````````````````````````
|
||||
+M````````````````````````````````````````````````````````````
|
||||
+M`````````"`````!``````````8```````````````````!``````````-@`
|
||||
+M```````````````````$```````````````;````!```````````````````
|
||||
+M```````````*>`````````!(````$@````$`````````"``````````8````
|
||||
+M)@````$``````````P```````````````````1@`````````````````````
|
||||
+M``````````$``````````````"P````(``````````,`````````````````
|
||||
+M``$8```````````````````````````````!```````````````V`````0``
|
||||
+M```````#```````````````````!&``````````0````````````````````
|
||||
+M"```````````````,0````0`````````````````````````````"L``````
|
||||
+M````,````!(````%``````````@`````````&````#L````!````````````
|
||||
+M``````````````````$H```````````````````````````````!````````
|
||||
+M``````!0`````0`````````````````````````````!*`````````!:````
|
||||
+M`````````````````0``````````````2P````0`````````````````````
|
||||
+M````````"O``````````&````!(````(``````````@`````````&````&$`
|
||||
+M```!``````````````````````````````&"`````````),`````````````
|
||||
+M```````!``````````````!<````!``````````````````````````````+
|
||||
+M"`````````!@````$@````H`````````"``````````8````;0````$`````
|
||||
+M`````````````````````````A4`````````%`````````````````````$`
|
||||
+M`````````````(`````!``````````````````````````````(P````````
|
||||
+M`#`````````````````````0``````````````![````!```````````````
|
||||
+M```````````````+:``````````P````$@````T`````````"``````````8
|
||||
+M````E`````$``````````@```````````````````F``````````2```````
|
||||
+M``````````````@``````````````(\````$````````````````````````
|
||||
+M``````N8`````````!@````2````#P`````````(`````````!@````1````
|
||||
+M`P`````````````````````````````"J`````````">````````````````
|
||||
+M`````0```````````````0````(`````````````````````````````"$@`
|
||||
+M```````!L````!,````+``````````@`````````&`````D````#````````
|
||||
+M``````````````````````GX`````````'H````````````````````!````
|
||||
+M`````````````````````````````````````````````P```0``````````
|
||||
+M`````````````````P```P```````````````````````````P``!```````
|
||||
+M`````````````````````P``!0```````````````````````````P``"@``
|
||||
+M`````````````````````````P``#````````````````````````````P``
|
||||
+M"````````````````````````````P``#0``````````````````````````
|
||||
+M`P``#P```````````````````````````P``!P``````````````````````
|
||||
+M```!$@``!0```````````````````-@````*$@```0`````````,````````
|
||||
+M`#`````@$``````````````````````````````P$```````````````````
|
||||
+M``````````!*$`````````````````````````````!E(@``!0``````````
|
||||
+M`````````-@```!S(@``!0```````````````````-@`7U]S96QE8W0`7U]?
|
||||
+M;F5W<V5L96-T7VYO8V%N8V5L`%]?<WES8V%L;%]E<G)O<@!?7VQI8F-?96YA
|
||||
+M8FQE7V%S>6YC8V%N8V5L`%]?;&EB8U]D:7-A8FQE7V%S>6YC8V%N8V5L`%]?
|
||||
+M;&EB8U]S96QE8W0`<V5L96-T```````````````````D````#0````H`````
|
||||
+M``````````````!<````#@````H```````````````````"4````#P````H`
|
||||
+M`````````````````````````0```"8````````````````````(````````
|
||||
+M`#,```````````````````!&`````0```"8````````````````````&````
|
||||
+M!@````$````````````````````,````!P````$````````````````````0
|
||||
+M`````0```"8````````````````````8`````0```"8`````````V```````
|
||||
+M```&````!0````$````````````````````0`````0```"8`````````````
|
||||
+6```````<`````0```!H`````````````
|
||||
+`
|
||||
+end
|
||||
diff --git a/gdb/testsuite/gdb.arch/s390x-prologue-skip.exp b/gdb/testsuite/gdb.arch/s390x-prologue-skip.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.arch/s390x-prologue-skip.exp
|
||||
@@ -0,0 +1,34 @@
|
||||
+# Copyright 2015 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/>.
|
||||
+
|
||||
+if { ![istarget s390x-*linux-*] || ![is_lp64_target] } {
|
||||
+ verbose "Skipping s390x-prologue-skip.exp"
|
||||
+ return
|
||||
+}
|
||||
+
|
||||
+set testfile "s390x-prologue-skip"
|
||||
+set uufile "${srcdir}/${subdir}/${testfile}.o.uu"
|
||||
+set ofile "${srcdir}/${subdir}/${testfile}.o"
|
||||
+
|
||||
+if { [catch "system \"uudecode -o ${ofile} ${uufile}\"" ] != 0 } {
|
||||
+ untested "failed uudecode"
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+gdb_exit
|
||||
+gdb_start
|
||||
+gdb_load $ofile
|
||||
+
|
||||
+gdb_test "break select" "Breakpoint $decimal at 0x48: file ../sysdeps/unix/syscall-template.S, line 81." "breakpoint on select"
|
||||
diff --git a/gdb/testsuite/gdb.arch/s390x-prologue-skip.o.uu b/gdb/testsuite/gdb.arch/s390x-prologue-skip.o.uu
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.arch/s390x-prologue-skip.o.uu
|
||||
@@ -0,0 +1,64 @@
|
||||
+begin 644 s390x-prologue-skip.o.uu
|
||||
+M?T5,1@("`0`````````````!`!8````!````````````````````````````
|
||||
+M``+```````!```````!``!(`#^LE\!``).O?\&@`)+D$`.^G^_]@X^#P```D
|
||||
+MP.4`````N00``NLE\+``!`J.N00`TKD$`"#`Y0````"Y!``MZ]_Q"``$I_0`
|
||||
+M"L`0`````+\/$`"G=/_7"HZG2?`!N2$`),"T``````?^````5@`"````.0$!
|
||||
+M^PX-``$!`0$````!```!+BXO<WES9&5P<R]U;FEX``!S>7-C86QL+71E;7!L
|
||||
+M871E+E,``0`````)`@```````````]```0)F$P("``$!````CP`"``````@!
|
||||
+M```````````````````````````N+B]S>7-D97!S+W5N:7@O<WES8V%L;"UT
|
||||
+M96UP;&%T92Y3`"]R;V]T+V=L:6)C+V=L:6)C+3(N,3<M-S@N96PW+G-R8R]G
|
||||
+M;&EB8RTR+C$W+6,W-3AA-C@V+VUI<V,`1TY5($%3(#(N,C,N-3(N,"XQ`(`!
|
||||
+M`1$`$`81`1(!`P@;""4($P4`````````````````+``"``````@`````````
|
||||
+M`````````````````&@`````````````````````````%``````!>E(``7@.
|
||||
+M`1L,#Z`!````````&````!P`````````1`!,CP6.!HT'2`[``@```!`````X
|
||||
+M`````````"```````"YS>6UT86(`+G-T<G1A8@`N<VAS=')T86(`+G)E;&$N
|
||||
+M=&5X=``N9&%T80`N8G-S`"YN;W1E+D=.52US=&%C:P`N<F5L82YD96)U9U]L
|
||||
+M:6YE`"YR96QA+F1E8G5G7VEN9F\`+F1E8G5G7V%B8G)E=@`N<F5L82YD96)U
|
||||
+M9U]A<F%N9V5S`"YR96QA+F5H7V9R86UE````````````````````````````
|
||||
+M````````````````````````````````````````````````````````````
|
||||
+M````````(`````$`````````!@```````````````````$``````````:```
|
||||
+M``````````````````0``````````````!L````$````````````````````
|
||||
+M``````````F``````````&`````0`````0`````````(`````````!@````F
|
||||
+M`````0`````````#````````````````````J```````````````````````
|
||||
+M````````!```````````````+`````@``````````P``````````````````
|
||||
+M`*@```````````````````````````````0``````````````#$````!````
|
||||
+M``````````````````````````"H```````````````````````````````!
|
||||
+M``````````````!&`````0``````````````````````````````J```````
|
||||
+M``!:`````````````````````0``````````````00````0`````````````
|
||||
+M````````````````">``````````&````!`````&``````````@`````````
|
||||
+M&````%<````!``````````````````````````````$"`````````),`````
|
||||
+M```````````````!``````````````!2````!```````````````````````
|
||||
+M```````)^`````````!@````$`````@`````````"``````````8````8P``
|
||||
+M``$``````````````````````````````94`````````%```````````````
|
||||
+M``````$``````````````'8````!``````````````````````````````&P
|
||||
+M`````````#`````````````````````0``````````````!Q````!```````
|
||||
+M```````````````````````*6``````````P````$`````L`````````"```
|
||||
+M```````8````B@````$``````````@```````````````````>``````````
|
||||
+M2`````````````````````@``````````````(4````$````````````````
|
||||
+M``````````````J(`````````#`````0````#0`````````(`````````!@`
|
||||
+M```1`````P`````````````````````````````"*`````````"4````````
|
||||
+M`````````````0```````````````0````(`````````````````````````
|
||||
+M````!T`````````!L````!$````*``````````@`````````&`````D````#
|
||||
+M``````````````````````````````CP`````````(X`````````````````
|
||||
+M```!`````````````````````````````````````````````````P```0``
|
||||
+M`````````````````````````P```P```````````````````````````P``
|
||||
+M!````````````````````````````P``"```````````````````````````
|
||||
+M`P``"@```````````````````````````P``!@``````````````````````
|
||||
+M`````P``"P```````````````````````````P``#0``````````````````
|
||||
+M`````````P``!0`````````````````````````!$```````````````````
|
||||
+M```````````;$``````````````````````````````V$@```0````````!(
|
||||
+M`````````"`````_$`````````````````````````````!7$@```0``````
|
||||
+M``!6`````````!````!I$`````````````````````````````!Y(@```0``
|
||||
+M``````!(`````````"````"'(@```0````````!(`````````"``7U]L:6)C
|
||||
+M7V5N86)L95]A<WEN8V-A;F-E;`!?7VQI8F-?9&ES86)L95]A<WEN8V-A;F-E
|
||||
+M;`!?7W-E;&5C=`!?7VQI8F-?;75L=&EP;&5?=&AR96%D<P!?7W-E;&5C=%]N
|
||||
+M;V-A;F-E;`!?7W-Y<V-A;&Q?97)R;W(`7U]L:6)C7W-E;&5C=`!S96QE8W0`
|
||||
+M````````````'`````H````3``````````(`````````-@````L````3````
|
||||
+M``````(`````````2@````T````3``````````(`````````8@````\````3
|
||||
+M``````````(`````````1@````$````6````````````````````!@````4`
|
||||
+M```$````````````````````#`````8````$````````````````````$```
|
||||
+M``$````6````````````````````&`````$````6`````````&@`````````
|
||||
+M!@````0````$````````````````````$`````$````6````````````````
|
||||
+L````(`````$````%````````````````````/`````$````%`````````$@`
|
||||
+`
|
||||
+end
|
123
gdb-rhbz1149205-catch-syscall-after-fork-test.patch
Normal file
123
gdb-rhbz1149205-catch-syscall-after-fork-test.patch
Normal file
@ -0,0 +1,123 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Fedora GDB patches <invalid@email.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-rhbz1149205-catch-syscall-after-fork-test.patch
|
||||
|
||||
;; Fix '`catch syscall' doesn't work for parent after `fork' is called'
|
||||
;; (Philippe Waroquiers, RH BZ 1149205).
|
||||
;;=fedoratest
|
||||
|
||||
URL: <https://sourceware.org/ml/gdb-patches/2013-05/msg00364.html>
|
||||
Message-ID: <1368136582.30058.7.camel@soleil>
|
||||
|
||||
From: Philippe Waroquiers <philippe dot waroquiers at skynet dot be>
|
||||
To: gdb-patches at sourceware dot org
|
||||
Subject: RFA: fix gdb_assert caused by 'catch signal ...' and fork
|
||||
Date: Thu, 09 May 2013 23:56:22 +0200
|
||||
|
||||
The attached patch fixes a gdb_assert caused by the combination of catch
|
||||
signal and fork:
|
||||
break-catch-sig.c:152: internal-error: signal_catchpoint_remove_location: Assertion `signal_catch_counts[iter] > 0' failed.
|
||||
|
||||
The problem is that the signal_catch_counts is decremented by detach_breakpoints.
|
||||
The fix consists in not detaching breakpoint locations of type bp_loc_other.
|
||||
The patch introduces a new test.
|
||||
|
||||
Comments by Sergio Durigan Junior:
|
||||
|
||||
I addded a specific testcase for this patch, which tests exactly the
|
||||
issue that the customer is facing. This patch does not solve the
|
||||
whole problem of catching a syscall and forking (for more details,
|
||||
see <https://sourceware.org/bugzilla/show_bug.cgi?id=13457>,
|
||||
specifically comment #3), but it solves the issue reported by the
|
||||
customer.
|
||||
|
||||
I also removed the original testcase of this patch, because it
|
||||
relied on "catch signal", which is a command that is not implemented
|
||||
in this version of GDB.
|
||||
|
||||
commit bd9673a4ded96ea5c108601501c8e59003ea1be6
|
||||
Author: Philippe Waroquiers <philippe@sourceware.org>
|
||||
Date: Tue May 21 18:47:05 2013 +0000
|
||||
|
||||
Fix internal error caused by interaction between catch signal and fork
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/gdb-rhbz1149205-catch-syscall-fork.c b/gdb/testsuite/gdb.base/gdb-rhbz1149205-catch-syscall-fork.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/gdb-rhbz1149205-catch-syscall-fork.c
|
||||
@@ -0,0 +1,11 @@
|
||||
+#include <stdio.h>
|
||||
+#include <unistd.h>
|
||||
+
|
||||
+int
|
||||
+main (int argc, char **argv)
|
||||
+{
|
||||
+ if (fork () == 0)
|
||||
+ sleep (1);
|
||||
+ chdir (".");
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.base/gdb-rhbz1149205-catch-syscall-fork.exp b/gdb/testsuite/gdb.base/gdb-rhbz1149205-catch-syscall-fork.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/gdb-rhbz1149205-catch-syscall-fork.exp
|
||||
@@ -0,0 +1,58 @@
|
||||
+# Copyright 2015 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/>.
|
||||
+
|
||||
+if { [is_remote target] || ![isnative] } then {
|
||||
+ continue
|
||||
+}
|
||||
+
|
||||
+set testfile "gdb-rhbz1149205-catch-syscall-fork"
|
||||
+set srcfile ${testfile}.c
|
||||
+set binfile [standard_output_file ${testfile}]
|
||||
+
|
||||
+# Until "catch syscall" is implemented on other targets...
|
||||
+if {![istarget "hppa*-hp-hpux*"] && ![istarget "*-linux*"]} then {
|
||||
+ continue
|
||||
+}
|
||||
+
|
||||
+# This shall be updated whenever 'catch syscall' is implemented
|
||||
+# on some architecture.
|
||||
+#if { ![istarget "i\[34567\]86-*-linux*"]
|
||||
+if { ![istarget "x86_64-*-linux*"] && ![istarget "i\[34567\]86-*-linux*"]
|
||||
+ && ![istarget "powerpc-*-linux*"] && ![istarget "powerpc64-*-linux*"]
|
||||
+ && ![istarget "sparc-*-linux*"] && ![istarget "sparc64-*-linux*"] } {
|
||||
+ continue
|
||||
+}
|
||||
+
|
||||
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
|
||||
+ untested ${testfile}.exp
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+gdb_exit
|
||||
+gdb_start
|
||||
+gdb_reinitialize_dir $srcdir/$subdir
|
||||
+gdb_load $binfile
|
||||
+
|
||||
+if { ![runto_main] } {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+gdb_test "catch syscall chdir" \
|
||||
+ "Catchpoint $decimal \\\(syscall (.)?chdir(.)? \\\[$decimal\\\]\\\)" \
|
||||
+ "catch syscall chdir"
|
||||
+
|
||||
+gdb_test "continue" \
|
||||
+ "Continuing\.\r\n.*\r\nCatchpoint $decimal \\\(call to syscall .?chdir.?.*" \
|
||||
+ "continue from catch syscall after fork"
|
104
gdb-rhbz1261564-aarch64-hw-watchpoint-test.patch
Normal file
104
gdb-rhbz1261564-aarch64-hw-watchpoint-test.patch
Normal file
@ -0,0 +1,104 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Fedora GDB patches <invalid@email.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-rhbz1261564-aarch64-hw-watchpoint-test.patch
|
||||
|
||||
;; [aarch64] Fix hardware watchpoints (RH BZ 1261564).
|
||||
;;=fedoratest
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/rhbz1261564-aarch64-watchpoint.c b/gdb/testsuite/gdb.base/rhbz1261564-aarch64-watchpoint.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/rhbz1261564-aarch64-watchpoint.c
|
||||
@@ -0,0 +1,33 @@
|
||||
+/* This testcase is part of GDB, the GNU debugger.
|
||||
+
|
||||
+ Copyright 2016 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/>. */
|
||||
+
|
||||
+__attribute__((aligned(16))) struct
|
||||
+{
|
||||
+ int var0, var4, var8;
|
||||
+} aligned;
|
||||
+
|
||||
+int
|
||||
+main (void)
|
||||
+{
|
||||
+ aligned.var0 = 1;
|
||||
+ aligned.var4 = 2;
|
||||
+ aligned.var8 = 3;
|
||||
+
|
||||
+ aligned.var4 = aligned.var0;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.base/rhbz1261564-aarch64-watchpoint.exp b/gdb/testsuite/gdb.base/rhbz1261564-aarch64-watchpoint.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/rhbz1261564-aarch64-watchpoint.exp
|
||||
@@ -0,0 +1,53 @@
|
||||
+# Copyright (C) 2016 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/>.
|
||||
+
|
||||
+if { [prepare_for_testing rhbz1261564-aarch64-watchpoint.exp "rhbz1261564-aarch64-watchpoint"] } {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+if { ! [ runto main ] } then { return 0 }
|
||||
+
|
||||
+set test "rwatch aligned.var4"
|
||||
+if [istarget "s390*-*-*"] {
|
||||
+ gdb_test $test {Target does not support this type of hardware watchpoint\.}
|
||||
+ untested "s390* does not support hw read watchpoint"
|
||||
+ return
|
||||
+}
|
||||
+gdb_test $test "Hardware read watchpoint \[0-9\]+: aligned.var4"
|
||||
+
|
||||
+proc checkvar { address } {
|
||||
+ global gdb_prompt
|
||||
+
|
||||
+ set test "p &aligned.var$address"
|
||||
+ gdb_test_multiple $test $test {
|
||||
+ -re " = \\(int \\*\\) 0x\[0-9a-f\]+$address <aligned(\\+\[0-9\]+)?>\r\n$gdb_prompt $" {
|
||||
+ pass $test
|
||||
+ }
|
||||
+ -re "\r\n$gdb_prompt $" {
|
||||
+ untested "$test (unexpected ELF layout)"
|
||||
+ return 0
|
||||
+ }
|
||||
+ }
|
||||
+ return 1
|
||||
+}
|
||||
+if ![checkvar "0"] { return }
|
||||
+if ![checkvar "4"] { return }
|
||||
+if ![checkvar "8"] { return }
|
||||
+
|
||||
+# Assumes: PPC_PTRACE_GETHWDBGINFO::data_bp_alignment == 8
|
||||
+# 'lwz' does read only 4 bytes but the hw watchpoint is 8 bytes wide.
|
||||
+setup_xfail "powerpc*-*-*"
|
||||
+
|
||||
+gdb_continue_to_end
|
77
gdb-rhbz2232086-refactor-selftest-support.patch
Normal file
77
gdb-rhbz2232086-refactor-selftest-support.patch
Normal file
@ -0,0 +1,77 @@
|
||||
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
|
48
gdb-rhbz2250652-avoid-PyOS_ReadlineTState.patch
Normal file
48
gdb-rhbz2250652-avoid-PyOS_ReadlineTState.patch
Normal file
@ -0,0 +1,48 @@
|
||||
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;
|
||||
}
|
||||
|
81
gdb-rhbz2250652-gdbpy_gil.patch
Normal file
81
gdb-rhbz2250652-gdbpy_gil.patch
Normal file
@ -0,0 +1,81 @@
|
||||
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
|
55
gdb-rhbz2261580-intrusive_list-assertion-fix.patch
Normal file
55
gdb-rhbz2261580-intrusive_list-assertion-fix.patch
Normal file
@ -0,0 +1,55 @@
|
||||
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);
|
147
gdb-rhbz947564-findvar-assertion-frame-failed-testcase.patch
Normal file
147
gdb-rhbz947564-findvar-assertion-frame-failed-testcase.patch
Normal file
@ -0,0 +1,147 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Fedora GDB patches <invalid@email.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-rhbz947564-findvar-assertion-frame-failed-testcase.patch
|
||||
|
||||
;; Import regression test for `gdb/findvar.c:417: internal-error:
|
||||
;; read_var_value: Assertion `frame' failed.' (RH BZ 947564) from RHEL 6.5.
|
||||
;;=fedoratest
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.threads/tls-rhbz947564.cc b/gdb/testsuite/gdb.threads/tls-rhbz947564.cc
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.threads/tls-rhbz947564.cc
|
||||
@@ -0,0 +1,53 @@
|
||||
+#include <iostream>
|
||||
+#include <pthread.h>
|
||||
+
|
||||
+class x
|
||||
+ {
|
||||
+ public:
|
||||
+ int n;
|
||||
+
|
||||
+ x() : n(0) {}
|
||||
+ };
|
||||
+
|
||||
+class y
|
||||
+ {
|
||||
+ public:
|
||||
+ int v;
|
||||
+
|
||||
+ y() : v(0) {}
|
||||
+ static __thread x *xp;
|
||||
+ };
|
||||
+
|
||||
+__thread x *y::xp;
|
||||
+
|
||||
+static void
|
||||
+foo (y *yp)
|
||||
+{
|
||||
+ yp->v = 1; /* foo_marker */
|
||||
+}
|
||||
+
|
||||
+static void *
|
||||
+bar (void *unused)
|
||||
+{
|
||||
+ x xinst;
|
||||
+ y::xp= &xinst;
|
||||
+
|
||||
+ y yy;
|
||||
+ foo(&yy);
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+main(int argc, char *argv[])
|
||||
+{
|
||||
+ pthread_t t[2];
|
||||
+
|
||||
+ pthread_create (&t[0], NULL, bar, NULL);
|
||||
+ pthread_create (&t[1], NULL, bar, NULL);
|
||||
+
|
||||
+ pthread_join (t[0], NULL);
|
||||
+ pthread_join (t[1], NULL);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.threads/tls-rhbz947564.exp b/gdb/testsuite/gdb.threads/tls-rhbz947564.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.threads/tls-rhbz947564.exp
|
||||
@@ -0,0 +1,75 @@
|
||||
+# Copyright (C) 2013 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/>. */
|
||||
+
|
||||
+set testfile tls-rhbz947564
|
||||
+set srcfile ${testfile}.cc
|
||||
+set binfile [standard_output_file ${testfile}]
|
||||
+
|
||||
+if [istarget "*-*-linux"] then {
|
||||
+ set target_cflags "-D_MIT_POSIX_THREADS"
|
||||
+} else {
|
||||
+ set target_cflags ""
|
||||
+}
|
||||
+
|
||||
+if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list c++ debug]] != "" } {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+gdb_exit
|
||||
+gdb_start
|
||||
+gdb_reinitialize_dir $srcdir/$subdir
|
||||
+
|
||||
+gdb_load ${binfile}
|
||||
+
|
||||
+if { ![runto_main] } {
|
||||
+ fail "Can't run to function main"
|
||||
+ return 0
|
||||
+}
|
||||
+
|
||||
+gdb_breakpoint "foo"
|
||||
+gdb_continue_to_breakpoint "foo" ".* foo_marker .*"
|
||||
+
|
||||
+proc get_xp_val {try} {
|
||||
+ global expect_out
|
||||
+ global gdb_prompt
|
||||
+ global hex
|
||||
+
|
||||
+ set xp_val ""
|
||||
+ gdb_test_multiple "print *yp" "print yp value" {
|
||||
+ -re { = \{v = 0, static xp = (0x[0-9a-f]+)\}.* } {
|
||||
+ pass "print $try value of *yp"
|
||||
+ set xp_val $expect_out(1,string)
|
||||
+ }
|
||||
+ -re "$gdb_prompt $" {
|
||||
+ fail "print $try value of *yp"
|
||||
+ }
|
||||
+ timeout {
|
||||
+ fail "print $try value of *yp (timeout)"
|
||||
+ }
|
||||
+ }
|
||||
+ return $xp_val
|
||||
+}
|
||||
+
|
||||
+set first_run [get_xp_val "first"]
|
||||
+
|
||||
+gdb_test "continue" "Breakpoint \[0-9\]+, foo \\\(yp=$hex\\\) at.*"
|
||||
+
|
||||
+set second_run [get_xp_val "second"]
|
||||
+
|
||||
+if { $first_run != $second_run } {
|
||||
+ pass "different values for TLS variable"
|
||||
+} else {
|
||||
+ fail "different values for TLS variable"
|
||||
+}
|
16
gdb-rpmlintrc
Normal file
16
gdb-rpmlintrc
Normal file
@ -0,0 +1,16 @@
|
||||
# This line is mandatory to access the configuration functions
|
||||
from Config import *
|
||||
|
||||
# The testresult logs contain part of the build log and thus
|
||||
# necessarily mention the buildroot
|
||||
addFilter ("gdb-testresults.*file-contains-buildroot")
|
||||
|
||||
# Historically libinproctrace was always in gdbserver. It's
|
||||
# LD_PRELOADed into processes, so there are no direct ELF
|
||||
# dependencies to it. It's required on the remote side (where
|
||||
# gdbserver is) so it makes sense to put it in the same package.
|
||||
# This never was a problem for rpmlint before because libinproctrace
|
||||
# had no SONAME, so the check wasn't active. Now it has, so it's checked
|
||||
# and because the gdbserver binary has no direct ELF visible dependency
|
||||
# it's thought to be necessary to follow shlib policy. That's not the case.
|
||||
addFilter ("gdbserver.*shlib-policy-name-error.*libinproctrace")
|
50
gdb-s390-add-arch14-record-replay-support.patch
Normal file
50
gdb-s390-add-arch14-record-replay-support.patch
Normal file
@ -0,0 +1,50 @@
|
||||
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
|
||||
|
162
gdb-simultaneous-step-resume-breakpoint-test.patch
Normal file
162
gdb-simultaneous-step-resume-breakpoint-test.patch
Normal file
@ -0,0 +1,162 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Fedora GDB patches <invalid@email.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-simultaneous-step-resume-breakpoint-test.patch
|
||||
|
||||
;; New test for step-resume breakpoint placed in multiple threads at once.
|
||||
;;=fedoratest
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.threads/simultaneous-step-resume-breakpoint.c b/gdb/testsuite/gdb.threads/simultaneous-step-resume-breakpoint.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.threads/simultaneous-step-resume-breakpoint.c
|
||||
@@ -0,0 +1,79 @@
|
||||
+/* Copyright 2009 Free Software Foundation, Inc.
|
||||
+
|
||||
+ Written by Fred Fish of Cygnus Support
|
||||
+ Contributed by Cygnus Support
|
||||
+
|
||||
+ This file is part of GDB.
|
||||
+
|
||||
+ This program is free software; you can redistribute it and/or modify
|
||||
+ it under the terms of the GNU General Public License as published by
|
||||
+ the Free Software Foundation; either version 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 multiple threads stepping into a .debug_line-less function with
|
||||
+ a breakpoint placed on its return-to-caller point. */
|
||||
+
|
||||
+#include <pthread.h>
|
||||
+#include <assert.h>
|
||||
+#include <unistd.h>
|
||||
+#include <errno.h>
|
||||
+#include <stdio.h>
|
||||
+
|
||||
+#define THREADS 3
|
||||
+
|
||||
+static void *
|
||||
+func (void *unused)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ errno = 0;
|
||||
+ i = 0xdeadf00d;
|
||||
+ i = sleep (THREADS); /* sleep-call */
|
||||
+ if (errno != 0) /* sleep-after */
|
||||
+ perror ("sleep");
|
||||
+
|
||||
+ /* The GDB bug with forgotten step-resume breakpoint could leave stale
|
||||
+ breakpoint on the I assignment making it a nop. */
|
||||
+ if (i == 0xdeadf00d)
|
||||
+ assert (0);
|
||||
+
|
||||
+ assert (i == 0);
|
||||
+
|
||||
+ pthread_exit (NULL);
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+main (void)
|
||||
+{
|
||||
+ pthread_t threads[THREADS];
|
||||
+ int threadi;
|
||||
+
|
||||
+ for (threadi = 0; threadi < THREADS; threadi++)
|
||||
+ {
|
||||
+ int i;
|
||||
+
|
||||
+ i = pthread_create (&threads[threadi], NULL, func, NULL);
|
||||
+ assert (i == 0);
|
||||
+
|
||||
+ i = sleep (1);
|
||||
+ assert (i == 0);
|
||||
+ }
|
||||
+
|
||||
+ for (threadi = 0; threadi < THREADS; threadi++)
|
||||
+ {
|
||||
+ int i;
|
||||
+
|
||||
+ i = pthread_join (threads[threadi], NULL);
|
||||
+ assert (i == 0);
|
||||
+ }
|
||||
+
|
||||
+ return 0; /* final-exit */
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.threads/simultaneous-step-resume-breakpoint.exp b/gdb/testsuite/gdb.threads/simultaneous-step-resume-breakpoint.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.threads/simultaneous-step-resume-breakpoint.exp
|
||||
@@ -0,0 +1,65 @@
|
||||
+# Copyright (C) 2009 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 multiple threads stepping into a .debug_line-less function with
|
||||
+# a breakpoint placed on its return-to-caller point.
|
||||
+
|
||||
+set testfile simultaneous-step-resume-breakpoint
|
||||
+set srcfile ${testfile}.c
|
||||
+set binfile [standard_output_file ${testfile}]
|
||||
+
|
||||
+if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+gdb_exit
|
||||
+gdb_start
|
||||
+gdb_reinitialize_dir $srcdir/$subdir
|
||||
+
|
||||
+# Ensure we have no debuginfo for the `sleep' call itself (=for libc).
|
||||
+gdb_test "set debug-file-directory /DoesNotExist"
|
||||
+
|
||||
+gdb_load ${binfile}
|
||||
+if ![runto_main] {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+# Red Hat vendor patch does set it to "step" by default.
|
||||
+gdb_test "set scheduler-locking off"
|
||||
+
|
||||
+gdb_breakpoint [gdb_get_line_number "final-exit"]
|
||||
+
|
||||
+gdb_breakpoint [gdb_get_line_number "sleep-call"]
|
||||
+gdb_continue_to_breakpoint "sleep-call"
|
||||
+
|
||||
+gdb_test "step" "sleep-call.*" "step thread 1"
|
||||
+gdb_test "step" "sleep-call.*" "step thread 2"
|
||||
+gdb_test "step" "sleep-after.*" "step thread 3"
|
||||
+
|
||||
+set test "first continue"
|
||||
+gdb_test_multiple "continue" $test {
|
||||
+ -re "final-exit.*$gdb_prompt $" {
|
||||
+ # gdb-7.0.
|
||||
+ pass $test
|
||||
+ return
|
||||
+ }
|
||||
+ -re "sleep-after.*$gdb_prompt $" {
|
||||
+ # Fedora/RHEL branch.
|
||||
+ pass $test
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+gdb_test "continue" "sleep-after.*" "second continue"
|
||||
+gdb_test "continue" "final-exit.*" "third continue"
|
125
gdb-symtab-add-producer_is_gas.patch
Normal file
125
gdb-symtab-add-producer_is_gas.patch
Normal file
@ -0,0 +1,125 @@
|
||||
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
|
||||
|
74
gdb-symtab-don-t-defer-backward-refs-inter-cu-intra-.patch
Normal file
74
gdb-symtab-don-t-defer-backward-refs-inter-cu-intra-.patch
Normal file
@ -0,0 +1,74 @@
|
||||
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
|
||||
|
76
gdb-symtab-factor-out-m_deferred_entries-usage.patch
Normal file
76
gdb-symtab-factor-out-m_deferred_entries-usage.patch
Normal file
@ -0,0 +1,76 @@
|
||||
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
|
||||
|
151
gdb-symtab-factor-out-m_die_range_map-usage.patch
Normal file
151
gdb-symtab-factor-out-m_die_range_map-usage.patch
Normal file
@ -0,0 +1,151 @@
|
||||
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
|
||||
|
112
gdb-symtab-fix-dw_tag_inlined_subroutine-entries-in-.patch
Normal file
112
gdb-symtab-fix-dw_tag_inlined_subroutine-entries-in-.patch
Normal file
@ -0,0 +1,112 @@
|
||||
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
|
||||
|
37
gdb-symtab-handle-nullptr-parent-in-parent_map-set_p.patch
Normal file
37
gdb-symtab-handle-nullptr-parent-in-parent_map-set_p.patch
Normal file
@ -0,0 +1,37 @@
|
||||
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
|
||||
|
38
gdb-symtab-keep-track-of-all-parents-for-cooked-inde.patch
Normal file
38
gdb-symtab-keep-track-of-all-parents-for-cooked-inde.patch
Normal file
@ -0,0 +1,38 @@
|
||||
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
|
||||
|
126
gdb-symtab-keep-track-of-processed-dies-in-shard.patch
Normal file
126
gdb-symtab-keep-track-of-processed-dies-in-shard.patch
Normal file
@ -0,0 +1,126 @@
|
||||
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
|
||||
|
31
gdb-symtab-recurse-into-c-dw_tag_subprogram-dies-for.patch
Normal file
31
gdb-symtab-recurse-into-c-dw_tag_subprogram-dies-for.patch
Normal file
@ -0,0 +1,31 @@
|
||||
From 0f53dc7e5cc07e30d11f3f5a0645239535824890 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Thu, 7 Dec 2023 10:36:07 +0100
|
||||
Subject: [PATCH 11/13] [gdb/symtab] Recurse into c++ DW_TAG_subprogram DIEs
|
||||
for cooked index
|
||||
|
||||
Recurse into c++ DW_TAG_subprogram DIEs for cooked index, to add
|
||||
DW_TAG_inlined_subroutine entries.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
---
|
||||
gdb/dwarf2/read.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index e7904532434..de7b655d26c 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -16781,7 +16781,8 @@ cooked_indexer::index_dies (cutu_reader *reader,
|
||||
|
||||
case DW_TAG_subprogram:
|
||||
if ((m_language == language_fortran
|
||||
- || m_language == language_ada)
|
||||
+ || m_language == language_ada
|
||||
+ || m_language == language_cplus)
|
||||
&& this_entry != nullptr)
|
||||
{
|
||||
info_ptr = recurse (reader, info_ptr, this_entry, true);
|
||||
--
|
||||
2.35.3
|
||||
|
70
gdb-symtab-refactor-condition-in-scan_attributes.patch
Normal file
70
gdb-symtab-refactor-condition-in-scan_attributes.patch
Normal file
@ -0,0 +1,70 @@
|
||||
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
|
||||
|
500
gdb-symtab-resolve-deferred-entries-inter-shard-case.patch
Normal file
500
gdb-symtab-resolve-deferred-entries-inter-shard-case.patch
Normal file
@ -0,0 +1,500 @@
|
||||
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
|
||||
|
120
gdb-symtab-resolve-deferred-entries-intra-shard-case.patch
Normal file
120
gdb-symtab-resolve-deferred-entries-intra-shard-case.patch
Normal file
@ -0,0 +1,120 @@
|
||||
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
|
||||
|
224
gdb-symtab-return-correct-reader-for-top-level-cu-in.patch
Normal file
224
gdb-symtab-return-correct-reader-for-top-level-cu-in.patch
Normal file
@ -0,0 +1,224 @@
|
||||
From 84b9218d98eb2ac242fe3afc81598206279f7b13 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Thu, 22 Aug 2024 10:00:27 +0200
|
||||
Subject: [PATCH] [gdb/symtab] Return correct reader for top-level CU in
|
||||
cooked_indexer::ensure_cu_exists
|
||||
|
||||
With the test-case included in this patch, we run into:
|
||||
...
|
||||
$ gdb -q -batch $exec
|
||||
Dwarf Error: Could not find abbrev number 3 in CU at offset 0xdb \
|
||||
[in module $exec]
|
||||
...
|
||||
|
||||
The debug info consists of two CUs:
|
||||
...
|
||||
Compilation Unit @ offset 0xb2:
|
||||
Length: 0x25 (32-bit)
|
||||
Version: 4
|
||||
Abbrev Offset: 0x6c
|
||||
Pointer Size: 8
|
||||
<0><bd>: Abbrev Number: 1 (DW_TAG_compile_unit)
|
||||
<be> DW_AT_language : 2 (non-ANSI C)
|
||||
<1><bf>: Abbrev Number: 2 (DW_TAG_subprogram)
|
||||
<c0> DW_AT_low_pc : 0x4004a7
|
||||
<c8> DW_AT_high_pc : 0x4004b2
|
||||
<d0> DW_AT_specification: <0xe8>
|
||||
<1><d4>: Abbrev Number: 3 (DW_TAG_subprogram)
|
||||
<d5> DW_AT_name : main
|
||||
<1><da>: Abbrev Number: 0
|
||||
Compilation Unit @ offset 0xdb:
|
||||
Length: 0xf (32-bit)
|
||||
Version: 4
|
||||
Abbrev Offset: 0x86
|
||||
Pointer Size: 8
|
||||
<0><e6>: Abbrev Number: 1 (DW_TAG_compile_unit)
|
||||
<e7> DW_AT_language : 2 (non-ANSI C)
|
||||
<1><e8>: Abbrev Number: 2 (DW_TAG_subprogram)
|
||||
<e9> DW_AT_specification: <0xd4>
|
||||
<1><ed>: Abbrev Number: 0
|
||||
...
|
||||
where:
|
||||
- DIE 0xbf in CU@0xb2 contains an inter-CU reference to
|
||||
- DIE 0xe8 in CU@0xdb, which contains an inter-CU reference to
|
||||
- DIE 0xd4 back in CU@0xb2.
|
||||
|
||||
The dwarf error is caused by this bit of code in
|
||||
cooked_indexer::ensure_cu_exists:
|
||||
...
|
||||
if (per_cu == m_per_cu)
|
||||
return reader;
|
||||
...
|
||||
|
||||
The dwarf error happens as follows:
|
||||
- a cutu_reader A is created for CU@0xb2
|
||||
- using cutu_reader A, the cooked index reader starts indexing dies, with
|
||||
m_per_cu set to CU@0xb2
|
||||
- while indexing it scans the attributes of DIE 0xbf and encounters the
|
||||
inter-CU reference to DIE 0xe8
|
||||
- it calls cooked_indexer::ensure_cu_exists, which creates a cutu_reader B for
|
||||
CU@0xdb and returns it
|
||||
- using cutu_reader B, it continues scanning attributes of DIE 0xe8 and
|
||||
encounters the inter-CU reference to DIE 0xd4
|
||||
- it calls cooked_indexer::ensure_cu_exists, the problematic bit is triggered
|
||||
and cutu_reader B is returned
|
||||
- using cutu_reader B, it continues scanning attributes of DIE 0xd4
|
||||
- this goes wrong because:
|
||||
- the attributes of the DIE are encoded using the abbreviation table at
|
||||
offset 0x6c, while
|
||||
- the decoding is done using cutu_reader B which uses the abbreviation table
|
||||
at offset 0x86.
|
||||
|
||||
Fix this by removing the problematic if clause.
|
||||
|
||||
Since cutu_reader A is not preserved in m_index_storage,
|
||||
cooked_indexer::ensure_cu_exists cannot find it there and creates a duplicate
|
||||
cutu_reader C for CU@0xb2. Fix this in process_psymtab_comp_unit by preserving
|
||||
the cutu_reader A as well in m_index_storage.
|
||||
|
||||
Tested on x86_64-linux and aarch64-linux.
|
||||
|
||||
PR symtab/32081
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32081
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
Reported-By: Andreas Schwab <schwab@linux-m68k.org>
|
||||
---
|
||||
gdb/dwarf2/read.c | 35 ++++++-----
|
||||
.../dw2-inter-cu-forth-and-back.exp | 60 +++++++++++++++++++
|
||||
2 files changed, 80 insertions(+), 15 deletions(-)
|
||||
create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-inter-cu-forth-and-back.exp
|
||||
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index 8f2d7a34aef..b72b5fe8c83 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -4880,28 +4880,35 @@ process_psymtab_comp_unit (dwarf2_per_cu_data *this_cu,
|
||||
dwarf2_per_objfile *per_objfile,
|
||||
cooked_index_storage *storage)
|
||||
{
|
||||
- cutu_reader reader (this_cu, per_objfile, nullptr, nullptr, false,
|
||||
- storage->get_abbrev_cache ());
|
||||
+ cutu_reader *reader = storage->get_reader (this_cu);
|
||||
+ if (reader == nullptr)
|
||||
+ {
|
||||
+ cutu_reader new_reader (this_cu, per_objfile, nullptr, nullptr, false,
|
||||
+ storage->get_abbrev_cache ());
|
||||
|
||||
- if (reader.comp_unit_die == nullptr)
|
||||
- return;
|
||||
+ if (new_reader.comp_unit_die == nullptr || new_reader.dummy_p)
|
||||
+ return;
|
||||
|
||||
- if (reader.dummy_p)
|
||||
- {
|
||||
- /* Nothing. */
|
||||
+ std::unique_ptr<cutu_reader> copy
|
||||
+ (new cutu_reader (std::move (new_reader)));
|
||||
+ reader = storage->preserve (std::move (copy));
|
||||
}
|
||||
- else if (this_cu->is_debug_types)
|
||||
- build_type_psymtabs_reader (&reader, storage);
|
||||
- else if (reader.comp_unit_die->tag != DW_TAG_partial_unit)
|
||||
+
|
||||
+ if (reader->comp_unit_die == nullptr || reader->dummy_p)
|
||||
+ return;
|
||||
+
|
||||
+ if (this_cu->is_debug_types)
|
||||
+ build_type_psymtabs_reader (reader, storage);
|
||||
+ else if (reader->comp_unit_die->tag != DW_TAG_partial_unit)
|
||||
{
|
||||
bool nope = false;
|
||||
if (this_cu->scanned.compare_exchange_strong (nope, true))
|
||||
{
|
||||
- prepare_one_comp_unit (reader.cu, reader.comp_unit_die,
|
||||
+ prepare_one_comp_unit (reader->cu, reader->comp_unit_die,
|
||||
language_minimal);
|
||||
gdb_assert (storage != nullptr);
|
||||
- cooked_indexer indexer (storage, this_cu, reader.cu->lang ());
|
||||
- indexer.make_index (&reader);
|
||||
+ cooked_indexer indexer (storage, this_cu, reader->cu->lang ());
|
||||
+ indexer.make_index (reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16280,8 +16287,6 @@ cooked_indexer::ensure_cu_exists (cutu_reader *reader,
|
||||
if (!per_cu->scanned.compare_exchange_strong (nope, true))
|
||||
return nullptr;
|
||||
}
|
||||
- if (per_cu == m_per_cu)
|
||||
- return reader;
|
||||
|
||||
cutu_reader *result = m_index_storage->get_reader (per_cu);
|
||||
if (result == nullptr)
|
||||
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-inter-cu-forth-and-back.exp b/gdb/testsuite/gdb.dwarf2/dw2-inter-cu-forth-and-back.exp
|
||||
new file mode 100644
|
||||
index 00000000000..62674bdb700
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.dwarf2/dw2-inter-cu-forth-and-back.exp
|
||||
@@ -0,0 +1,60 @@
|
||||
+# 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/>.
|
||||
+
|
||||
+# Check that the cooked index reader can handle inter-CU references:
|
||||
+# - DIE1@CU1 -> DIE2@CU2
|
||||
+# - DIE2@CU2 -> DIE3@CU1.
|
||||
+
|
||||
+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 .S
|
||||
+
|
||||
+# Create the DWARF.
|
||||
+set asm_file [standard_output_file $srcfile2]
|
||||
+Dwarf::assemble $asm_file {
|
||||
+ declare_labels label1 label2
|
||||
+
|
||||
+ cu {} {
|
||||
+ compile_unit {{language @DW_LANG_C}} {
|
||||
+ subprogram {
|
||||
+ {MACRO_AT_range { main }}
|
||||
+ {DW_AT_specification %$label1}
|
||||
+ }
|
||||
+
|
||||
+ label2: subprogram {
|
||||
+ {DW_AT_name main}
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ cu {} {
|
||||
+ compile_unit {{language @DW_LANG_C}} {
|
||||
+ label1: subprogram {
|
||||
+ {DW_AT_specification %$label2}
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+if [prepare_for_testing "failed to prepare" $testfile \
|
||||
+ [list $asm_file $srcfile] {nodebug}] {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+# Regression test for PR32081.
|
||||
+gdb_assert { ![regexp -nocase "error:" $gdb_file_cmd_msg] } "No Error message"
|
||||
|
||||
base-commit: 102b31b0b7f62e6e4f685e725f325f2ab6283c2a
|
||||
--
|
||||
2.35.3
|
||||
|
13
gdb-symtab-set-default-dwarf-max-cache-age-1000.patch
Normal file
13
gdb-symtab-set-default-dwarf-max-cache-age-1000.patch
Normal file
@ -0,0 +1,13 @@
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index f8797537108..cb8f86fa352 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -1250,7 +1250,7 @@ struct field_info
|
||||
compilation units. Set this to zero to disable caching. Cache
|
||||
sizes of up to at least twenty will improve startup time for
|
||||
typical inter-CU-reference binaries, at an obvious memory cost. */
|
||||
-static int dwarf_max_cache_age = 5;
|
||||
+static int dwarf_max_cache_age = 1000;
|
||||
static void
|
||||
show_dwarf_max_cache_age (struct ui_file *file, int from_tty,
|
||||
struct cmd_list_element *c, const char *value)
|
278
gdb-symtab-work-around-gas-pr28629.patch
Normal file
278
gdb-symtab-work-around-gas-pr28629.patch
Normal file
@ -0,0 +1,278 @@
|
||||
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
|
||||
|
137
gdb-symtab-work-around-pr-gas-29517-dwarf2-case.patch
Normal file
137
gdb-symtab-work-around-pr-gas-29517-dwarf2-case.patch
Normal file
@ -0,0 +1,137 @@
|
||||
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
|
||||
|
256
gdb-symtab-work-around-pr-gas-29517.patch
Normal file
256
gdb-symtab-work-around-pr-gas-29517.patch
Normal file
@ -0,0 +1,256 @@
|
||||
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
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user