- 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:
Tom de Vries 2025-01-08 13:22:00 +00:00 committed by Git OBS Bridge
commit 4ba6c6a136
181 changed files with 33350 additions and 0 deletions

23
.gitattributes vendored Normal file
View 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
View File

@ -0,0 +1 @@
.osc

117
README.qa Normal file
View 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
View 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
View File

@ -0,0 +1,3 @@
<multibuild>
<package>testsuite</package>
</multibuild>

11
baselibs.conf Normal file
View 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

View 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
View 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

View 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.

View 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

View 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

View 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

View 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

View 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]

View 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

View 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
}

View 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

View 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

View 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}]] != ""

View 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

View 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
View 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

Binary file not shown.

View 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}"

View 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

View 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
+ }
+}

View 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?

View 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"
+ }
+}

View 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
+}

View 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

View 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"

View 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;
};

View 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"));
}

File diff suppressed because it is too large Load Diff

View 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

File diff suppressed because it is too large Load Diff

View 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"

View 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"

View 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"

View 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

View 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

View 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

View 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

View 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

View 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

View 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"

View 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

View 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

View 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

View 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

View 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

View 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"

View 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

View 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

View 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

View 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
View 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.

View 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
View 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
View 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
View 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;
}

View 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

View 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

View File

@ -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

View 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 &reg : *unwind_info->saved_regs)
--
2.35.3

View 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

View 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);

View 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}\""]

View 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.
#

View 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"

View 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"

View 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 ()

View 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

View 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"

View 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

View 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

View 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;
}

View 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

View 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);

View 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
View 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")

View 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

View 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"

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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)

View 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

View 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

View 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