Sync from SUSE:SLFO:Main gdb revision de16ec04e97db4a7d01aef1f6f4187fa
This commit is contained in:
100
add-dwarf_expr_piece.op.patch
Normal file
100
add-dwarf_expr_piece.op.patch
Normal file
@@ -0,0 +1,100 @@
|
||||
From 89cf6ba4a207f5342db58d9e43178ae516cc220e Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Wed, 15 Jan 2025 17:02:00 +0100
|
||||
Subject: [PATCH 23/46] Add dwarf_expr_piece.op
|
||||
|
||||
Add a new field "dwarf_location_atom op" to dwarf_expr_piece to keep track of
|
||||
which dwarf_location_atom caused a dwarf_expr_piece to be added.
|
||||
|
||||
This is used in the following patch.
|
||||
|
||||
Tested on s390x-linux.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
---
|
||||
gdb/dwarf2/expr.c | 10 ++++++----
|
||||
gdb/dwarf2/expr.h | 6 +++++-
|
||||
2 files changed, 11 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/gdb/dwarf2/expr.c b/gdb/dwarf2/expr.c
|
||||
index cb80dbf60b1..03107f90575 100644
|
||||
--- a/gdb/dwarf2/expr.c
|
||||
+++ b/gdb/dwarf2/expr.c
|
||||
@@ -1198,13 +1198,15 @@ dwarf_expr_context::stack_empty_p () const
|
||||
|
||||
/* Add a new piece to the dwarf_expr_context's piece list. */
|
||||
void
|
||||
-dwarf_expr_context::add_piece (ULONGEST size, ULONGEST offset)
|
||||
+dwarf_expr_context::add_piece (ULONGEST size, ULONGEST offset,
|
||||
+ enum dwarf_location_atom op)
|
||||
{
|
||||
dwarf_expr_piece &p = this->m_pieces.emplace_back ();
|
||||
|
||||
p.location = this->m_location;
|
||||
p.size = size;
|
||||
p.offset = offset;
|
||||
+ p.op = op;
|
||||
|
||||
if (p.location == DWARF_VALUE_LITERAL)
|
||||
{
|
||||
@@ -2169,7 +2171,7 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
|
||||
|
||||
/* Record the piece. */
|
||||
op_ptr = safe_read_uleb128 (op_ptr, op_end, &size);
|
||||
- add_piece (8 * size, 0);
|
||||
+ add_piece (8 * size, 0, op);
|
||||
|
||||
/* Pop off the address/regnum, and reset the location
|
||||
type. */
|
||||
@@ -2187,7 +2189,7 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
|
||||
/* Record the piece. */
|
||||
op_ptr = safe_read_uleb128 (op_ptr, op_end, &size);
|
||||
op_ptr = safe_read_uleb128 (op_ptr, op_end, &uleb_offset);
|
||||
- add_piece (size, uleb_offset);
|
||||
+ add_piece (size, uleb_offset, op);
|
||||
|
||||
/* Pop off the address/regnum, and reset the location
|
||||
type. */
|
||||
@@ -2389,7 +2391,7 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
|
||||
pointer, then make a pieced value. This is ok because we can't
|
||||
have implicit pointers in contexts where pieces are invalid. */
|
||||
if (this->m_location == DWARF_VALUE_IMPLICIT_POINTER)
|
||||
- add_piece (8 * this->m_addr_size, 0);
|
||||
+ add_piece (8 * this->m_addr_size, 0, DW_OP_implicit_pointer);
|
||||
|
||||
this->m_recursion_depth--;
|
||||
gdb_assert (this->m_recursion_depth >= 0);
|
||||
diff --git a/gdb/dwarf2/expr.h b/gdb/dwarf2/expr.h
|
||||
index b02cc531640..957c58f30c4 100644
|
||||
--- a/gdb/dwarf2/expr.h
|
||||
+++ b/gdb/dwarf2/expr.h
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "leb128.h"
|
||||
#include "dwarf2/call-site.h"
|
||||
+#include "dwarf2.h"
|
||||
|
||||
struct dwarf2_per_objfile;
|
||||
|
||||
@@ -54,6 +55,9 @@ enum dwarf_value_location
|
||||
/* A piece of an object, as recorded by DW_OP_piece or DW_OP_bit_piece. */
|
||||
struct dwarf_expr_piece
|
||||
{
|
||||
+ /* The DWARF operation for which the piece was created. */
|
||||
+ enum dwarf_location_atom op;
|
||||
+
|
||||
enum dwarf_value_location location;
|
||||
|
||||
union
|
||||
@@ -208,7 +212,7 @@ struct dwarf_expr_context
|
||||
struct type *address_type () const;
|
||||
void push (struct value *value, bool in_stack_memory);
|
||||
bool stack_empty_p () const;
|
||||
- void add_piece (ULONGEST size, ULONGEST offset);
|
||||
+ void add_piece (ULONGEST size, ULONGEST offset, enum dwarf_location_atom op);
|
||||
void execute_stack_op (const gdb_byte *op_ptr, const gdb_byte *op_end);
|
||||
void pop ();
|
||||
struct value *fetch (int n);
|
||||
--
|
||||
2.43.0
|
||||
|
220
add-gdbarch_dwarf2_reg_piece_offset-hook.patch
Normal file
220
add-gdbarch_dwarf2_reg_piece_offset-hook.patch
Normal file
@@ -0,0 +1,220 @@
|
||||
From 29b185c531fcd933da62142debcb088321be7c4c Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Wed, 15 Jan 2025 17:02:00 +0100
|
||||
Subject: [PATCH 24/46] Add gdbarch_dwarf2_reg_piece_offset hook
|
||||
|
||||
In rw_pieced_value, when reading/writing part of a register, DW_OP_piece and
|
||||
DW_OP_bit_piece are handled the same, but the standard tells us:
|
||||
- DW_OP_piece: if the piece is located in a register, but does not occupy the
|
||||
entire register, the placement of the piece within that register is defined
|
||||
by the ABI.
|
||||
- DW_OP_bit_piece: if the location is a register, the offset is from the least
|
||||
significant bit end of the register.
|
||||
|
||||
Add a new hook gdbarch_dwarf2_reg_piece_offset that allows us to define the
|
||||
ABI-specific behaviour for DW_OP_piece.
|
||||
|
||||
The default implementation of the hook is the behaviour of DW_OP_bit_piece, so
|
||||
there should not be any functional changes.
|
||||
|
||||
Tested on s390x-linux.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
---
|
||||
gdb/dwarf2/expr.c | 31 +++++++++++++++++++++++++------
|
||||
gdb/findvar.c | 18 ++++++++++++++++++
|
||||
gdb/gdbarch-gen.h | 8 ++++++++
|
||||
gdb/gdbarch.c | 22 ++++++++++++++++++++++
|
||||
gdb/gdbarch_components.py | 16 ++++++++++++++++
|
||||
gdb/value.h | 2 ++
|
||||
6 files changed, 91 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/gdb/dwarf2/expr.c b/gdb/dwarf2/expr.c
|
||||
index 03107f90575..ece713ee7cd 100644
|
||||
--- a/gdb/dwarf2/expr.c
|
||||
+++ b/gdb/dwarf2/expr.c
|
||||
@@ -211,14 +211,33 @@ rw_pieced_value (value *v, value *from, bool check_optimized)
|
||||
ULONGEST reg_bits = 8 * register_size (arch, gdb_regnum);
|
||||
int optim, unavail;
|
||||
|
||||
- if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG
|
||||
- && p->offset + p->size < reg_bits)
|
||||
+ if (p->offset + p->size < reg_bits)
|
||||
{
|
||||
- /* Big-endian, and we want less than full size. */
|
||||
- bits_to_skip += reg_bits - (p->offset + p->size);
|
||||
+ /* We want less than full size. */
|
||||
+
|
||||
+ if (p->op == DW_OP_piece)
|
||||
+ {
|
||||
+ gdb_assert (p->offset == 0);
|
||||
+
|
||||
+ /* If the piece is located in a register, but does not
|
||||
+ occupy the entire register, the placement of the piece
|
||||
+ within that register is defined by the ABI. */
|
||||
+ bits_to_skip
|
||||
+ += 8 * gdbarch_dwarf2_reg_piece_offset (arch, gdb_regnum,
|
||||
+ p->size / 8);
|
||||
+ }
|
||||
+ else if (p->op == DW_OP_bit_piece)
|
||||
+ {
|
||||
+ /* If the location is a register, the offset is from the
|
||||
+ least significant bit end of the register. */
|
||||
+ if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG)
|
||||
+ bits_to_skip += reg_bits - (p->offset + p->size);
|
||||
+ else
|
||||
+ bits_to_skip += p->offset;
|
||||
+ }
|
||||
+ else
|
||||
+ error (_("Don't know how to get part of implicit pointer"));
|
||||
}
|
||||
- else
|
||||
- bits_to_skip += p->offset;
|
||||
|
||||
this_size = bits_to_bytes (bits_to_skip, this_size_bits);
|
||||
buffer.resize (this_size);
|
||||
diff --git a/gdb/findvar.c b/gdb/findvar.c
|
||||
index df4ab1a28b9..3b20974474a 100644
|
||||
--- a/gdb/findvar.c
|
||||
+++ b/gdb/findvar.c
|
||||
@@ -541,6 +541,24 @@ default_value_from_register (gdbarch *gdbarch, type *type, int regnum,
|
||||
return value;
|
||||
}
|
||||
|
||||
+/* Default implementation of gdbarch_dwarf2_reg_piece_offset. Implements
|
||||
+ DW_OP_bits_piece for DW_OP_piece. */
|
||||
+
|
||||
+ULONGEST
|
||||
+default_dwarf2_reg_piece_offset (gdbarch *gdbarch, int gdb_regnum, ULONGEST size)
|
||||
+{
|
||||
+ ULONGEST reg_size = register_size (gdbarch, gdb_regnum);
|
||||
+ gdb_assert (size <= reg_size);
|
||||
+ if (reg_size == size)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
|
||||
+ return reg_size - size;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
/* VALUE must be an lval_register value. If regnum is the value's
|
||||
associated register number, and len the length of the value's type,
|
||||
read one or more registers in VALUE's frame, starting with register REGNUM,
|
||||
diff --git a/gdb/gdbarch-gen.h b/gdb/gdbarch-gen.h
|
||||
index b982fd7cd09..2e20a9dbccd 100644
|
||||
--- a/gdb/gdbarch-gen.h
|
||||
+++ b/gdb/gdbarch-gen.h
|
||||
@@ -430,6 +430,14 @@ typedef struct value * (gdbarch_value_from_register_ftype) (struct gdbarch *gdba
|
||||
extern struct value * gdbarch_value_from_register (struct gdbarch *gdbarch, struct type *type, int regnum, const frame_info_ptr &this_frame);
|
||||
extern void set_gdbarch_value_from_register (struct gdbarch *gdbarch, gdbarch_value_from_register_ftype *value_from_register);
|
||||
|
||||
+/* For a DW_OP_piece located in a register, but not occupying the
|
||||
+ entire register, return the placement of the piece within that
|
||||
+ register as defined by the ABI. */
|
||||
+
|
||||
+typedef ULONGEST (gdbarch_dwarf2_reg_piece_offset_ftype) (struct gdbarch *gdbarch, int regnum, ULONGEST size);
|
||||
+extern ULONGEST gdbarch_dwarf2_reg_piece_offset (struct gdbarch *gdbarch, int regnum, ULONGEST size);
|
||||
+extern void set_gdbarch_dwarf2_reg_piece_offset (struct gdbarch *gdbarch, gdbarch_dwarf2_reg_piece_offset_ftype *dwarf2_reg_piece_offset);
|
||||
+
|
||||
typedef CORE_ADDR (gdbarch_pointer_to_address_ftype) (struct gdbarch *gdbarch, struct type *type, const gdb_byte *buf);
|
||||
extern CORE_ADDR gdbarch_pointer_to_address (struct gdbarch *gdbarch, struct type *type, const gdb_byte *buf);
|
||||
extern void set_gdbarch_pointer_to_address (struct gdbarch *gdbarch, gdbarch_pointer_to_address_ftype *pointer_to_address);
|
||||
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
|
||||
index 58e9ebbdc59..ed5b5859277 100644
|
||||
--- a/gdb/gdbarch.c
|
||||
+++ b/gdb/gdbarch.c
|
||||
@@ -109,6 +109,7 @@ struct gdbarch
|
||||
gdbarch_register_to_value_ftype *register_to_value = nullptr;
|
||||
gdbarch_value_to_register_ftype *value_to_register = nullptr;
|
||||
gdbarch_value_from_register_ftype *value_from_register = default_value_from_register;
|
||||
+ gdbarch_dwarf2_reg_piece_offset_ftype *dwarf2_reg_piece_offset = default_dwarf2_reg_piece_offset;
|
||||
gdbarch_pointer_to_address_ftype *pointer_to_address = unsigned_pointer_to_address;
|
||||
gdbarch_address_to_pointer_ftype *address_to_pointer = unsigned_address_to_pointer;
|
||||
gdbarch_integer_to_address_ftype *integer_to_address = nullptr;
|
||||
@@ -371,6 +372,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
|
||||
/* Skip verify of value_from_register, invalid_p == 0 */
|
||||
/* Skip verify of pointer_to_address, invalid_p == 0 */
|
||||
/* Skip verify of address_to_pointer, invalid_p == 0 */
|
||||
+ /* Skip verify of dwarf2_reg_piece_offset, invalid_p == 0. */
|
||||
/* Skip verify of integer_to_address, has predicate. */
|
||||
/* Skip verify of return_value, invalid_p == 0 */
|
||||
if ((gdbarch->return_value_as_value == default_gdbarch_return_value) == (gdbarch->return_value == nullptr))
|
||||
@@ -783,6 +785,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
|
||||
gdb_printf (file,
|
||||
"gdbarch_dump: value_from_register = <%s>\n",
|
||||
host_address_to_string (gdbarch->value_from_register));
|
||||
+ gdb_printf (file,
|
||||
+ "gdbarch_dump: dwarf2_reg_piece_offset = <%s>\n",
|
||||
+ host_address_to_string (gdbarch->dwarf2_reg_piece_offset));
|
||||
gdb_printf (file,
|
||||
"gdbarch_dump: pointer_to_address = <%s>\n",
|
||||
host_address_to_string (gdbarch->pointer_to_address));
|
||||
@@ -2573,6 +2578,23 @@ set_gdbarch_value_from_register (struct gdbarch *gdbarch,
|
||||
gdbarch->value_from_register = value_from_register;
|
||||
}
|
||||
|
||||
+ULONGEST
|
||||
+gdbarch_dwarf2_reg_piece_offset (struct gdbarch *gdbarch, int regnum, ULONGEST size)
|
||||
+{
|
||||
+ gdb_assert (gdbarch != NULL);
|
||||
+ gdb_assert (gdbarch->dwarf2_reg_piece_offset != NULL);
|
||||
+ if (gdbarch_debug >= 2)
|
||||
+ gdb_printf (gdb_stdlog, "gdbarch_dwarf2_reg_piece_offset called\n");
|
||||
+ return gdbarch->dwarf2_reg_piece_offset (gdbarch, regnum, size);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+set_gdbarch_dwarf2_reg_piece_offset (struct gdbarch *gdbarch,
|
||||
+ gdbarch_dwarf2_reg_piece_offset_ftype dwarf2_reg_piece_offset)
|
||||
+{
|
||||
+ gdbarch->dwarf2_reg_piece_offset = dwarf2_reg_piece_offset;
|
||||
+}
|
||||
+
|
||||
CORE_ADDR
|
||||
gdbarch_pointer_to_address (struct gdbarch *gdbarch, struct type *type, const gdb_byte *buf)
|
||||
{
|
||||
diff --git a/gdb/gdbarch_components.py b/gdb/gdbarch_components.py
|
||||
index 4006380076d..4a228b5d27c 100644
|
||||
--- a/gdb/gdbarch_components.py
|
||||
+++ b/gdb/gdbarch_components.py
|
||||
@@ -829,6 +829,22 @@ allocate and return a struct value with all value attributes
|
||||
invalid=False,
|
||||
)
|
||||
|
||||
+Method(
|
||||
+ comment="""
|
||||
+For a DW_OP_piece located in a register, but not occupying the
|
||||
+entire register, return the placement of the piece within that
|
||||
+register as defined by the ABI.
|
||||
+""",
|
||||
+ type="ULONGEST",
|
||||
+ name="dwarf2_reg_piece_offset",
|
||||
+ params=[
|
||||
+ ("int", "regnum"),
|
||||
+ ("ULONGEST", "size")
|
||||
+ ],
|
||||
+ predefault="default_dwarf2_reg_piece_offset",
|
||||
+ invalid=False,
|
||||
+)
|
||||
+
|
||||
Method(
|
||||
type="CORE_ADDR",
|
||||
name="pointer_to_address",
|
||||
diff --git a/gdb/value.h b/gdb/value.h
|
||||
index 9d7e88d9433..47df66e0961 100644
|
||||
--- a/gdb/value.h
|
||||
+++ b/gdb/value.h
|
||||
@@ -1128,6 +1128,8 @@ extern value *default_value_from_register (gdbarch *gdbarch, type *type,
|
||||
int regnum,
|
||||
const frame_info_ptr &this_frame);
|
||||
|
||||
+extern ULONGEST default_dwarf2_reg_piece_offset (gdbarch *gdbarch, int regnum, ULONGEST size);
|
||||
+
|
||||
extern struct value *value_from_register (struct type *type, int regnum,
|
||||
const frame_info_ptr &frame);
|
||||
|
||||
--
|
||||
2.43.0
|
||||
|
@@ -1,25 +0,0 @@
|
||||
From 28c32a89ab9ed6caa60dd6fb8e13ef0b447aa779 Mon Sep 17 00:00:00 2001
|
||||
From: Nick Clifton <nickc@redhat.com>
|
||||
Date: Thu, 13 Mar 2025 15:09:49 +0100
|
||||
Subject: [PATCH 12/28] Add note to translators not to translate z/Architecture
|
||||
|
||||
(cherry picked from commit 0d656dfe5b4)
|
||||
---
|
||||
opcodes/s390-dis.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/opcodes/s390-dis.c b/opcodes/s390-dis.c
|
||||
index fca965fbb5d..ebf56c1c7e4 100644
|
||||
--- a/opcodes/s390-dis.c
|
||||
+++ b/opcodes/s390-dis.c
|
||||
@@ -42,6 +42,7 @@ typedef struct
|
||||
static const s390_options_t options[] =
|
||||
{
|
||||
{ "esa" , N_("Disassemble in ESA architecture mode") },
|
||||
+ /* TRANSLATORS: Please do not translate 'z/Architecture' as this is a technical name. */
|
||||
{ "zarch", N_("Disassemble in z/Architecture mode") },
|
||||
{ "insnlength", N_("Print unknown instructions according to "
|
||||
"length from first two bits") },
|
||||
--
|
||||
2.43.0
|
||||
|
@@ -1,53 +0,0 @@
|
||||
From acc7b542a08819bec4aae767de547c531a7ab62e Mon Sep 17 00:00:00 2001
|
||||
From: Aditya Vidyadhar Kamath <Aditya.Kamath1@ibm.com>
|
||||
Date: Mon, 6 Nov 2023 07:26:24 -0600
|
||||
Subject: [PATCH 03/48] Change gdb.base/examine-backwards.exp for AIX.
|
||||
|
||||
In AIX unused or constant variables are collected as garbage by the linker and in the dwarf dump
|
||||
an address with all f's in hexadecimal are assigned. Hence the testcase fails with many failures stating
|
||||
it cannot access memory.
|
||||
|
||||
This patch is a small change to get it working in AIX as well.
|
||||
---
|
||||
gdb/testsuite/gdb.base/examine-backward.c | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/examine-backward.c b/gdb/testsuite/gdb.base/examine-backward.c
|
||||
index e30b58fb005..354c2e2f323 100644
|
||||
--- a/gdb/testsuite/gdb.base/examine-backward.c
|
||||
+++ b/gdb/testsuite/gdb.base/examine-backward.c
|
||||
@@ -36,11 +36,11 @@ literals. The content of each array is the same as followings:
|
||||
TestStrings, to avoid showing garbage when we look for strings
|
||||
backwards from TestStrings. */
|
||||
|
||||
-const unsigned char Barrier[] = {
|
||||
+unsigned char Barrier[] = {
|
||||
0x00,
|
||||
};
|
||||
|
||||
-const unsigned char TestStrings[] = {
|
||||
+unsigned char TestStrings[] = {
|
||||
0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
|
||||
0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
|
||||
0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
|
||||
@@ -54,7 +54,7 @@ const unsigned char TestStrings[] = {
|
||||
0x00
|
||||
};
|
||||
|
||||
-const short TestStringsH[] = {
|
||||
+short TestStringsH[] = {
|
||||
0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048,
|
||||
0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
|
||||
0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
|
||||
@@ -67,7 +67,7 @@ const short TestStringsH[] = {
|
||||
0x0000
|
||||
};
|
||||
|
||||
-const int TestStringsW[] = {
|
||||
+int TestStringsW[] = {
|
||||
0x00000041, 0x00000042, 0x00000043, 0x00000044,
|
||||
0x00000045, 0x00000046, 0x00000047, 0x00000048,
|
||||
0x00000049, 0x0000004a, 0x0000004b, 0x0000004c,
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,30 +0,0 @@
|
||||
From e2d364caa1ddd8b046bd671e71c407522224b42c Mon Sep 17 00:00:00 2001
|
||||
From: Nick Clifton <nickc@redhat.com>
|
||||
Date: Thu, 13 Mar 2025 15:09:46 +0100
|
||||
Subject: [PATCH 05/28] Fix building for the s390 target with clang
|
||||
|
||||
(cherry picked from commit 6c0c7d489bd)
|
||||
---
|
||||
opcodes/s390-opc.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/opcodes/s390-opc.c b/opcodes/s390-opc.c
|
||||
index 0427bd8b2e0..cbfdb3df0b7 100644
|
||||
--- a/opcodes/s390-opc.c
|
||||
+++ b/opcodes/s390-opc.c
|
||||
@@ -262,9 +262,10 @@ const struct s390_operand s390_operands[] =
|
||||
|
||||
};
|
||||
|
||||
-static inline void unused_s390_operands_static_asserts(void)
|
||||
+static inline void ATTRIBUTE_UNUSED
|
||||
+unused_s390_operands_static_asserts (void)
|
||||
{
|
||||
- static_assert(ARRAY_SIZE(s390_operands) - 1 == J32_16);
|
||||
+ static_assert (ARRAY_SIZE (s390_operands) - 1 == J32_16);
|
||||
}
|
||||
|
||||
/* Macros used to form opcodes. */
|
||||
--
|
||||
2.43.0
|
||||
|
144
fix-gdb.ada-o2_float_param.exp-on-s390x-linux.patch
Normal file
144
fix-gdb.ada-o2_float_param.exp-on-s390x-linux.patch
Normal file
@@ -0,0 +1,144 @@
|
||||
From 0ac8e9af3cd6713f4b230e9e335e1398c3161210 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Fri, 10 Jan 2025 21:25:53 +0100
|
||||
Subject: [PATCH 26/46] Fix gdb.ada/O2_float_param.exp on s390x-linux
|
||||
|
||||
With test-case gdb.ada/O2_float_param.exp on s390x-linux, I get:
|
||||
...
|
||||
(gdb) frame^M
|
||||
#0 callee.increment (val=99.0, val@entry=<error reading variable: \
|
||||
register has not been saved in frame>, msg=...) at callee.adb:19^M
|
||||
19 procedure Increment (Val : in out Float; Msg: String) is^M
|
||||
(gdb) FAIL: $exp: scenario=all: frame
|
||||
...
|
||||
|
||||
The frame command calls read_frame_arg to get:
|
||||
- the current value of val, and
|
||||
- the value of val at function entry.
|
||||
|
||||
The first scenario succeeds, and the second scenario fails.
|
||||
|
||||
For context and contrast, let's also investigate the first scenario: getting
|
||||
the current value of val.
|
||||
|
||||
Function parameter val:
|
||||
...
|
||||
<2><b51>: Abbrev Number: 4 (DW_TAG_formal_parameter)
|
||||
<b52> DW_AT_name : val
|
||||
<b58> DW_AT_type : <0xb86>
|
||||
<b5c> DW_AT_location : 0xab (location list)
|
||||
...
|
||||
has location list:
|
||||
...
|
||||
000000ab 0000000001002928 0000000001002967
|
||||
(DW_OP_reg16 (f0))
|
||||
000000be 0000000001002967 0000000001002968
|
||||
(DW_OP_reg24 (f8))
|
||||
000000d1 0000000001002968 0000000001002974
|
||||
(DW_OP_GNU_regval_type: 24 (f8) <0xb29>;
|
||||
DW_OP_GNU_const_type: <0xb29> 4 byte block: 3f 80 0 0 ; DW_OP_plus;
|
||||
DW_OP_stack_value)
|
||||
000000ef 0000000001002974 0000000001002982
|
||||
(DW_OP_GNU_entry_value: (DW_OP_GNU_regval_type: 16 (f0) <0xb29>);
|
||||
DW_OP_GNU_const_type: <0xb29> 4 byte block: 3f 80 0 0 ; DW_OP_plus;
|
||||
DW_OP_stack_value)
|
||||
0000010f <End of list>
|
||||
...
|
||||
and since we're stopped at address 0x1002928:
|
||||
...
|
||||
(gdb) print $pc
|
||||
$1 = (access procedure) 0x1002928 <callee.increment>
|
||||
...
|
||||
we get the value from dwarf register 16.
|
||||
|
||||
The s390x ABI [1] specifies that dwarf register 16 maps onto 8-byte register
|
||||
f0 or 16-byte register v0 (where f0 is part of v0), and in this case (because
|
||||
the v0 register is available) s390_dwarf_reg_to_regnum maps it to v0.
|
||||
|
||||
Val is only 4 bytes:
|
||||
...
|
||||
(gdb) ptype val
|
||||
type = <4-byte float>
|
||||
...
|
||||
and s390_value_from_register takes care to get the value from the correct part
|
||||
of v0.
|
||||
|
||||
The value of v0 is found in the prologue cache, and the value of parameter val
|
||||
is printed.
|
||||
|
||||
Now the second scenario: getting the value of val at function entry.
|
||||
|
||||
FWIW, since we're stopped at function entry, we could simply return the same
|
||||
value, reading the same register, but that's currently not implemented [2].
|
||||
|
||||
Instead we start from the fact that val is in dwarf reg 16 at function entry,
|
||||
and then use call site information:
|
||||
...
|
||||
<4><cf7>: Abbrev Number: 13 (DW_TAG_GNU_call_site)
|
||||
<cf8> DW_AT_low_pc : 0x1002a46
|
||||
<d00> DW_AT_abstract_origin: <0xdda>
|
||||
<5><d04>: Abbrev Number: 12 (DW_TAG_GNU_call_site_parameter)
|
||||
<d05> DW_AT_location : 1 byte block: 60 (DW_OP_reg16 (f0))
|
||||
<d07> DW_AT_GNU_call_site_value: 3 byte block: f5 18 2d \
|
||||
(DW_OP_GNU_regval_type: 24 (f8) <0xc42>)
|
||||
<5><d0b>: Abbrev Number: 12 (DW_TAG_GNU_call_site_parameter)
|
||||
...
|
||||
to conclude that the value we're looking for is in dwarf reg 24, which
|
||||
s390_dwarf_reg_to_regnum maps to v8.
|
||||
|
||||
As before, s390_value_from_register takes care to get the value from the
|
||||
correct part of v8.
|
||||
|
||||
However, v8 is not available in the prologue cache, and we take a different
|
||||
path and end up in s390_unwind_pseudo_register, where v8 and similar
|
||||
(regnum_is_vxr_full) is unhandled, and we get:
|
||||
...
|
||||
return value::allocate_optimized_out (type);
|
||||
...
|
||||
which eventually causes the "error reading variable: register has not been
|
||||
saved in frame".
|
||||
|
||||
Fix this by handling the regnum_is_vxr_full case in
|
||||
s390_unwind_pseudo_register, similar to how that is done in
|
||||
s390_pseudo_register_read.
|
||||
|
||||
Tested on s390x-linux.
|
||||
|
||||
This also fixes test-case gdb.base/savedregs.exp.
|
||||
|
||||
[1] https://github.com/IBM/s390x-abi
|
||||
[2] https://sourceware.org/pipermail/gdb-patches/2024-September/211589.html
|
||||
---
|
||||
gdb/s390-tdep.c | 16 ++++++++++++++++
|
||||
1 file changed, 16 insertions(+)
|
||||
|
||||
diff --git a/gdb/s390-tdep.c b/gdb/s390-tdep.c
|
||||
index a7c58b37276..31730296ef1 100644
|
||||
--- a/gdb/s390-tdep.c
|
||||
+++ b/gdb/s390-tdep.c
|
||||
@@ -2332,6 +2332,22 @@ s390_unwind_pseudo_register (const frame_info_ptr &this_frame, int regnum)
|
||||
return value_cast (type, val);
|
||||
}
|
||||
|
||||
+ if (regnum_is_vxr_full (tdep, regnum))
|
||||
+ {
|
||||
+ struct value *val = value::allocate_register (this_frame, regnum);
|
||||
+
|
||||
+ int reg = regnum - tdep->v0_full_regnum;
|
||||
+ struct value *val1
|
||||
+ = frame_unwind_register_value (this_frame, S390_F0_REGNUM + reg);
|
||||
+ struct value *val2
|
||||
+ = frame_unwind_register_value (this_frame, S390_V0_LOWER_REGNUM + reg);
|
||||
+
|
||||
+ val1->contents_copy (val, 0, 0, 8);
|
||||
+ val2->contents_copy (val, 8, 0, 8);
|
||||
+
|
||||
+ return value_cast (type, val);
|
||||
+ }
|
||||
+
|
||||
return value::allocate_optimized_out (type);
|
||||
}
|
||||
|
||||
--
|
||||
2.43.0
|
||||
|
188
fix-gdb.base-finish-pretty.exp-on-s390x.patch
Normal file
188
fix-gdb.base-finish-pretty.exp-on-s390x.patch
Normal file
@@ -0,0 +1,188 @@
|
||||
From de696a57729423bf643e530fdb638dff6cf3c08b Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Sat, 4 Jan 2025 11:31:02 +0100
|
||||
Subject: [PATCH 21/46] Fix gdb.base/finish-pretty.exp on s390x
|
||||
|
||||
On s390x-linux, with test-case gdb.base/finish-pretty.exp I ran into:
|
||||
...
|
||||
(gdb) finish
|
||||
Run till exit from #0 foo () at finish-pretty.c:28
|
||||
main () at finish-pretty.c:40
|
||||
40 return v.a + v.b;
|
||||
Value returned has type: struct s. Cannot determine contents
|
||||
(gdb) FAIL: $exp: finish foo prettyprinted function result
|
||||
...
|
||||
|
||||
The function being finished is foo, which returns a value of type struct s.
|
||||
|
||||
The ABI [1] specifies:
|
||||
- that the value is returned in a storage buffer allocated by the caller, and
|
||||
- that the address of this buffer is passed as a hidden argument in r2.
|
||||
|
||||
GDB fails to print the value when finishing foo, because it doesn't know the
|
||||
address of the buffer.
|
||||
|
||||
Implement the gdbarch_get_return_buf_addr hook for s390x to fix this.
|
||||
|
||||
This is based on ppc_sysv_get_return_buf_addr, the only other implementation
|
||||
of gdbarch_get_return_buf_addr. For readability I've factored out
|
||||
dwarf_reg_on_entry.
|
||||
|
||||
There is one difference with ppc_sysv_get_return_buf_addr: only
|
||||
NO_ENTRY_VALUE_ERROR is caught. If this patch is approved, I intend to submit
|
||||
a follow-up patch to fix this in ppc_sysv_get_return_buf_addr as well.
|
||||
|
||||
The hook is not guaranteed to work, because it attempts to get the value r2
|
||||
had at function entry.
|
||||
|
||||
The hook can be called after function entry, and the ABI doesn't guarantee
|
||||
that r2 is the same throughout the function.
|
||||
|
||||
Using -fvar-tracking adds debug information, which allows the hook to succeed
|
||||
more often, and indeed after adding this to the test-case, it passes.
|
||||
|
||||
Do likewise in one more test-case.
|
||||
|
||||
Tested on s390x-linux.
|
||||
|
||||
Fixes:
|
||||
- gdb.ada/finish-large.exp
|
||||
- gdb.base/finish-pretty.exp
|
||||
- gdb.base/retval-large-struct.exp
|
||||
- gdb.cp/non-trivial-retval.exp
|
||||
- gdb.ada/array_return.exp
|
||||
|
||||
AFAICT, I've also enabled the hook for s390 and from the ABI I get the
|
||||
impression that it should work, but I haven't been able to test it.
|
||||
|
||||
[1] https://github.com/IBM/s390x-abi
|
||||
---
|
||||
gdb/s390-tdep.c | 58 ++++++++++++++++++++++++
|
||||
gdb/testsuite/gdb.ada/array_return.exp | 8 +++-
|
||||
gdb/testsuite/gdb.base/finish-pretty.exp | 8 +++-
|
||||
3 files changed, 72 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/gdb/s390-tdep.c b/gdb/s390-tdep.c
|
||||
index 4844b7e9bc8..4e7dce70c12 100644
|
||||
--- a/gdb/s390-tdep.c
|
||||
+++ b/gdb/s390-tdep.c
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "trad-frame.h"
|
||||
#include "value.h"
|
||||
#include "inferior.h"
|
||||
+#include "dwarf2/loc.h"
|
||||
|
||||
#include "features/s390-linux32.c"
|
||||
#include "features/s390x-linux64.c"
|
||||
@@ -2119,6 +2120,62 @@ s390_return_value (struct gdbarch *gdbarch, struct value *function,
|
||||
return rvc;
|
||||
}
|
||||
|
||||
+/* Try to get the value of DWARF_REG in FRAME at function entry. If successful,
|
||||
+ return it as value of type VAL_TYPE. */
|
||||
+
|
||||
+static struct value *
|
||||
+dwarf_reg_on_entry (int dwarf_reg, struct type *val_type,
|
||||
+ const frame_info_ptr &frame)
|
||||
+{
|
||||
+ enum call_site_parameter_kind kind = CALL_SITE_PARAMETER_DWARF_REG;
|
||||
+ union call_site_parameter_u kind_u = { .dwarf_reg = dwarf_reg };
|
||||
+
|
||||
+ try
|
||||
+ {
|
||||
+ return value_of_dwarf_reg_entry (val_type, frame, kind, kind_u);
|
||||
+ }
|
||||
+ catch (const gdb_exception_error &e)
|
||||
+ {
|
||||
+ if (e.error == NO_ENTRY_VALUE_ERROR)
|
||||
+ return nullptr;
|
||||
+
|
||||
+ throw;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* Both the 32-bit and 64-bit ABIs specify that values of some types are
|
||||
+ returned in a storage buffer provided by the caller. Return the address of
|
||||
+ that storage buffer, if possible. Implements the
|
||||
+ gdbarch_get_return_buf_addr hook. */
|
||||
+
|
||||
+static CORE_ADDR
|
||||
+s390_get_return_buf_addr (struct type *val_type,
|
||||
+ const frame_info_ptr &cur_frame)
|
||||
+{
|
||||
+ /* The address of the storage buffer is provided as a hidden argument in
|
||||
+ register r2. */
|
||||
+ int dwarf_reg = 2;
|
||||
+
|
||||
+ /* The ABI does not guarantee that the register will not be changed while
|
||||
+ executing the function. Hence, it cannot be assumed that it will still
|
||||
+ contain the address of the storage buffer when execution reaches the end
|
||||
+ of the function.
|
||||
+
|
||||
+ Attempt to determine the value on entry using the DW_OP_entry_value DWARF
|
||||
+ entries. This requires compiling the user program with -fvar-tracking. */
|
||||
+ struct value *val_on_entry
|
||||
+ = dwarf_reg_on_entry (dwarf_reg, lookup_pointer_type (val_type), cur_frame);
|
||||
+
|
||||
+ if (val_on_entry == nullptr)
|
||||
+ {
|
||||
+ warning ("Cannot determine the function return value.\n"
|
||||
+ "Try compiling with -fvar-tracking.");
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ return value_as_address (val_on_entry);
|
||||
+}
|
||||
+
|
||||
/* Frame unwinding. */
|
||||
|
||||
/* Implement the stack_frame_destroyed_p gdbarch method. */
|
||||
@@ -7183,6 +7240,7 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
||||
set_gdbarch_dummy_id (gdbarch, s390_dummy_id);
|
||||
set_gdbarch_frame_align (gdbarch, s390_frame_align);
|
||||
set_gdbarch_return_value (gdbarch, s390_return_value);
|
||||
+ set_gdbarch_get_return_buf_addr (gdbarch, s390_get_return_buf_addr);
|
||||
|
||||
/* Frame handling. */
|
||||
/* Stack grows downward. */
|
||||
diff --git a/gdb/testsuite/gdb.ada/array_return.exp b/gdb/testsuite/gdb.ada/array_return.exp
|
||||
index c6edee11f17..d1fc2ac2c98 100644
|
||||
--- a/gdb/testsuite/gdb.ada/array_return.exp
|
||||
+++ b/gdb/testsuite/gdb.ada/array_return.exp
|
||||
@@ -19,7 +19,13 @@ require allow_ada_tests
|
||||
|
||||
standard_ada_testfile p
|
||||
|
||||
-if {[gdb_compile_ada "${srcfile}" "${binfile}" executable {debug}] != ""} {
|
||||
+set opts {}
|
||||
+lappend opts debug
|
||||
+if { [have_fvar_tracking] } {
|
||||
+ lappend opts "additional_flags=-fvar-tracking"
|
||||
+}
|
||||
+
|
||||
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable $opts] != ""} {
|
||||
return -1
|
||||
}
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/finish-pretty.exp b/gdb/testsuite/gdb.base/finish-pretty.exp
|
||||
index 44f3340f41c..0b6bea6681d 100644
|
||||
--- a/gdb/testsuite/gdb.base/finish-pretty.exp
|
||||
+++ b/gdb/testsuite/gdb.base/finish-pretty.exp
|
||||
@@ -18,7 +18,13 @@
|
||||
|
||||
standard_testfile
|
||||
|
||||
-if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } {
|
||||
+set opts {}
|
||||
+lappend opts debug
|
||||
+if { [have_fvar_tracking] } {
|
||||
+ lappend opts "additional_flags=-fvar-tracking"
|
||||
+}
|
||||
+
|
||||
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile $opts] } {
|
||||
return -1
|
||||
}
|
||||
|
||||
--
|
||||
2.43.0
|
||||
|
187
fix-gdb.base-readnever.exp-on-s390x.patch
Normal file
187
fix-gdb.base-readnever.exp-on-s390x.patch
Normal file
@@ -0,0 +1,187 @@
|
||||
From 1d761604714b32883d2bbc4a5f274fc3e2c668fe Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Thu, 9 Jan 2025 14:32:19 +0100
|
||||
Subject: [PATCH 22/46] Fix gdb.base/readnever.exp on s390x
|
||||
|
||||
On s390x-linux, I run into:
|
||||
...
|
||||
(gdb) backtrace
|
||||
#0 0x000000000100061a in fun_three ()
|
||||
#1 0x000000000100067a in fun_two ()
|
||||
#2 0x000003fffdfa9470 in ?? ()
|
||||
Backtrace stopped: frame did not save the PC
|
||||
(gdb) FAIL: gdb.base/readnever.exp: backtrace
|
||||
...
|
||||
|
||||
This is really due to a problem handling the fun_three frame. When generating
|
||||
a backtrace from fun_two, everying looks ok:
|
||||
...
|
||||
$ gdb -readnever -q -batch outputs/gdb.base/readnever/readnever \
|
||||
-ex "b fun_two" \
|
||||
-ex run \
|
||||
-ex bt
|
||||
...
|
||||
#0 0x0000000001000650 in fun_two ()
|
||||
#1 0x00000000010006b6 in fun_one ()
|
||||
#2 0x00000000010006ee in main ()
|
||||
...
|
||||
|
||||
For reference the frame info with debug info (without -readnever) looks like this:
|
||||
...
|
||||
$ gdb -q -batch outputs/gdb.base/readnever/readnever \
|
||||
-ex "b fun_three" \
|
||||
-ex run \
|
||||
-ex "info frame"
|
||||
...
|
||||
Stack level 0, frame at 0x3fffffff140:
|
||||
pc = 0x1000632 in fun_three (readnever.c:20); saved pc = 0x100067a
|
||||
called by frame at 0x3fffffff1f0
|
||||
source language c.
|
||||
Arglist at 0x3fffffff140, args: a=10, b=49 '1', c=0x3fffffff29c
|
||||
Locals at 0x3fffffff140, Previous frame's sp in v0
|
||||
...
|
||||
|
||||
But with -readnever, like this instead:
|
||||
...
|
||||
Stack level 0, frame at 0x0:
|
||||
pc = 0x100061a in fun_three; saved pc = 0x100067a
|
||||
called by frame at 0x3fffffff140
|
||||
Arglist at 0xffffffffffffffff, args:
|
||||
Locals at 0xffffffffffffffff, Previous frame's sp in r15
|
||||
...
|
||||
|
||||
An obvious difference is the "Previous frame's sp in" v0 vs. r15.
|
||||
|
||||
Looking at the code:
|
||||
...
|
||||
0000000001000608 <fun_three>:
|
||||
1000608: b3 c1 00 2b ldgr %f2,%r11
|
||||
100060c: b3 c1 00 0f ldgr %f0,%r15
|
||||
1000610: e3 f0 ff 50 ff 71 lay %r15,-176(%r15)
|
||||
1000616: b9 04 00 bf lgr %r11,%r15
|
||||
...
|
||||
it becomes clear what is going on. This is an unusual prologue.
|
||||
|
||||
Rather than saving r11 (frame pointer) and r15 (stack pointer) to stack,
|
||||
instead they're saved into call-clobbered floating point registers.
|
||||
|
||||
[ For reference, this is the prologue of fun_two:
|
||||
...
|
||||
0000000001000640 <fun_two>:
|
||||
1000640: eb bf f0 58 00 24 stmg %r11,%r15,88(%r15)
|
||||
1000646: e3 f0 ff 50 ff 71 lay %r15,-176(%r15)
|
||||
100064c: b9 04 00 bf lgr %r11,%r15
|
||||
...
|
||||
where the first instruction stores registers r11 to r15 to stack. ]
|
||||
|
||||
Gdb fails to properly analyze the prologue, which causes the problems getting
|
||||
the frame info.
|
||||
|
||||
Fix this by:
|
||||
- adding handling of the ldgr insn [1] in s390_analyze_prologue, and
|
||||
- recognizing the insn as saving a register in
|
||||
s390_prologue_frame_unwind_cache.
|
||||
|
||||
This gets us instead:
|
||||
...
|
||||
Stack level 0, frame at 0x0:
|
||||
pc = 0x100061a in fun_three; saved pc = 0x100067a
|
||||
called by frame at 0x3fffffff1f0
|
||||
Arglist at 0xffffffffffffffff, args:
|
||||
Locals at 0xffffffffffffffff, Previous frame's sp in f0
|
||||
...
|
||||
and:
|
||||
...
|
||||
(gdb) backtrace^M
|
||||
#0 0x000000000100061a in fun_three ()^M
|
||||
#1 0x000000000100067a in fun_two ()^M
|
||||
#2 0x00000000010006b6 in fun_one ()^M
|
||||
#3 0x00000000010006ee in main ()^M
|
||||
(gdb) PASS: gdb.base/readnever.exp: backtrace
|
||||
...
|
||||
|
||||
Tested on s390x-linux.
|
||||
|
||||
PR tdep/32417
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32417
|
||||
|
||||
Approved-By: Andreas Arnez <arnez@linux.ibm.com>
|
||||
|
||||
[1] https://www.ibm.com/support/pages/sites/default/files/2021-05/SA22-7871-10.pdf
|
||||
---
|
||||
gdb/s390-tdep.c | 39 +++++++++++++++++++++++++++++++++++++++
|
||||
gdb/s390-tdep.h | 1 +
|
||||
2 files changed, 40 insertions(+)
|
||||
|
||||
diff --git a/gdb/s390-tdep.c b/gdb/s390-tdep.c
|
||||
index 4e7dce70c12..2609b42f797 100644
|
||||
--- a/gdb/s390-tdep.c
|
||||
+++ b/gdb/s390-tdep.c
|
||||
@@ -855,6 +855,11 @@ s390_analyze_prologue (struct gdbarch *gdbarch,
|
||||
|| is_rre (insn64, op_lgr, &r1, &r2))
|
||||
data->gpr[r1] = data->gpr[r2];
|
||||
|
||||
+ /* LDGR r1, r2 --- load from register to floating-point register
|
||||
+ (64-bit version). */
|
||||
+ else if (is_rre (insn64, op_ldgr, &r1, &r2))
|
||||
+ data->fpr[r1] = data->gpr[r2];
|
||||
+
|
||||
/* L r1, d2(x2, b2) --- load. */
|
||||
/* LY r1, d2(x2, b2) --- load (long-displacement version). */
|
||||
/* LG r1, d2(x2, b2) --- load (64-bit version). */
|
||||
@@ -2542,6 +2547,40 @@ s390_prologue_frame_unwind_cache (const frame_info_ptr &this_frame,
|
||||
&& data.fpr_slot[i] != 0)
|
||||
info->saved_regs[S390_F0_REGNUM + i].set_addr (cfa - data.fpr_slot[i]);
|
||||
|
||||
+ /* Handle this type of prologue:
|
||||
+ ldgr %f2,%r11
|
||||
+ ldgr %f0,%r15
|
||||
+ where call-clobbered floating point registers are used as register save
|
||||
+ slots. */
|
||||
+ for (i = 0; i < S390_NUM_FPRS; i++)
|
||||
+ {
|
||||
+ int fpr = S390_F0_REGNUM + i;
|
||||
+
|
||||
+ /* Check that fpr is a call-clobbered register. */
|
||||
+ if (s390_register_call_saved (gdbarch, fpr))
|
||||
+ continue;
|
||||
+
|
||||
+ /* Check that fpr contains the value of a register at function
|
||||
+ entry. */
|
||||
+ if (data.fpr[i].kind != pvk_register)
|
||||
+ continue;
|
||||
+
|
||||
+ int entry_val_reg = data.fpr[i].reg;
|
||||
+
|
||||
+ /* Check that entry_val_reg is a call-saved register. */
|
||||
+ if (!s390_register_call_saved (gdbarch, entry_val_reg))
|
||||
+ continue;
|
||||
+
|
||||
+ /* In the prologue, we've copied:
|
||||
+ - the value of a call-saved register (entry_val_reg) at function
|
||||
+ entry, to
|
||||
+ - a call-clobbered floating point register (fpr).
|
||||
+
|
||||
+ Heuristic: assume that makes the floating point register a register
|
||||
+ save slot, leaving the value constant throughout the function. */
|
||||
+ info->saved_regs[entry_val_reg].set_realreg (fpr);
|
||||
+ }
|
||||
+
|
||||
/* Function return will set PC to %r14. */
|
||||
info->saved_regs[S390_PSWA_REGNUM] = info->saved_regs[S390_RETADDR_REGNUM];
|
||||
|
||||
diff --git a/gdb/s390-tdep.h b/gdb/s390-tdep.h
|
||||
index 10f775f468f..b098d735a13 100644
|
||||
--- a/gdb/s390-tdep.h
|
||||
+++ b/gdb/s390-tdep.h
|
||||
@@ -82,6 +82,7 @@ enum
|
||||
op1_lgfi = 0xc0, op2_lgfi = 0x01,
|
||||
op_lr = 0x18,
|
||||
op_lgr = 0xb904,
|
||||
+ op_ldgr = 0xb3c1,
|
||||
op_l = 0x58,
|
||||
op1_ly = 0xe3, op2_ly = 0x58,
|
||||
op1_lg = 0xe3, op2_lg = 0x04,
|
||||
--
|
||||
2.43.0
|
||||
|
143
fix-gdb.base-store.exp-on-s390x.patch
Normal file
143
fix-gdb.base-store.exp-on-s390x.patch
Normal file
@@ -0,0 +1,143 @@
|
||||
From 69e165afa3d45cfac89ed6be298ac6465c84c0fd Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Wed, 15 Jan 2025 17:02:00 +0100
|
||||
Subject: [PATCH 25/46] Fix gdb.base/store.exp on s390x
|
||||
|
||||
On s390x-linux, I get:
|
||||
...
|
||||
(gdb) print l^M
|
||||
$29 = 0^M
|
||||
(gdb) FAIL: gdb.base/store.exp: var doublest l; print old l, expecting -1
|
||||
...
|
||||
|
||||
So, we're in wack_doublest trying to print l, which is a copy of parameter u:
|
||||
...
|
||||
register doublest l = u, r = v;
|
||||
...
|
||||
which does have the expected value:
|
||||
...
|
||||
(gdb) p u
|
||||
$1 = -1
|
||||
...
|
||||
which is a long double, 16 bytes and looks like this:
|
||||
...
|
||||
(gdb) p /x u
|
||||
$3 = 0xbfff0000000000000000000000000000
|
||||
...
|
||||
|
||||
Parameter u is passed in two registers:
|
||||
...
|
||||
<2><6a5>: Abbrev Number: 15 (DW_TAG_formal_parameter)
|
||||
<6a6> DW_AT_name : v
|
||||
<69e> DW_AT_location : 6 byte block: 50 93 8 51 93 8 \
|
||||
(DW_OP_reg0 (r0); DW_OP_piece: 8; DW_OP_reg1 (r1); DW_OP_piece: 8)
|
||||
...
|
||||
and indeed we find the msw in r0 and the lsw in r1:
|
||||
...
|
||||
(gdb) p /x $r0
|
||||
$4 = 0xbfff000000000000
|
||||
(gdb) p /x $r1
|
||||
$5 = 0x0
|
||||
(gdb)
|
||||
...
|
||||
|
||||
Likewise, variable l consists of two registers:
|
||||
...
|
||||
<2><6b5>: Abbrev Number: 13 (DW_TAG_variable)
|
||||
<6b6> DW_AT_name : l
|
||||
<6be> DW_AT_location : 6 byte block: 68 93 8 69 93 8 \
|
||||
(DW_OP_reg24 (f8); DW_OP_piece: 8; DW_OP_reg25 (f10); DW_OP_piece: 8)
|
||||
...
|
||||
and we find the same values there:
|
||||
...
|
||||
(gdb) p /x $f8
|
||||
$6 = 0xbfff000000000000
|
||||
(gdb) p /x $f10
|
||||
$7 = 0x0
|
||||
...
|
||||
|
||||
So, we get the expected results when fetching the value from two gprs, but not
|
||||
when fetching the value from two fprs.
|
||||
|
||||
When fetching the values from the two fprs, we stumble upon a particularity of
|
||||
the DWARF register numbers as defined by the s390x ABI [1]: dwarf register 24
|
||||
maps to both floating-point register f8 (8 bytes), and vector register v8
|
||||
(16 bytes).
|
||||
|
||||
In s390_dwarf_reg_to_regnum, it's determined which of the two is chosen, and
|
||||
if available vector registers are preferred over floating-point registers, so
|
||||
v8 is chosen, and used to fetch the value.
|
||||
|
||||
Since the size of the DW_OP_piece is 8 bytes, and the register size is 16
|
||||
bytes, this bit in rw_pieced_value is activated:
|
||||
...
|
||||
/* If the piece is located in a register, but does not
|
||||
occupy the entire register, the placement of the piece
|
||||
within that register is defined by the ABI. */
|
||||
bits_to_skip
|
||||
+= 8 * gdbarch_dwarf2_reg_piece_offset (arch, gdb_regnum,
|
||||
p->size / 8);
|
||||
...
|
||||
but since the default implemention default_dwarf2_reg_piece_offset does not
|
||||
match the s390x ABI, we get the wrong answer.
|
||||
|
||||
This is a known problem, see FOSDEM 2018 presentation "DWARF Pieces And Other
|
||||
DWARF Location Woes" [2].
|
||||
|
||||
Fix this by adding s390_dwarf2_reg_piece_offset, roughly implementing the same
|
||||
logic as in s390_value_from_register.
|
||||
|
||||
Tested on s390x-linux.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
[1] https://github.com/IBM/s390x-abi
|
||||
[2] https://archive.fosdem.org/2018/schedule/event/dwarfpieces
|
||||
---
|
||||
gdb/s390-tdep.c | 23 +++++++++++++++++++++++
|
||||
1 file changed, 23 insertions(+)
|
||||
|
||||
diff --git a/gdb/s390-tdep.c b/gdb/s390-tdep.c
|
||||
index 2609b42f797..a7c58b37276 100644
|
||||
--- a/gdb/s390-tdep.c
|
||||
+++ b/gdb/s390-tdep.c
|
||||
@@ -1260,6 +1260,28 @@ s390_value_from_register (gdbarch *gdbarch, type *type, int regnum,
|
||||
return value;
|
||||
}
|
||||
|
||||
+/* Implementation of the gdbarch_dwarf2_reg_piece_offset hook. */
|
||||
+
|
||||
+static ULONGEST
|
||||
+s390_dwarf2_reg_piece_offset (gdbarch *gdbarch, int gdb_regnum, ULONGEST size)
|
||||
+{
|
||||
+ s390_gdbarch_tdep *tdep = gdbarch_tdep<s390_gdbarch_tdep> (gdbarch);
|
||||
+
|
||||
+ /* Floating point register. */
|
||||
+ if (gdb_regnum >= S390_F0_REGNUM && gdb_regnum <= S390_F15_REGNUM)
|
||||
+ return 0;
|
||||
+
|
||||
+ /* Vector register, v0 - v15. */
|
||||
+ if (regnum_is_vxr_full (tdep, gdb_regnum))
|
||||
+ return 0;
|
||||
+
|
||||
+ /* Vector register, v16 - v31. */
|
||||
+ if (gdb_regnum >= S390_V16_REGNUM && gdb_regnum <= S390_V31_REGNUM)
|
||||
+ return 0;
|
||||
+
|
||||
+ return default_dwarf2_reg_piece_offset (gdbarch, gdb_regnum, size);
|
||||
+}
|
||||
+
|
||||
/* Implement pseudo_register_name tdesc method. */
|
||||
|
||||
static const char *
|
||||
@@ -7259,6 +7281,7 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
||||
set_gdbarch_stab_reg_to_regnum (gdbarch, s390_dwarf_reg_to_regnum);
|
||||
set_gdbarch_dwarf2_reg_to_regnum (gdbarch, s390_dwarf_reg_to_regnum);
|
||||
set_gdbarch_value_from_register (gdbarch, s390_value_from_register);
|
||||
+ set_gdbarch_dwarf2_reg_piece_offset (gdbarch, s390_dwarf2_reg_piece_offset);
|
||||
|
||||
/* Pseudo registers. */
|
||||
set_gdbarch_pseudo_register_read (gdbarch, s390_pseudo_register_read);
|
||||
--
|
||||
2.43.0
|
||||
|
97
fix-gdb.dap-step-out.exp-on-s390x.patch
Normal file
97
fix-gdb.dap-step-out.exp-on-s390x.patch
Normal file
@@ -0,0 +1,97 @@
|
||||
From 6775ce3f5e936a50d883abfb60cafa80f8b76cf6 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Tue, 10 Dec 2024 11:53:31 +0100
|
||||
Subject: [PATCH 19/46] Fix gdb.dap/step-out.exp on s390x
|
||||
|
||||
With test-case gdb.dap/step-out.exp on s390x-linux, I get:
|
||||
...
|
||||
>>> {"seq": 7, "type": "request", "command": "scopes", "arguments": {"frameId": 0}}
|
||||
Content-Length: 569^M
|
||||
^M
|
||||
{"request_seq": 7, "type": "response", "command": "scopes", "body": {"scopes": [{"variablesReference": 1, "name": "Locals", "presentationHint": "locals", "expensive": false, "namedVariables": 1, "line": 35, "source": {"name": "step-out.c", "path": "/home/vries/gdb/src/gdb/testsuite/gdb.dap/step-out.c"}}, {"variablesReference": 2, "name": "Registers", "presentationHint": "registers", "expensive": false, "namedVariables": 114, "line": 35, "source": {"name": "step-out.c", "path": "/home/vries/gdb/src/gdb/testsuite/gdb.dap/step-out.c"}}]}, "success": true, "seq": 21}PASS: gdb.dap/step-out.exp: get scopes success
|
||||
FAIL: gdb.dap/step-out.exp: three scopes
|
||||
...
|
||||
|
||||
The problem is that the test-case expects three scopes:
|
||||
...
|
||||
lassign $scopes scope reg_scope return_scope
|
||||
...
|
||||
but the return_scope is missing because this doesn't work:
|
||||
...
|
||||
$ gdb -q -batch outputs/gdb.dap/step-out/step-out \
|
||||
-ex "b function_breakpoint_here" \
|
||||
-ex run \
|
||||
-ex finish
|
||||
...
|
||||
Value returned has type: struct result. Cannot determine contents
|
||||
...
|
||||
|
||||
This is likely caused by a problem in gdb, but there's nothing wrong the DAP
|
||||
support.
|
||||
|
||||
Fix this by:
|
||||
- allowing two scopes, and
|
||||
- declaring the tests of return_scope unsupported.
|
||||
|
||||
Tested on s390x-linux.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
---
|
||||
gdb/testsuite/gdb.dap/step-out.exp | 42 ++++++++++++++++--------------
|
||||
1 file changed, 23 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.dap/step-out.exp b/gdb/testsuite/gdb.dap/step-out.exp
|
||||
index 757f4ebdaca..491eaf71197 100644
|
||||
--- a/gdb/testsuite/gdb.dap/step-out.exp
|
||||
+++ b/gdb/testsuite/gdb.dap/step-out.exp
|
||||
@@ -59,24 +59,28 @@ set scopes [dap_check_request_and_response "get scopes" scopes \
|
||||
[format {o frameId [i %d]} $frame_id]]
|
||||
set scopes [dict get [lindex $scopes 0] body scopes]
|
||||
|
||||
-gdb_assert {[llength $scopes] == 2} "two scopes"
|
||||
-
|
||||
-lassign $scopes scope reg_scope
|
||||
-gdb_assert {[dict get $scope name] == "Locals"} "scope is locals"
|
||||
-gdb_assert {[dict get $scope presentationHint] == "locals"} \
|
||||
- "locals presentation hint"
|
||||
-gdb_assert {[dict get $scope namedVariables] == 2} "two vars in scope"
|
||||
-
|
||||
-set num [dict get $scope variablesReference]
|
||||
-set refs [lindex [dap_check_request_and_response "fetch arguments" \
|
||||
- "variables" \
|
||||
- [format {o variablesReference [i %d]} $num]] \
|
||||
- 0]
|
||||
-set varlist [lindex [dict get $refs body variables] 0]
|
||||
-
|
||||
-gdb_assert {[dict get $varlist variablesReference] > 0} \
|
||||
- "variable has children"
|
||||
-gdb_assert {[dict get $varlist name] == "(return)"} \
|
||||
- "variable is return value"
|
||||
+gdb_assert {[llength $scopes] == 2 || [llength $scopes] == 3} "two or three scopes"
|
||||
+lassign $scopes scope reg_scope return_scope
|
||||
+
|
||||
+set test "scope is locals"
|
||||
+if { $return_scope == "" } {
|
||||
+ unsupported $test
|
||||
+} else {
|
||||
+ gdb_assert {[dict get $scope presentationHint] == "locals"} \
|
||||
+ "locals presentation hint"
|
||||
+ gdb_assert {[dict get $scope namedVariables] == 2} "two vars in scope"
|
||||
+
|
||||
+ set num [dict get $scope variablesReference]
|
||||
+ set refs [lindex [dap_check_request_and_response "fetch arguments" \
|
||||
+ "variables" \
|
||||
+ [format {o variablesReference [i %d]} $num]] \
|
||||
+ 0]
|
||||
+ set varlist [lindex [dict get $refs body variables] 0]
|
||||
+
|
||||
+ gdb_assert {[dict get $varlist variablesReference] > 0} \
|
||||
+ "variable has children"
|
||||
+ gdb_assert {[dict get $varlist name] == "(return)"} \
|
||||
+ "variable is return value"
|
||||
+}
|
||||
|
||||
dap_shutdown
|
||||
--
|
||||
2.43.0
|
||||
|
56
fix-gdb.dwarf2-shortpiece.exp-on-s390x.patch
Normal file
56
fix-gdb.dwarf2-shortpiece.exp-on-s390x.patch
Normal file
@@ -0,0 +1,56 @@
|
||||
From 2ccefe53891d9c1393853f5179f8e8046c95a6ce Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Wed, 19 Jun 2024 10:04:22 +0200
|
||||
Subject: [PATCH 17/46] Fix gdb.dwarf2/shortpiece.exp on s390x
|
||||
|
||||
On s390x-linux, I run into:
|
||||
...
|
||||
(gdb) p (short []) s1^M
|
||||
$3 = {0, 1, 0, <optimized out>}^M
|
||||
(gdb) FAIL: gdb.dwarf2/shortpiece.exp: p (short []) s1
|
||||
...
|
||||
while this is expected:
|
||||
...
|
||||
(gdb) p (short []) s1^M
|
||||
$3 = {1, 0, 0, <optimized out>}^M
|
||||
(gdb) PASS: gdb.dwarf2/shortpiece.exp: p (short []) s1
|
||||
...
|
||||
|
||||
The type of s1 is:
|
||||
...
|
||||
(gdb) ptype s1
|
||||
type = struct S {
|
||||
myint a;
|
||||
myushort b;
|
||||
}
|
||||
...
|
||||
so the difference is due the fact that viewing an int as two shorts gives
|
||||
different results depending on the endianness.
|
||||
|
||||
Fix this by allowing both results.
|
||||
|
||||
Tested on x86_64-linux and s390x-linux.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
---
|
||||
gdb/testsuite/gdb.dwarf2/shortpiece.exp | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.dwarf2/shortpiece.exp b/gdb/testsuite/gdb.dwarf2/shortpiece.exp
|
||||
index f7ff805de7c..4fcdfcae57a 100644
|
||||
--- a/gdb/testsuite/gdb.dwarf2/shortpiece.exp
|
||||
+++ b/gdb/testsuite/gdb.dwarf2/shortpiece.exp
|
||||
@@ -138,7 +138,9 @@ gdb_test "p s2" \
|
||||
# This test verifies that GDB can print a pieced value casted to a
|
||||
# different type.
|
||||
gdb_test "p (int \[\]) s1" " = \\{1, <optimized out>\\}"
|
||||
-gdb_test "p (short \[\]) s1" " = \\{1, 0, 0, <optimized out>\\}"
|
||||
+set re_little [string_to_regexp "{1, 0, 0, <optimized out>}"]
|
||||
+set re_big [string_to_regexp "{0, 1, 0, <optimized out>}"]
|
||||
+gdb_test {p (short []) s1} " = ($re_little|$re_big)"
|
||||
|
||||
# Test for correct output if the size of the original object is not a
|
||||
# multiple of the array's element size.
|
||||
--
|
||||
2.43.0
|
||||
|
@@ -1,366 +0,0 @@
|
||||
From 2a7e48ca27f4c080151ce9da5a29239aa5d3b66f Mon Sep 17 00:00:00 2001
|
||||
From: Tom Tromey <tromey@adacore.com>
|
||||
Date: Fri, 19 Apr 2024 07:54:19 -0600
|
||||
Subject: [PATCH 15/48] Fix regression on aarch64-linux gdbserver
|
||||
|
||||
Commit 9a03f218 ("Fix gdb.base/watchpoint-unaligned.exp on aarch64")
|
||||
fixed a watchpoint bug in gdb -- but did not touch the corresponding
|
||||
code in gdbserver.
|
||||
|
||||
This patch moves the gdb code into gdb/nat, so that it can be shared
|
||||
with gdbserver, and then changes gdbserver to use it, fixing the bug.
|
||||
|
||||
This is yet another case where having a single back end would prevent
|
||||
bugs.
|
||||
|
||||
I tested this using the AdaCore internal gdb testsuite.
|
||||
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29423
|
||||
Approved-By: Luis Machado <luis.machado@arm.com>
|
||||
---
|
||||
gdb/aarch64-nat.c | 115 ---------------------------------
|
||||
gdb/aarch64-nat.h | 8 ---
|
||||
gdb/nat/aarch64-hw-point.c | 115 +++++++++++++++++++++++++++++++++
|
||||
gdb/nat/aarch64-hw-point.h | 8 +++
|
||||
gdbserver/linux-aarch64-low.cc | 38 +----------
|
||||
5 files changed, 126 insertions(+), 158 deletions(-)
|
||||
|
||||
diff --git a/gdb/aarch64-nat.c b/gdb/aarch64-nat.c
|
||||
index a173e4e18d5..97e3048568a 100644
|
||||
--- a/gdb/aarch64-nat.c
|
||||
+++ b/gdb/aarch64-nat.c
|
||||
@@ -225,121 +225,6 @@ aarch64_remove_watchpoint (CORE_ADDR addr, int len, enum target_hw_bp_type type,
|
||||
return ret;
|
||||
}
|
||||
|
||||
-/* See aarch64-nat.h. */
|
||||
-
|
||||
-bool
|
||||
-aarch64_stopped_data_address (const struct aarch64_debug_reg_state *state,
|
||||
- CORE_ADDR addr_trap, CORE_ADDR *addr_p)
|
||||
-{
|
||||
- bool found = false;
|
||||
- for (int phase = 0; phase <= 1; ++phase)
|
||||
- for (int i = aarch64_num_wp_regs - 1; i >= 0; --i)
|
||||
- {
|
||||
- if (!(state->dr_ref_count_wp[i]
|
||||
- && DR_CONTROL_ENABLED (state->dr_ctrl_wp[i])))
|
||||
- {
|
||||
- /* Watchpoint disabled. */
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- const enum target_hw_bp_type type
|
||||
- = aarch64_watchpoint_type (state->dr_ctrl_wp[i]);
|
||||
- if (type == hw_execute)
|
||||
- {
|
||||
- /* Watchpoint disabled. */
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- if (phase == 0)
|
||||
- {
|
||||
- /* Phase 0: No hw_write. */
|
||||
- if (type == hw_write)
|
||||
- continue;
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- /* Phase 1: Only hw_write. */
|
||||
- if (type != hw_write)
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- const unsigned int offset
|
||||
- = aarch64_watchpoint_offset (state->dr_ctrl_wp[i]);
|
||||
- const unsigned int len
|
||||
- = aarch64_watchpoint_length (state->dr_ctrl_wp[i]);
|
||||
- const CORE_ADDR addr_watch = state->dr_addr_wp[i] + offset;
|
||||
- const CORE_ADDR addr_watch_aligned
|
||||
- = align_down (state->dr_addr_wp[i], AARCH64_HWP_MAX_LEN_PER_REG);
|
||||
- const CORE_ADDR addr_orig = state->dr_addr_orig_wp[i];
|
||||
-
|
||||
- /* ADDR_TRAP reports the first address of the memory range
|
||||
- accessed by the CPU, regardless of what was the memory
|
||||
- range watched. Thus, a large CPU access that straddles
|
||||
- the ADDR_WATCH..ADDR_WATCH+LEN range may result in an
|
||||
- ADDR_TRAP that is lower than the
|
||||
- ADDR_WATCH..ADDR_WATCH+LEN range. E.g.:
|
||||
-
|
||||
- addr: | 4 | 5 | 6 | 7 | 8 |
|
||||
- |---- range watched ----|
|
||||
- |----------- range accessed ------------|
|
||||
-
|
||||
- In this case, ADDR_TRAP will be 4.
|
||||
-
|
||||
- The access size also can be larger than that of the watchpoint
|
||||
- itself. For instance, the access size of an stp instruction is 16.
|
||||
- So, if we use stp to store to address p, and set a watchpoint on
|
||||
- address p + 8, the reported ADDR_TRAP can be p + 8 (observed on
|
||||
- RK3399 SOC). But it also can be p (observed on M1 SOC). Checking
|
||||
- for this situation introduces the possibility of false positives,
|
||||
- so we only do this for hw_write watchpoints. */
|
||||
- const CORE_ADDR max_access_size = type == hw_write ? 16 : 8;
|
||||
- const CORE_ADDR addr_watch_base = addr_watch_aligned -
|
||||
- (max_access_size - AARCH64_HWP_MAX_LEN_PER_REG);
|
||||
- if (!(addr_trap >= addr_watch_base
|
||||
- && addr_trap < addr_watch + len))
|
||||
- {
|
||||
- /* Not a match. */
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- /* To match a watchpoint known to GDB core, we must never
|
||||
- report *ADDR_P outside of any ADDR_WATCH..ADDR_WATCH+LEN
|
||||
- range. ADDR_WATCH <= ADDR_TRAP < ADDR_ORIG is a false
|
||||
- positive on kernels older than 4.10. See PR
|
||||
- external/20207. */
|
||||
- if (addr_p != nullptr)
|
||||
- *addr_p = addr_orig;
|
||||
-
|
||||
- if (phase == 0)
|
||||
- {
|
||||
- /* Phase 0: Return first match. */
|
||||
- return true;
|
||||
- }
|
||||
-
|
||||
- /* Phase 1. */
|
||||
- if (addr_p == nullptr)
|
||||
- {
|
||||
- /* First match, and we don't need to report an address. No need
|
||||
- to look for other matches. */
|
||||
- return true;
|
||||
- }
|
||||
-
|
||||
- if (!found)
|
||||
- {
|
||||
- /* First match, and we need to report an address. Look for other
|
||||
- matches. */
|
||||
- found = true;
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- /* More than one match, and we need to return an address. No need to
|
||||
- look for further matches. */
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
- return found;
|
||||
-}
|
||||
-
|
||||
/* Define AArch64 maintenance commands. */
|
||||
|
||||
static void
|
||||
diff --git a/gdb/aarch64-nat.h b/gdb/aarch64-nat.h
|
||||
index fee6bda2577..f95a9d745e5 100644
|
||||
--- a/gdb/aarch64-nat.h
|
||||
+++ b/gdb/aarch64-nat.h
|
||||
@@ -45,14 +45,6 @@ struct aarch64_debug_reg_state *aarch64_get_debug_reg_state (pid_t pid);
|
||||
|
||||
void aarch64_remove_debug_reg_state (pid_t pid);
|
||||
|
||||
-/* Helper for the "stopped_data_address" target method. Returns TRUE
|
||||
- if a hardware watchpoint trap at ADDR_TRAP matches a set
|
||||
- watchpoint. The address of the matched watchpoint is returned in
|
||||
- *ADDR_P. */
|
||||
-
|
||||
-bool aarch64_stopped_data_address (const struct aarch64_debug_reg_state *state,
|
||||
- CORE_ADDR addr_trap, CORE_ADDR *addr_p);
|
||||
-
|
||||
/* Helper functions used by aarch64_nat_target below. See their
|
||||
definitions. */
|
||||
|
||||
diff --git a/gdb/nat/aarch64-hw-point.c b/gdb/nat/aarch64-hw-point.c
|
||||
index 3b8cdcba23b..9eb78923e86 100644
|
||||
--- a/gdb/nat/aarch64-hw-point.c
|
||||
+++ b/gdb/nat/aarch64-hw-point.c
|
||||
@@ -647,3 +647,118 @@ aarch64_region_ok_for_watchpoint (CORE_ADDR addr, int len)
|
||||
the checking is costly. */
|
||||
return 1;
|
||||
}
|
||||
+
|
||||
+/* See nat/aarch64-hw-point.h. */
|
||||
+
|
||||
+bool
|
||||
+aarch64_stopped_data_address (const struct aarch64_debug_reg_state *state,
|
||||
+ CORE_ADDR addr_trap, CORE_ADDR *addr_p)
|
||||
+{
|
||||
+ bool found = false;
|
||||
+ for (int phase = 0; phase <= 1; ++phase)
|
||||
+ for (int i = aarch64_num_wp_regs - 1; i >= 0; --i)
|
||||
+ {
|
||||
+ if (!(state->dr_ref_count_wp[i]
|
||||
+ && DR_CONTROL_ENABLED (state->dr_ctrl_wp[i])))
|
||||
+ {
|
||||
+ /* Watchpoint disabled. */
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ const enum target_hw_bp_type type
|
||||
+ = aarch64_watchpoint_type (state->dr_ctrl_wp[i]);
|
||||
+ if (type == hw_execute)
|
||||
+ {
|
||||
+ /* Watchpoint disabled. */
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (phase == 0)
|
||||
+ {
|
||||
+ /* Phase 0: No hw_write. */
|
||||
+ if (type == hw_write)
|
||||
+ continue;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /* Phase 1: Only hw_write. */
|
||||
+ if (type != hw_write)
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ const unsigned int offset
|
||||
+ = aarch64_watchpoint_offset (state->dr_ctrl_wp[i]);
|
||||
+ const unsigned int len
|
||||
+ = aarch64_watchpoint_length (state->dr_ctrl_wp[i]);
|
||||
+ const CORE_ADDR addr_watch = state->dr_addr_wp[i] + offset;
|
||||
+ const CORE_ADDR addr_watch_aligned
|
||||
+ = align_down (state->dr_addr_wp[i], AARCH64_HWP_MAX_LEN_PER_REG);
|
||||
+ const CORE_ADDR addr_orig = state->dr_addr_orig_wp[i];
|
||||
+
|
||||
+ /* ADDR_TRAP reports the first address of the memory range
|
||||
+ accessed by the CPU, regardless of what was the memory
|
||||
+ range watched. Thus, a large CPU access that straddles
|
||||
+ the ADDR_WATCH..ADDR_WATCH+LEN range may result in an
|
||||
+ ADDR_TRAP that is lower than the
|
||||
+ ADDR_WATCH..ADDR_WATCH+LEN range. E.g.:
|
||||
+
|
||||
+ addr: | 4 | 5 | 6 | 7 | 8 |
|
||||
+ |---- range watched ----|
|
||||
+ |----------- range accessed ------------|
|
||||
+
|
||||
+ In this case, ADDR_TRAP will be 4.
|
||||
+
|
||||
+ The access size also can be larger than that of the watchpoint
|
||||
+ itself. For instance, the access size of an stp instruction is 16.
|
||||
+ So, if we use stp to store to address p, and set a watchpoint on
|
||||
+ address p + 8, the reported ADDR_TRAP can be p + 8 (observed on
|
||||
+ RK3399 SOC). But it also can be p (observed on M1 SOC). Checking
|
||||
+ for this situation introduces the possibility of false positives,
|
||||
+ so we only do this for hw_write watchpoints. */
|
||||
+ const CORE_ADDR max_access_size = type == hw_write ? 16 : 8;
|
||||
+ const CORE_ADDR addr_watch_base = addr_watch_aligned -
|
||||
+ (max_access_size - AARCH64_HWP_MAX_LEN_PER_REG);
|
||||
+ if (!(addr_trap >= addr_watch_base
|
||||
+ && addr_trap < addr_watch + len))
|
||||
+ {
|
||||
+ /* Not a match. */
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* To match a watchpoint known to GDB core, we must never
|
||||
+ report *ADDR_P outside of any ADDR_WATCH..ADDR_WATCH+LEN
|
||||
+ range. ADDR_WATCH <= ADDR_TRAP < ADDR_ORIG is a false
|
||||
+ positive on kernels older than 4.10. See PR
|
||||
+ external/20207. */
|
||||
+ if (addr_p != nullptr)
|
||||
+ *addr_p = addr_orig;
|
||||
+
|
||||
+ if (phase == 0)
|
||||
+ {
|
||||
+ /* Phase 0: Return first match. */
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ /* Phase 1. */
|
||||
+ if (addr_p == nullptr)
|
||||
+ {
|
||||
+ /* First match, and we don't need to report an address. No need
|
||||
+ to look for other matches. */
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ if (!found)
|
||||
+ {
|
||||
+ /* First match, and we need to report an address. Look for other
|
||||
+ matches. */
|
||||
+ found = true;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* More than one match, and we need to return an address. No need to
|
||||
+ look for further matches. */
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ return found;
|
||||
+}
|
||||
diff --git a/gdb/nat/aarch64-hw-point.h b/gdb/nat/aarch64-hw-point.h
|
||||
index 71ae2864927..2386cf60f90 100644
|
||||
--- a/gdb/nat/aarch64-hw-point.h
|
||||
+++ b/gdb/nat/aarch64-hw-point.h
|
||||
@@ -110,6 +110,14 @@ unsigned int aarch64_watchpoint_offset (unsigned int ctrl);
|
||||
unsigned int aarch64_watchpoint_length (unsigned int ctrl);
|
||||
enum target_hw_bp_type aarch64_watchpoint_type (unsigned int ctrl);
|
||||
|
||||
+/* Helper for the "stopped_data_address" target method. Returns TRUE
|
||||
+ if a hardware watchpoint trap at ADDR_TRAP matches a set
|
||||
+ watchpoint. The address of the matched watchpoint is returned in
|
||||
+ *ADDR_P. */
|
||||
+
|
||||
+bool aarch64_stopped_data_address (const struct aarch64_debug_reg_state *state,
|
||||
+ CORE_ADDR addr_trap, CORE_ADDR *addr_p);
|
||||
+
|
||||
int aarch64_handle_breakpoint (enum target_hw_bp_type type, CORE_ADDR addr,
|
||||
int len, int is_insert, ptid_t ptid,
|
||||
struct aarch64_debug_reg_state *state);
|
||||
diff --git a/gdbserver/linux-aarch64-low.cc b/gdbserver/linux-aarch64-low.cc
|
||||
index fcbe7bb64d7..14346b89822 100644
|
||||
--- a/gdbserver/linux-aarch64-low.cc
|
||||
+++ b/gdbserver/linux-aarch64-low.cc
|
||||
@@ -577,41 +577,9 @@ aarch64_target::low_stopped_data_address ()
|
||||
|
||||
/* Check if the address matches any watched address. */
|
||||
state = aarch64_get_debug_reg_state (pid_of (current_thread));
|
||||
- for (i = aarch64_num_wp_regs - 1; i >= 0; --i)
|
||||
- {
|
||||
- const unsigned int offset
|
||||
- = aarch64_watchpoint_offset (state->dr_ctrl_wp[i]);
|
||||
- const unsigned int len = aarch64_watchpoint_length (state->dr_ctrl_wp[i]);
|
||||
- const CORE_ADDR addr_watch = state->dr_addr_wp[i] + offset;
|
||||
- const CORE_ADDR addr_watch_aligned = align_down (state->dr_addr_wp[i], 8);
|
||||
- const CORE_ADDR addr_orig = state->dr_addr_orig_wp[i];
|
||||
-
|
||||
- if (state->dr_ref_count_wp[i]
|
||||
- && DR_CONTROL_ENABLED (state->dr_ctrl_wp[i])
|
||||
- && addr_trap >= addr_watch_aligned
|
||||
- && addr_trap < addr_watch + len)
|
||||
- {
|
||||
- /* ADDR_TRAP reports the first address of the memory range
|
||||
- accessed by the CPU, regardless of what was the memory
|
||||
- range watched. Thus, a large CPU access that straddles
|
||||
- the ADDR_WATCH..ADDR_WATCH+LEN range may result in an
|
||||
- ADDR_TRAP that is lower than the
|
||||
- ADDR_WATCH..ADDR_WATCH+LEN range. E.g.:
|
||||
-
|
||||
- addr: | 4 | 5 | 6 | 7 | 8 |
|
||||
- |---- range watched ----|
|
||||
- |----------- range accessed ------------|
|
||||
-
|
||||
- In this case, ADDR_TRAP will be 4.
|
||||
-
|
||||
- To match a watchpoint known to GDB core, we must never
|
||||
- report *ADDR_P outside of any ADDR_WATCH..ADDR_WATCH+LEN
|
||||
- range. ADDR_WATCH <= ADDR_TRAP < ADDR_ORIG is a false
|
||||
- positive on kernels older than 4.10. See PR
|
||||
- external/20207. */
|
||||
- return addr_orig;
|
||||
- }
|
||||
- }
|
||||
+ CORE_ADDR result;
|
||||
+ if (aarch64_stopped_data_address (state, addr_trap, &result))
|
||||
+ return result;
|
||||
|
||||
return (CORE_ADDR) 0;
|
||||
}
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,80 +0,0 @@
|
||||
From c21fd9f7d5911fce0c17af7094d8861d1195dfda Mon Sep 17 00:00:00 2001
|
||||
From: Carl Love <cel@linux.ibm.com>
|
||||
Date: Mon, 13 Nov 2023 14:14:08 -0500
|
||||
Subject: [PATCH 01/48] Fix the gdb.ada/inline-section-gc.exp test
|
||||
|
||||
The original intention of the test appears to be checking to make sure
|
||||
setting a breakpoint in an inlined function didn't set multiple
|
||||
breakpoints where one of them was at address 0.
|
||||
|
||||
The gdb.ada/inline-section-gc.exp test may pass or fail depending on the
|
||||
version of gnat. Per the discussion on IRC, the ada inlining appears to
|
||||
have some target dependencies. In this test there are two functions,
|
||||
callee and caller. Function calee is inlined into caller. The test sets
|
||||
a breakpoint in function callee. The reported location where the
|
||||
breakpoint is set may be at the requested location in callee or the
|
||||
location in caller after callee has been inlined. The test needs to
|
||||
accept either location as correct provided the breakpoint address is not
|
||||
zero.
|
||||
|
||||
This patch checks to see if the reported breakpoint is in function callee
|
||||
or function caller and fails if the breakpoint address is 0x0. The line
|
||||
number where the breakpoint is set will match the requested line if the
|
||||
breakpoint location is reported is callee.adb. If the breakpoint is
|
||||
reported in caller.adb, the line number in caller is the breakpoint
|
||||
location in callee where it is inlined into caller.
|
||||
|
||||
This patch fixes the single regression failure for the test on PowerPC.
|
||||
It does not introduce any failures on X86-64.
|
||||
---
|
||||
gdb/testsuite/gdb.ada/inline-section-gc.exp | 21 ++++++++++++++++---
|
||||
.../gdb.ada/inline-section-gc/caller.adb | 3 ++-
|
||||
2 files changed, 20 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.ada/inline-section-gc.exp b/gdb/testsuite/gdb.ada/inline-section-gc.exp
|
||||
index b707335eb04..4f8b8c95395 100644
|
||||
--- a/gdb/testsuite/gdb.ada/inline-section-gc.exp
|
||||
+++ b/gdb/testsuite/gdb.ada/inline-section-gc.exp
|
||||
@@ -34,8 +34,23 @@ if {[gdb_compile_ada "${srcfile}" "${binfile}" executable $options] != ""} {
|
||||
|
||||
clean_restart ${testfile}
|
||||
|
||||
-set bp_location [gdb_get_line_number "BREAK" ${testdir}/callee.adb]
|
||||
+
|
||||
+# Depending on the version of gnat, the location of the set breakpoint may
|
||||
+# be reported as being at the requested location in file callee.adb or in
|
||||
+# file caller.adb where the callee function was inlined. Either way, only
|
||||
+# one breakpoint should be reported and its address should not be at 0x0.
|
||||
+set bp_location1 [gdb_get_line_number "BREAK" ${testdir}/callee.adb]
|
||||
+set bp_location2 [gdb_get_line_number "CALLEE_LOC" ${testdir}/caller.adb]
|
||||
+set test "break callee.adb:$bp_location1"
|
||||
+set message "Breakpoint set"
|
||||
+
|
||||
# The bug here was that gdb would set a breakpoint with two locations,
|
||||
# one of them at 0x0.
|
||||
-gdb_test "break callee.adb:$bp_location" \
|
||||
- "Breakpoint $decimal at $hex: file .*callee.adb, line $bp_location."
|
||||
+gdb_test_multiple $test $message {
|
||||
+ -re "Breakpoint $decimal at $hex: file .*callee.adb, line $bp_location1." {
|
||||
+ pass $test
|
||||
+ }
|
||||
+ -re "Breakpoint $decimal at $hex: file .*caller.adb, line $bp_location2." {
|
||||
+ pass $test
|
||||
+ }
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.ada/inline-section-gc/caller.adb b/gdb/testsuite/gdb.ada/inline-section-gc/caller.adb
|
||||
index 66eb2d9a910..161f3e85542 100644
|
||||
--- a/gdb/testsuite/gdb.ada/inline-section-gc/caller.adb
|
||||
+++ b/gdb/testsuite/gdb.ada/inline-section-gc/caller.adb
|
||||
@@ -18,4 +18,5 @@ with Callee;
|
||||
procedure Caller is
|
||||
begin
|
||||
Callee;
|
||||
-end Caller;
|
||||
+end Caller; -- CALLEE_LOC, this is where the inlined callee breakpoint
|
||||
+ -- is located.
|
||||
|
||||
base-commit: 582fc35843fdf71b82d645d83d2903e2546cc21a
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,30 +0,0 @@
|
||||
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
|
||||
|
@@ -1,25 +0,0 @@
|
||||
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
|
||||
|
@@ -1,35 +0,0 @@
|
||||
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]
|
25
fixup-gdb-6.5-gcore-buffer-limit-test.patch
Normal file
25
fixup-gdb-6.5-gcore-buffer-limit-test.patch
Normal file
@@ -0,0 +1,25 @@
|
||||
From 388654c78086e5240fec47260e47d1deff4af43d Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Thu, 6 Feb 2025 13:27:57 +0100
|
||||
Subject: [PATCH 43/46] fixup-gdb-6.5-gcore-buffer-limit-test.patch
|
||||
|
||||
---
|
||||
gdb/testsuite/gdb.base/gcore-excessive-memory.exp | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/gcore-excessive-memory.exp b/gdb/testsuite/gdb.base/gcore-excessive-memory.exp
|
||||
index 31cf88ce78a..1ef595923ad 100644
|
||||
--- a/gdb/testsuite/gdb.base/gcore-excessive-memory.exp
|
||||
+++ b/gdb/testsuite/gdb.base/gcore-excessive-memory.exp
|
||||
@@ -14,6 +14,8 @@
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
+require can_spawn_for_attach
|
||||
+
|
||||
if {[use_gdb_stub]} {
|
||||
untested "skipping test because of use_gdb_stub"
|
||||
return -1
|
||||
--
|
||||
2.43.0
|
||||
|
26
fixup-gdb-add-rpm-suggestion-script.patch
Normal file
26
fixup-gdb-add-rpm-suggestion-script.patch
Normal file
@@ -0,0 +1,26 @@
|
||||
From a7d9abecbc24e3d68746ea5b905eba11913980e1 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Tue, 25 Mar 2025 17:15:01 +0100
|
||||
Subject: [PATCH 2/2] fixup-gdb-add-rpm-suggestion-script.patch
|
||||
|
||||
---
|
||||
gdb/python/lib/gdb/command/rpm-suggestions.py | 3 +--
|
||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||
|
||||
diff --git a/gdb/python/lib/gdb/command/rpm-suggestions.py b/gdb/python/lib/gdb/command/rpm-suggestions.py
|
||||
index bb049bc66e7..066ce98d947 100644
|
||||
--- a/gdb/python/lib/gdb/command/rpm-suggestions.py
|
||||
+++ b/gdb/python/lib/gdb/command/rpm-suggestions.py
|
||||
@@ -510,8 +510,7 @@ class rpm_suggestion_build_id_mode(gdb.Parameter):
|
||||
|
||||
# The 'info rpm-suggestions' command.
|
||||
class rpm_suggestion_info(gdb.Command):
|
||||
- """Relist any RPM installation suggestions that have been made
|
||||
- since the executable was last changed."""
|
||||
+ """Relist any RPM installation suggestions that have been made since the executable was last changed."""
|
||||
def __init__(self):
|
||||
super().__init__("info rpm-suggestions", gdb.COMMAND_NONE, gdb.COMPLETE_NONE)
|
||||
|
||||
--
|
||||
2.43.0
|
||||
|
@@ -1,22 +0,0 @@
|
||||
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
|
||||
|
@@ -1,19 +0,0 @@
|
||||
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
|
||||
}
|
@@ -1,40 +0,0 @@
|
||||
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
|
||||
|
@@ -1,43 +0,0 @@
|
||||
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
|
||||
|
@@ -1,38 +0,0 @@
|
||||
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}]] != ""
|
@@ -1,21 +0,0 @@
|
||||
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
|
||||
|
@@ -1,70 +0,0 @@
|
||||
From d60b57fe1a98094a7e4f19481193b2b5a9bb1e57 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Thu, 2 May 2024 12:02:50 +0200
|
||||
Subject: [PATCH 079/147] fixup PowerPC and aarch64: Fix reverse stepping
|
||||
failure
|
||||
|
||||
---
|
||||
gdb/infrun.c | 2 +-
|
||||
gdb/symtab.c | 3 +--
|
||||
gdb/symtab.h | 3 +--
|
||||
3 files changed, 3 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/gdb/infrun.c b/gdb/infrun.c
|
||||
index 069ef144a76..7be98cfc252 100644
|
||||
--- a/gdb/infrun.c
|
||||
+++ b/gdb/infrun.c
|
||||
@@ -6897,7 +6897,7 @@ update_line_range_start (CORE_ADDR pc, struct execution_control_state *ecs)
|
||||
Given the PC, check the line table and return the PC that corresponds
|
||||
to the line table entry for the source line that PC is in. */
|
||||
CORE_ADDR start_line_pc = ecs->event_thread->control.step_range_start;
|
||||
- std::optional<CORE_ADDR> real_range_start;
|
||||
+ gdb::optional<CORE_ADDR> real_range_start;
|
||||
|
||||
/* Call find_line_range_start to get the smallest address in the
|
||||
linetable for multiple Line X entries in the line table. */
|
||||
diff --git a/gdb/symtab.c b/gdb/symtab.c
|
||||
index ef63ec93c5a..9a47796e5e0 100644
|
||||
--- a/gdb/symtab.c
|
||||
+++ b/gdb/symtab.c
|
||||
@@ -73,7 +73,6 @@
|
||||
#include "gdbsupport/gdb_string_view.h"
|
||||
#include "gdbsupport/pathstuff.h"
|
||||
#include "gdbsupport/common-utils.h"
|
||||
-#include <optional>
|
||||
|
||||
/* Forward declarations for local functions. */
|
||||
|
||||
@@ -3328,7 +3327,7 @@ sal_line_symtab_matches_p (const symtab_and_line &sal1,
|
||||
|
||||
/* See symtah.h. */
|
||||
|
||||
-std::optional<CORE_ADDR>
|
||||
+gdb::optional<CORE_ADDR>
|
||||
find_line_range_start (CORE_ADDR pc)
|
||||
{
|
||||
struct symtab_and_line current_sal = find_pc_line (pc, 0);
|
||||
diff --git a/gdb/symtab.h b/gdb/symtab.h
|
||||
index e17d15c595b..6a611d42880 100644
|
||||
--- a/gdb/symtab.h
|
||||
+++ b/gdb/symtab.h
|
||||
@@ -38,7 +38,6 @@
|
||||
#include "gdb-demangle.h"
|
||||
#include "split-name.h"
|
||||
#include "frame.h"
|
||||
-#include <optional>
|
||||
|
||||
/* Opaque declarations. */
|
||||
struct ui_file;
|
||||
@@ -2377,7 +2376,7 @@ extern struct symtab_and_line find_pc_sect_line (CORE_ADDR,
|
||||
the starting PC of line X, and the ranges are contiguous.
|
||||
*/
|
||||
|
||||
-extern std::optional<CORE_ADDR> find_line_range_start (CORE_ADDR pc);
|
||||
+extern gdb::optional<CORE_ADDR> find_line_range_start (CORE_ADDR pc);
|
||||
|
||||
/* Wrapper around find_pc_line to just return the symtab. */
|
||||
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,101 +0,0 @@
|
||||
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)
BIN
gdb-14.2.tar.bz2
(Stored with Git LFS)
Binary file not shown.
BIN
gdb-15.2.tar.bz2
(Stored with Git LFS)
Normal file
BIN
gdb-15.2.tar.bz2
(Stored with Git LFS)
Normal file
Binary file not shown.
@@ -1,120 +0,0 @@
|
||||
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}"
|
@@ -16,7 +16,7 @@ Subject: gdb-6.3-gstack-20050411.patch
|
||||
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
|
||||
--- a/gdb/Makefile.in
|
||||
+++ b/gdb/Makefile.in
|
||||
@@ -2035,7 +2035,7 @@ info install-info clean-info dvi pdf install-pdf html install-html: force
|
||||
@@ -2071,7 +2071,7 @@ info install-info clean-info dvi install-dvi pdf install-pdf html install-html:
|
||||
install: all
|
||||
@$(MAKE) $(FLAGS_TO_PASS) install-only
|
||||
|
||||
@@ -25,7 +25,7 @@ diff --git a/gdb/Makefile.in b/gdb/Makefile.in
|
||||
transformed_name=`t='$(program_transform_name)'; \
|
||||
echo gdb | sed -e "$$t"` ; \
|
||||
if test "x$$transformed_name" = x; then \
|
||||
@@ -2085,7 +2085,25 @@ install-guile:
|
||||
@@ -2121,7 +2121,25 @@ install-guile:
|
||||
install-python:
|
||||
$(SHELL) $(srcdir)/../mkinstalldirs $(DESTDIR)$(GDB_DATADIR)/python/gdb
|
||||
|
||||
@@ -52,7 +52,7 @@ diff --git a/gdb/Makefile.in b/gdb/Makefile.in
|
||||
transformed_name=`t='$(program_transform_name)'; \
|
||||
echo gdb | sed -e $$t` ; \
|
||||
if test "x$$transformed_name" = x; then \
|
||||
@@ -2116,6 +2134,18 @@ uninstall: force $(CONFIG_UNINSTALL)
|
||||
@@ -2152,6 +2170,28 @@ uninstall: force $(CONFIG_UNINSTALL)
|
||||
rm -f $(DESTDIR)$(bindir)/$$transformed_name
|
||||
@$(MAKE) DO=uninstall "DODIRS=$(SUBDIRS)" $(FLAGS_TO_PASS) subdir_do
|
||||
|
||||
@@ -68,9 +68,19 @@ diff --git a/gdb/Makefile.in b/gdb/Makefile.in
|
||||
+ rm -f $(DESTDIR)$(bindir)/$$transformed_name$(EXEEXT) \
|
||||
+ $(DESTDIR)$(man1dir)/$$transformed_name.1
|
||||
+
|
||||
# The C++ name parser can be built standalone for testing.
|
||||
test-cp-name-parser.o: cp-name-parser.c
|
||||
$(COMPILE) -DTEST_CPNAMES cp-name-parser.c
|
||||
+# The C++ name parser can be built standalone for testing.
|
||||
+test-cp-name-parser.o: cp-name-parser.c
|
||||
+ $(COMPILE) -DTEST_CPNAMES cp-name-parser.c
|
||||
+ $(POSTCOMPILE)
|
||||
+
|
||||
+test-cp-name-parser$(EXEEXT): test-cp-name-parser.o $(LIBIBERTY)
|
||||
+ $(ECHO_CXXLD) $(CC_LD) $(INTERNAL_LDFLAGS) \
|
||||
+ -o test-cp-name-parser$(EXEEXT) test-cp-name-parser.o \
|
||||
+ $(LIBIBERTY)
|
||||
+
|
||||
# We do this by grepping through sources. If that turns out to be too slow,
|
||||
# maybe we could just require every .o file to have an initialization routine
|
||||
# of a given name (top.o -> _initialize_top, etc.).
|
||||
diff --git a/gdb/gstack.sh b/gdb/gstack.sh
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
@@ -226,7 +236,7 @@ new file mode 100644
|
||||
+# 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."
|
||||
|
@@ -1,265 +0,0 @@
|
||||
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?
|
@@ -1,89 +0,0 @@
|
||||
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
|
||||
+}
|
@@ -1,127 +0,0 @@
|
||||
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"
|
@@ -1,19 +0,0 @@
|
||||
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;
|
||||
};
|
@@ -1,123 +0,0 @@
|
||||
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
40
gdb-6.6-buildid-locate-tests-suse.patch
Normal file
40
gdb-6.6-buildid-locate-tests-suse.patch
Normal file
@@ -0,0 +1,40 @@
|
||||
From 4aaa960916b069dd82a293bf0e876dbc8710801e Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Wed, 26 Mar 2025 10:25:38 +0100
|
||||
Subject: [PATCH 4/4] gdb-6.6-buildid-locate-tests-suse.patch
|
||||
|
||||
---
|
||||
...z981154-misleading-yum-install-warning.exp | 20 ++++++++++++++++---
|
||||
1 file changed, 17 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/rhbz981154-misleading-yum-install-warning.exp b/gdb/testsuite/gdb.base/rhbz981154-misleading-yum-install-warning.exp
|
||||
index 991ffef474d..ab5f1667f31 100644
|
||||
--- a/gdb/testsuite/gdb.base/rhbz981154-misleading-yum-install-warning.exp
|
||||
+++ b/gdb/testsuite/gdb.base/rhbz981154-misleading-yum-install-warning.exp
|
||||
@@ -55,6 +55,20 @@ gdb_test "set build-id-verbose 1" "" \
|
||||
gdb_test "set debug-file-directory /usr/lib/" "" \
|
||||
"set debug-file-directory"
|
||||
|
||||
-gdb_test "core-file [standard_output_file gcore.test]" \
|
||||
- "Missing file\\(s\\), try: dnf --enablerepo='\\*debug\\*' install [string_to_regexp /usr/lib/$build_id_without_debug] [string_to_regexp /usr/lib/debug/$build_id_debug_file]" \
|
||||
- "test first yum/dnf warning"
|
||||
+# Supporting this for SUSE/openSUSE requires a gdb.missing_objfile handler,
|
||||
+# but that's not enabled. Zypper doesn't support finding packages based on
|
||||
+# build-id, unless the package's installed.
|
||||
+# So, instead of testing for the SUSE/openSUSE-specific solution, check that
|
||||
+# the fedora solution doesn't appear.
|
||||
+
|
||||
+set cmd "core-file [standard_output_file gcore.test]"
|
||||
+set test "test first yum/dnf warning"
|
||||
+set fail_re [string_to_regexp "Missing file(s), try: dnf "].*
|
||||
+gdb_test_multiple $cmd $test {
|
||||
+ -re -wrap $fail_re {
|
||||
+ fail $gdb_test_name
|
||||
+ }
|
||||
+ -re -wrap "" {
|
||||
+ pass $gdb_test_name
|
||||
+ }
|
||||
+}
|
||||
--
|
||||
2.43.0
|
||||
|
@@ -1,75 +1,10 @@
|
||||
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
|
||||
Subject: gdb-6.6-buildid-locate-tests.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
|
||||
;; Tests and test updates related to the rpm suggestion feature.
|
||||
|
||||
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
|
||||
@@ -130,7 +65,7 @@ diff --git a/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib.exp b/gdb/t
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib.exp
|
||||
@@ -0,0 +1,105 @@
|
||||
@@ -0,0 +1,104 @@
|
||||
+# Copyright 2016 Free Software Foundation, Inc.
|
||||
+
|
||||
+# This program is free software; you can redistribute it and/or modify
|
||||
@@ -146,9 +81,7 @@ new file mode 100644
|
||||
+# 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
|
||||
@@ -226,7 +159,8 @@ new file mode 100644
|
||||
+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 solib-absolute-prefix $debugdir" \
|
||||
+ "set solib-absolute-prefix"
|
||||
+
|
||||
+gdb_test_no_output "set debug-file-directory $debugdir" "set debug-file-directory"
|
||||
+
|
||||
@@ -236,3 +170,68 @@ new file mode 100644
|
||||
+
|
||||
+gdb_test "bt"
|
||||
+gdb_test "info shared"
|
||||
diff --git a/gdb/testsuite/gdb.base/rhbz981154-misleading-yum-install-warning.exp b/gdb/testsuite/gdb.base/rhbz981154-misleading-yum-install-warning.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/rhbz981154-misleading-yum-install-warning.exp
|
||||
@@ -0,0 +1,60 @@
|
||||
+# 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/>.
|
||||
+
|
||||
+# Create a core file, then hide the executable. Restart GDB and load
|
||||
+# the core file. Check GDB gives a message suggesting a 'dnf' command
|
||||
+# to try and install the executable based on its build-id.
|
||||
+
|
||||
+standard_testfile "normal.c"
|
||||
+
|
||||
+if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+# Get the build-id of the file.
|
||||
+set build_id_debug_file [build_id_debug_filename_get $binfile]
|
||||
+regsub -all ".debug$" $build_id_debug_file "" build_id_without_debug
|
||||
+
|
||||
+# Run to main.
|
||||
+if { ![runto_main] } {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+# We first need to generate a corefile.
|
||||
+set corefilename "[standard_output_file gcore.test]"
|
||||
+if { ![gdb_gcore_cmd "$corefilename" "save corefile"] } {
|
||||
+ untested "could not generate a corefile"
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+# Move the binfile to a temporary name.
|
||||
+remote_exec build "mv $binfile ${binfile}.old"
|
||||
+
|
||||
+# Reinitialize GDB and see if we get a dnf suggestion.
|
||||
+clean_restart
|
||||
+
|
||||
+gdb_test "set build-id-verbose 1" "" \
|
||||
+ "set build-id-verbose"
|
||||
+
|
||||
+# GDB only makes build-id based RPM suggestions if /usr/lib is in
|
||||
+# the debug-file-directory list, the reason being that system RPMs
|
||||
+# will always install under this location. If GDB is not looking
|
||||
+# here then there's no point making suggestions.
|
||||
+gdb_test "set debug-file-directory /usr/lib/" "" \
|
||||
+ "set debug-file-directory"
|
||||
+
|
||||
+gdb_test "core-file [standard_output_file gcore.test]" \
|
||||
+ "Missing file\\(s\\), try: dnf --enablerepo='\\*debug\\*' install [string_to_regexp /usr/lib/$build_id_without_debug] [string_to_regexp /usr/lib/debug/$build_id_debug_file]" \
|
||||
+ "test first yum/dnf warning"
|
File diff suppressed because it is too large
Load Diff
@@ -1,188 +0,0 @@
|
||||
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"
|
@@ -1,32 +0,0 @@
|
||||
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"
|
68
gdb-add-deprecated-settings-py-script.patch
Normal file
68
gdb-add-deprecated-settings-py-script.patch
Normal file
@@ -0,0 +1,68 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Burgess <aburgess@redhat.com>
|
||||
Date: Tue, 19 Nov 2024 13:56:56 +0000
|
||||
Subject: gdb-add-deprecated-settings-py-script.patch
|
||||
|
||||
;; Not a backport. Add a new script which defines a setting which is
|
||||
;; deprecated, but we don't want to remove it from Fedora GDB just yet.
|
||||
|
||||
gdb: add script which defines a deprecated settings
|
||||
|
||||
The build-id-core-load setting has not been useful since 2020, but its
|
||||
not clear when it will be OK to remove this from GDB.
|
||||
|
||||
Rather than defining this setting in C++ code, lets just create it
|
||||
using this Python script, this helps keep the Fedora stuff out of core
|
||||
GDB.
|
||||
|
||||
diff --git a/gdb/data-directory/Makefile.in b/gdb/data-directory/Makefile.in
|
||||
--- a/gdb/data-directory/Makefile.in
|
||||
+++ b/gdb/data-directory/Makefile.in
|
||||
@@ -86,6 +86,7 @@ PYTHON_FILE_LIST = \
|
||||
gdb/unwinder.py \
|
||||
gdb/xmethod.py \
|
||||
gdb/command/__init__.py \
|
||||
+ gdb/command/deprecated-settings.py \
|
||||
gdb/command/explore.py \
|
||||
gdb/command/frame_filters.py \
|
||||
gdb/command/missing_files.py \
|
||||
diff --git a/gdb/python/lib/gdb/command/deprecated-settings.py b/gdb/python/lib/gdb/command/deprecated-settings.py
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/python/lib/gdb/command/deprecated-settings.py
|
||||
@@ -0,0 +1,35 @@
|
||||
+import gdb
|
||||
+
|
||||
+# This setting was added to Fedora GDB back in 2007. It controlled
|
||||
+# whether GDB would use the build-id extracted from a core file to
|
||||
+# auto-load the executable if the user had not already loaded an
|
||||
+# executable.
|
||||
+#
|
||||
+# In 2020 this setting was effectively deprecated as the only use of
|
||||
+# the setting's value was removed. After this GDB would always
|
||||
+# auto-load an executable based on the build-id if no executable was
|
||||
+# already loaded.
|
||||
+#
|
||||
+# For now we maintain this setting for backward compatibility reasons.
|
||||
+
|
||||
+class build_id_core_load(gdb.Parameter):
|
||||
+ """This setting is deprecated. Changing it will have no effect.
|
||||
+ This is maintained only for backwards compatibility.
|
||||
+
|
||||
+ When opening a core-file, and no executable is loaded, GDB will
|
||||
+ always try to auto-load a suitable executable using the build-id
|
||||
+ extracted from the core file (if a suitable build-id can be
|
||||
+ found)."""
|
||||
+
|
||||
+ def __init__(self):
|
||||
+ self.set_doc = "This setting is deprecated and has no effect."
|
||||
+ self.show_doc = "This setting is deprecated and has no effect."
|
||||
+ self.value = True
|
||||
+
|
||||
+ super().__init__("build-id-core-load", gdb.COMMAND_DATA, gdb.PARAM_BOOLEAN)
|
||||
+ def validate(self):
|
||||
+ return True
|
||||
+ def get_set_string(self):
|
||||
+ raise gdb.GdbError("The 'build-id-core-load' setting is deprecated.")
|
||||
+
|
||||
+build_id_core_load()
|
40
gdb-add-rpm-suggestion-script-suse.patch
Normal file
40
gdb-add-rpm-suggestion-script-suse.patch
Normal file
@@ -0,0 +1,40 @@
|
||||
From 423c53757e2fe22815fef8a04abf21caff951937 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Tue, 25 Mar 2025 14:12:51 +0100
|
||||
Subject: [PATCH 1/4] [distro] Update gdb-add-rpm-suggestion-script.patch for
|
||||
SUSE
|
||||
|
||||
---
|
||||
gdb/python/lib/gdb/command/rpm-suggestions.py | 7 +++++--
|
||||
1 file changed, 5 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/gdb/python/lib/gdb/command/rpm-suggestions.py b/gdb/python/lib/gdb/command/rpm-suggestions.py
|
||||
index 156fce0672b..f1034070989 100644
|
||||
--- a/gdb/python/lib/gdb/command/rpm-suggestions.py
|
||||
+++ b/gdb/python/lib/gdb/command/rpm-suggestions.py
|
||||
@@ -358,7 +358,7 @@ else:
|
||||
# Take a non-empty list of RPM names and print a command line a
|
||||
# user could run to install these RPMs.
|
||||
def print_rpm_suggestions(rpm_name_list):
|
||||
- print("Missing rpms, try: dnf --enablerepo='*debug*' install " + ' '.join(rpm_name_list))
|
||||
+ print("Missing separate debuginfos, use: zypper install " + ' '.join(rpm_name_list))
|
||||
|
||||
# Take a non-empty list of build-id strings and print a series of
|
||||
# lines that a user could run to instll the RPMs that provide
|
||||
@@ -423,7 +423,10 @@ else:
|
||||
|
||||
# Register the missing debug and missing objfile handlers with GDB.
|
||||
gdb.missing_debug.register_handler(None, RPM_MissingDebugHandler())
|
||||
- gdb.missing_objfile.register_handler(None, RPM_MissingObjfileHandler())
|
||||
+
|
||||
+ # Not enabled for SUSE/openSUSE. Zypper doesn't support finding packages
|
||||
+ # based on build-id, unless the package's installed.
|
||||
+ #gdb.missing_objfile.register_handler(None, RPM_MissingObjfileHandler())
|
||||
|
||||
# Implement the core of 'info rpm-suggestions'. Reprint all rpm
|
||||
# suggestions.
|
||||
|
||||
base-commit: 956ad1d51aa6e4117a98c4124bd7154a1aaeec55
|
||||
--
|
||||
2.43.0
|
||||
|
806
gdb-add-rpm-suggestion-script.patch
Normal file
806
gdb-add-rpm-suggestion-script.patch
Normal file
@@ -0,0 +1,806 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Burgess <aburgess@redhat.com>
|
||||
Date: Thu, 7 Mar 2024 15:14:23 +0000
|
||||
Subject: gdb-add-rpm-suggestion-script.patch
|
||||
|
||||
;; Not a backport. Add a new script which hooks into GDB and suggests
|
||||
;; RPMs to install when GDB finds an objfile with no debug info.
|
||||
|
||||
gdb: add script which will suggest debuginfo RPMs to install
|
||||
|
||||
This script hooks into GDB's missing debug info Python API and
|
||||
suggests debuginfo RPMs to install.
|
||||
|
||||
diff --git a/gdb/data-directory/Makefile.in b/gdb/data-directory/Makefile.in
|
||||
--- a/gdb/data-directory/Makefile.in
|
||||
+++ b/gdb/data-directory/Makefile.in
|
||||
@@ -91,6 +91,7 @@ PYTHON_FILE_LIST = \
|
||||
gdb/command/missing_files.py \
|
||||
gdb/command/pretty_printers.py \
|
||||
gdb/command/prompt.py \
|
||||
+ gdb/command/rpm-suggestions.py \
|
||||
gdb/command/type_printers.py \
|
||||
gdb/command/unwinders.py \
|
||||
gdb/command/xmethods.py \
|
||||
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
|
||||
--- a/gdb/doc/gdb.texinfo
|
||||
+++ b/gdb/doc/gdb.texinfo
|
||||
@@ -186,6 +186,7 @@
|
||||
* Trace File Format:: @value{GDBN} trace file format
|
||||
* Index Section Format:: .gdb_index section format
|
||||
* Debuginfod:: Download debugging resources with @code{debuginfod}
|
||||
+* RPM Suggestions:: RPM Suggestions from GDB
|
||||
* Man Pages:: Manual pages
|
||||
* Copying:: GNU General Public License says
|
||||
how you can copy and share @value{GDBN}
|
||||
@@ -50341,6 +50342,111 @@
|
||||
|
||||
@end table
|
||||
|
||||
+@node RPM Suggestions
|
||||
+@appendix Receiving RPM installation suggestions
|
||||
+@cindex rpm suggestions
|
||||
+
|
||||
+When @value{GDBN} loads an executable, or shared library, and cannot
|
||||
+find the corresponding debug information, @value{GDBN} will check to
|
||||
+see if an RPM is available which could provide the missing debug
|
||||
+information. If a suitable RPM is found then @value{GDBN} will print
|
||||
+a hint before the next prompt is displayed:
|
||||
+
|
||||
+@smallexample
|
||||
+(@value{GDBP}) file /bin/ls
|
||||
+Reading symbols from /bin/ls...
|
||||
+Reading symbols from .gnu_debugdata for /usr/bin/ls...
|
||||
+(No debugging symbols found in .gnu_debugdata for /usr/bin/ls)
|
||||
+Missing rpms, try: dnf --enablerepo='*debug*' install coreutils-debuginfo-9.3-7.fc39.x86_64
|
||||
+(@value{GDBP})
|
||||
+@end smallexample
|
||||
+
|
||||
+In this case, installing @file{coreutils-debuginfo-9.3-7.fc39.x86_64}
|
||||
+will provide the missing debug information for @file{/bin/ls}. It is
|
||||
+up to you to install the suggested package, if possible, and after
|
||||
+that reload the executable in @value{GDBN} so that the newly installed
|
||||
+debug information can be found.
|
||||
+
|
||||
+The RPM suggestion feature can be disabled:
|
||||
+
|
||||
+@table @code
|
||||
+@kindex set rpm-suggestion enabled
|
||||
+@kindex show rpm-suggestion enabled
|
||||
+@cindex rpm suggestions, disabling
|
||||
+@item set rpm-suggestion enabled @r{[}on@r{|}off@r{]}
|
||||
+@itemx show rpm-suggestion enabled
|
||||
+When @samp{on} @value{GDBN} will make RPM suggestions where possible.
|
||||
+When @samp{off} all RPM suggestion will be disabled.
|
||||
+@end table
|
||||
+
|
||||
+When opening a core file (@pxref{core-file command}), it may be the
|
||||
+case that not only is the debug information missing, but the
|
||||
+corresponding executable itself is missing. For example, if a core
|
||||
+file is copied from one machine to another in order to debug.
|
||||
+
|
||||
+In this case @value{GDBN} is able to suggest a command which will
|
||||
+install the missing executable based on the build-id of the
|
||||
+executable. For example:
|
||||
+
|
||||
+@smallexample
|
||||
+(@value{GDBP}) core-file /tmp/core.5489
|
||||
+warning: Can't open file /usr/bin/sl during file-backed mapping note processing
|
||||
+[New LWP 5489]
|
||||
+Core was generated by `sl'.
|
||||
+Program terminated with signal SIGQUIT, Quit.
|
||||
+#0 0x00007f1b41ced1a7 in ?? ()
|
||||
+Missing file(s), try: dnf --enablerepo='*debug*' install /usr/lib/.build-id/33/2f1a8e56693960e3beb2d70cd79ddfec451cc3 /usr/lib/debug/.build-id/33/2f1a8e56693960e3beb2d70cd79ddfec451cc3.debug
|
||||
+(@value{GDBP})
|
||||
+@end smallexample
|
||||
+
|
||||
+The core file was generated from the @file{/usr/bin/sl} binary, which
|
||||
+is not present on the machine opening the core file. @value{GDBN} has
|
||||
+suggested a command, based on the build-id of the binary, which was
|
||||
+extracted from the core file, that would install both the missing
|
||||
+binary, and the corresponding debug information.
|
||||
+
|
||||
+Unfortunately, @value{GDBN} doesn't know if the suggested command will
|
||||
+actually find a matching RPM or not. Querying the RPM database to see
|
||||
+which packages, if any, will provide a file with the given build-id,
|
||||
+is rather slow. As @file{/usr/bin/sl} is available in an RPM, then
|
||||
+the above command will succeed.
|
||||
+
|
||||
+It is possible to have @value{GDBN} check to see if there is a package
|
||||
+available before making the suggestion, but this is significantly
|
||||
+slower. To enable this mode use the following command:
|
||||
+
|
||||
+@table @code
|
||||
+@kindex set rpm-suggestion build-id-mode
|
||||
+@kindex show rpm-suggestion build-id-mode
|
||||
+@cindex rpm suggestions, build-id-mode
|
||||
+@item set rpm-suggestion build-id-mode @r{[}fast@r{|}slow@r{]}
|
||||
+@itemx show rpm-suggestion build-id-mode
|
||||
+When set to @samp{fast}, which is the default, @value{GDBN} will offer
|
||||
+suggestions based on the build-id of any missing executables or shared
|
||||
+libraries while opening a core file. This is fast, but @value{GDBN}
|
||||
+has not checked if there is a package available that can supply the
|
||||
+required file, so running the suggested command might not install any
|
||||
+packages.
|
||||
+
|
||||
+When set to @samp{slow}, each time @value{GDBN} encounters an
|
||||
+executable, or shared library, that is missing, @value{GDBN} will
|
||||
+check to see if there is an RPM available that will supply the missing
|
||||
+binary. If a suitable RPM is found then @value{GDBN} will offer a
|
||||
+command which will install the missing RPM. If no suitable RPM is
|
||||
+found then @value{GDBN} will make no suggestions.
|
||||
+@end table
|
||||
+
|
||||
+It is possible to review all of the previous RPM suggestions that
|
||||
+@value{GDBN} has made using the following command:
|
||||
+
|
||||
+@table @code
|
||||
+@kindex info rpm-suggestions
|
||||
+@cindex rpm suggestions, listing
|
||||
+@item info rpm-suggestions
|
||||
+List all of the RPM suggestions @value{GDBN} has made since the
|
||||
+executable was last changed.
|
||||
+@end table
|
||||
+
|
||||
@node Man Pages
|
||||
@appendix Manual pages
|
||||
@cindex Man pages
|
||||
diff --git a/gdb/python/lib/gdb/command/rpm-suggestions.py b/gdb/python/lib/gdb/command/rpm-suggestions.py
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/python/lib/gdb/command/rpm-suggestions.py
|
||||
@@ -0,0 +1,552 @@
|
||||
+# 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/>.
|
||||
+
|
||||
+import gdb
|
||||
+import gdb.missing_debug
|
||||
+import gdb.missing_objfile
|
||||
+
|
||||
+# These modules are all system modules, and should be available on any
|
||||
+# correctly setup Python install.
|
||||
+import sys
|
||||
+import os
|
||||
+import subprocess
|
||||
+import re
|
||||
+from threading import Thread
|
||||
+import time
|
||||
+
|
||||
+try:
|
||||
+ import rpm
|
||||
+except ModuleNotFoundError:
|
||||
+ # The "RPM suggestions" mechanism will not work without the (python)
|
||||
+ # rpm module. Inform the user of this, but wait to do so until
|
||||
+ # just prior to printing the GDB prompt. If we do it right away,
|
||||
+ # the message typically appears before the version and copyright
|
||||
+ # info, which is easily missed by many users. Additionally, it
|
||||
+ # seems that several other packages which parse GDB version info
|
||||
+ # are confused by an early error message regarding a missing
|
||||
+ # python3-rpm package, so waiting to print the error allows those
|
||||
+ # applications to work as they used to.
|
||||
+ def before_prompt():
|
||||
+ print(
|
||||
+ ("\nUnable to load the Python 'rpm' module. Lack of this module disables\n"
|
||||
+ "the RPM suggestions mechanism which recommends shell commands for\n"
|
||||
+ "installing missing debuginfo packages. To enable this functionality,\n"
|
||||
+ "please install the python3-rpm package."),
|
||||
+ file=sys.stderr
|
||||
+ )
|
||||
+ gdb.events.before_prompt.disconnect(before_prompt)
|
||||
+
|
||||
+ gdb.events.before_prompt.connect(before_prompt)
|
||||
+
|
||||
+ # Implement 'info rpm-suggestions' when the 'rpm' module is not
|
||||
+ # available. Just throws an error.
|
||||
+ def info_rpm_suggestions():
|
||||
+ raise gdb.GdbError("rpm-suggestions are disabled as the Python 'rpm' module is not installed")
|
||||
+else:
|
||||
+ # Track all the RPMs suggested during a single debug session so we
|
||||
+ # don't suggest the same RPM twice. This is only cleared when the
|
||||
+ # main executable is changed.
|
||||
+ __missing_rpms = {}
|
||||
+
|
||||
+ # Track any missing RPMs that have been discovered since the last time
|
||||
+ # the prompt was displayed. RPMs in here are also present in the
|
||||
+ # __MISSING_RPMS dictionary, but this dictionary is cleared each time
|
||||
+ # the prompt is shown.
|
||||
+ __suggest_rpms = {}
|
||||
+
|
||||
+ # Track all the build-ids suggested during a single debug session so we
|
||||
+ # don't suggest installing using the same build-id twice. This is only
|
||||
+ # cleared when the main executable is changed.
|
||||
+ __missing_build_ids = {}
|
||||
+
|
||||
+ # Track any build-ids that have been discovered missing since the last
|
||||
+ # time the prompt was displayed. Build-ids in here are also present in
|
||||
+ # the __MISSING_BUILD_IDS dictionary, but this dictionary is cleared
|
||||
+ # each time the prompt is shown.
|
||||
+ __suggest_build_ids = {}
|
||||
+
|
||||
+ # The build-id to RPM lookup is very slow. This cache maps
|
||||
+ # build-ids to the set of RPM we can suggest installing. The key
|
||||
+ # is the build-id string, and the value is a list of RPM names, or
|
||||
+ # None if there was an error with the build-id to RPM lookup.
|
||||
+ #
|
||||
+ # This cache is never cleared, even when the executable is
|
||||
+ # changed. The build-ids should be unique, so a build-id lookup
|
||||
+ # should be good for the lifetime of the session.
|
||||
+ __build_id_lookup_cache = {}
|
||||
+
|
||||
+ # When searching for an RPM given a build-id, if the search takes
|
||||
+ # too long, then a message is printed to the user. We only print
|
||||
+ # the message once between each GDB prompt. This flag is set True
|
||||
+ # when the message is printed, and reset to False when a prompt is
|
||||
+ # displayed.
|
||||
+ __searching_message_printed = False
|
||||
+
|
||||
+ # Add a suggestion to install RPM_NAME (the full name of an RPM)
|
||||
+ # to the list of suggestions to make the next time a prompt is
|
||||
+ # displayed.
|
||||
+ def add_rpm_suggestion(rpm_name):
|
||||
+ global __missing_rpms
|
||||
+ global __suggest_rpms
|
||||
+
|
||||
+ if not rpm_name in __missing_rpms:
|
||||
+ __suggest_rpms[rpm_name] = True
|
||||
+ __missing_rpms[rpm_name] = True
|
||||
+
|
||||
+ # Return True if RPM_NAME is installed, where RPM_NAME is the full
|
||||
+ # name of an RPM.
|
||||
+ def is_rpm_installed(ts, rpm_name):
|
||||
+ res = ts.dbMatch(rpm.RPMDBI_LABEL, rpm_name)
|
||||
+ return len(res) > 0
|
||||
+
|
||||
+ # Add a suggestion to install RPMs based on BUILD_ID, a string
|
||||
+ # containing a build-id, to the list of suggestions to make the next
|
||||
+ # time a prompt is displayed.
|
||||
+ def add_build_id_suggestion(build_id):
|
||||
+ global __missing_build_ids
|
||||
+ global __suggest_build_ids
|
||||
+
|
||||
+ if not build_id in __missing_build_ids:
|
||||
+ __suggest_build_ids[build_id] = True
|
||||
+ __missing_build_ids[build_id] = True
|
||||
+
|
||||
+ # Return true if '/usr/lib' is in the debug-file-directory list.
|
||||
+ # System packages install their debug information into /usr/lib,
|
||||
+ # so if GDB isn't looking in that directory, then there's no
|
||||
+ # reason to try and figure out a suitable RPM to install.
|
||||
+ def using_suitable_debug_file_directory():
|
||||
+ debug_file_directories = gdb.parameter("debug-file-directory")
|
||||
+ for d in debug_file_directories.split(os.pathsep):
|
||||
+ if d[:8] == "/usr/lib":
|
||||
+ return True
|
||||
+ return False
|
||||
+
|
||||
+ # Return True if rpm-suggestion is disabled for any reason.
|
||||
+ def rpm_suggestion_is_disabled():
|
||||
+ global param_build_id_verbose
|
||||
+
|
||||
+ # If /usr/lib/ is not being used to find debug information
|
||||
+ # then there's no point offering any RPMs as GDB would not
|
||||
+ # find the newly installed content.
|
||||
+ if not using_suitable_debug_file_directory():
|
||||
+ return True
|
||||
+
|
||||
+ # For backwards compatibility, if build-id-verbose is set to
|
||||
+ # zero, then disable RPM suggestion.
|
||||
+ if param_build_id_verbose.value == 0:
|
||||
+ return True
|
||||
+
|
||||
+ # Is 'rpm-suggestion enabled' set to 'off'?
|
||||
+ if not param_rpm_suggestion_enabled.value:
|
||||
+ return True
|
||||
+
|
||||
+ return False
|
||||
+
|
||||
+
|
||||
+ # Lookup RPMs that might provide the debug information for FILENAME,
|
||||
+ # which is a string containing the path to an object file GDB could
|
||||
+ # not find any debug information for.
|
||||
+ #
|
||||
+ # If a possible RPM is found then this is added to the globals
|
||||
+ # __MISSING_RPMS and __SUGGEST_RPMS, which are used elsewhere in this
|
||||
+ # script.
|
||||
+ def find_debug_suggestions(filename):
|
||||
+ if rpm_suggestion_is_disabled():
|
||||
+ return
|
||||
+
|
||||
+ ts = rpm.TransactionSet()
|
||||
+ mi = ts.dbMatch(rpm.RPMDBI_BASENAMES, filename)
|
||||
+ for h in mi:
|
||||
+ # Build the debuginfo package name.
|
||||
+ obj = h.format("%{name}-debuginfo-%{version}-%{release}.%{arch}")
|
||||
+ rpm_name = str(obj)
|
||||
+
|
||||
+ # Check to see if the package is installed.
|
||||
+ if is_rpm_installed(ts, rpm_name):
|
||||
+ continue
|
||||
+
|
||||
+ add_rpm_suggestion(rpm_name)
|
||||
+
|
||||
+
|
||||
+ # Return a string which is the filename of the filename
|
||||
+ # corresponding to BUILD_ID in one of the two locations under
|
||||
+ # /usr/lib.
|
||||
+ #
|
||||
+ # When DEBUG_P is True, return a filename within:
|
||||
+ # /usr/lib/debug/.build-id/ and when DEBUG_P is False, return a
|
||||
+ # filename within: /usr/lib/.build-id/.
|
||||
+ #
|
||||
+ # The SUFFIX string is appended to the generated filename.
|
||||
+ def build_id_to_usr_lib_filename(build_id, debug_p, suffix = ""):
|
||||
+ key = build_id[:2]
|
||||
+ rst = build_id[2:]
|
||||
+
|
||||
+ filename = '/usr/lib'
|
||||
+ if debug_p:
|
||||
+ filename += '/debug'
|
||||
+ filename += '/.build-id/' + key + '/' + rst + suffix
|
||||
+
|
||||
+ return filename
|
||||
+
|
||||
+ # A regexp object used to match against the output of `dnf`. This
|
||||
+ # is initialised the first time it is needed.
|
||||
+ find_objfile_suggestions_re = None
|
||||
+
|
||||
+ # Given BUILD_ID, a string containing a build-id, run a `dnf`
|
||||
+ # command to figure out if any RPMs can provide a file with that
|
||||
+ # build-id.
|
||||
+ #
|
||||
+ # If any suitable RPMs are found then `add_rpm_suggestion` is called
|
||||
+ # to register the suggestion.
|
||||
+ #
|
||||
+ # This function is pretty slow, which is a shame, as the results
|
||||
+ # returned are much nicer than just telling the user to try the
|
||||
+ # lookup command for themselves.
|
||||
+ def find_objfile_suggestions_in_thread(build_id):
|
||||
+ global find_objfile_suggestions_re
|
||||
+
|
||||
+ if find_objfile_suggestions_re is None:
|
||||
+ find_objfile_suggestions_re = re.compile("^(.*)-debuginfo-(.*) : Debug information for package (.*)$")
|
||||
+
|
||||
+ result = subprocess.run(['dnf', "--enablerepo=*debug*", '--nogpgcheck', '-C', 'provides',
|
||||
+ build_id_to_usr_lib_filename(build_id, True)],
|
||||
+ capture_output=True, timeout=30)
|
||||
+
|
||||
+ lines = result.stdout.decode('utf-8').splitlines()
|
||||
+ ts = rpm.TransactionSet()
|
||||
+
|
||||
+ for l in lines:
|
||||
+ m = find_objfile_suggestions_re.match(l)
|
||||
+ if not m:
|
||||
+ continue
|
||||
+ if m.group(1) != m.group(3):
|
||||
+ return
|
||||
+
|
||||
+ main_rpm = m.group(1) + '-' + m.group(2)
|
||||
+ dbg_rpm = m.group(1) + '-debuginfo-' + m.group(2)
|
||||
+
|
||||
+ if not is_rpm_installed(ts, main_rpm):
|
||||
+ add_rpm_suggestion(main_rpm)
|
||||
+
|
||||
+ if not is_rpm_installed(ts, dbg_rpm):
|
||||
+ add_rpm_suggestion(dbg_rpm)
|
||||
+
|
||||
+ return
|
||||
+
|
||||
+ # Call `find_objfile_suggestions_in_thread` is a separate thread,
|
||||
+ # then wait for the thread to complete. Don't touch any shared
|
||||
+ # state while waiting for the thread to complete. There's no
|
||||
+ # locking on any of our caches, and the worker thread will add RPM
|
||||
+ # suggestions as it wants.
|
||||
+ #
|
||||
+ # If thre thread takes too long to complete then print a message
|
||||
+ # to the user telling them what's going on.
|
||||
+ def find_objfile_suggestions_slow_core(build_id):
|
||||
+ global __searching_message_printed
|
||||
+
|
||||
+ thread = Thread(target = find_objfile_suggestions_in_thread, args = (build_id, ))
|
||||
+ thread.start()
|
||||
+ start = time.time_ns()
|
||||
+
|
||||
+ while thread.is_alive ():
|
||||
+ time.sleep(0.05)
|
||||
+ now = time.time_ns ()
|
||||
+ if not __searching_message_printed and (now - start > 1000000000):
|
||||
+ print("Searching for packages to install that could improve debugging...")
|
||||
+ __searching_message_printed = True
|
||||
+
|
||||
+ thread.join()
|
||||
+
|
||||
+
|
||||
+ # Given BUILD_ID, a string containing a build-id, lookup suitable
|
||||
+ # RPMs that could be installed to provide a file with the required
|
||||
+ # build-id.
|
||||
+ #
|
||||
+ # Any suitable RPMs are recorded by calling `add_rpm_suggestion`, and
|
||||
+ # will be printed before the next prompt.
|
||||
+ def find_objfile_suggestions_slow(build_id):
|
||||
+ global __build_id_lookup_cache
|
||||
+ global __suggest_rpms
|
||||
+
|
||||
+ # The code to lookup an RPM given only a build-id is pretty
|
||||
+ # slow. Cache the results to try and reduce the UI delays.
|
||||
+ if build_id in __build_id_lookup_cache:
|
||||
+ rpms = __build_id_lookup_cache[build_id]
|
||||
+ if rpms is not None:
|
||||
+ for r in rpms:
|
||||
+ add_rpm_suggestion(r)
|
||||
+ return
|
||||
+
|
||||
+ # Make sure the cache entry exists before we do the lookup.
|
||||
+ # If, for any reason, the lookup raises an exception, then
|
||||
+ # having a cache entry will prevent us retrying this lookup in
|
||||
+ # the future.
|
||||
+ __build_id_lookup_cache[build_id] = None
|
||||
+
|
||||
+ # Now do the lookup. This is the slow part.
|
||||
+ find_objfile_suggestions_slow_core(build_id)
|
||||
+
|
||||
+ # Fill in the cache, for a given build-id which RPMs were
|
||||
+ # suggested.
|
||||
+ rpms = []
|
||||
+ for r in __suggest_rpms:
|
||||
+ rpms.append(r)
|
||||
+ __build_id_lookup_cache[build_id] = rpms
|
||||
+
|
||||
+
|
||||
+ # Given BUILD_ID, a string containing a build-id, just record that we
|
||||
+ # should advise the user to try installing RPMs based on this build-id.
|
||||
+ def find_objfile_suggestions_fast(build_id):
|
||||
+ add_build_id_suggestion(build_id)
|
||||
+
|
||||
+ # Given BUILD_ID, a string containing a build-id, which GDB has failed
|
||||
+ # to find, possibly record some information so that we can, at the next
|
||||
+ # prompt, give some RPM installation advice to the user.
|
||||
+ #
|
||||
+ # We have two different strategies for RPM lookup based on a build-id,
|
||||
+ # one approach is that we actually lookup the RPMs and only suggest
|
||||
+ # something if there is a suitable RPM. However, this is pretty slow,
|
||||
+ # and users will probably find this annoying.
|
||||
+ #
|
||||
+ # So we also have a fast way. With this approach we just record the
|
||||
+ # build-id that was missing and tell the user to try installing based on
|
||||
+ # the build-id. The downside with this is that if there is no RPM for
|
||||
+ # that build-id, then the user will try the command, but nothing will
|
||||
+ # install.
|
||||
+ def find_objfile_suggestions(build_id):
|
||||
+ if rpm_suggestion_is_disabled():
|
||||
+ return
|
||||
+
|
||||
+ if param_rpm_suggestion_build_id_mode.fast_mode():
|
||||
+ find_objfile_suggestions_fast(build_id)
|
||||
+ else:
|
||||
+ find_objfile_suggestions_slow(build_id)
|
||||
+
|
||||
+ # A missing debug handler class. Just forwards the name of the
|
||||
+ # objfile for which we are missing debug information to
|
||||
+ # find_debug_suggestions.
|
||||
+ class RPM_MissingDebugHandler(gdb.missing_debug.MissingDebugHandler):
|
||||
+ def __init__(self):
|
||||
+ super().__init__("rpm-suggestions")
|
||||
+
|
||||
+ def __call__(self, objfile):
|
||||
+ find_debug_suggestions(objfile.filename)
|
||||
+ return False
|
||||
+
|
||||
+ # A missing objfile handler class. Just forwards the build-id of
|
||||
+ # the objfile that is missing to find_objfile_suggestions.
|
||||
+ class RPM_MissingObjfileHandler(gdb.missing_objfile.MissingObjfileHandler):
|
||||
+ def __init__(self):
|
||||
+ super().__init__("rpm-suggestions")
|
||||
+
|
||||
+ def __call__(self, pspace, build_id, filename):
|
||||
+ find_objfile_suggestions(build_id)
|
||||
+ return False
|
||||
+
|
||||
+ # Take a non-empty list of RPM names and print a command line a
|
||||
+ # user could run to install these RPMs.
|
||||
+ def print_rpm_suggestions(rpm_name_list):
|
||||
+ print("Missing rpms, try: dnf --enablerepo='*debug*' install " + ' '.join(rpm_name_list))
|
||||
+
|
||||
+ # Take a non-empty list of build-id strings and print a series of
|
||||
+ # lines that a user could run to instll the RPMs that provide
|
||||
+ # files with this build-id.
|
||||
+ #
|
||||
+ # The printed commands will also install the corresponding debug
|
||||
+ # packages for the executable with the given build-id.
|
||||
+ def print_build_id_suggestions(build_id_list):
|
||||
+ for build_id in build_id_list:
|
||||
+ print("Missing file(s), try: dnf --enablerepo='*debug*' install "
|
||||
+ + build_id_to_usr_lib_filename(build_id, False)
|
||||
+ + ' '
|
||||
+ + build_id_to_usr_lib_filename(build_id, True, ".debug"))
|
||||
+
|
||||
+ # Called before GDB displays its prompt. If the global __SUGGEST_RPMS
|
||||
+ # dictionary is not empty, then this hook prints the keys of this
|
||||
+ # dictionary as strings which are the names of RPMs. This hook formats
|
||||
+ # each RPM name into a suggested 'dnf install' command and suggests this
|
||||
+ # to the user.
|
||||
+ #
|
||||
+ # Additionally, if the global __SUGGEST_BUILD_IDS dictionary is not
|
||||
+ # empty, then this hook uses the keys of this dictionary as build-ids
|
||||
+ # that were found to be missing, and formats these into some file based
|
||||
+ # 'dnf install' suggestions to the user.
|
||||
+ def before_prompt():
|
||||
+ global __suggest_rpms
|
||||
+ global __suggest_build_ids
|
||||
+ global __searching_message_printed
|
||||
+
|
||||
+ # We allow the searching message to be printed just once
|
||||
+ # between prompts.
|
||||
+ __searching_message_printed = False
|
||||
+
|
||||
+ if len(__suggest_rpms) > 0:
|
||||
+ print_rpm_suggestions(__suggest_rpms.keys())
|
||||
+ __suggest_rpms = {}
|
||||
+
|
||||
+ if len(__suggest_build_ids) > 0:
|
||||
+ print_build_id_suggestions(__suggest_build_ids.keys())
|
||||
+ __suggest_build_ids = {}
|
||||
+
|
||||
+ # Called when the executable within a progrm space is changed. Clear
|
||||
+ # the lists of RPM suggestions. We only clear the previous suggestion
|
||||
+ # list when the executable really changes. If the user simply
|
||||
+ # recompiles the executable, then we don't both clearing this list.
|
||||
+ def executable_changed_handler(event):
|
||||
+ global __missing_rpms
|
||||
+ global __suggest_rpms
|
||||
+ global __suggest_build_ids
|
||||
+ global __missing_build_ids
|
||||
+
|
||||
+ if not event.reload:
|
||||
+ __missing_rpms = {}
|
||||
+ __suggest_rpms = {}
|
||||
+ __missing_build_ids = {}
|
||||
+ __suggest_build_ids = {}
|
||||
+
|
||||
+
|
||||
+ # Attach to the required GDB events.
|
||||
+ gdb.events.executable_changed.connect(executable_changed_handler)
|
||||
+ gdb.events.before_prompt.connect(before_prompt)
|
||||
+
|
||||
+ # Register the missing debug and missing objfile handlers with GDB.
|
||||
+ gdb.missing_debug.register_handler(None, RPM_MissingDebugHandler())
|
||||
+ gdb.missing_objfile.register_handler(None, RPM_MissingObjfileHandler())
|
||||
+
|
||||
+ # Implement the core of 'info rpm-suggestions'. Reprint all rpm
|
||||
+ # suggestions.
|
||||
+ def info_rpm_suggestions():
|
||||
+ global __missing_rpms
|
||||
+ global __missing_build_ids
|
||||
+
|
||||
+ if len(__missing_rpms) == 0 and len(__missing_build_ids) == 0:
|
||||
+ print("No RPM suggestions have been made so far.")
|
||||
+ return
|
||||
+
|
||||
+ if len(__missing_rpms) > 0:
|
||||
+ print_rpm_suggestions(__missing_rpms.keys())
|
||||
+ if len(__missing_build_ids) > 0:
|
||||
+ print_build_id_suggestions(__missing_build_ids.keys())
|
||||
+
|
||||
+####################################################################
|
||||
+# The following code is outside the 'else' block of the attempt to #
|
||||
+# load the 'rpm' module. Nothing after this point depends on the #
|
||||
+# 'rpm' module. #
|
||||
+####################################################################
|
||||
+
|
||||
+# The 'set rpm-suggestion' prefix command.
|
||||
+class rpm_suggestion_set_prefix(gdb.Command):
|
||||
+ """Prefix command for 'set' rpm-suggestion related commands."""
|
||||
+
|
||||
+ def __init__(self):
|
||||
+ super().__init__("set rpm-suggestion", gdb.COMMAND_NONE,
|
||||
+ gdb.COMPLETE_NONE, True)
|
||||
+
|
||||
+# The 'show rpm-suggestion' prefix command.
|
||||
+class rpm_suggestion_show_prefix(gdb.Command):
|
||||
+ """Prefix command for 'show' rpm-suggestion related commands."""
|
||||
+
|
||||
+ def __init__(self):
|
||||
+ super().__init__("show rpm-suggestion", gdb.COMMAND_NONE,
|
||||
+ gdb.COMPLETE_NONE, True)
|
||||
+
|
||||
+# The 'set/show rpm-suggestion enabled' command.
|
||||
+class rpm_suggestion_enabled(gdb.Parameter):
|
||||
+ """
|
||||
+ When 'on' GDB will search for RPMS that might provide additional
|
||||
+ debug information, or provide missing executables or shared
|
||||
+ libraries (when opening a core file), and will make suggestions
|
||||
+ about what should be installed.
|
||||
+
|
||||
+ When 'off' GDB will not make these suggestions.
|
||||
+ """
|
||||
+
|
||||
+ set_doc = "Set whether to perform rpm-suggestion."
|
||||
+ show_doc = "Show whether rpm-suggestion is enabled."
|
||||
+
|
||||
+ def __init__(self):
|
||||
+ super().__init__("rpm-suggestion enabled", gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)
|
||||
+ self.value = True
|
||||
+
|
||||
+# The 'set/show rpm-suggestion enabled' command.
|
||||
+class rpm_suggestion_build_id_mode(gdb.Parameter):
|
||||
+ """
|
||||
+ When set to 'fast' (the default), GDB doesn't try to map a build-id to
|
||||
+ an actual RPM, instead, GDB just suggests a command based on the
|
||||
+ build-id which might install some RPMs, if there are any RPMs that
|
||||
+ supply that build-id. However, it is equally possible that there are no
|
||||
+ suitable RPMs, and nothing will install. This approach has almost zero
|
||||
+ overhead.
|
||||
+
|
||||
+ When set to 'slow', GDB first does the build-id to RPM check itself, and
|
||||
+ only if something is found are RPMs installation commands suggested.
|
||||
+ The suggested command will include the name of the RPM to install. This
|
||||
+ approach is considerably slower as querying the RPM database for the RPM
|
||||
+ that supplies a specific file is slow.
|
||||
+ """
|
||||
+
|
||||
+ set_doc = "Set how build-id based rpm suggestions should be performed."
|
||||
+ show_doc = "Show how build-id based rpm suggestions shoud be performed."
|
||||
+
|
||||
+ def __init__(self):
|
||||
+ super().__init__("rpm-suggestion build-id-mode",
|
||||
+ gdb.COMMAND_NONE, gdb.PARAM_ENUM, ["fast", "slow"])
|
||||
+ self.value = "fast"
|
||||
+
|
||||
+ def fast_mode(self):
|
||||
+ return self.value == "fast"
|
||||
+
|
||||
+# The 'info rpm-suggestions' command.
|
||||
+class rpm_suggestion_info(gdb.Command):
|
||||
+ """Relist any RPM installation suggestions that have been made
|
||||
+ since the executable was last changed."""
|
||||
+ def __init__(self):
|
||||
+ super().__init__("info rpm-suggestions", gdb.COMMAND_NONE, gdb.COMPLETE_NONE)
|
||||
+
|
||||
+ def invoke(self, args, from_tty):
|
||||
+ if args != "":
|
||||
+ raise gdb.GdbError("unexpected arguments: %s" % args)
|
||||
+
|
||||
+ info_rpm_suggestions ()
|
||||
+
|
||||
+
|
||||
+# Create the 'set/show rpm-suggestion' commands.
|
||||
+rpm_suggestion_set_prefix()
|
||||
+rpm_suggestion_show_prefix()
|
||||
+param_rpm_suggestion_enabled = rpm_suggestion_enabled()
|
||||
+param_rpm_suggestion_build_id_mode = rpm_suggestion_build_id_mode()
|
||||
+
|
||||
+# Create the 'info rpm-suggestions' commands.
|
||||
+rpm_suggestion_info()
|
||||
+
|
||||
+# Create the 'build-id-verbose' parameter. This is implemented as an
|
||||
+# integer for backward compatibility reasons. It would be nice to
|
||||
+# convert this to a boolean, but it's not clear if that will break
|
||||
+# existing users uses of this flag.
|
||||
+
|
||||
+class build_id_verbose(gdb.Parameter):
|
||||
+ """
|
||||
+ Level 0 disable printing the missing debug filesname,
|
||||
+ Level 1 (default) enables printing the missing debug filenames,
|
||||
+ """
|
||||
+
|
||||
+ set_doc = "Set debugging level of the build-id locator."
|
||||
+ show_doc = "Show debugging level of the build-id locator."
|
||||
+
|
||||
+ def __init__(self):
|
||||
+ super().__init__("build-id-verbose", gdb.COMMAND_NONE, gdb.PARAM_ZINTEGER)
|
||||
+ self.value = 1
|
||||
+
|
||||
+param_build_id_verbose = build_id_verbose()
|
||||
diff --git a/gdb/testsuite/gdb.base/gdbinit-history.exp b/gdb/testsuite/gdb.base/gdbinit-history.exp
|
||||
--- a/gdb/testsuite/gdb.base/gdbinit-history.exp
|
||||
+++ b/gdb/testsuite/gdb.base/gdbinit-history.exp
|
||||
@@ -179,7 +179,8 @@ proc test_empty_history_filename { } {
|
||||
global env
|
||||
global gdb_prompt
|
||||
|
||||
- set common_history [list "set height 0" "set width 0"]
|
||||
+ set common_history [list "set height 0" "set width 0" \
|
||||
+ "set build-id-verbose 0"]
|
||||
|
||||
set test_dir [standard_output_file history_test]
|
||||
remote_exec host "mkdir -p $test_dir"
|
||||
diff --git a/gdb/testsuite/gdb.python/py-missing-debug.py b/gdb/testsuite/gdb.python/py-missing-debug.py
|
||||
--- a/gdb/testsuite/gdb.python/py-missing-debug.py
|
||||
+++ b/gdb/testsuite/gdb.python/py-missing-debug.py
|
||||
@@ -19,6 +19,13 @@ from enum import Enum
|
||||
import gdb
|
||||
from gdb.missing_debug import MissingDebugHandler
|
||||
|
||||
+# This is a RHEL/Fedora work around: There's already a
|
||||
+# missing-debug-info handler registered for these versions of GDB.
|
||||
+# Discard the handler now so that the tests will pass (the tests
|
||||
+# assume no handler is currently registered).
|
||||
+gdb.missing_debug_handlers = []
|
||||
+
|
||||
+
|
||||
# A global log that is filled in by instances of the LOG_HANDLER class
|
||||
# when they are called.
|
||||
handler_call_log = []
|
||||
@@ -118,4 +125,7 @@ def register(name, locus=None):
|
||||
rhandler = exception_handler()
|
||||
handler_obj = handler()
|
||||
|
||||
+# Discard the rpm-suggestion handler.
|
||||
+gdb.missing_file_handlers = []
|
||||
+
|
||||
print("Success")
|
||||
diff --git a/gdb/testsuite/gdb.python/py-missing-objfile.py b/gdb/testsuite/gdb.python/py-missing-objfile.py
|
||||
--- a/gdb/testsuite/gdb.python/py-missing-objfile.py
|
||||
+++ b/gdb/testsuite/gdb.python/py-missing-objfile.py
|
||||
@@ -164,4 +164,7 @@ def register(name, locus=None):
|
||||
rhandler = exception_handler()
|
||||
handler_obj = handler()
|
||||
|
||||
+# Discard the rpm-suggestion handler.
|
||||
+gdb.missing_file_handlers = []
|
||||
+
|
||||
print("Success")
|
||||
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
|
||||
@@ -238,7 +238,8 @@ if ![info exists INTERNAL_GDBFLAGS] {
|
||||
"-nx" \
|
||||
"-q" \
|
||||
{-iex "set height 0"} \
|
||||
- {-iex "set width 0"}]]
|
||||
+ {-iex "set width 0"} \
|
||||
+ {-iex "set build-id-verbose 0"}]]
|
||||
|
||||
# If DEBUGINFOD_URLS is set, gdb will try to download sources and
|
||||
# debug info for f.i. system libraries. Prevent this.
|
||||
@@ -2493,6 +2494,18 @@ proc default_gdb_start { } {
|
||||
}
|
||||
}
|
||||
|
||||
+ # Turn off the missing debug info messages as the testsuite does
|
||||
+ # not expect them.
|
||||
+ send_gdb "set build-id-verbose 0\n"
|
||||
+ gdb_expect 10 {
|
||||
+ -re "$gdb_prompt $" {
|
||||
+ verbose "Disabled the missing debug info messages." 2
|
||||
+ }
|
||||
+ timeout {
|
||||
+ warning "Could not disable the missing debug info messages."
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
gdb_debug_init
|
||||
return 0
|
||||
}
|
||||
diff --git a/gdb/testsuite/lib/mi-support.exp b/gdb/testsuite/lib/mi-support.exp
|
||||
--- a/gdb/testsuite/lib/mi-support.exp
|
||||
+++ b/gdb/testsuite/lib/mi-support.exp
|
||||
@@ -321,6 +321,17 @@ proc default_mi_gdb_start { { flags {} } } {
|
||||
warning "Couldn't set the width to 0."
|
||||
}
|
||||
}
|
||||
+ # Turn off the missing debug info messages as the testsuite does
|
||||
+ # not expect them.
|
||||
+ send_gdb "190-gdb-set build-id-verbose 0\n"
|
||||
+ gdb_expect 10 {
|
||||
+ -re ".*190-gdb-set build-id-verbose 0\r\n190\\\^done\r\n$mi_gdb_prompt$" {
|
||||
+ verbose "Disabled the missing debug info messages." 2
|
||||
+ }
|
||||
+ timeout {
|
||||
+ warning "Could not disable the missing debug info messages."
|
||||
+ }
|
||||
+ }
|
||||
|
||||
if { $separate_inferior_pty } {
|
||||
mi_create_inferior_pty
|
@@ -59,7 +59,7 @@ new file mode 100644
|
||||
+# 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}] } {
|
||||
|
@@ -1,47 +0,0 @@
|
||||
From 40b2857e42b477832ca7fc2771b6cde910e22f05 Mon Sep 17 00:00:00 2001
|
||||
From: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
|
||||
Date: Tue, 23 Jan 2024 14:11:33 -0300
|
||||
Subject: [PATCH 4/7] gdb/arm: Fix epilogue frame id
|
||||
|
||||
arm_epilogue_frame_this_id has a comment saying that it fall backs to using
|
||||
the current PC if the function start address can't be identified, but it
|
||||
actually uses only the PC to make the frame id.
|
||||
|
||||
This patch makes the code match the comment. Another hint that it's what
|
||||
is intended is that arm_prologue_this_id, a function almost identical to
|
||||
it, does that.
|
||||
|
||||
The problem was found by code inspection. It fixes the following testsuite
|
||||
failures:
|
||||
|
||||
FAIL: gdb.base/unwind-on-each-insn.exp: foo: instruction 9: check frame-id matches
|
||||
FAIL: gdb.reverse/solib-reverse.exp: reverse-next third shr1
|
||||
FAIL: gdb.reverse/solib-reverse.exp: reverse-next second shr1
|
||||
FAIL: gdb.reverse/solib-reverse.exp: reverse-next first shr1
|
||||
FAIL: gdb.reverse/solib-reverse.exp: reverse-next generic
|
||||
FAIL: gdb.reverse/solib-reverse.exp: reverse-step into solib function one
|
||||
FAIL: gdb.reverse/solib-reverse.exp: reverse-step within solib function one
|
||||
FAIL: gdb.reverse/solib-reverse.exp: reverse-step into solib function two
|
||||
FAIL: gdb.reverse/solib-reverse.exp: reverse-step within solib function two
|
||||
|
||||
Tested on arm-linux-gnueabi-hf.
|
||||
---
|
||||
gdb/arm-tdep.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
|
||||
index 3b1682a2aea..21dad198dc7 100644
|
||||
--- a/gdb/arm-tdep.c
|
||||
+++ b/gdb/arm-tdep.c
|
||||
@@ -3252,7 +3252,7 @@ arm_epilogue_frame_this_id (frame_info_ptr this_frame,
|
||||
|
||||
arm_gdbarch_tdep *tdep
|
||||
= gdbarch_tdep<arm_gdbarch_tdep> (get_frame_arch (this_frame));
|
||||
- *this_id = frame_id_build (arm_cache_get_prev_sp_value (cache, tdep), pc);
|
||||
+ *this_id = frame_id_build (arm_cache_get_prev_sp_value (cache, tdep), func);
|
||||
}
|
||||
|
||||
/* Implementation of function hook 'prev_register' in
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,77 +0,0 @@
|
||||
From 51a5415b3313470cb62fda7ad6762fc1c41c8cbd Mon Sep 17 00:00:00 2001
|
||||
From: Simon Marchi <simon.marchi@efficios.com>
|
||||
Date: Tue, 7 Nov 2023 11:11:18 -0500
|
||||
Subject: [PATCH] gdb/arm: remove thumb bit in arm_adjust_breakpoint_address
|
||||
|
||||
When compiling gdb with -fsanitize=address on ARM, I get a crash in test
|
||||
gdb.arch/arm-disp-step.exp, reproduced easily with:
|
||||
|
||||
$ ./gdb -nx -q --data-directory=data-directory testsuite/outputs/gdb.arch/arm-disp-step/arm-disp-step -ex "break *test_call_end"
|
||||
Reading symbols from testsuite/outputs/gdb.arch/arm-disp-step/arm-disp-step...
|
||||
=================================================================
|
||||
==23295==ERROR: AddressSanitizer: heap-buffer-overflow on address 0xb4a14fd1 at pc 0x01a48871 bp 0xbeab8490 sp 0xbeab8494
|
||||
|
||||
Since it doesn't require running the program, it can be reproduced locally on a
|
||||
dev machine other than ARM, after acquiring the test binary.
|
||||
|
||||
The length of the allocate buffer `buf` is 1, and we try to extract an
|
||||
integer of size 2 from it. The length of 1 comes from the subtraction
|
||||
`bpaddr - boundary`. Normally, on ARM, all instructions are aligned on
|
||||
a multiple of 2, so it's weird for this subtraction to result in 1. In
|
||||
this case, boundary comes from the result of find_pc_partial_function
|
||||
returning 0x549:
|
||||
|
||||
(gdb) p/x bpaddr
|
||||
$2 = 0x54a
|
||||
(gdb) p/x boundary
|
||||
$3 = 0x549
|
||||
(gdb) p/x bpaddr - boundary
|
||||
$4 = 0x1
|
||||
|
||||
0x549 is the address of the test_call_subr label, 0x548, with the thumb
|
||||
bit enabled. Before doing some math with the address, I think we need
|
||||
to strip the thumb bit, like is done elsewhere (for instance for bpaddr
|
||||
earlier in the same function).
|
||||
|
||||
I wonder if find_pc_partial_function should do that itself, in order to
|
||||
return an address that is suitable for arithmetic. In any case, that
|
||||
would be a change with a broad impact, so for now just fix the issue
|
||||
locally.
|
||||
|
||||
After the patch:
|
||||
|
||||
$ ./gdb -nx -q --data-directory=data-directory testsuite/outputs/gdb.arch/arm-disp-step/arm-disp-step -ex "break *test_call_end"
|
||||
Reading symbols from testsuite/outputs/gdb.arch/arm-disp-step/arm-disp-step...
|
||||
Breakpoint 1 at 0x54a: file /home/smarchi/src/binutils-gdb/gdb/testsuite/gdb.arch/arm-disp-step.S, line 103.
|
||||
|
||||
Change-Id: I74fc458dbea0d2c1e1f5eadd90755188df089288
|
||||
Approved-By: Luis Machado <luis.machado@arm.com>
|
||||
---
|
||||
gdb/arm-tdep.c | 9 ++++++---
|
||||
1 file changed, 6 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
|
||||
index 21dad198dc7..e61342f3ccb 100644
|
||||
--- a/gdb/arm-tdep.c
|
||||
+++ b/gdb/arm-tdep.c
|
||||
@@ -5340,9 +5340,12 @@ arm_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr)
|
||||
|
||||
bpaddr = gdbarch_addr_bits_remove (gdbarch, bpaddr);
|
||||
|
||||
- if (find_pc_partial_function (bpaddr, NULL, &func_start, NULL)
|
||||
- && func_start > boundary)
|
||||
- boundary = func_start;
|
||||
+ if (find_pc_partial_function (bpaddr, NULL, &func_start, NULL))
|
||||
+ {
|
||||
+ func_start = gdbarch_addr_bits_remove (gdbarch, func_start);
|
||||
+ if (func_start > boundary)
|
||||
+ boundary = func_start;
|
||||
+ }
|
||||
|
||||
/* Search for a candidate IT instruction. We have to do some fancy
|
||||
footwork to distinguish a real IT instruction from the second
|
||||
|
||||
base-commit: eafca1ce3d589c731927e5481199db715bcbeff3
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,219 +0,0 @@
|
||||
From 7973eaf11e33ddd405830b9bd29495991db5901d Mon Sep 17 00:00:00 2001
|
||||
From: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
|
||||
Date: Mon, 26 Feb 2024 19:11:45 -0300
|
||||
Subject: [PATCH 2/7] gdb/arm: Remove tpidruro register from non-FreeBSD target
|
||||
descriptions
|
||||
|
||||
Commit 92d48a1e4eac ("Add an arm-tls feature which includes the tpidruro
|
||||
register from CP15.") introduced the org.gnu.gdb.arm.tls feature, which
|
||||
adds the tpidruro register, and unconditionally enabled it in
|
||||
aarch32_create_target_description.
|
||||
|
||||
In Linux, the tpidruro register isn't available via ptrace in the 32-bit
|
||||
kernel but it is available for an aarch32 program running under an arm64
|
||||
kernel via the ptrace compat interface. This isn't currently implemented
|
||||
however, which causes GDB on arm-linux with 64-bit kernel to list the
|
||||
register but show it as unavailable, as reported by Tom de Vries:
|
||||
|
||||
$ gdb -q -batch a.out -ex start -ex 'p $tpidruro'
|
||||
Temporary breakpoint 1 at 0x512
|
||||
|
||||
Temporary breakpoint 1, 0xaaaaa512 in main ()
|
||||
$1 = <unavailable>
|
||||
|
||||
Simon Marchi then clarified:
|
||||
|
||||
> The only time we should be seeing some "unavailable" registers or memory
|
||||
> is in the context of tracepoints, for things that are not collected.
|
||||
> Seeing an unavailable register here is a sign that something is not
|
||||
> right.
|
||||
|
||||
Therefore, disable the TLS feature in aarch32 target descriptions for Linux
|
||||
and NetBSD targets (the latter also doesn't seem to support accessing
|
||||
tpidruro either, based on a quick look at arm-netbsd-nat.c).
|
||||
|
||||
This patch fixes the following tests:
|
||||
|
||||
Running gdb.base/inline-frame-cycle-unwind.exp ...
|
||||
FAIL: gdb.base/inline-frame-cycle-unwind.exp: cycle at level 3: backtrace when the unwind is broken at frame 3
|
||||
FAIL: gdb.base/inline-frame-cycle-unwind.exp: cycle at level 5: backtrace when the unwind is broken at frame 5
|
||||
FAIL: gdb.base/inline-frame-cycle-unwind.exp: cycle at level 1: backtrace when the unwind is broken at frame 1
|
||||
|
||||
Tested with Ubuntu 22.04.3 on armv8l-linux-gnueabihf in native,
|
||||
native-gdbserver and native-extended-gdbserver targets with no regressions.
|
||||
|
||||
PR tdep/31418
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31418
|
||||
|
||||
Approved-By: John Baldwin <jhb@FreeBSD.org>
|
||||
---
|
||||
gdb/aarch32-tdep.c | 15 ++++++++++-----
|
||||
gdb/aarch32-tdep.h | 2 +-
|
||||
gdb/aarch64-linux-nat.c | 2 +-
|
||||
gdb/arch/aarch32.c | 5 +++--
|
||||
gdb/arch/aarch32.h | 2 +-
|
||||
gdb/arm-fbsd-tdep.c | 2 +-
|
||||
gdb/arm-linux-nat.c | 2 +-
|
||||
gdb/arm-linux-tdep.c | 2 +-
|
||||
gdb/arm-netbsd-nat.c | 2 +-
|
||||
gdbserver/linux-aarch32-tdesc.cc | 2 +-
|
||||
10 files changed, 21 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/gdb/aarch32-tdep.c b/gdb/aarch32-tdep.c
|
||||
index bfa88a96522..395328936e4 100644
|
||||
--- a/gdb/aarch32-tdep.c
|
||||
+++ b/gdb/aarch32-tdep.c
|
||||
@@ -22,15 +22,20 @@
|
||||
#include "gdbsupport/common-regcache.h"
|
||||
#include "arch/aarch32.h"
|
||||
|
||||
-static struct target_desc *tdesc_aarch32;
|
||||
+static struct target_desc *tdesc_aarch32_list[2];
|
||||
|
||||
/* See aarch32-tdep.h. */
|
||||
|
||||
const target_desc *
|
||||
-aarch32_read_description ()
|
||||
+aarch32_read_description (bool tls)
|
||||
{
|
||||
- if (tdesc_aarch32 == nullptr)
|
||||
- tdesc_aarch32 = aarch32_create_target_description ();
|
||||
+ struct target_desc *tdesc = tdesc_aarch32_list[tls];
|
||||
|
||||
- return tdesc_aarch32;
|
||||
+ if (tdesc == nullptr)
|
||||
+ {
|
||||
+ tdesc = aarch32_create_target_description (tls);
|
||||
+ tdesc_aarch32_list[tls] = tdesc;
|
||||
+ }
|
||||
+
|
||||
+ return tdesc;
|
||||
}
|
||||
diff --git a/gdb/aarch32-tdep.h b/gdb/aarch32-tdep.h
|
||||
index bee4d4e9fc0..efc93351298 100644
|
||||
--- a/gdb/aarch32-tdep.h
|
||||
+++ b/gdb/aarch32-tdep.h
|
||||
@@ -22,6 +22,6 @@ struct target_desc;
|
||||
|
||||
/* Get the AArch32 target description. */
|
||||
|
||||
-const target_desc *aarch32_read_description ();
|
||||
+const target_desc *aarch32_read_description (bool tls);
|
||||
|
||||
#endif /* aarch32-tdep.h. */
|
||||
diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
|
||||
index 768748a20db..c680d6de0c9 100644
|
||||
--- a/gdb/aarch64-linux-nat.c
|
||||
+++ b/gdb/aarch64-linux-nat.c
|
||||
@@ -887,7 +887,7 @@ aarch64_linux_nat_target::read_description ()
|
||||
|
||||
ret = ptrace (PTRACE_GETREGSET, tid, NT_ARM_VFP, &iovec);
|
||||
if (ret == 0)
|
||||
- return aarch32_read_description ();
|
||||
+ return aarch32_read_description (false);
|
||||
|
||||
CORE_ADDR hwcap = linux_get_hwcap ();
|
||||
CORE_ADDR hwcap2 = linux_get_hwcap2 ();
|
||||
diff --git a/gdb/arch/aarch32.c b/gdb/arch/aarch32.c
|
||||
index 5be2cc0156e..b7510ee41e9 100644
|
||||
--- a/gdb/arch/aarch32.c
|
||||
+++ b/gdb/arch/aarch32.c
|
||||
@@ -25,7 +25,7 @@
|
||||
/* See aarch32.h. */
|
||||
|
||||
target_desc *
|
||||
-aarch32_create_target_description ()
|
||||
+aarch32_create_target_description (bool tls)
|
||||
{
|
||||
target_desc_up tdesc = allocate_target_description ();
|
||||
|
||||
@@ -39,7 +39,8 @@ aarch32_create_target_description ()
|
||||
/* Create a vfpv3 feature, then a blank NEON feature. */
|
||||
regnum = create_feature_arm_arm_vfpv3 (tdesc.get (), regnum);
|
||||
tdesc_create_feature (tdesc.get (), "org.gnu.gdb.arm.neon");
|
||||
- regnum = create_feature_arm_arm_tls (tdesc.get (), regnum);
|
||||
+ if (tls)
|
||||
+ regnum = create_feature_arm_arm_tls (tdesc.get (), regnum);
|
||||
|
||||
return tdesc.release ();
|
||||
}
|
||||
diff --git a/gdb/arch/aarch32.h b/gdb/arch/aarch32.h
|
||||
index 6b24ae94335..e06e260e370 100644
|
||||
--- a/gdb/arch/aarch32.h
|
||||
+++ b/gdb/arch/aarch32.h
|
||||
@@ -22,6 +22,6 @@
|
||||
|
||||
/* Create the AArch32 target description. */
|
||||
|
||||
-target_desc *aarch32_create_target_description ();
|
||||
+target_desc *aarch32_create_target_description (bool tls);
|
||||
|
||||
#endif /* aarch32.h. */
|
||||
diff --git a/gdb/arm-fbsd-tdep.c b/gdb/arm-fbsd-tdep.c
|
||||
index b46fa91d0a0..a4cea77f388 100644
|
||||
--- a/gdb/arm-fbsd-tdep.c
|
||||
+++ b/gdb/arm-fbsd-tdep.c
|
||||
@@ -228,7 +228,7 @@ arm_fbsd_read_description_auxv (const gdb::optional<gdb::byte_vector> &auxv,
|
||||
if (arm_hwcap & HWCAP_VFP)
|
||||
{
|
||||
if (arm_hwcap & HWCAP_NEON)
|
||||
- return aarch32_read_description ();
|
||||
+ return aarch32_read_description (tls);
|
||||
else if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPD32))
|
||||
== (HWCAP_VFPv3 | HWCAP_VFPD32))
|
||||
return arm_read_description (ARM_FP_TYPE_VFPV3, tls);
|
||||
diff --git a/gdb/arm-linux-nat.c b/gdb/arm-linux-nat.c
|
||||
index 70c6bc684fa..07af23d3881 100644
|
||||
--- a/gdb/arm-linux-nat.c
|
||||
+++ b/gdb/arm-linux-nat.c
|
||||
@@ -568,7 +568,7 @@ arm_linux_nat_target::read_description ()
|
||||
/* NEON implies VFPv3-D32 or no-VFP unit. Say that we only support
|
||||
Neon with VFPv3-D32. */
|
||||
if (arm_hwcap & HWCAP_NEON)
|
||||
- return aarch32_read_description ();
|
||||
+ return aarch32_read_description (false);
|
||||
else if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPv3D16)) == HWCAP_VFPv3)
|
||||
return arm_read_description (ARM_FP_TYPE_VFPV3, false);
|
||||
|
||||
diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c
|
||||
index dfa816990ff..33748731cfd 100644
|
||||
--- a/gdb/arm-linux-tdep.c
|
||||
+++ b/gdb/arm-linux-tdep.c
|
||||
@@ -740,7 +740,7 @@ arm_linux_core_read_description (struct gdbarch *gdbarch,
|
||||
/* NEON implies VFPv3-D32 or no-VFP unit. Say that we only support
|
||||
Neon with VFPv3-D32. */
|
||||
if (arm_hwcap & HWCAP_NEON)
|
||||
- return aarch32_read_description ();
|
||||
+ return aarch32_read_description (false);
|
||||
else if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPv3D16)) == HWCAP_VFPv3)
|
||||
return arm_read_description (ARM_FP_TYPE_VFPV3, false);
|
||||
|
||||
diff --git a/gdb/arm-netbsd-nat.c b/gdb/arm-netbsd-nat.c
|
||||
index d83714a46c3..018964b010d 100644
|
||||
--- a/gdb/arm-netbsd-nat.c
|
||||
+++ b/gdb/arm-netbsd-nat.c
|
||||
@@ -350,7 +350,7 @@ arm_netbsd_nat_target::read_description ()
|
||||
|
||||
len = sizeof(flag);
|
||||
if (sysctlbyname("machdep.neon_present", &flag, &len, NULL, 0) == 0 && flag)
|
||||
- return aarch32_read_description ();
|
||||
+ return aarch32_read_description (false);
|
||||
|
||||
return arm_read_description (ARM_FP_TYPE_VFPV3, false);
|
||||
}
|
||||
diff --git a/gdbserver/linux-aarch32-tdesc.cc b/gdbserver/linux-aarch32-tdesc.cc
|
||||
index e1380fa2a40..443f91e3585 100644
|
||||
--- a/gdbserver/linux-aarch32-tdesc.cc
|
||||
+++ b/gdbserver/linux-aarch32-tdesc.cc
|
||||
@@ -32,7 +32,7 @@ aarch32_linux_read_description ()
|
||||
{
|
||||
if (tdesc_aarch32 == nullptr)
|
||||
{
|
||||
- tdesc_aarch32 = aarch32_create_target_description ();
|
||||
+ tdesc_aarch32 = aarch32_create_target_description (false);
|
||||
|
||||
static const char *expedite_regs[] = { "r11", "sp", "pc", 0 };
|
||||
init_target_desc (tdesc_aarch32, expedite_regs);
|
||||
--
|
||||
2.35.3
|
||||
|
6753
gdb-backport-buildid-related-changes.patch
Normal file
6753
gdb-backport-buildid-related-changes.patch
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,41 +0,0 @@
|
||||
From 0397481ff25b76d43b123f3d51828982ceb92834 Mon Sep 17 00:00:00 2001
|
||||
From: Mark Wielaard <mark@klomp.org>
|
||||
Date: Fri, 3 May 2024 15:17:42 +0200
|
||||
Subject: [PATCH] [gdb/build] Fix gdbserver/linux-aarch64-low.cc build
|
||||
|
||||
Commit 0ee25f97d21e ("Fix regression on aarch64-linux gdbserver")
|
||||
removed the last use of i in gdbserver/linux-aarch64-low.cc
|
||||
(aarch64_target::low_stopped_data_address). Breaking the build on
|
||||
aarch64 with:
|
||||
|
||||
gdbserver/linux-aarch64-low.cc: In member function ?virtual CORE_ADDR aarch64_target::low_stopped_data_address()?:
|
||||
gdbserver/linux-aarch64-low.cc:557:12: error: unused variable ?i? [-Werror=unused-variable]
|
||||
557 | int pid, i;
|
||||
| ^
|
||||
cc1plus: all warnings being treated as errors
|
||||
|
||||
Fix this by removing the variable i completely.
|
||||
|
||||
Fixes: 0ee25f97d21e ("Fix regression on aarch64-linux gdbserver")
|
||||
---
|
||||
gdbserver/linux-aarch64-low.cc | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdbserver/linux-aarch64-low.cc b/gdbserver/linux-aarch64-low.cc
|
||||
index 14346b89822..ce0029b885f 100644
|
||||
--- a/gdbserver/linux-aarch64-low.cc
|
||||
+++ b/gdbserver/linux-aarch64-low.cc
|
||||
@@ -555,7 +555,7 @@ CORE_ADDR
|
||||
aarch64_target::low_stopped_data_address ()
|
||||
{
|
||||
siginfo_t siginfo;
|
||||
- int pid, i;
|
||||
+ int pid;
|
||||
struct aarch64_debug_reg_state *state;
|
||||
|
||||
pid = lwpid_of (current_thread);
|
||||
|
||||
base-commit: b33811a85ff53af77cdad995ad8cb50431c8c362
|
||||
--
|
||||
2.35.3
|
||||
|
46
gdb-build-fix-unused-var-in-corelow.c.patch
Normal file
46
gdb-build-fix-unused-var-in-corelow.c.patch
Normal file
@@ -0,0 +1,46 @@
|
||||
From c179fc89cf61d3d9c58db571d709969bfa566289 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Tue, 10 Sep 2024 10:08:29 +0200
|
||||
Subject: [PATCH] [gdb/build] Fix unused var in corelow.c
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
On x86_64-linux, with gcc 7.5.0 and CFLAGS/CXXFLAGS="-O0 -g -Wall" I ran into
|
||||
a build breaker:
|
||||
...
|
||||
gdb/corelow.c: In member function ‘void mapped_file_info::add(const char*, const char*, const char*, std::vector<mem_range>&&, const bfd_build_id*)’:
|
||||
gdb/corelow.c:1822:27: error: unused variable ‘it’ [-Werror=unused-variable]
|
||||
const auto [it, inserted]
|
||||
^
|
||||
...
|
||||
|
||||
Fix this by dropping the variable it.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
|
||||
Reviewed-By: Lancelot Six<lancelot.six@amd.com>
|
||||
---
|
||||
gdb/corelow.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/gdb/corelow.c b/gdb/corelow.c
|
||||
index 1884075ec67..30b98c2865d 100644
|
||||
--- a/gdb/corelow.c
|
||||
+++ b/gdb/corelow.c
|
||||
@@ -1872,8 +1872,8 @@ mapped_file_info::add (const char *soname,
|
||||
parsed, we group the build-id information based on the file name. As
|
||||
a consequence, we should see each EXPECTED_FILENAME value exactly
|
||||
once. This means that each insertion should always succeed. */
|
||||
- const auto [it, inserted]
|
||||
- = m_filename_to_build_id_map.emplace (expected_filename, build_id);
|
||||
+ const auto inserted
|
||||
+ = m_filename_to_build_id_map.emplace (expected_filename, build_id).second;
|
||||
gdb_assert (inserted);
|
||||
|
||||
/* Setup the reverse build-id to file name map. */
|
||||
|
||||
base-commit: a7d9abecbc24e3d68746ea5b905eba11913980e1
|
||||
--
|
||||
2.43.0
|
||||
|
@@ -1,41 +0,0 @@
|
||||
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"
|
575
gdb-catchpoint-re-set.patch
Normal file
575
gdb-catchpoint-re-set.patch
Normal file
@@ -0,0 +1,575 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Burgess <aburgess@redhat.com>
|
||||
Date: Wed, 14 Aug 2024 15:16:46 +0100
|
||||
Subject: gdb-catchpoint-re-set.patch
|
||||
|
||||
;; Backport upstream commit a92e943014f to fix rhbz2304296.
|
||||
|
||||
gdb: implement ::re_set method for catchpoint class
|
||||
|
||||
It is possible to attach a condition to a catchpoint. This can't be
|
||||
done when the catchpoint is created, but can be done with the
|
||||
'condition' command, this is documented in the GDB manual:
|
||||
|
||||
You can also use the 'if' keyword with the 'watch' command. The
|
||||
'catch' command does not recognize the 'if' keyword; 'condition' is the
|
||||
only way to impose a further condition on a catchpoint.
|
||||
|
||||
A GDB crash was reported against Fedora GDB where a user had attached
|
||||
a condition to a catchpoint and then restarted the inferior. When the
|
||||
catchpoint was hit GDB would immediately segfault. I was able to
|
||||
reproduce the failure on upstream GDB:
|
||||
|
||||
(gdb) file ./some/binary
|
||||
(gdb) catch syscall write
|
||||
(gdb) run
|
||||
...
|
||||
Catchpoint 1 (returned from syscall write), 0x00007ffff7b594a7 in write () from /lib64/libc.so.6
|
||||
(gdb) condition 1 $_streq((char *) $rsi, "foobar") == 0
|
||||
(gdb) run
|
||||
...
|
||||
Fatal signal: Segmentation fault
|
||||
...
|
||||
|
||||
What happened here is that on the system in question we had debug
|
||||
information available for both the main application and also for
|
||||
libc.
|
||||
|
||||
When the condition was attached GDB was stopped inside libc and as the
|
||||
debug information was available GDB found a reference to the 'char'
|
||||
type (for the cast) inside libc's debug information.
|
||||
|
||||
When the inferior is restarted GDB discards all of the objfiles
|
||||
associated with shared libraries, and this includes libc. As such the
|
||||
'char' type, which is objfile owned, is discarded and the reference to
|
||||
it from the catchpoint's condition expression becomes invalid.
|
||||
|
||||
Now, if it were a breakpoint instead of a catchpoint, what would
|
||||
happen is that after the shared library objfiles had been discarded
|
||||
we'd call the virtual breakpoint::re_set method on the breakpoint, and
|
||||
this would update the breakpoint's condition expression. This is
|
||||
because user breakpoints are actually instances of the code_breakpoint
|
||||
class and the code_breakpoint::re_set method contains the code to
|
||||
recompute the breakpoint's condition expression.
|
||||
|
||||
However, catchpoints are instances of the catchpoint class which
|
||||
inherits from the base breakpoint class. The catchpoint class does
|
||||
not override breakpoint::re_set, and breakpoint::re_set is empty!
|
||||
|
||||
The consequence of this is that catchpoint condition expressions are
|
||||
never recomputed, and the dangling pointer to the now deleted, objfile
|
||||
owned type 'char' is left around, and, when the catchpoint is hit, the
|
||||
invalid pointer is used when GDB tries to evaluate the condition
|
||||
expression.
|
||||
|
||||
In this commit I have implemented catchpoint::re_set. This is pretty
|
||||
simple and just recomputes the condition expression as you'd expect.
|
||||
If the condition doesn't evaluate then the catchpoint is marked as
|
||||
disabled_by_cond.
|
||||
|
||||
I have also made breakpoint::re_set pure virtual. With the addition
|
||||
of catchpoint::re_set every sub-class of breakpoint now implements the
|
||||
::re_set method, and if new sub-classes are added in the future I
|
||||
think that they _must_ implement ::re_set in order to avoid this
|
||||
problem. As such falling back to an empty breakpoint::re_set doesn't
|
||||
seem helpful.
|
||||
|
||||
For testing I have not relied on stopping in libc and having libc
|
||||
debug information available, this doesn't seem like a good idea for
|
||||
the GDB testsuite. Instead I create a (rather pointless) condition
|
||||
check that uses a type defined only within a shared library. When the
|
||||
inferior is restarted the catchpoint will temporarily be marked as
|
||||
disabled_by_cond (due to the type not being available), but once the
|
||||
shared library is loaded again the catchpoint will be re-enabled.
|
||||
Without the fixes above then the same crashing behaviour can be
|
||||
observed.
|
||||
|
||||
One point of note: the dangling pointer of course exposes undefined
|
||||
behaviour, with no guarantee of a crash. Though a crash is what I
|
||||
usually see I have see GDB throw random errors from the expression
|
||||
evaluation code, and once, I saw no problem at all! If you recompile
|
||||
GDB with the address sanitizer, or run under valgrind, then the bug
|
||||
will be exposed every time.
|
||||
|
||||
After fixing this bug I checked bugzilla and found PR gdb/29960 which
|
||||
is the same bug. I was able to reproduce the bug before this commit,
|
||||
and after this commit GDB is no longer crashing.
|
||||
|
||||
Before:
|
||||
|
||||
(gdb) file /tmp/hello.x
|
||||
Reading symbols from /tmp/hello.x...
|
||||
(gdb) run
|
||||
Starting program: /tmp/hello.x
|
||||
Hello World
|
||||
[Inferior 1 (process 1101855) exited normally]
|
||||
(gdb) catch syscall 1
|
||||
Catchpoint 1 (syscall 'write' [1])
|
||||
(gdb) condition 1 write.fd == 1
|
||||
(gdb) run
|
||||
Starting program: /tmp/hello.x
|
||||
|
||||
Fatal signal: Segmentation fault
|
||||
...
|
||||
|
||||
And after:
|
||||
|
||||
(gdb) file /tmp/hello.x
|
||||
Reading symbols from /tmp/hello.x...
|
||||
(gdb) run
|
||||
Starting program: /tmp/hello.x
|
||||
Hello World
|
||||
Args: ( 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 )
|
||||
[Inferior 1 (process 1102373) exited normally]
|
||||
(gdb) catch syscall 1
|
||||
Catchpoint 1 (syscall 'write' [1])
|
||||
(gdb) condition 1 write.fd == 1
|
||||
(gdb) r
|
||||
Starting program: /tmp/hello.x
|
||||
Error in testing condition for breakpoint 1:
|
||||
Attempt to extract a component of a value that is not a structure.
|
||||
|
||||
Catchpoint 1 (call to syscall write), 0x00007ffff7eb94a7 in write ()
|
||||
from /lib64/libc.so.6
|
||||
(gdb) ptype write
|
||||
type = <unknown return type> ()
|
||||
(gdb)
|
||||
|
||||
Notice we get the error now when the condition fails to evaluate.
|
||||
This seems reasonable given that 'write' will be a function, and
|
||||
indeed the final 'ptype' shows that it's a function, not a struct.
|
||||
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29960
|
||||
|
||||
Reviewed-By: Tom de Vries <tdevries@suse.de>
|
||||
|
||||
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
|
||||
--- a/gdb/breakpoint.c
|
||||
+++ b/gdb/breakpoint.c
|
||||
@@ -8146,6 +8146,60 @@ catchpoint::catchpoint (struct gdbarch *gdbarch, bool temp,
|
||||
pspace = current_program_space;
|
||||
}
|
||||
|
||||
+/* See breakpoint.h. */
|
||||
+
|
||||
+void
|
||||
+catchpoint::re_set ()
|
||||
+{
|
||||
+ /* All catchpoints are associated with a specific program_space. */
|
||||
+ gdb_assert (pspace != nullptr);
|
||||
+
|
||||
+ /* Catchpoints have a single dummy location. */
|
||||
+ gdb_assert (locations ().size () == 1);
|
||||
+ bp_location &bl = m_locations.front ();
|
||||
+
|
||||
+ if (cond_string == nullptr)
|
||||
+ {
|
||||
+ /* It shouldn't be possible to have a parsed condition expression
|
||||
+ cached on this location if the catchpoint doesn't have a condition
|
||||
+ string set. */
|
||||
+ gdb_assert (bl.cond == nullptr);
|
||||
+
|
||||
+ /* Nothing to re-compute, and the catchpoint cannot change. */
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ bool previous_disabled_by_cond = bl.disabled_by_cond;
|
||||
+
|
||||
+ /* Start by marking the location disabled and discarding the previously
|
||||
+ computed condition expression. Now if we get an exception, even if
|
||||
+ it's a quit exception, we'll leave the location disabled and there
|
||||
+ will be no (possibly invalid) expression cached. */
|
||||
+ bl.disabled_by_cond = true;
|
||||
+ bl.cond = nullptr;
|
||||
+
|
||||
+ const char *s = cond_string.get ();
|
||||
+ try
|
||||
+ {
|
||||
+ switch_to_program_space_and_thread (pspace);
|
||||
+
|
||||
+ bl.cond = parse_exp_1 (&s, bl.address, block_for_pc (bl.address),
|
||||
+ nullptr);
|
||||
+ bl.disabled_by_cond = false;
|
||||
+ }
|
||||
+ catch (const gdb_exception_error &e)
|
||||
+ {
|
||||
+ /* Any exception thrown must be from either the parse_exp_1 or
|
||||
+ earlier in the try block. As such the following two asserts
|
||||
+ should be true. */
|
||||
+ gdb_assert (bl.disabled_by_cond);
|
||||
+ gdb_assert (bl.cond == nullptr);
|
||||
+ }
|
||||
+
|
||||
+ if (previous_disabled_by_cond != bl.disabled_by_cond)
|
||||
+ notify_breakpoint_modified (this);
|
||||
+}
|
||||
+
|
||||
/* Notify interpreters and observers that breakpoint B was created. */
|
||||
|
||||
static void
|
||||
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
|
||||
--- a/gdb/breakpoint.h
|
||||
+++ b/gdb/breakpoint.h
|
||||
@@ -702,11 +702,10 @@ struct breakpoint : public intrusive_list_node<breakpoint>
|
||||
|
||||
/* Reevaluate a breakpoint. This is necessary after symbols change
|
||||
(e.g., an executable or DSO was loaded, or the inferior just
|
||||
- started). */
|
||||
- virtual void re_set ()
|
||||
- {
|
||||
- /* Nothing to re-set. */
|
||||
- }
|
||||
+ started). This is pure virtual as, at a minimum, each sub-class must
|
||||
+ recompute any cached condition expressions based off of the
|
||||
+ cond_string member variable. */
|
||||
+ virtual void re_set () = 0;
|
||||
|
||||
/* Insert the breakpoint or watchpoint or activate the catchpoint.
|
||||
Return 0 for success, 1 if the breakpoint, watchpoint or
|
||||
@@ -1120,6 +1119,10 @@ struct catchpoint : public breakpoint
|
||||
catchpoint (struct gdbarch *gdbarch, bool temp, const char *cond_string);
|
||||
|
||||
~catchpoint () override = 0;
|
||||
+
|
||||
+ /* If the catchpoint has a condition set then recompute the cached
|
||||
+ expression within the single dummy location. */
|
||||
+ void re_set () override;
|
||||
};
|
||||
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/reset-catchpoint-cond-lib.c b/gdb/testsuite/gdb.base/reset-catchpoint-cond-lib.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/reset-catchpoint-cond-lib.c
|
||||
@@ -0,0 +1,76 @@
|
||||
+/* 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/>. */
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+#include <signal.h>
|
||||
+#include <unistd.h>
|
||||
+#include <sys/types.h>
|
||||
+#include <sys/wait.h>
|
||||
+#include <unistd.h>
|
||||
+#include <assert.h>
|
||||
+#include <stdlib.h>
|
||||
+
|
||||
+/* This type is used by GDB. */
|
||||
+struct lib_type
|
||||
+{
|
||||
+ int a;
|
||||
+ int b;
|
||||
+ int c;
|
||||
+};
|
||||
+
|
||||
+/* Ensure the type above is used. */
|
||||
+volatile struct lib_type global_lib_object = { 1, 2, 3 };
|
||||
+
|
||||
+/* This pointer is checked by GDB. */
|
||||
+volatile void *opaque_ptr = 0;
|
||||
+
|
||||
+void
|
||||
+lib_func_test_syscall (void)
|
||||
+{
|
||||
+ puts ("Inside library\n");
|
||||
+ fflush (stdout);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+sig_handler (int signo)
|
||||
+{
|
||||
+ /* Nothing. */
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+lib_func_test_signal (void)
|
||||
+{
|
||||
+ signal (SIGUSR1, sig_handler);
|
||||
+
|
||||
+ kill (getpid (), SIGUSR1);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+lib_func_test_fork (void)
|
||||
+{
|
||||
+ pid_t pid = fork ();
|
||||
+ assert (pid != -1);
|
||||
+
|
||||
+ if (pid == 0)
|
||||
+ {
|
||||
+ /* Child: just exit. */
|
||||
+ exit (0);
|
||||
+ }
|
||||
+
|
||||
+ /* Parent. */
|
||||
+ waitpid (pid, NULL, 0);
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.base/reset-catchpoint-cond.c b/gdb/testsuite/gdb.base/reset-catchpoint-cond.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/reset-catchpoint-cond.c
|
||||
@@ -0,0 +1,50 @@
|
||||
+/* This testcase is part of GDB, the GNU debugger.
|
||||
+
|
||||
+ Copyright 2024 Free Software Foundation, Inc.
|
||||
+
|
||||
+ This program is free software; you can redistribute it and/or modify
|
||||
+ it under the terms of the GNU General Public License as published by
|
||||
+ the Free Software Foundation; either version 3 of the License, or
|
||||
+ (at your option) any later version.
|
||||
+
|
||||
+ This program is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ GNU General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU General Public License
|
||||
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+extern void lib_func_test_syscall (void);
|
||||
+extern void lib_func_test_signal (void);
|
||||
+extern void lib_func_test_fork (void);
|
||||
+
|
||||
+/* We use this to perform some filler work. */
|
||||
+volatile int global_var = 0;
|
||||
+
|
||||
+/* Just somewhere for GDB to put a breakpoint. */
|
||||
+void
|
||||
+breakpt_before_exit (void)
|
||||
+{
|
||||
+ /* Nothing. */
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+main (void)
|
||||
+{
|
||||
+#if defined TEST_SYSCALL
|
||||
+ lib_func_test_syscall ();
|
||||
+#elif defined TEST_SIGNAL
|
||||
+ lib_func_test_signal ();
|
||||
+#elif defined TEST_FORK
|
||||
+ lib_func_test_fork ();
|
||||
+#else
|
||||
+# error compile with suitable -DTEST_xxx macro defined
|
||||
+#endif
|
||||
+
|
||||
+ ++global_var;
|
||||
+
|
||||
+ breakpt_before_exit ();
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.base/reset-catchpoint-cond.exp b/gdb/testsuite/gdb.base/reset-catchpoint-cond.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/reset-catchpoint-cond.exp
|
||||
@@ -0,0 +1,169 @@
|
||||
+# 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/>.
|
||||
+
|
||||
+# Test that the condition for a catchpoint is correctly reset after
|
||||
+# shared libraries are unloaded, as happens when an inferior is
|
||||
+# restarted.
|
||||
+#
|
||||
+# If this is not done then, when the catchpoint is hit on the second
|
||||
+# run, we'll evaluate the parsed expression from the first run, which
|
||||
+# might include references to types owned by the now deleted objfile
|
||||
+# (for the shared library loaded in the first run).
|
||||
+#
|
||||
+# This scripts tests a number of different catchpoint types. Inside
|
||||
+# GDB these are all sub-classes of the 'catchpoint' type, which is
|
||||
+# where the fix for the above issue resides, so all catchpoint types
|
||||
+# should work correctly.
|
||||
+
|
||||
+standard_testfile .c -lib.c
|
||||
+
|
||||
+set libfile $binfile-lib.so
|
||||
+
|
||||
+set pyfile [gdb_remote_download host ${srcdir}/${subdir}/${testfile}.py]
|
||||
+
|
||||
+if {[build_executable "build shared library" $libfile $srcfile2 \
|
||||
+ {debug shlib}] == -1} {
|
||||
+ return
|
||||
+}
|
||||
+
|
||||
+# Depending on whether or not libc debug info is installed, when we
|
||||
+# hit a syscall catchpoint inside libc there might be a source line
|
||||
+# included in the output.
|
||||
+#
|
||||
+# This regexp will match an optional line and can be added to the
|
||||
+# expected catchpoint output to ignore the (possibly missing) source
|
||||
+# line.
|
||||
+set libc_src_line_re "(?:\r\n\[^\r\n\]+)?"
|
||||
+
|
||||
+# Check the Python bp_modified_list and then reset the list back to
|
||||
+# empty. TESTNAME is just a string. BP_NUM is a list of breakpoint
|
||||
+# numbers that are expected to appear (in the given order) in the
|
||||
+# bp_modified_list.
|
||||
+
|
||||
+proc check_modified_bp_list { testname bp_num } {
|
||||
+ if { [allow_python_tests] } {
|
||||
+ set expected [join $bp_num ", "]
|
||||
+
|
||||
+ gdb_test "python print(bp_modified_list)" "\\\[$expected\\\]" \
|
||||
+ $testname
|
||||
+ gdb_test_no_output -nopass "python bp_modified_list=\[\]" \
|
||||
+ "reset bp_modified_list after $testname"
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+# Build an executable and run tests on 'catch MODE'.
|
||||
+
|
||||
+proc run_test { mode } {
|
||||
+ set exec_name ${::binfile}-${mode}
|
||||
+
|
||||
+ set macro TEST_[string toupper $mode]
|
||||
+
|
||||
+ if {[build_executable "build test executable" $exec_name $::srcfile \
|
||||
+ [list debug shlib=$::libfile additional_flags=-D${macro}]] == -1} {
|
||||
+ return
|
||||
+ }
|
||||
+
|
||||
+ clean_restart $exec_name
|
||||
+ gdb_load_shlib $::libfile
|
||||
+
|
||||
+ if {![runto_main]} {
|
||||
+ return
|
||||
+ }
|
||||
+
|
||||
+ if { $mode eq "syscall" } {
|
||||
+ gdb_test "catch syscall write" \
|
||||
+ "Catchpoint $::decimal \\(syscall 'write' \[^)\]+\\)"
|
||||
+ set catch_re "call to syscall write"
|
||||
+ } elseif { $mode eq "signal" } {
|
||||
+ gdb_test "catch signal SIGUSR1" \
|
||||
+ "Catchpoint $::decimal \\(signal SIGUSR1\\)"
|
||||
+ set catch_re "signal SIGUSR1"
|
||||
+ } elseif { $mode eq "fork" } {
|
||||
+ gdb_test "catch fork" \
|
||||
+ "Catchpoint $::decimal \\(fork\\)"
|
||||
+ set catch_re "forked process $::decimal"
|
||||
+ } else {
|
||||
+ error "unknown mode $mode"
|
||||
+ }
|
||||
+ set cp_num [get_integer_valueof "\$bpnum" "*UNKNOWN*"]
|
||||
+
|
||||
+ gdb_breakpoint "breakpt_before_exit"
|
||||
+
|
||||
+ gdb_test "continue" \
|
||||
+ "Catchpoint ${cp_num} \[^\r\n\]+$::libc_src_line_re"
|
||||
+
|
||||
+ if { [allow_python_tests] } {
|
||||
+ gdb_test_no_output "source $::pyfile" "import python scripts"
|
||||
+ check_modified_bp_list \
|
||||
+ "check b/p modified observer has not yet triggered" {}
|
||||
+ }
|
||||
+
|
||||
+ with_test_prefix "with false condition" {
|
||||
+ gdb_test_no_output "condition $cp_num ((struct lib_type *) opaque_ptr) != 0" \
|
||||
+ "set catchpoint condition"
|
||||
+
|
||||
+ check_modified_bp_list \
|
||||
+ "catchpoint modified once by setting condition" \
|
||||
+ [list $cp_num]
|
||||
+
|
||||
+ gdb_run_cmd
|
||||
+ gdb_test "" [multi_line \
|
||||
+ "Breakpoint $::decimal, main \\(\\) \[^\r\n\]+" \
|
||||
+ "$::decimal\\s+\[^\r\n\]+"]
|
||||
+
|
||||
+ check_modified_bp_list "catchpoint modified twice at startup" \
|
||||
+ [list $cp_num $cp_num "$::decimal"]
|
||||
+
|
||||
+ gdb_test "continue" \
|
||||
+ [multi_line \
|
||||
+ "Breakpoint $::decimal, breakpt_before_exit \\(\\) at \[^\r\n\]+" \
|
||||
+ "$::decimal\\s+\[^\r\n\]+"] \
|
||||
+ "continue to breakpt_before_exit"
|
||||
+ }
|
||||
+
|
||||
+ # Check the bp_modified_list against '.*'. We don't care at this
|
||||
+ # point what's in the list (nothing relevant has happened since we
|
||||
+ # last checked), but this has the side effect of clearing the list.
|
||||
+ check_modified_bp_list "clear bp modified list" { .* }
|
||||
+
|
||||
+ with_test_prefix "with true condition" {
|
||||
+ gdb_test_no_output "condition $cp_num ((struct lib_type *) opaque_ptr) == 0" \
|
||||
+ "set catchpoint condition"
|
||||
+
|
||||
+ check_modified_bp_list \
|
||||
+ "catchpoint modified once by setting condition" \
|
||||
+ [list $cp_num]
|
||||
+
|
||||
+ gdb_run_cmd
|
||||
+ gdb_test "" [multi_line \
|
||||
+ "Breakpoint $::decimal, main \\(\\) \[^\r\n\]+" \
|
||||
+ "$::decimal\\s+\[^\r\n\]+"]
|
||||
+
|
||||
+ check_modified_bp_list "catchpoint modified twice at startup" \
|
||||
+ [list $cp_num $cp_num "$::decimal"]
|
||||
+
|
||||
+ gdb_test "continue" \
|
||||
+ "Catchpoint $cp_num \\($catch_re\\), \[^\r\n\]+$::libc_src_line_re" \
|
||||
+ "continue until catchpoint hit"
|
||||
+
|
||||
+ check_modified_bp_list "catchpoint modified again when hit" \
|
||||
+ [list $cp_num]
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+# Run the tests.
|
||||
+foreach_with_prefix mode { syscall signal fork } {
|
||||
+ run_test $mode
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.base/reset-catchpoint-cond.py b/gdb/testsuite/gdb.base/reset-catchpoint-cond.py
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/reset-catchpoint-cond.py
|
||||
@@ -0,0 +1,21 @@
|
||||
+# 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/>.
|
||||
+
|
||||
+bp_modified_list = []
|
||||
+
|
||||
+def bp_modified(bp):
|
||||
+ bp_modified_list.append (bp.number)
|
||||
+
|
||||
+gdb.events.breakpoint_modified.connect(bp_modified)
|
41
gdb-cli-print-at_hwcap3-and-at_hwcap4.patch
Normal file
41
gdb-cli-print-at_hwcap3-and-at_hwcap4.patch
Normal file
@@ -0,0 +1,41 @@
|
||||
From 442c996a4de355459eeabd280649ddb282d7de41 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Sat, 25 Jan 2025 10:08:53 +0100
|
||||
Subject: [PATCH 2/2] [gdb/cli] Print AT_HWCAP3 and AT_HWCAP4
|
||||
|
||||
PR cli/32590
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32590
|
||||
---
|
||||
gdb/auxv.c | 9 +++++++++
|
||||
1 file changed, 9 insertions(+)
|
||||
|
||||
diff --git a/gdb/auxv.c b/gdb/auxv.c
|
||||
index 8cda0b687b4..bb4c7ea70a0 100644
|
||||
--- a/gdb/auxv.c
|
||||
+++ b/gdb/auxv.c
|
||||
@@ -453,6 +453,13 @@ fprint_auxv_entry (struct ui_file *file, const char *name,
|
||||
}
|
||||
}
|
||||
|
||||
+#ifndef AT_HWCAP3
|
||||
+#define AT_HWCAP3 29
|
||||
+#endif
|
||||
+#ifndef AT_HWCAP4
|
||||
+#define AT_HWCAP4 30
|
||||
+#endif
|
||||
+
|
||||
/* The default implementation of gdbarch_print_auxv_entry. */
|
||||
|
||||
void
|
||||
@@ -495,6 +502,8 @@ default_print_auxv_entry (struct gdbarch *gdbarch, struct ui_file *file,
|
||||
AUXV_FORMAT_STR);
|
||||
TAG (AT_RANDOM, _("Address of 16 random bytes"), AUXV_FORMAT_HEX);
|
||||
TAG (AT_HWCAP2, _("Extension of AT_HWCAP"), AUXV_FORMAT_HEX);
|
||||
+ TAG (AT_HWCAP3, _("Extension of AT_HWCAP"), AUXV_FORMAT_HEX);
|
||||
+ TAG (AT_HWCAP4, _("Extension of AT_HWCAP"), AUXV_FORMAT_HEX);
|
||||
TAG (AT_RSEQ_FEATURE_SIZE, _("rseq supported feature size"),
|
||||
AUXV_FORMAT_DEC);
|
||||
TAG (AT_RSEQ_ALIGN, _("rseq allocation alignment"),
|
||||
--
|
||||
2.43.0
|
||||
|
@@ -1,58 +0,0 @@
|
||||
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
|
61
gdb-doc-fix-gdb.unwinder-docs.patch
Normal file
61
gdb-doc-fix-gdb.unwinder-docs.patch
Normal file
@@ -0,0 +1,61 @@
|
||||
From b57066d1eaafab3100a8d7d788feba5802c409b7 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Mon, 27 Jan 2025 10:33:28 +0100
|
||||
Subject: [PATCH] [gdb/doc] Fix gdb.unwinder docs
|
||||
|
||||
When building gdb with an older makeinfo (4.13), I run into:
|
||||
...
|
||||
gdb/doc/python.texi:3015: warning: `(' follows defined name \
|
||||
`gdb.unwinder.Unwinder.__init__' instead of whitespace.
|
||||
gdb/doc/python.texi:3041: warning: `(' follows defined name \
|
||||
`gdb.unwinder.FrameId.__init__' instead of whitespace.
|
||||
...
|
||||
|
||||
The warnings are related to these two lines:
|
||||
...
|
||||
@defun gdb.unwinder.Unwinder.__init__(name)
|
||||
...
|
||||
@defun gdb.unwinder.FrameId.__init__(sp, pc, special = @code{None})
|
||||
...
|
||||
|
||||
Indeed, when checking the command and variable index, we can see that it
|
||||
contains an incorrect entry:
|
||||
...
|
||||
gdb.unwinder.FrameId.__init__(sp,: Unwinding Frames in Python
|
||||
...
|
||||
|
||||
Fix this by adding a space before the left parenthesis.
|
||||
|
||||
Tested by rebuilding the documentation and checking the command and variable
|
||||
index.
|
||||
---
|
||||
gdb/doc/python.texi | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
|
||||
index e49cc580b1b..58904298c71 100644
|
||||
--- a/gdb/doc/python.texi
|
||||
+++ b/gdb/doc/python.texi
|
||||
@@ -3011,7 +3011,7 @@ unwinders can derive, though it is not required that unwinders derive
|
||||
from this class, so long as any user created unwinder has the required
|
||||
@code{name} and @code{enabled} attributes.
|
||||
|
||||
-@defun gdb.unwinder.Unwinder.__init__(name)
|
||||
+@defun gdb.unwinder.Unwinder.__init__ (name)
|
||||
The @var{name} is a string used to reference this unwinder within some
|
||||
@value{GDBN} commands (@pxref{Managing Registered Unwinders}).
|
||||
@end defun
|
||||
@@ -3037,7 +3037,7 @@ most cases this class will be sufficient.
|
||||
|
||||
@code{gdb.unwinder.FrameId} has the following method:
|
||||
|
||||
-@defun gdb.unwinder.FrameId.__init__(sp, pc, special = @code{None})
|
||||
+@defun gdb.unwinder.FrameId.__init__ (sp, pc, special = @code{None})
|
||||
The @var{sp} and @var{pc} arguments are required and should be either
|
||||
a @code{gdb.Value} object, or an integer.
|
||||
|
||||
|
||||
base-commit: fe0e6edbcb65ab5eca50c1a0ad8ddc9844f8ea98
|
||||
--
|
||||
2.43.0
|
||||
|
41
gdb-doc-fix-qisaddresstagged-anchor.patch
Normal file
41
gdb-doc-fix-qisaddresstagged-anchor.patch
Normal file
@@ -0,0 +1,41 @@
|
||||
From c23182d85ad9b5b6a45ba74993de55eac00a71bc Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Mon, 27 Jan 2025 11:22:12 +0100
|
||||
Subject: [PATCH] [gdb/doc] Fix qIsAddressTagged anchor
|
||||
|
||||
When building gdb with an older makeinfo (4.13), I run into:
|
||||
...
|
||||
gdb/doc/gdb.texinfo:44159: @anchor expected braces.
|
||||
gdb/doc/gdb.texinfo:44159: ` {qIsAddressTagged}
|
||||
...
|
||||
|
||||
This is related to this line:
|
||||
...
|
||||
@anchor {qIsAddressTagged}
|
||||
...
|
||||
|
||||
Fix this by removing the space before the left brace.
|
||||
|
||||
Tested by rebuilding the documentation.
|
||||
---
|
||||
gdb/doc/gdb.texinfo | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
|
||||
index 6b08838862c..97508863776 100644
|
||||
--- a/gdb/doc/gdb.texinfo
|
||||
+++ b/gdb/doc/gdb.texinfo
|
||||
@@ -44156,7 +44156,7 @@ tags found in the requested memory range.
|
||||
@cindex check if a given address is in a memory tagged region
|
||||
@cindex @samp{qIsAddressTagged} packet
|
||||
@item qIsAddressTagged:@var{address}
|
||||
-@anchor {qIsAddressTagged}
|
||||
+@anchor{qIsAddressTagged}
|
||||
Check if address @var{address} is in a memory tagged region; if it is, it's
|
||||
said to be @dfn{tagged}. The target is responsible for checking it, as this
|
||||
is architecture-specific.
|
||||
|
||||
base-commit: 3e2d8d7edd244dd5a82588c3e7145c47c7b539ab
|
||||
--
|
||||
2.43.0
|
||||
|
44
gdb-doc-fix-standard-replies-xref.patch
Normal file
44
gdb-doc-fix-standard-replies-xref.patch
Normal file
@@ -0,0 +1,44 @@
|
||||
From 2004e74e0e28ed0b762d98380972b1e6984b9c46 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Tue, 28 Jan 2025 08:01:46 +0100
|
||||
Subject: [PATCH] [gdb/doc] Fix "Standard Replies" xref
|
||||
|
||||
When building gdb with an older makeinfo (4.13), I run into:
|
||||
...
|
||||
gdb/doc/gdb.texinfo:42613: warning: `.' or `,' must follow @xref, not `f'.
|
||||
...
|
||||
|
||||
This is related to this line:
|
||||
...
|
||||
@xref{Standard Replies} for standard error responses, and how to
|
||||
respond indicating a command is not supported.
|
||||
...
|
||||
|
||||
Fix this by adding a comma.
|
||||
|
||||
Tested by rebuilding the docs.
|
||||
|
||||
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
|
||||
Co-Authored-By: Eli Zaretskii <eliz@gnu.org>
|
||||
---
|
||||
gdb/doc/gdb.texinfo | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
|
||||
index e5d562c00b4..0bfe6be6126 100644
|
||||
--- a/gdb/doc/gdb.texinfo
|
||||
+++ b/gdb/doc/gdb.texinfo
|
||||
@@ -42610,7 +42610,7 @@ seven repeats (@samp{$}) can be expanded using a repeat count of only
|
||||
five (@samp{"}). For example, @samp{00000000} can be encoded as
|
||||
@samp{0*"00}.
|
||||
|
||||
-@xref{Standard Replies} for standard error responses, and how to
|
||||
+@xref{Standard Replies}, for standard error responses, and how to
|
||||
respond indicating a command is not supported.
|
||||
|
||||
In describing packets (commands and responses), each description has a
|
||||
|
||||
base-commit: 7992b582e5a55bf2fd64f2f94b854d335c36c6a5
|
||||
--
|
||||
2.43.0
|
||||
|
@@ -1,150 +0,0 @@
|
||||
From b96d3adafdb636898913710ec40ee86647665ae8 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Fri, 3 May 2024 09:37:19 +0200
|
||||
Subject: [PATCH 24/48] [gdb/exp] Fix cast handling for indirection
|
||||
|
||||
Consider a test-case compiled without debug info, containing:
|
||||
...
|
||||
char a = 'a';
|
||||
|
||||
char *
|
||||
a_loc (void)
|
||||
{
|
||||
return &a;
|
||||
}
|
||||
...
|
||||
|
||||
We get:
|
||||
...
|
||||
(gdb) p (char)*a_loc ()
|
||||
Cannot access memory at address 0x10
|
||||
...
|
||||
|
||||
There's a bug in unop_ind_base_operation::evaluate that evaluates
|
||||
"(char)*a_loc ()" the same as:
|
||||
...
|
||||
(gdb) p (char)*(char)a_loc ()
|
||||
Cannot access memory at address 0x10
|
||||
...
|
||||
|
||||
Fix this by instead doing:
|
||||
...
|
||||
(gdb) p (char)*a_loc ()
|
||||
'a_loc' has unknown return type; cast the call to its declared return type
|
||||
...
|
||||
|
||||
Tested on x86_64-linux.
|
||||
|
||||
PR exp/31693
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31693
|
||||
---
|
||||
gdb/expop.h | 5 +--
|
||||
gdb/testsuite/gdb.base/cast-indirection.c | 31 ++++++++++++++++
|
||||
gdb/testsuite/gdb.base/cast-indirection.exp | 41 +++++++++++++++++++++
|
||||
3 files changed, 74 insertions(+), 3 deletions(-)
|
||||
create mode 100644 gdb/testsuite/gdb.base/cast-indirection.c
|
||||
create mode 100644 gdb/testsuite/gdb.base/cast-indirection.exp
|
||||
|
||||
diff --git a/gdb/expop.h b/gdb/expop.h
|
||||
index 25769d5b810..25d50fe00d0 100644
|
||||
--- a/gdb/expop.h
|
||||
+++ b/gdb/expop.h
|
||||
@@ -1513,9 +1513,8 @@ class unop_ind_base_operation
|
||||
struct expression *exp,
|
||||
enum noside noside) override
|
||||
{
|
||||
- if (expect_type != nullptr && expect_type->code () == TYPE_CODE_PTR)
|
||||
- expect_type = check_typedef (expect_type)->target_type ();
|
||||
- value *val = std::get<0> (m_storage)->evaluate (expect_type, exp, noside);
|
||||
+ value *val
|
||||
+ = std::get<0> (m_storage)->evaluate (nullptr, exp, noside);
|
||||
return eval_op_ind (expect_type, exp, noside, val);
|
||||
}
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/cast-indirection.c b/gdb/testsuite/gdb.base/cast-indirection.c
|
||||
new file mode 100644
|
||||
index 00000000000..d59c66ead35
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/cast-indirection.c
|
||||
@@ -0,0 +1,31 @@
|
||||
+/* This testcase is part of GDB, the GNU debugger.
|
||||
+
|
||||
+ Copyright 2024 Free Software Foundation, Inc.
|
||||
+
|
||||
+ This program is free software; you can redistribute it and/or modify
|
||||
+ it under the terms of the GNU General Public License as published by
|
||||
+ the Free Software Foundation; either version 3 of the License, or
|
||||
+ (at your option) any later version.
|
||||
+
|
||||
+ This program is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ GNU General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU General Public License
|
||||
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+char a = 'a';
|
||||
+
|
||||
+char *
|
||||
+a_loc (void)
|
||||
+{
|
||||
+ return &a;
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+main (void)
|
||||
+{
|
||||
+ int res = *a_loc () == 'a';
|
||||
+ return !res;
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.base/cast-indirection.exp b/gdb/testsuite/gdb.base/cast-indirection.exp
|
||||
new file mode 100644
|
||||
index 00000000000..f1fe4302d27
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/cast-indirection.exp
|
||||
@@ -0,0 +1,41 @@
|
||||
+# Copyright (C) 2024 Free Software Foundation, Inc.
|
||||
+
|
||||
+# This program is free software; you can redistribute it and/or modify
|
||||
+# it under the terms of the GNU General Public License as published by
|
||||
+# the Free Software Foundation; either version 3 of the License, or
|
||||
+# (at your option) any later version.
|
||||
+#
|
||||
+# This program is distributed in the hope that it will be useful,
|
||||
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+# GNU General Public License for more details.
|
||||
+#
|
||||
+# You should have received a copy of the GNU General Public License
|
||||
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
+
|
||||
+# Check that "p (char)*a_loc ()" is handled as "p (char)*(char *)a_loc ()".
|
||||
+
|
||||
+standard_testfile
|
||||
+
|
||||
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile \
|
||||
+ {nodebug}] == -1} {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+if ![runto_main] {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+gdb_test "p a_loc ()" \
|
||||
+ "'a_loc' has unknown return type; cast the call to its declared return type"
|
||||
+
|
||||
+gdb_test "p *a_loc ()" \
|
||||
+ "'a_loc' has unknown return type; cast the call to its declared return type"
|
||||
+
|
||||
+gdb_test "p *(char *)a_loc ()" " = 97 'a'"
|
||||
+
|
||||
+gdb_test "p (char)*(char *)a_loc ()" " = 97 'a'"
|
||||
+
|
||||
+# Regression test for PR31693.
|
||||
+gdb_test "p (char)*a_loc ()" \
|
||||
+ "'a_loc' has unknown return type; cast the call to its declared return type"
|
||||
--
|
||||
2.35.3
|
||||
|
232
gdb-exp-fix-gdb.fortran-intrinsics.exp-fail-on-arm.patch
Normal file
232
gdb-exp-fix-gdb.fortran-intrinsics.exp-fail-on-arm.patch
Normal file
@@ -0,0 +1,232 @@
|
||||
From 1e295ef5fa3a5a89e9ee08d6e60d971ddb9e6e46 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Wed, 31 Jul 2024 13:11:48 +0200
|
||||
Subject: [PATCH 13/46] [gdb/exp] Fix gdb.fortran/intrinsics.exp fail on arm
|
||||
|
||||
When running test-case gdb.fortran/intrinsics.exp on arm-linux, I get:
|
||||
...
|
||||
(gdb) p cmplx (4,4,16)^M
|
||||
/home/linux/gdb/src/gdb/f-lang.c:1002: internal-error: eval_op_f_cmplx: \
|
||||
Assertion `kind_arg->code () == TYPE_CODE_COMPLEX' failed.^M
|
||||
A problem internal to GDB has been detected,^M
|
||||
further debugging may prove unreliable.^M
|
||||
----- Backtrace -----^M
|
||||
FAIL: gdb.fortran/intrinsics.exp: p cmplx (4,4,16) (GDB internal error)
|
||||
...
|
||||
|
||||
The problem is that 16-byte floats are unsupported:
|
||||
...
|
||||
$ gfortran test.f90
|
||||
test.f90:2:17:
|
||||
|
||||
2 | REAL(kind=16) :: foo = 1
|
||||
| 1
|
||||
Error: Kind 16 not supported for type REAL at (1)
|
||||
...
|
||||
and consequently we end up with a builtin_real_s16 and builtin_complex_s16 with
|
||||
code TYPE_CODE_ERROR.
|
||||
|
||||
Fix this by bailing out asap when encountering such a type.
|
||||
|
||||
Without this patch we're able to do the rather useless:
|
||||
...
|
||||
(gdb) ptype real*16
|
||||
type = real*16
|
||||
(gdb) ptype real_16
|
||||
type = real*16
|
||||
...
|
||||
but with this patch we get:
|
||||
...
|
||||
(gdb) ptype real*16
|
||||
unsupported kind 16 for type real*4
|
||||
(gdb) ptype real_16
|
||||
unsupported type real*16
|
||||
...
|
||||
|
||||
Tested on arm-linux.
|
||||
|
||||
PR fortran/30537
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30537
|
||||
---
|
||||
gdb/f-exp.y | 39 +++++++++++++++++-------
|
||||
gdb/testsuite/gdb.fortran/intrinsics.exp | 8 +++--
|
||||
gdb/testsuite/gdb.fortran/type-kinds.exp | 22 ++++++++++---
|
||||
gdb/testsuite/gdb.fortran/types.exp | 19 +++++++++++-
|
||||
4 files changed, 70 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/gdb/f-exp.y b/gdb/f-exp.y
|
||||
index bdf9c32a81b..259f274d341 100644
|
||||
--- a/gdb/f-exp.y
|
||||
+++ b/gdb/f-exp.y
|
||||
@@ -754,7 +754,11 @@ typebase /* Implements (approximately): (type-qualifier)* type-specifier */
|
||||
| REAL_S8_KEYWORD
|
||||
{ $$ = parse_f_type (pstate)->builtin_real_s8; }
|
||||
| REAL_S16_KEYWORD
|
||||
- { $$ = parse_f_type (pstate)->builtin_real_s16; }
|
||||
+ { $$ = parse_f_type (pstate)->builtin_real_s16;
|
||||
+ if ($$->code () == TYPE_CODE_ERROR)
|
||||
+ error (_("unsupported type %s"),
|
||||
+ TYPE_SAFE_NAME ($$));
|
||||
+ }
|
||||
| COMPLEX_KEYWORD
|
||||
{ $$ = parse_f_type (pstate)->builtin_complex; }
|
||||
| COMPLEX_S4_KEYWORD
|
||||
@@ -762,7 +766,11 @@ typebase /* Implements (approximately): (type-qualifier)* type-specifier */
|
||||
| COMPLEX_S8_KEYWORD
|
||||
{ $$ = parse_f_type (pstate)->builtin_complex_s8; }
|
||||
| COMPLEX_S16_KEYWORD
|
||||
- { $$ = parse_f_type (pstate)->builtin_complex_s16; }
|
||||
+ { $$ = parse_f_type (pstate)->builtin_complex_s16;
|
||||
+ if ($$->code () == TYPE_CODE_ERROR)
|
||||
+ error (_("unsupported type %s"),
|
||||
+ TYPE_SAFE_NAME ($$));
|
||||
+ }
|
||||
| SINGLE PRECISION
|
||||
{ $$ = parse_f_type (pstate)->builtin_real;}
|
||||
| DOUBLE PRECISION
|
||||
@@ -1156,12 +1164,9 @@ push_kind_type (LONGEST val, struct type *type)
|
||||
type_stack->push (tp_kind);
|
||||
}
|
||||
|
||||
-/* Called when a type has a '(kind=N)' modifier after it, for example
|
||||
- 'character(kind=1)'. The BASETYPE is the type described by 'character'
|
||||
- in our example, and KIND is the integer '1'. This function returns a
|
||||
- new type that represents the basetype of a specific kind. */
|
||||
+/* Helper function for convert_to_kind_type. */
|
||||
static struct type *
|
||||
-convert_to_kind_type (struct type *basetype, int kind)
|
||||
+convert_to_kind_type_1 (struct type *basetype, int kind)
|
||||
{
|
||||
if (basetype == parse_f_type (pstate)->builtin_character)
|
||||
{
|
||||
@@ -1211,13 +1216,25 @@ convert_to_kind_type (struct type *basetype, int kind)
|
||||
return parse_f_type (pstate)->builtin_integer_s8;
|
||||
}
|
||||
|
||||
- error (_("unsupported kind %d for type %s"),
|
||||
- kind, TYPE_SAFE_NAME (basetype));
|
||||
-
|
||||
- /* Should never get here. */
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
+/* Called when a type has a '(kind=N)' modifier after it, for example
|
||||
+ 'character(kind=1)'. The BASETYPE is the type described by 'character'
|
||||
+ in our example, and KIND is the integer '1'. This function returns a
|
||||
+ new type that represents the basetype of a specific kind. */
|
||||
+static struct type *
|
||||
+convert_to_kind_type (struct type *basetype, int kind)
|
||||
+{
|
||||
+ struct type *res = convert_to_kind_type_1 (basetype, kind);
|
||||
+
|
||||
+ if (res == nullptr || res->code () == TYPE_CODE_ERROR)
|
||||
+ error (_("unsupported kind %d for type %s"),
|
||||
+ kind, TYPE_SAFE_NAME (basetype));
|
||||
+
|
||||
+ return res;
|
||||
+}
|
||||
+
|
||||
struct f_token
|
||||
{
|
||||
/* The string to match against. */
|
||||
diff --git a/gdb/testsuite/gdb.fortran/intrinsics.exp b/gdb/testsuite/gdb.fortran/intrinsics.exp
|
||||
index 60c79f956dc..060bb53db97 100644
|
||||
--- a/gdb/testsuite/gdb.fortran/intrinsics.exp
|
||||
+++ b/gdb/testsuite/gdb.fortran/intrinsics.exp
|
||||
@@ -112,10 +112,14 @@ gdb_test "ptype cmplx (4,4)" "= complex\\*4"
|
||||
gdb_test "p cmplx (-14,-4)" "= \\(-14,-4\\)"
|
||||
gdb_test "p cmplx (4,4,4)" "\\(4,4\\)"
|
||||
gdb_test "p cmplx (4,4,8)" "\\(4,4\\)"
|
||||
-gdb_test "p cmplx (4,4,16)" "\\(4,4\\)"
|
||||
+set re_unsupported_kind_16 \
|
||||
+ [string_to_regexp "unsupported kind 16 for type complex*4"]
|
||||
+gdb_test "p cmplx (4,4,16)" \
|
||||
+ ([string_to_regexp " = (4,4)"]|$re_unsupported_kind_16)
|
||||
gdb_test "ptype cmplx (4,4,4)" "= complex\\*4"
|
||||
gdb_test "ptype cmplx (4,4,8)" "= complex\\*8"
|
||||
-gdb_test "ptype cmplx (4,4,16)" "= complex\\*16"
|
||||
+gdb_test "ptype cmplx (4,4,16)" \
|
||||
+ ([string_to_regexp " = complex*16"]|$re_unsupported_kind_16)
|
||||
|
||||
gdb_test "p cmplx (4,4,1)" "unsupported kind 1 for type complex\\*4"
|
||||
gdb_test "p cmplx (4,4,-1)" "unsupported kind -1 for type complex\\*4"
|
||||
diff --git a/gdb/testsuite/gdb.fortran/type-kinds.exp b/gdb/testsuite/gdb.fortran/type-kinds.exp
|
||||
index ab5f19f97a4..a6f2aa4e870 100644
|
||||
--- a/gdb/testsuite/gdb.fortran/type-kinds.exp
|
||||
+++ b/gdb/testsuite/gdb.fortran/type-kinds.exp
|
||||
@@ -43,12 +43,20 @@ proc test_basic_parsing_of_type_kinds {} {
|
||||
test_cast_1_to_type_kind "complex" "" "\\(1,0\\)" "8"
|
||||
test_cast_1_to_type_kind "complex" "4" "\\(1,0\\)" "8"
|
||||
test_cast_1_to_type_kind "complex" "8" "\\(1,0\\)" "16"
|
||||
- test_cast_1_to_type_kind "complex" "16" "\\(1,0\\)" "32"
|
||||
+ set re_unsupported_kind \
|
||||
+ [string_to_regexp "unsupported kind 16 for type complex*4"]
|
||||
+ test_cast_1_to_type_kind "complex" "16" \
|
||||
+ [string_to_regexp (1,0)]|$re_unsupported_kind \
|
||||
+ 32|$re_unsupported_kind
|
||||
|
||||
test_cast_1_to_type_kind "real" "" "1" "4"
|
||||
test_cast_1_to_type_kind "real" "4" "1" "4"
|
||||
test_cast_1_to_type_kind "real" "8" "1" "8"
|
||||
- test_cast_1_to_type_kind "real" "16" "1" "16"
|
||||
+ set re_unsupported_kind \
|
||||
+ [string_to_regexp "unsupported kind 16 for type real*4"]
|
||||
+ test_cast_1_to_type_kind "real" "16" \
|
||||
+ 1|$re_unsupported_kind \
|
||||
+ 16|$re_unsupported_kind
|
||||
|
||||
test_cast_1_to_type_kind "logical" "" "\\.TRUE\\." "4"
|
||||
test_cast_1_to_type_kind "logical" "1" "\\.TRUE\\." "1"
|
||||
@@ -83,11 +91,17 @@ proc test_old_star_type_sizes {} {
|
||||
|
||||
gdb_test "p ((complex*4) 1)" " = \\(1,0\\)"
|
||||
gdb_test "p ((complex*8) 1)" " = \\(1,0\\)"
|
||||
- gdb_test "p ((complex*16) 1)" " = \\(1,0\\)"
|
||||
+ set re_unsupported_kind \
|
||||
+ [string_to_regexp "unsupported kind 16 for type complex*4"]
|
||||
+ gdb_test "p ((complex*16) 1)" \
|
||||
+ [string_to_regexp " = (1,0)"]|$re_unsupported_kind
|
||||
|
||||
gdb_test "p ((real*4) 1)" " = 1"
|
||||
gdb_test "p ((real*8) 1)" " = 1"
|
||||
- gdb_test "p ((real*16) 1)" " = 1"
|
||||
+ set re_unsupported_kind \
|
||||
+ [string_to_regexp "unsupported kind 16 for type real*4"]
|
||||
+ gdb_test "p ((real*16) 1)" \
|
||||
+ "( = 1|$re_unsupported_kind)"
|
||||
|
||||
gdb_test "p ((logical*1) 1)" " = \\.TRUE\\."
|
||||
gdb_test "p ((logical*4) 1)" " = \\.TRUE\\."
|
||||
diff --git a/gdb/testsuite/gdb.fortran/types.exp b/gdb/testsuite/gdb.fortran/types.exp
|
||||
index 83b109869e6..edbf5abee97 100644
|
||||
--- a/gdb/testsuite/gdb.fortran/types.exp
|
||||
+++ b/gdb/testsuite/gdb.fortran/types.exp
|
||||
@@ -94,7 +94,24 @@ proc test_primitive_types_known {} {
|
||||
# While TYPE_KIND is allowed as input, GDB will always return the
|
||||
# Fortran notation TYPE*KIND
|
||||
regsub -all "_" $type "\*" type_res
|
||||
- gdb_test "ptype $type" [string_to_regexp "type = $type_res"]
|
||||
+ set re [string_to_regexp "type = $type_res"]
|
||||
+ switch $type {
|
||||
+ real*16 - complex*16 {
|
||||
+ regexp {^[^*_]*} $type base
|
||||
+ set re_unsupported \
|
||||
+ [string_to_regexp \
|
||||
+ "unsupported kind 16 for type $base*4"]
|
||||
+ set re ($re|$re_unsupported)
|
||||
+ }
|
||||
+ real_16 - complex_16 {
|
||||
+ set re_unsupported \
|
||||
+ [string_to_regexp \
|
||||
+ "unsupported type $type_res"]
|
||||
+ set re ($re|$re_unsupported)
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ gdb_test "ptype $type" $re
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.43.0
|
||||
|
@@ -1,365 +0,0 @@
|
||||
From 86e379aa22ba5e77ba0c6fa26588c5fd1d9e6abe Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Mon, 19 Feb 2024 09:59:15 +0100
|
||||
Subject: [PATCH 13/48] [gdb/exp] Fix printing of out of bounds struct members
|
||||
|
||||
When building gdb with -O0 -fsanitize=address, and running test-case
|
||||
gdb.ada/uninitialized_vars.exp, I run into:
|
||||
...
|
||||
(gdb) info locals
|
||||
a = 0
|
||||
z = (a => 1, b => false, c => 2.0)
|
||||
=================================================================
|
||||
==66372==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000097f58 at pc 0xffff52c0da1c bp 0xffffc90a1d40 sp 0xffffc90a1d80
|
||||
READ of size 4 at 0x602000097f58 thread T0
|
||||
#0 0xffff52c0da18 in memmove (/lib64/libasan.so.8+0x6da18)
|
||||
#1 0xbcab24 in unsigned char* std::__copy_move_backward<false, true, std::random_access_iterator_tag>::__copy_move_b<unsigned char const, unsigned char>(unsigned char const*, unsigned char const*, unsigned char*) /usr/include/c++/13/bits/stl_algobase.h:748
|
||||
#2 0xbc9bf4 in unsigned char* std::__copy_move_backward_a2<false, unsigned char const*, unsigned char*>(unsigned char const*, unsigned char const*, unsigned char*) /usr/include/c++/13/bits/stl_algobase.h:769
|
||||
#3 0xbc898c in unsigned char* std::__copy_move_backward_a1<false, unsigned char const*, unsigned char*>(unsigned char const*, unsigned char const*, unsigned char*) /usr/include/c++/13/bits/stl_algobase.h:778
|
||||
#4 0xbc715c in unsigned char* std::__copy_move_backward_a<false, unsigned char const*, unsigned char*>(unsigned char const*, unsigned char const*, unsigned char*) /usr/include/c++/13/bits/stl_algobase.h:807
|
||||
#5 0xbc4e6c in unsigned char* std::copy_backward<unsigned char const*, unsigned char*>(unsigned char const*, unsigned char const*, unsigned char*) /usr/include/c++/13/bits/stl_algobase.h:867
|
||||
#6 0xbc2934 in void gdb::copy<unsigned char const, unsigned char>(gdb::array_view<unsigned char const>, gdb::array_view<unsigned char>) gdb/../gdbsupport/array-view.h:223
|
||||
#7 0x20e0100 in value::contents_copy_raw(value*, long, long, long) gdb/value.c:1239
|
||||
#8 0x20e9830 in value::primitive_field(long, int, type*) gdb/value.c:3078
|
||||
#9 0x20e98f8 in value_field(value*, int) gdb/value.c:3095
|
||||
#10 0xcafd64 in print_field_values gdb/ada-valprint.c:658
|
||||
#11 0xcb0fa0 in ada_val_print_struct_union gdb/ada-valprint.c:857
|
||||
#12 0xcb1bb4 in ada_value_print_inner(value*, ui_file*, int, value_print_options const*) gdb/ada-valprint.c:1042
|
||||
#13 0xc66e04 in ada_language::value_print_inner(value*, ui_file*, int, value_print_options const*) const (/home/vries/gdb/build/gdb/gdb+0xc66e04)
|
||||
#14 0x20ca1e8 in common_val_print(value*, ui_file*, int, value_print_options const*, language_defn const*) gdb/valprint.c:1092
|
||||
#15 0x20caabc in common_val_print_checked(value*, ui_file*, int, value_print_options const*, language_defn const*) gdb/valprint.c:1184
|
||||
#16 0x196c524 in print_variable_and_value(char const*, symbol*, frame_info_ptr, ui_file*, int) gdb/printcmd.c:2355
|
||||
#17 0x1d99ca0 in print_variable_and_value_data::operator()(char const*, symbol*) gdb/stack.c:2308
|
||||
#18 0x1dabca0 in gdb::function_view<void (char const*, symbol*)>::bind<print_variable_and_value_data>(print_variable_and_value_data&)::{lambda(gdb::fv_detail::erased_callable, char const*, symbol*)#1}::operator()(gdb::fv_detail::erased_callable, char const*, symbol*) const gdb/../gdbsupport/function-view.h:305
|
||||
#19 0x1dabd14 in gdb::function_view<void (char const*, symbol*)>::bind<print_variable_and_value_data>(print_variable_and_value_data&)::{lambda(gdb::fv_detail::erased_callable, char const*, symbol*)#1}::_FUN(gdb::fv_detail::erased_callable, char const*, symbol*) gdb/../gdbsupport/function-view.h:299
|
||||
#20 0x1dab34c in gdb::function_view<void (char const*, symbol*)>::operator()(char const*, symbol*) const gdb/../gdbsupport/function-view.h:289
|
||||
#21 0x1d9963c in iterate_over_block_locals gdb/stack.c:2240
|
||||
#22 0x1d99790 in iterate_over_block_local_vars(block const*, gdb::function_view<void (char const*, symbol*)>) gdb/stack.c:2259
|
||||
#23 0x1d9a598 in print_frame_local_vars gdb/stack.c:2380
|
||||
#24 0x1d9afac in info_locals_command(char const*, int) gdb/stack.c:2458
|
||||
#25 0xfd7b30 in do_simple_func gdb/cli/cli-decode.c:95
|
||||
#26 0xfe5a2c in cmd_func(cmd_list_element*, char const*, int) gdb/cli/cli-decode.c:2735
|
||||
#27 0x1f03790 in execute_command(char const*, int) gdb/top.c:575
|
||||
#28 0x1384080 in command_handler(char const*) gdb/event-top.c:566
|
||||
#29 0x1384e2c in command_line_handler(std::unique_ptr<char, gdb::xfree_deleter<char> >&&) gdb/event-top.c:802
|
||||
#30 0x1f731e4 in tui_command_line_handler gdb/tui/tui-interp.c:104
|
||||
#31 0x1382a58 in gdb_rl_callback_handler gdb/event-top.c:259
|
||||
#32 0x21dbb80 in rl_callback_read_char readline/readline/callback.c:290
|
||||
#33 0x1382510 in gdb_rl_callback_read_char_wrapper_noexcept gdb/event-top.c:195
|
||||
#34 0x138277c in gdb_rl_callback_read_char_wrapper gdb/event-top.c:234
|
||||
#35 0x1fe9b40 in stdin_event_handler gdb/ui.c:155
|
||||
#36 0x35ff1bc in handle_file_event gdbsupport/event-loop.cc:573
|
||||
#37 0x35ff9d8 in gdb_wait_for_event gdbsupport/event-loop.cc:694
|
||||
#38 0x35fd284 in gdb_do_one_event(int) gdbsupport/event-loop.cc:264
|
||||
#39 0x1768080 in start_event_loop gdb/main.c:408
|
||||
#40 0x17684c4 in captured_command_loop gdb/main.c:472
|
||||
#41 0x176cfc8 in captured_main gdb/main.c:1342
|
||||
#42 0x176d088 in gdb_main(captured_main_args*) gdb/main.c:1361
|
||||
#43 0xb73edc in main gdb/gdb.c:39
|
||||
#44 0xffff519b09d8 in __libc_start_call_main (/lib64/libc.so.6+0x309d8)
|
||||
#45 0xffff519b0aac in __libc_start_main@@GLIBC_2.34 (/lib64/libc.so.6+0x30aac)
|
||||
#46 0xb73c2c in _start (/home/vries/gdb/build/gdb/gdb+0xb73c2c)
|
||||
|
||||
0x602000097f58 is located 0 bytes after 8-byte region [0x602000097f50,0x602000097f58)
|
||||
allocated by thread T0 here:
|
||||
#0 0xffff52c65218 in calloc (/lib64/libasan.so.8+0xc5218)
|
||||
#1 0xcbc278 in xcalloc gdb/alloc.c:97
|
||||
#2 0x35f21e8 in xzalloc(unsigned long) gdbsupport/common-utils.cc:29
|
||||
#3 0x20de270 in value::allocate_contents(bool) gdb/value.c:937
|
||||
#4 0x20edc08 in value::fetch_lazy() gdb/value.c:4033
|
||||
#5 0x20dadc0 in value::entirely_covered_by_range_vector(std::vector<range, std::allocator<range> > const&) gdb/value.c:229
|
||||
#6 0xcb2298 in value::entirely_optimized_out() gdb/value.h:560
|
||||
#7 0x20ca6fc in value_check_printable gdb/valprint.c:1133
|
||||
#8 0x20caa8c in common_val_print_checked(value*, ui_file*, int, value_print_options const*, language_defn const*) gdb/valprint.c:1182
|
||||
#9 0x196c524 in print_variable_and_value(char const*, symbol*, frame_info_ptr, ui_file*, int) gdb/printcmd.c:2355
|
||||
#10 0x1d99ca0 in print_variable_and_value_data::operator()(char const*, symbol*) gdb/stack.c:2308
|
||||
#11 0x1dabca0 in gdb::function_view<void (char const*, symbol*)>::bind<print_variable_and_value_data>(print_variable_and_value_data&)::{lambda(gdb::fv_detail::erased_callable, char const*, symbol*)#1}::operator()(gdb::fv_detail::erased_callable, char const*, symbol*) const gdb/../gdbsupport/function-view.h:305
|
||||
#12 0x1dabd14 in gdb::function_view<void (char const*, symbol*)>::bind<print_variable_and_value_data>(print_variable_and_value_data&)::{lambda(gdb::fv_detail::erased_callable, char const*, symbol*)#1}::_FUN(gdb::fv_detail::erased_callable, char const*, symbol*) gdb/../gdbsupport/function-view.h:299
|
||||
#13 0x1dab34c in gdb::function_view<void (char const*, symbol*)>::operator()(char const*, symbol*) const gdb/../gdbsupport/function-view.h:289
|
||||
#14 0x1d9963c in iterate_over_block_locals gdb/stack.c:2240
|
||||
#15 0x1d99790 in iterate_over_block_local_vars(block const*, gdb::function_view<void (char const*, symbol*)>) gdb/stack.c:2259
|
||||
#16 0x1d9a598 in print_frame_local_vars gdb/stack.c:2380
|
||||
#17 0x1d9afac in info_locals_command(char const*, int) gdb/stack.c:2458
|
||||
#18 0xfd7b30 in do_simple_func gdb/cli/cli-decode.c:95
|
||||
#19 0xfe5a2c in cmd_func(cmd_list_element*, char const*, int) gdb/cli/cli-decode.c:2735
|
||||
#20 0x1f03790 in execute_command(char const*, int) gdb/top.c:575
|
||||
#21 0x1384080 in command_handler(char const*) gdb/event-top.c:566
|
||||
#22 0x1384e2c in command_line_handler(std::unique_ptr<char, gdb::xfree_deleter<char> >&&) gdb/event-top.c:802
|
||||
#23 0x1f731e4 in tui_command_line_handler gdb/tui/tui-interp.c:104
|
||||
#24 0x1382a58 in gdb_rl_callback_handler gdb/event-top.c:259
|
||||
#25 0x21dbb80 in rl_callback_read_char readline/readline/callback.c:290
|
||||
#26 0x1382510 in gdb_rl_callback_read_char_wrapper_noexcept gdb/event-top.c:195
|
||||
#27 0x138277c in gdb_rl_callback_read_char_wrapper gdb/event-top.c:234
|
||||
#28 0x1fe9b40 in stdin_event_handler gdb/ui.c:155
|
||||
#29 0x35ff1bc in handle_file_event gdbsupport/event-loop.cc:573
|
||||
|
||||
SUMMARY: AddressSanitizer: heap-buffer-overflow (/lib64/libasan.so.8+0x6da18) in memmove
|
||||
...
|
||||
|
||||
The error happens when trying to print either variable y or y2:
|
||||
...
|
||||
type Variable_Record (A : Boolean := True) is record
|
||||
case A is
|
||||
when True =>
|
||||
B : Integer;
|
||||
when False =>
|
||||
C : Float;
|
||||
D : Integer;
|
||||
end case;
|
||||
end record;
|
||||
Y : Variable_Record := (A => True, B => 1);
|
||||
Y2 : Variable_Record := (A => False, C => 1.0, D => 2);
|
||||
...
|
||||
when the variables are uninitialized.
|
||||
|
||||
The error happens only when printing the entire variable:
|
||||
...
|
||||
(gdb) p y.a
|
||||
$2 = 216
|
||||
(gdb) p y.b
|
||||
There is no member named b.
|
||||
(gdb) p y.c
|
||||
$3 = 9.18340949e-41
|
||||
(gdb) p y.d
|
||||
$4 = 1
|
||||
(gdb) p y
|
||||
<AddressSanitizer: heap-buffer-overflow>
|
||||
...
|
||||
|
||||
The error happens as follows:
|
||||
- field a functions as discriminant, choosing either the b, or c+d variant.
|
||||
- when y.a happens to be set to 216, as above, gdb interprets this as the
|
||||
variable having the c+d variant (which is why trying to print y.b fails).
|
||||
- when printing y, gdb allocates a value, copies the bytes into it from the
|
||||
target, and then prints the value.
|
||||
- gdb allocates the value using the type size, which is 8. It's 8 because
|
||||
that's what the DW_AT_byte_size indicates. Note that for valid values of a,
|
||||
it gives correct results: if a is 0 (c+d variant), size is 12, if a is 1
|
||||
(b variant), size is 8.
|
||||
- gdb tries to print field d, which is at an 8 byte offset, and that results
|
||||
in a out-of-bounds access for the allocated 8-byte value.
|
||||
|
||||
Fix this by handling this case in value::contents_copy_raw, such that we have:
|
||||
...
|
||||
(gdb) p y
|
||||
$1 = (a => 24, c => 9.18340949e-41,
|
||||
d => <error reading variable: access outside bounds of object>)
|
||||
...
|
||||
|
||||
An alternative (additional) fix could be this: in compute_variant_fields_inner
|
||||
gdb reads the discriminant y.a to decide which variant is active. It would be
|
||||
nice to detect that the value (y.a == 24) is not a valid Boolean, and give up
|
||||
on choosing a variant altoghether. However, the situation regarding the
|
||||
internal type CODE_TYPE_BOOL is currently ambiguous (see PR31282) and it's not
|
||||
possible to reliably decide what valid values are.
|
||||
|
||||
The test-case source file gdb.ada/uninitialized-variable-record/parse.adb is
|
||||
a reduced version of gdb.ada/uninitialized_vars/parse.adb, so it copies the
|
||||
copyright years.
|
||||
|
||||
Note that the test-case needs gcc-12 or newer, it's unsupported for older gcc
|
||||
versions. [ So, it would be nice to rewrite it into a dwarf assembly
|
||||
test-case. ]
|
||||
|
||||
The test-case loops over all languages. This is inherited from an earlier
|
||||
attempt to fix this, which had language-specific fixes (in print_field_values,
|
||||
cp_print_value_fields, pascal_object_print_value_fields and
|
||||
f_language::value_print_inner). I've left this in, but I suppose it's not
|
||||
strictly necessary anymore.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
|
||||
PR exp/31258
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31258
|
||||
---
|
||||
.../gdb.ada/uninitialized-variable-record.exp | 122 ++++++++++++++++++
|
||||
.../uninitialized-variable-record/parse.adb | 33 +++++
|
||||
gdb/value.c | 3 +
|
||||
3 files changed, 158 insertions(+)
|
||||
create mode 100644 gdb/testsuite/gdb.ada/uninitialized-variable-record.exp
|
||||
create mode 100644 gdb/testsuite/gdb.ada/uninitialized-variable-record/parse.adb
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.ada/uninitialized-variable-record.exp b/gdb/testsuite/gdb.ada/uninitialized-variable-record.exp
|
||||
new file mode 100644
|
||||
index 00000000000..7fc72395edf
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.ada/uninitialized-variable-record.exp
|
||||
@@ -0,0 +1,122 @@
|
||||
+# Copyright 2024 Free Software Foundation, Inc.
|
||||
+#
|
||||
+# This program is free software; you can redistribute it and/or modify
|
||||
+# it under the terms of the GNU General Public License as published by
|
||||
+# the Free Software Foundation; either version 3 of the License, or
|
||||
+# (at your option) any later version.
|
||||
+#
|
||||
+# This program is distributed in the hope that it will be useful,
|
||||
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+# GNU General Public License for more details.
|
||||
+#
|
||||
+# You should have received a copy of the GNU General Public License
|
||||
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
+
|
||||
+load_lib "ada.exp"
|
||||
+
|
||||
+require allow_ada_tests
|
||||
+
|
||||
+standard_ada_testfile parse
|
||||
+
|
||||
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable {debug}] != "" } {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+clean_restart ${testfile}
|
||||
+
|
||||
+set bp_location [gdb_get_line_number "START" ${testdir}/parse.adb]
|
||||
+runto "parse.adb:$bp_location"
|
||||
+
|
||||
+# Check that we have the expected value for variable y2.
|
||||
+
|
||||
+gdb_test "p y2" [string_to_regexp " = (a => false, c => 1.0, d => 2)"]
|
||||
+
|
||||
+# Shorthand.
|
||||
+
|
||||
+proc set_lang { lang } {
|
||||
+ gdb_test_multiple "set language $lang" "" {
|
||||
+ -re -wrap "" {
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+# Calculate the offset of y2.d.
|
||||
+
|
||||
+set re_cast [string_to_regexp "(access integer)"]
|
||||
+gdb_test_multiple "print &y2.d - &y2" "" {
|
||||
+ -re -wrap " = $re_cast ($hex)" {
|
||||
+ set offset_d $expect_out(1,string)
|
||||
+ pass $gdb_test_name
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+# Try to find a interesting discriminator value, such that at the same time:
|
||||
+# - the d field is part of the variable, and
|
||||
+# - the type size is too small to contain d.
|
||||
+
|
||||
+set interesting_discriminator -1
|
||||
+set_lang c
|
||||
+for { set i 0 } { $i < 256 } { incr i } {
|
||||
+ with_test_prefix $i {
|
||||
+
|
||||
+ # Patch in the discriminator value.
|
||||
+ gdb_test_multiple "set var *(unsigned char *)(&y2.a)=$i" "" {
|
||||
+ -re -wrap "" {
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ # Check that we have the variant with fields c+d instead of b.
|
||||
+ set have_b 0
|
||||
+ gdb_test_multiple "with language ada -- print y2.b" "" {
|
||||
+ -re -wrap " = $decimal" {
|
||||
+ set have_b 1
|
||||
+ }
|
||||
+ -re -wrap "" {
|
||||
+ }
|
||||
+ }
|
||||
+ if { $have_b } {
|
||||
+ # This is the variant with field b.
|
||||
+ continue
|
||||
+ }
|
||||
+
|
||||
+ set size 0
|
||||
+ gdb_test_multiple "print sizeof (y2)" "" {
|
||||
+ -re -wrap " = (.*)" {
|
||||
+ set size $expect_out(1,string)
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if { ! $size } {
|
||||
+ continue
|
||||
+ }
|
||||
+
|
||||
+ if { [expr $size > $offset_d] } {
|
||||
+ # Field d fits in the size.
|
||||
+ continue
|
||||
+ }
|
||||
+
|
||||
+ set interesting_discriminator $i
|
||||
+ break
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+require {expr $interesting_discriminator != -1}
|
||||
+
|
||||
+foreach lang [gdb_supported_languages] {
|
||||
+ with_test_prefix $lang {
|
||||
+ set_lang $lang
|
||||
+
|
||||
+ gdb_test_multiple "print y2" "" {
|
||||
+ -re -wrap ", d => $decimal.*" {
|
||||
+ fail $gdb_test_name
|
||||
+ }
|
||||
+ -re -wrap ", d = $decimal.*" {
|
||||
+ fail $gdb_test_name
|
||||
+ }
|
||||
+ -re -wrap "" {
|
||||
+ pass $gdb_test_name
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.ada/uninitialized-variable-record/parse.adb b/gdb/testsuite/gdb.ada/uninitialized-variable-record/parse.adb
|
||||
new file mode 100644
|
||||
index 00000000000..f00c75ca2dc
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.ada/uninitialized-variable-record/parse.adb
|
||||
@@ -0,0 +1,33 @@
|
||||
+-- Copyright 2009-2024 Free Software Foundation, Inc.
|
||||
+--
|
||||
+-- This program is free software; you can redistribute it and/or modify
|
||||
+-- it under the terms of the GNU General Public License as published by
|
||||
+-- the Free Software Foundation; either version 3 of the License, or
|
||||
+-- (at your option) any later version.
|
||||
+--
|
||||
+-- This program is distributed in the hope that it will be useful,
|
||||
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+-- GNU General Public License for more details.
|
||||
+--
|
||||
+-- You should have received a copy of the GNU General Public License
|
||||
+-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
+
|
||||
+-- Based on gdb.ada/uninitialized_vars/parse.adb.
|
||||
+
|
||||
+procedure Parse is
|
||||
+
|
||||
+ type Variable_Record (A : Boolean := True) is record
|
||||
+ case A is
|
||||
+ when True =>
|
||||
+ B : Integer;
|
||||
+ when False =>
|
||||
+ C : Float;
|
||||
+ D : Integer;
|
||||
+ end case;
|
||||
+ end record;
|
||||
+ Y2 : Variable_Record := (A => False, C => 1.0, D => 2);
|
||||
+
|
||||
+begin
|
||||
+ null; -- START
|
||||
+end Parse;
|
||||
diff --git a/gdb/value.c b/gdb/value.c
|
||||
index 1cc32625629..56ae9db6603 100644
|
||||
--- a/gdb/value.c
|
||||
+++ b/gdb/value.c
|
||||
@@ -1188,6 +1188,9 @@ value::contents_copy_raw (struct value *dst, LONGEST dst_offset,
|
||||
gdb_assert (!dst->bits_any_optimized_out (TARGET_CHAR_BIT * dst_offset,
|
||||
TARGET_CHAR_BIT * length));
|
||||
|
||||
+ if ((src_offset + copy_length) * unit_size > enclosing_type ()-> length ())
|
||||
+ error (_("access outside bounds of object"));
|
||||
+
|
||||
/* Copy the data. */
|
||||
gdb::array_view<gdb_byte> dst_contents
|
||||
= dst->contents_all_raw ().slice (dst_offset * unit_size,
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,86 +0,0 @@
|
||||
From a6800d9c8145f25001dd39afc3571e3350573e81 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Mon, 6 May 2024 14:23:25 +0200
|
||||
Subject: [PATCH] [gdb/exp] Redo cast handling for indirection
|
||||
|
||||
In commit ed8fd0a342f ("[gdb/exp] Fix cast handling for indirection"), I
|
||||
introduced the behaviour that even though we have:
|
||||
...
|
||||
(gdb) p *a_loc ()
|
||||
'a_loc' has unknown return type; cast the call to its declared return type
|
||||
...
|
||||
we get:
|
||||
...
|
||||
(gdb) p (char)*a_loc ()
|
||||
$1 = 97 'a'
|
||||
...
|
||||
|
||||
In other words, the unknown return type of a_loc is inferred from the cast,
|
||||
effectually evaluating:
|
||||
...
|
||||
(gdb) p (char)*(char *)a_loc ()
|
||||
...
|
||||
|
||||
This is convient for the case that errno is defined as:
|
||||
...
|
||||
#define errno (*__errno_location ())
|
||||
...
|
||||
and the return type of __errno_location is unknown but the macro definition is
|
||||
known, such that we can use:
|
||||
...
|
||||
(gdb) p (int)errno
|
||||
...
|
||||
instead of
|
||||
...
|
||||
(gdb) p *(int *)__errno_location ()
|
||||
...
|
||||
|
||||
However, as Pedro has pointed out in post-commit review [1], this makes it
|
||||
harder to reason about the semantics of an expression.
|
||||
|
||||
For instance, this:
|
||||
...
|
||||
(gdb) p (long long)*a_loc ()"
|
||||
...
|
||||
would be evaluated without debug info as:
|
||||
...
|
||||
(gdb) p (long long)*(long long *)a_loc ()"
|
||||
...
|
||||
but with debug info as:
|
||||
...
|
||||
(gdb) p (long long)*(char *)a_loc ()"
|
||||
...
|
||||
|
||||
Fix this by instead simply erroring out for this case:
|
||||
...
|
||||
(gdb) p (char)*a_loc ()
|
||||
'a_loc' has unknown return type; cast the call to its declared return type
|
||||
...
|
||||
|
||||
Tested on x86_64-linux.
|
||||
|
||||
Approved-By: Pedro Alves <pedro@palves.net>
|
||||
|
||||
[1] https://sourceware.org/pipermail/gdb-patches/2024-May/208821.html
|
||||
---
|
||||
gdb/testsuite/gdb.base/cast-indirection.exp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/cast-indirection.exp b/gdb/testsuite/gdb.base/cast-indirection.exp
|
||||
index f1fe4302d27..7b9b5a5d677 100644
|
||||
--- a/gdb/testsuite/gdb.base/cast-indirection.exp
|
||||
+++ b/gdb/testsuite/gdb.base/cast-indirection.exp
|
||||
@@ -13,7 +13,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
-# Check that "p (char)*a_loc ()" is handled as "p (char)*(char *)a_loc ()".
|
||||
+# Check that "p (char)*a_loc ()" is handled correctly.
|
||||
|
||||
standard_testfile
|
||||
|
||||
|
||||
base-commit: fc73000faa1798573090994167b7e2d451c211db
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,333 +0,0 @@
|
||||
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"
|
@@ -1,144 +0,0 @@
|
||||
From 350172ea215c7074601e8424ff636563612f91e8 Mon Sep 17 00:00:00 2001
|
||||
From: Pedro Alves <pedro@palves.net>
|
||||
Date: Wed, 21 Feb 2024 16:23:55 +0000
|
||||
Subject: [PATCH 14/48] [gdb] Fix heap-use-after-free in select_event_lwp
|
||||
|
||||
PR gdb/31259 reveals one scenario where we run into a
|
||||
heap-use-after-free reported by thread sanitizer, while running
|
||||
gdb.base/vfork-follow-parent.exp.
|
||||
|
||||
The heap-use-after-free happens during the following scenario:
|
||||
|
||||
- linux_nat_wait_1 is about to return an event for T2. It stops all
|
||||
other threads, and while doing so, stop_wait_callback -> wait_lwp
|
||||
sees T1 exit, and decides to leave the exit event pending. It
|
||||
should have set the lp->stopped flag too, but does not -- this is
|
||||
the bug.
|
||||
|
||||
- The event for T2 is reported, is processed by infrun, and we're
|
||||
back at linux_nat_wait_1.
|
||||
|
||||
- linux_nat_wait_1 selects LWP T1 with the pending exit status to
|
||||
report.
|
||||
|
||||
- it sets variable lp to point to the corresponding lwp_info.
|
||||
|
||||
- it calls stop_callback and stop_wait_callback for all threads
|
||||
(because !target_is_non_stop_p ()).
|
||||
|
||||
- it calls select_event_lwp to maybe pick another thread than T1, to
|
||||
prevent starvation.
|
||||
|
||||
The problem is the following:
|
||||
|
||||
- while calling stop_wait_callback for all threads, it also does this
|
||||
for T1. While doing so, the corresponding lwp_info is deleted
|
||||
(callstack stop_wait_callback -> wait_lwp -> exit_lwp ->
|
||||
delete_lwp), leaving variable lp as a dangling pointer.
|
||||
|
||||
- variable lp is passed to select_event_lwp, which derefences it,
|
||||
which causes the heap-use-after-free.
|
||||
|
||||
Note that the comment here mentions "all other LWP's":
|
||||
...
|
||||
/* Now stop all other LWP's ... */
|
||||
iterate_over_lwps (minus_one_ptid, stop_callback);
|
||||
/* ... and wait until all of them have reported back that
|
||||
they're no longer running. */
|
||||
iterate_over_lwps (minus_one_ptid, stop_wait_callback);
|
||||
...
|
||||
|
||||
The reason the comments say "all other LWP's", and doesn't bother
|
||||
filtering out LP is that lp->stopped should be true at this point, and
|
||||
the callbacks (both stop_callback and stop_wait_callback) check that
|
||||
flag, and do nothing if set. I.e., they skip already-stopped threads,
|
||||
so they should skip LP.
|
||||
|
||||
In this particular scenario, though, we missed setting the stopped
|
||||
flag right in the first step described above, so LP was iterated over
|
||||
incorrectly.
|
||||
|
||||
The fix is to make wait_lwp set the lp->stopped flag when it decides
|
||||
to leave the exit event pending. However, going a bit further,
|
||||
gdbserver has a mark_lwp_dead function to centralize setting up
|
||||
various lwp flags such that the rest of the code doesn't mishandle
|
||||
them, and it seems like a good idea to do a similar thing in gdb as
|
||||
well. That is what this patch does.
|
||||
|
||||
PR gdb/31259
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31259
|
||||
Co-Authored-By: Tom de Vries <tdevries@suse.de>
|
||||
Change-Id: I4a6169976f89bf714c478cbb2b7d4c32365e62a9
|
||||
---
|
||||
gdb/linux-nat.c | 34 +++++++++++++++++++++++++---------
|
||||
1 file changed, 25 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
|
||||
index 7e36ced6292..ed445c5e5bb 100644
|
||||
--- a/gdb/linux-nat.c
|
||||
+++ b/gdb/linux-nat.c
|
||||
@@ -2029,6 +2029,27 @@ wait_for_signal ()
|
||||
}
|
||||
}
|
||||
|
||||
+/* Mark LWP dead, with STATUS as exit status pending to report
|
||||
+ later. */
|
||||
+
|
||||
+static void
|
||||
+mark_lwp_dead (lwp_info *lp, int status)
|
||||
+{
|
||||
+ /* Store the exit status lp->waitstatus, because lp->status would be
|
||||
+ ambiguous (W_EXITCODE(0,0) == 0). */
|
||||
+ lp->waitstatus = host_status_to_waitstatus (status);
|
||||
+
|
||||
+ /* If we're processing LP's status, there should be no other event
|
||||
+ already recorded as pending. */
|
||||
+ gdb_assert (lp->status == 0);
|
||||
+
|
||||
+ /* Dead LWPs aren't expected to report a pending sigstop. */
|
||||
+ lp->signalled = 0;
|
||||
+
|
||||
+ /* Prevent trying to stop it. */
|
||||
+ lp->stopped = 1;
|
||||
+}
|
||||
+
|
||||
/* Wait for LP to stop. Returns the wait status, or 0 if the LWP has
|
||||
exited. */
|
||||
|
||||
@@ -2114,9 +2135,8 @@ wait_lwp (struct lwp_info *lp)
|
||||
|
||||
/* If this is the leader exiting, it means the whole
|
||||
process is gone. Store the status to report to the
|
||||
- core. Store it in lp->waitstatus, because lp->status
|
||||
- would be ambiguous (W_EXITCODE(0,0) == 0). */
|
||||
- lp->waitstatus = host_status_to_waitstatus (status);
|
||||
+ core. */
|
||||
+ mark_lwp_dead (lp, status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2908,12 +2928,7 @@ linux_nat_filter_event (int lwpid, int status)
|
||||
linux_nat_debug_printf ("LWP %ld exited (resumed=%d)",
|
||||
lp->ptid.lwp (), lp->resumed);
|
||||
|
||||
- /* Dead LWP's aren't expected to reported a pending sigstop. */
|
||||
- lp->signalled = 0;
|
||||
-
|
||||
- /* Store the pending event in the waitstatus, because
|
||||
- W_EXITCODE(0,0) == 0. */
|
||||
- lp->waitstatus = host_status_to_waitstatus (status);
|
||||
+ mark_lwp_dead (lp, status);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3248,6 +3263,7 @@ linux_nat_wait_1 (ptid_t ptid, struct target_waitstatus *ourstatus,
|
||||
}
|
||||
|
||||
gdb_assert (lp);
|
||||
+ gdb_assert (lp->stopped);
|
||||
|
||||
status = lp->status;
|
||||
lp->status = 0;
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,636 +0,0 @@
|
||||
From 1d02ba0f4adcba2595a67e88fb1ba6d35c7f8e5b Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Tue, 7 May 2024 11:33:57 +0200
|
||||
Subject: [PATCH] [gdb] Fix segfault in for_each_block, part 1
|
||||
|
||||
When running test-case gdb.base/vfork-follow-parent.exp on powerpc64 (likewise
|
||||
on s390x), I run into:
|
||||
...
|
||||
(gdb) PASS: gdb.base/vfork-follow-parent.exp: \
|
||||
exec_file=vfork-follow-parent-exit: target-non-stop=on: non-stop=off: \
|
||||
resolution_method=schedule-multiple: print unblock_parent = 1
|
||||
continue^M
|
||||
Continuing.^M
|
||||
Reading symbols from vfork-follow-parent-exit...^M
|
||||
^M
|
||||
^M
|
||||
Fatal signal: Segmentation fault^M
|
||||
----- Backtrace -----^M
|
||||
0x1027d3e7 gdb_internal_backtrace_1^M
|
||||
src/gdb/bt-utils.c:122^M
|
||||
0x1027d54f _Z22gdb_internal_backtracev^M
|
||||
src/gdb/bt-utils.c:168^M
|
||||
0x1057643f handle_fatal_signal^M
|
||||
src/gdb/event-top.c:889^M
|
||||
0x10576677 handle_sigsegv^M
|
||||
src/gdb/event-top.c:962^M
|
||||
0x3fffa7610477 ???^M
|
||||
0x103f2144 for_each_block^M
|
||||
src/gdb/dcache.c:199^M
|
||||
0x103f235b _Z17dcache_invalidateP13dcache_struct^M
|
||||
src/gdb/dcache.c:251^M
|
||||
0x10bde8c7 _Z24target_dcache_invalidatev^M
|
||||
src/gdb/target-dcache.c:50^M
|
||||
...
|
||||
or similar.
|
||||
|
||||
The root cause for the segmentation fault is that linux_is_uclinux gives an
|
||||
incorrect result: it should always return false, given that we're running on a
|
||||
regular linux system, but instead it returns first true, then false.
|
||||
|
||||
In more detail, the segmentation fault happens as follows:
|
||||
- a program space with an address space is created
|
||||
- a second program space is about to be created. maybe_new_address_space
|
||||
is called, and because linux_is_uclinux returns true, maybe_new_address_space
|
||||
returns false, and no new address space is created
|
||||
- a second program space with the same address space is created
|
||||
- a program space is deleted. Because linux_is_uclinux now returns false,
|
||||
gdbarch_has_shared_address_space (current_inferior ()->arch ()) returns
|
||||
false, and the address space is deleted
|
||||
- when gdb uses the address space of the remaining program space, we run into
|
||||
the segfault, because the address space is deleted.
|
||||
|
||||
Hardcoding linux_is_uclinux to false makes the test-case pass.
|
||||
|
||||
We leave addressing the root cause for the following commit in this series.
|
||||
|
||||
For now, prevent the segmentation fault by making the address space a refcounted
|
||||
object.
|
||||
|
||||
This was already suggested here [1]:
|
||||
...
|
||||
A better solution might be to have the address spaces be reference counted
|
||||
...
|
||||
|
||||
Tested on top of trunk on x86_64-linux and ppc64le-linux.
|
||||
Tested on top of gdb-14-branch on ppc64-linux.
|
||||
|
||||
Co-Authored-By: Simon Marchi <simon.marchi@polymtl.ca>
|
||||
|
||||
PR gdb/30547
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30547
|
||||
|
||||
[1] https://sourceware.org/pipermail/gdb-patches/2023-October/202928.html
|
||||
---
|
||||
gdb/breakpoint.c | 29 ++++++++-------
|
||||
gdb/inferior.c | 8 ++---
|
||||
gdb/inferior.h | 2 +-
|
||||
gdb/infrun.c | 18 +++++-----
|
||||
gdb/linux-nat.c | 2 +-
|
||||
gdb/process-stratum-target.c | 2 +-
|
||||
gdb/progspace.c | 22 +++++-------
|
||||
gdb/progspace.h | 64 +++++++++++++++++++++-------------
|
||||
gdb/record-btrace.c | 2 +-
|
||||
gdb/regcache.c | 2 +-
|
||||
gdb/scoped-mock-context.h | 2 +-
|
||||
gdb/target-dcache.c | 11 +++---
|
||||
gdbsupport/refcounted-object.h | 17 +++++++++
|
||||
13 files changed, 102 insertions(+), 79 deletions(-)
|
||||
|
||||
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
|
||||
index 01f187ca4fe..a22bdb091cd 100644
|
||||
--- a/gdb/breakpoint.c
|
||||
+++ b/gdb/breakpoint.c
|
||||
@@ -1723,7 +1723,7 @@ one_breakpoint_xfer_memory (gdb_byte *readbuf, gdb_byte *writebuf,
|
||||
int bptoffset = 0;
|
||||
|
||||
if (!breakpoint_address_match (target_info->placed_address_space, 0,
|
||||
- current_program_space->aspace, 0))
|
||||
+ current_program_space->aspace.get (), 0))
|
||||
{
|
||||
/* The breakpoint is inserted in a different address space. */
|
||||
return;
|
||||
@@ -2409,7 +2409,7 @@ should_be_inserted (struct bp_location *bl)
|
||||
a breakpoint. */
|
||||
if ((bl->loc_type == bp_loc_software_breakpoint
|
||||
|| bl->loc_type == bp_loc_hardware_breakpoint)
|
||||
- && stepping_past_instruction_at (bl->pspace->aspace,
|
||||
+ && stepping_past_instruction_at (bl->pspace->aspace.get (),
|
||||
bl->address)
|
||||
/* The single-step breakpoint may be inserted at the location
|
||||
we're trying to step if the instruction branches to itself.
|
||||
@@ -2847,7 +2847,7 @@ insert_bp_location (struct bp_location *bl,
|
||||
read the breakpoint instead of returning the data saved in
|
||||
the breakpoint location's shadow contents. */
|
||||
bl->target_info.reqstd_address = bl->address;
|
||||
- bl->target_info.placed_address_space = bl->pspace->aspace;
|
||||
+ bl->target_info.placed_address_space = bl->pspace->aspace.get ();
|
||||
bl->target_info.length = bl->length;
|
||||
|
||||
/* When working with target-side conditions, we must pass all the conditions
|
||||
@@ -4429,7 +4429,7 @@ bp_location_inserted_here_p (const struct bp_location *bl,
|
||||
const address_space *aspace, CORE_ADDR pc)
|
||||
{
|
||||
if (bl->inserted
|
||||
- && breakpoint_address_match (bl->pspace->aspace, bl->address,
|
||||
+ && breakpoint_address_match (bl->pspace->aspace.get (), bl->address,
|
||||
aspace, pc))
|
||||
{
|
||||
/* An unmapped overlay can't be a match. */
|
||||
@@ -4508,7 +4508,7 @@ hardware_watchpoint_inserted_in_range (const address_space *aspace,
|
||||
continue;
|
||||
|
||||
for (bp_location &loc : bpt.locations ())
|
||||
- if (loc.pspace->aspace == aspace && loc.inserted)
|
||||
+ if (loc.pspace->aspace.get () == aspace && loc.inserted)
|
||||
{
|
||||
CORE_ADDR l, h;
|
||||
|
||||
@@ -7330,10 +7330,10 @@ breakpoint_location_address_match (struct bp_location *bl,
|
||||
const address_space *aspace,
|
||||
CORE_ADDR addr)
|
||||
{
|
||||
- return (breakpoint_address_match (bl->pspace->aspace, bl->address,
|
||||
+ return (breakpoint_address_match (bl->pspace->aspace.get (), bl->address,
|
||||
aspace, addr)
|
||||
|| (bl->length
|
||||
- && breakpoint_address_match_range (bl->pspace->aspace,
|
||||
+ && breakpoint_address_match_range (bl->pspace->aspace.get (),
|
||||
bl->address, bl->length,
|
||||
aspace, addr)));
|
||||
}
|
||||
@@ -7350,7 +7350,7 @@ breakpoint_location_address_range_overlap (struct bp_location *bl,
|
||||
CORE_ADDR addr, int len)
|
||||
{
|
||||
if (gdbarch_has_global_breakpoints (target_gdbarch ())
|
||||
- || bl->pspace->aspace == aspace)
|
||||
+ || bl->pspace->aspace.get () == aspace)
|
||||
{
|
||||
int bl_len = bl->length != 0 ? bl->length : 1;
|
||||
|
||||
@@ -7407,8 +7407,10 @@ breakpoint_locations_match (const struct bp_location *loc1,
|
||||
/* We compare bp_location.length in order to cover ranged
|
||||
breakpoints. Keep this in sync with
|
||||
bp_location_is_less_than. */
|
||||
- return (breakpoint_address_match (loc1->pspace->aspace, loc1->address,
|
||||
- loc2->pspace->aspace, loc2->address)
|
||||
+ return (breakpoint_address_match (loc1->pspace->aspace.get (),
|
||||
+ loc1->address,
|
||||
+ loc2->pspace->aspace.get (),
|
||||
+ loc2->address)
|
||||
&& (loc1->loc_type == loc2->loc_type || sw_hw_bps_match)
|
||||
&& loc1->length == loc2->length);
|
||||
}
|
||||
@@ -9568,8 +9570,9 @@ ranged_breakpoint::breakpoint_hit (const struct bp_location *bl,
|
||||
|| ws.sig () != GDB_SIGNAL_TRAP)
|
||||
return 0;
|
||||
|
||||
- return breakpoint_address_match_range (bl->pspace->aspace, bl->address,
|
||||
- bl->length, aspace, bp_addr);
|
||||
+ return breakpoint_address_match_range (bl->pspace->aspace.get (),
|
||||
+ bl->address, bl->length, aspace,
|
||||
+ bp_addr);
|
||||
}
|
||||
|
||||
/* Implement the "resources_needed" method for ranged breakpoints. */
|
||||
@@ -12018,7 +12021,7 @@ code_breakpoint::breakpoint_hit (const struct bp_location *bl,
|
||||
|| ws.sig () != GDB_SIGNAL_TRAP)
|
||||
return 0;
|
||||
|
||||
- if (!breakpoint_address_match (bl->pspace->aspace, bl->address,
|
||||
+ if (!breakpoint_address_match (bl->pspace->aspace.get (), bl->address,
|
||||
aspace, bp_addr))
|
||||
return 0;
|
||||
|
||||
diff --git a/gdb/inferior.c b/gdb/inferior.c
|
||||
index 550bbd2827c..461f4fc076a 100644
|
||||
--- a/gdb/inferior.c
|
||||
+++ b/gdb/inferior.c
|
||||
@@ -831,15 +831,13 @@ remove_inferior_command (const char *args, int from_tty)
|
||||
struct inferior *
|
||||
add_inferior_with_spaces (void)
|
||||
{
|
||||
- struct address_space *aspace;
|
||||
struct program_space *pspace;
|
||||
struct inferior *inf;
|
||||
|
||||
/* If all inferiors share an address space on this system, this
|
||||
doesn't really return a new address space; otherwise, it
|
||||
really does. */
|
||||
- aspace = maybe_new_address_space ();
|
||||
- pspace = new program_space (aspace);
|
||||
+ pspace = new program_space (maybe_new_address_space ());
|
||||
inf = add_inferior (0);
|
||||
inf->pspace = pspace;
|
||||
inf->aspace = pspace->aspace;
|
||||
@@ -1002,15 +1000,13 @@ clone_inferior_command (const char *args, int from_tty)
|
||||
|
||||
for (i = 0; i < copies; ++i)
|
||||
{
|
||||
- struct address_space *aspace;
|
||||
struct program_space *pspace;
|
||||
struct inferior *inf;
|
||||
|
||||
/* If all inferiors share an address space on this system, this
|
||||
doesn't really return a new address space; otherwise, it
|
||||
really does. */
|
||||
- aspace = maybe_new_address_space ();
|
||||
- pspace = new program_space (aspace);
|
||||
+ pspace = new program_space (maybe_new_address_space ());
|
||||
inf = add_inferior (0);
|
||||
inf->pspace = pspace;
|
||||
inf->aspace = pspace->aspace;
|
||||
diff --git a/gdb/inferior.h b/gdb/inferior.h
|
||||
index 29c90d15efa..4139791740f 100644
|
||||
--- a/gdb/inferior.h
|
||||
+++ b/gdb/inferior.h
|
||||
@@ -577,7 +577,7 @@ class inferior : public refcounted_object,
|
||||
bool removable = false;
|
||||
|
||||
/* The address space bound to this inferior. */
|
||||
- struct address_space *aspace = NULL;
|
||||
+ address_space_ref_ptr aspace;
|
||||
|
||||
/* The program space bound to this inferior. */
|
||||
struct program_space *pspace = NULL;
|
||||
diff --git a/gdb/infrun.c b/gdb/infrun.c
|
||||
index 7be98cfc252..3854c66bf6c 100644
|
||||
--- a/gdb/infrun.c
|
||||
+++ b/gdb/infrun.c
|
||||
@@ -531,8 +531,8 @@ holding the child stopped. Try \"set detach-on-fork\" or \
|
||||
}
|
||||
else
|
||||
{
|
||||
- child_inf->aspace = new address_space ();
|
||||
- child_inf->pspace = new program_space (child_inf->aspace);
|
||||
+ child_inf->pspace = new program_space (new_address_space ());
|
||||
+ child_inf->aspace = child_inf->pspace->aspace;
|
||||
child_inf->removable = true;
|
||||
clone_program_space (child_inf->pspace, parent_inf->pspace);
|
||||
}
|
||||
@@ -610,8 +610,8 @@ holding the child stopped. Try \"set detach-on-fork\" or \
|
||||
|
||||
child_inf->aspace = parent_inf->aspace;
|
||||
child_inf->pspace = parent_inf->pspace;
|
||||
- parent_inf->aspace = new address_space ();
|
||||
- parent_inf->pspace = new program_space (parent_inf->aspace);
|
||||
+ parent_inf->pspace = new program_space (new_address_space ());
|
||||
+ parent_inf->aspace = parent_inf->pspace->aspace;
|
||||
clone_program_space (parent_inf->pspace, child_inf->pspace);
|
||||
|
||||
/* The parent inferior is still the current one, so keep things
|
||||
@@ -620,8 +620,8 @@ holding the child stopped. Try \"set detach-on-fork\" or \
|
||||
}
|
||||
else
|
||||
{
|
||||
- child_inf->aspace = new address_space ();
|
||||
- child_inf->pspace = new program_space (child_inf->aspace);
|
||||
+ child_inf->pspace = new program_space (new_address_space ());
|
||||
+ child_inf->aspace = child_inf->pspace->aspace;
|
||||
child_inf->removable = true;
|
||||
child_inf->symfile_flags = SYMFILE_NO_READ;
|
||||
clone_program_space (child_inf->pspace, parent_inf->pspace);
|
||||
@@ -1031,7 +1031,6 @@ handle_vfork_child_exec_or_exit (int exec)
|
||||
if (vfork_parent->pending_detach)
|
||||
{
|
||||
struct program_space *pspace;
|
||||
- struct address_space *aspace;
|
||||
|
||||
/* follow-fork child, detach-on-fork on. */
|
||||
|
||||
@@ -1056,9 +1055,8 @@ handle_vfork_child_exec_or_exit (int exec)
|
||||
of" a hack. */
|
||||
|
||||
pspace = inf->pspace;
|
||||
- aspace = inf->aspace;
|
||||
- inf->aspace = nullptr;
|
||||
inf->pspace = nullptr;
|
||||
+ address_space_ref_ptr aspace = std::move (inf->aspace);
|
||||
|
||||
if (print_inferior_events)
|
||||
{
|
||||
@@ -5906,7 +5904,7 @@ handle_inferior_event (struct execution_control_state *ecs)
|
||||
= get_thread_arch_aspace_regcache (parent_inf,
|
||||
ecs->ws.child_ptid (),
|
||||
gdbarch,
|
||||
- parent_inf->aspace);
|
||||
+ parent_inf->aspace.get ());
|
||||
/* Read PC value of parent process. */
|
||||
parent_pc = regcache_read_pc (regcache);
|
||||
|
||||
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
|
||||
index ed445c5e5bb..c8991cc3da4 100644
|
||||
--- a/gdb/linux-nat.c
|
||||
+++ b/gdb/linux-nat.c
|
||||
@@ -4365,7 +4365,7 @@ linux_nat_target::thread_address_space (ptid_t ptid)
|
||||
|
||||
inf = find_inferior_pid (this, pid);
|
||||
gdb_assert (inf != NULL);
|
||||
- return inf->aspace;
|
||||
+ return inf->aspace.get ();
|
||||
}
|
||||
|
||||
/* Return the cached value of the processor core for thread PTID. */
|
||||
diff --git a/gdb/process-stratum-target.c b/gdb/process-stratum-target.c
|
||||
index 5c031203e89..4bcca4f39c2 100644
|
||||
--- a/gdb/process-stratum-target.c
|
||||
+++ b/gdb/process-stratum-target.c
|
||||
@@ -37,7 +37,7 @@ process_stratum_target::thread_address_space (ptid_t ptid)
|
||||
"address space of thread %s\n"),
|
||||
target_pid_to_str (ptid).c_str ());
|
||||
|
||||
- return inf->aspace;
|
||||
+ return inf->aspace.get ();
|
||||
}
|
||||
|
||||
struct gdbarch *
|
||||
diff --git a/gdb/progspace.c b/gdb/progspace.c
|
||||
index 1dbcd5875dd..b4d25ba6196 100644
|
||||
--- a/gdb/progspace.c
|
||||
+++ b/gdb/progspace.c
|
||||
@@ -55,8 +55,8 @@ address_space::address_space ()
|
||||
return a pointer to an existing address space, in case inferiors
|
||||
share an address space on this target system. */
|
||||
|
||||
-struct address_space *
|
||||
-maybe_new_address_space (void)
|
||||
+address_space_ref_ptr
|
||||
+maybe_new_address_space ()
|
||||
{
|
||||
int shared_aspace = gdbarch_has_shared_address_space (target_gdbarch ());
|
||||
|
||||
@@ -66,7 +66,7 @@ maybe_new_address_space (void)
|
||||
return program_spaces[0]->aspace;
|
||||
}
|
||||
|
||||
- return new address_space ();
|
||||
+ return new_address_space ();
|
||||
}
|
||||
|
||||
/* Start counting over from scratch. */
|
||||
@@ -94,9 +94,9 @@ remove_program_space (program_space *pspace)
|
||||
|
||||
/* See progspace.h. */
|
||||
|
||||
-program_space::program_space (address_space *aspace_)
|
||||
+program_space::program_space (address_space_ref_ptr aspace_)
|
||||
: num (++last_program_space_num),
|
||||
- aspace (aspace_)
|
||||
+ aspace (std::move (aspace_))
|
||||
{
|
||||
program_spaces.push_back (this);
|
||||
gdb::observers::new_program_space.notify (this);
|
||||
@@ -121,8 +121,6 @@ program_space::~program_space ()
|
||||
/* Defer breakpoint re-set because we don't want to create new
|
||||
locations for this pspace which we're tearing down. */
|
||||
clear_symtab_users (SYMFILE_DEFER_BP_RESET);
|
||||
- if (!gdbarch_has_shared_address_space (target_gdbarch ()))
|
||||
- delete this->aspace;
|
||||
}
|
||||
|
||||
/* See progspace.h. */
|
||||
@@ -408,18 +406,14 @@ update_address_spaces (void)
|
||||
|
||||
if (shared_aspace)
|
||||
{
|
||||
- struct address_space *aspace = new address_space ();
|
||||
+ address_space_ref_ptr aspace = new_address_space ();
|
||||
|
||||
- delete current_program_space->aspace;
|
||||
for (struct program_space *pspace : program_spaces)
|
||||
pspace->aspace = aspace;
|
||||
}
|
||||
else
|
||||
for (struct program_space *pspace : program_spaces)
|
||||
- {
|
||||
- delete pspace->aspace;
|
||||
- pspace->aspace = new address_space ();
|
||||
- }
|
||||
+ pspace->aspace = new_address_space ();
|
||||
|
||||
for (inferior *inf : all_inferiors ())
|
||||
if (gdbarch_has_global_solist (target_gdbarch ()))
|
||||
@@ -456,5 +450,5 @@ initialize_progspace (void)
|
||||
modules have done that. Do this before
|
||||
initialize_current_architecture, because that accesses the ebfd
|
||||
of current_program_space. */
|
||||
- current_program_space = new program_space (new address_space ());
|
||||
+ current_program_space = new program_space (new_address_space ());
|
||||
}
|
||||
diff --git a/gdb/progspace.h b/gdb/progspace.h
|
||||
index ee12d89c173..12f113f6d9c 100644
|
||||
--- a/gdb/progspace.h
|
||||
+++ b/gdb/progspace.h
|
||||
@@ -28,6 +28,8 @@
|
||||
#include "solist.h"
|
||||
#include "gdbsupport/next-iterator.h"
|
||||
#include "gdbsupport/safe-iterator.h"
|
||||
+#include "gdbsupport/refcounted-object.h"
|
||||
+#include "gdbsupport/gdb_ref_ptr.h"
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
@@ -42,6 +44,40 @@ struct so_list;
|
||||
|
||||
typedef std::list<std::unique_ptr<objfile>> objfile_list;
|
||||
|
||||
+/* An address space. It is used for comparing if
|
||||
+ pspaces/inferior/threads see the same address space and for
|
||||
+ associating caches to each address space. */
|
||||
+struct address_space : public refcounted_object
|
||||
+{
|
||||
+ /* Create a new address space object, and add it to the list. */
|
||||
+ address_space ();
|
||||
+ DISABLE_COPY_AND_ASSIGN (address_space);
|
||||
+
|
||||
+ /* Returns the integer address space id of this address space. */
|
||||
+ int num () const
|
||||
+ {
|
||||
+ return m_num;
|
||||
+ }
|
||||
+
|
||||
+ /* Per aspace data-pointers required by other GDB modules. */
|
||||
+ registry<address_space> registry_fields;
|
||||
+
|
||||
+private:
|
||||
+ int m_num;
|
||||
+};
|
||||
+
|
||||
+using address_space_ref_ptr
|
||||
+ = gdb::ref_ptr<address_space,
|
||||
+ refcounted_object_delete_ref_policy<address_space>>;
|
||||
+
|
||||
+/* Create a new address space. */
|
||||
+
|
||||
+static inline address_space_ref_ptr
|
||||
+new_address_space ()
|
||||
+{
|
||||
+ return address_space_ref_ptr::new_reference (new address_space);
|
||||
+}
|
||||
+
|
||||
/* An iterator that wraps an iterator over std::unique_ptr<objfile>,
|
||||
and dereferences the returned object. This is useful for iterating
|
||||
over a list of shared pointers and returning raw pointers -- which
|
||||
@@ -191,7 +227,7 @@ struct program_space
|
||||
{
|
||||
/* Constructs a new empty program space, binds it to ASPACE, and
|
||||
adds it to the program space list. */
|
||||
- explicit program_space (address_space *aspace);
|
||||
+ explicit program_space (address_space_ref_ptr aspace);
|
||||
|
||||
/* Releases a program space, and all its contents (shared libraries,
|
||||
objfiles, and any other references to the program space in other
|
||||
@@ -336,7 +372,7 @@ struct program_space
|
||||
are global, then this field is ignored (we don't currently
|
||||
support inferiors sharing a program space if the target doesn't
|
||||
make breakpoints global). */
|
||||
- struct address_space *aspace = NULL;
|
||||
+ address_space_ref_ptr aspace;
|
||||
|
||||
/* True if this program space's section offsets don't yet represent
|
||||
the final offsets of the "live" address space (that is, the
|
||||
@@ -383,28 +419,6 @@ struct program_space
|
||||
target_section_table m_target_sections;
|
||||
};
|
||||
|
||||
-/* An address space. It is used for comparing if
|
||||
- pspaces/inferior/threads see the same address space and for
|
||||
- associating caches to each address space. */
|
||||
-struct address_space
|
||||
-{
|
||||
- /* Create a new address space object, and add it to the list. */
|
||||
- address_space ();
|
||||
- DISABLE_COPY_AND_ASSIGN (address_space);
|
||||
-
|
||||
- /* Returns the integer address space id of this address space. */
|
||||
- int num () const
|
||||
- {
|
||||
- return m_num;
|
||||
- }
|
||||
-
|
||||
- /* Per aspace data-pointers required by other GDB modules. */
|
||||
- registry<address_space> registry_fields;
|
||||
-
|
||||
-private:
|
||||
- int m_num;
|
||||
-};
|
||||
-
|
||||
/* The list of all program spaces. There's always at least one. */
|
||||
extern std::vector<struct program_space *>program_spaces;
|
||||
|
||||
@@ -447,7 +461,7 @@ class scoped_restore_current_program_space
|
||||
/* Maybe create a new address space object, and add it to the list, or
|
||||
return a pointer to an existing address space, in case inferiors
|
||||
share an address space. */
|
||||
-extern struct address_space *maybe_new_address_space (void);
|
||||
+extern address_space_ref_ptr maybe_new_address_space ();
|
||||
|
||||
/* Update all program spaces matching to address spaces. The user may
|
||||
have created several program spaces, and loaded executables into
|
||||
diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
|
||||
index 97447d3e8f8..a4d6c1b5bf2 100644
|
||||
--- a/gdb/record-btrace.c
|
||||
+++ b/gdb/record-btrace.c
|
||||
@@ -2321,7 +2321,7 @@ record_btrace_replay_at_breakpoint (struct thread_info *tp)
|
||||
if (insn == NULL)
|
||||
return 0;
|
||||
|
||||
- return record_check_stopped_by_breakpoint (tp->inf->aspace, insn->pc,
|
||||
+ return record_check_stopped_by_breakpoint (tp->inf->aspace.get (), insn->pc,
|
||||
&btinfo->stop_reason);
|
||||
}
|
||||
|
||||
diff --git a/gdb/regcache.c b/gdb/regcache.c
|
||||
index 91b20b7a2a2..a78fe0a80e7 100644
|
||||
--- a/gdb/regcache.c
|
||||
+++ b/gdb/regcache.c
|
||||
@@ -1628,7 +1628,7 @@ get_thread_arch_aspace_regcache_and_check (inferior *inf_for_target_calls,
|
||||
the current inferior's gdbarch. Also use the current inferior's address
|
||||
space. */
|
||||
gdbarch *arch = inf_for_target_calls->gdbarch;
|
||||
- address_space *aspace = inf_for_target_calls->aspace;
|
||||
+ address_space *aspace = inf_for_target_calls->aspace.get ();
|
||||
regcache *regcache = get_thread_arch_aspace_regcache (inf_for_target_calls,
|
||||
ptid, arch, aspace);
|
||||
|
||||
diff --git a/gdb/scoped-mock-context.h b/gdb/scoped-mock-context.h
|
||||
index 9ad7ebf5f0c..5f25dc7ed6b 100644
|
||||
--- a/gdb/scoped-mock-context.h
|
||||
+++ b/gdb/scoped-mock-context.h
|
||||
@@ -38,7 +38,7 @@ struct scoped_mock_context
|
||||
|
||||
Target mock_target;
|
||||
ptid_t mock_ptid {1, 1};
|
||||
- program_space mock_pspace {new address_space ()};
|
||||
+ program_space mock_pspace {new_address_space ()};
|
||||
inferior mock_inferior {mock_ptid.pid ()};
|
||||
thread_info mock_thread {&mock_inferior, mock_ptid};
|
||||
|
||||
diff --git a/gdb/target-dcache.c b/gdb/target-dcache.c
|
||||
index 13c2888e7ea..b1b772ab76e 100644
|
||||
--- a/gdb/target-dcache.c
|
||||
+++ b/gdb/target-dcache.c
|
||||
@@ -33,7 +33,7 @@ int
|
||||
target_dcache_init_p (void)
|
||||
{
|
||||
DCACHE *dcache
|
||||
- = target_dcache_aspace_key.get (current_program_space->aspace);
|
||||
+ = target_dcache_aspace_key.get (current_program_space->aspace.get ());
|
||||
|
||||
return (dcache != NULL);
|
||||
}
|
||||
@@ -44,7 +44,7 @@ void
|
||||
target_dcache_invalidate (void)
|
||||
{
|
||||
DCACHE *dcache
|
||||
- = target_dcache_aspace_key.get (current_program_space->aspace);
|
||||
+ = target_dcache_aspace_key.get (current_program_space->aspace.get ());
|
||||
|
||||
if (dcache != NULL)
|
||||
dcache_invalidate (dcache);
|
||||
@@ -56,7 +56,7 @@ target_dcache_invalidate (void)
|
||||
DCACHE *
|
||||
target_dcache_get (void)
|
||||
{
|
||||
- return target_dcache_aspace_key.get (current_program_space->aspace);
|
||||
+ return target_dcache_aspace_key.get (current_program_space->aspace.get ());
|
||||
}
|
||||
|
||||
/* Return the target dcache. If it is not initialized yet, initialize
|
||||
@@ -66,12 +66,13 @@ DCACHE *
|
||||
target_dcache_get_or_init (void)
|
||||
{
|
||||
DCACHE *dcache
|
||||
- = target_dcache_aspace_key.get (current_program_space->aspace);
|
||||
+ = target_dcache_aspace_key.get (current_program_space->aspace.get ());
|
||||
|
||||
if (dcache == NULL)
|
||||
{
|
||||
dcache = dcache_init ();
|
||||
- target_dcache_aspace_key.set (current_program_space->aspace, dcache);
|
||||
+ target_dcache_aspace_key.set (current_program_space->aspace.get (),
|
||||
+ dcache);
|
||||
}
|
||||
|
||||
return dcache;
|
||||
diff --git a/gdbsupport/refcounted-object.h b/gdbsupport/refcounted-object.h
|
||||
index d8fdb950043..294fd873df1 100644
|
||||
--- a/gdbsupport/refcounted-object.h
|
||||
+++ b/gdbsupport/refcounted-object.h
|
||||
@@ -67,4 +67,21 @@ struct refcounted_object_ref_policy
|
||||
}
|
||||
};
|
||||
|
||||
+/* A policy class to interface gdb::ref_ptr with a refcounted_object, that
|
||||
+ deletes the object once the refcount reaches 0.. */
|
||||
+
|
||||
+template<typename T>
|
||||
+struct refcounted_object_delete_ref_policy
|
||||
+{
|
||||
+ static void incref (T *obj)
|
||||
+ { obj->incref (); }
|
||||
+
|
||||
+ static void decref (T *obj)
|
||||
+ {
|
||||
+ obj->decref ();
|
||||
+ if (obj->refcount () == 0)
|
||||
+ delete obj;
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
#endif /* COMMON_REFCOUNTED_OBJECT_H */
|
||||
|
||||
base-commit: 0bb6f49bb9ad577667075550ca2ad4cb49931078
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,168 +0,0 @@
|
||||
From 3490f51a80a10d46dc1885ba672d9390a8221170 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Thu, 2 Nov 2023 14:51:02 +0100
|
||||
Subject: [PATCH] Fix segfault in for_each_block, part 2
|
||||
|
||||
The previous commit describes PR gdb/30547, a segfault when running test-case
|
||||
gdb.base/vfork-follow-parent.exp on powerpc64 (likewise on s390x).
|
||||
|
||||
The root cause for the segmentation fault is that linux_is_uclinux gives an
|
||||
incorrect result: it returns true instead of false.
|
||||
|
||||
So, why does linux_is_uclinux:
|
||||
...
|
||||
int
|
||||
linux_is_uclinux (void)
|
||||
{
|
||||
CORE_ADDR dummy;
|
||||
|
||||
return (target_auxv_search (AT_NULL, &dummy) > 0
|
||||
&& target_auxv_search (AT_PAGESZ, &dummy) == 0);
|
||||
...
|
||||
return true?
|
||||
|
||||
This is because ppc_linux_target_wordsize returns 4 instead of 8, causing
|
||||
ppc_linux_nat_target::auxv_parse to misinterpret the auxv vector.
|
||||
|
||||
So, why does ppc_linux_target_wordsize:
|
||||
...
|
||||
int
|
||||
ppc_linux_target_wordsize (int tid)
|
||||
{
|
||||
int wordsize = 4;
|
||||
|
||||
/* Check for 64-bit inferior process. This is the case when the host is
|
||||
64-bit, and in addition the top bit of the MSR register is set. */
|
||||
long msr;
|
||||
|
||||
errno = 0;
|
||||
msr = (long) ptrace (PTRACE_PEEKUSER, tid, PT_MSR * 8, 0);
|
||||
if (errno == 0 && ppc64_64bit_inferior_p (msr))
|
||||
wordsize = 8;
|
||||
|
||||
return wordsize;
|
||||
}
|
||||
...
|
||||
return 4?
|
||||
|
||||
Specifically, we get this result because because tid == 0, so we get
|
||||
errno == ESRCH.
|
||||
|
||||
The tid == 0 is caused by the switch_to_no_thread in
|
||||
handle_vfork_child_exec_or_exit:
|
||||
...
|
||||
/* Switch to no-thread while running clone_program_space, so
|
||||
that clone_program_space doesn't want to read the
|
||||
selected frame of a dead process. */
|
||||
scoped_restore_current_thread restore_thread;
|
||||
switch_to_no_thread ();
|
||||
|
||||
inf->pspace = new program_space (maybe_new_address_space ());
|
||||
...
|
||||
but moving the maybe_new_address_space call to before that gives us the
|
||||
same result. The tid is no longer 0, but we still get ESRCH because the
|
||||
thread has exited.
|
||||
|
||||
Fix this in handle_vfork_child_exec_or_exit by doing the
|
||||
maybe_new_address_space call in the context of the vfork parent.
|
||||
|
||||
Tested on top of trunk on x86_64-linux and ppc64le-linux.
|
||||
Tested on top of gdb-14-branch on ppc64-linux.
|
||||
|
||||
Co-Authored-By: Simon Marchi <simon.marchi@polymtl.ca>
|
||||
|
||||
PR gdb/30547
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30547
|
||||
---
|
||||
gdb/infrun.c | 16 +++++++++++-----
|
||||
gdb/nat/ppc-linux.c | 2 ++
|
||||
gdb/ppc-linux-nat.c | 2 ++
|
||||
gdb/s390-linux-nat.c | 5 ++++-
|
||||
4 files changed, 19 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/gdb/infrun.c b/gdb/infrun.c
|
||||
index 3854c66bf6c..d259e81df84 100644
|
||||
--- a/gdb/infrun.c
|
||||
+++ b/gdb/infrun.c
|
||||
@@ -1105,13 +1105,19 @@ handle_vfork_child_exec_or_exit (int exec)
|
||||
go ahead and create a new one for this exiting
|
||||
inferior. */
|
||||
|
||||
- /* Switch to no-thread while running clone_program_space, so
|
||||
- that clone_program_space doesn't want to read the
|
||||
- selected frame of a dead process. */
|
||||
scoped_restore_current_thread restore_thread;
|
||||
- switch_to_no_thread ();
|
||||
|
||||
- inf->pspace = new program_space (maybe_new_address_space ());
|
||||
+ /* Temporarily switch to the vfork parent, to facilitate ptrace
|
||||
+ calls done during maybe_new_address_space. */
|
||||
+ switch_to_thread (any_live_thread_of_inferior (vfork_parent));
|
||||
+ address_space_ref_ptr aspace = maybe_new_address_space ();
|
||||
+
|
||||
+ /* Switch back to the vfork child inferior. Switch to no-thread
|
||||
+ while running clone_program_space, so that clone_program_space
|
||||
+ doesn't want to read the selected frame of a dead process. */
|
||||
+ switch_to_inferior_no_thread (inf);
|
||||
+
|
||||
+ inf->pspace = new program_space (std::move (aspace));
|
||||
inf->aspace = inf->pspace->aspace;
|
||||
set_current_program_space (inf->pspace);
|
||||
inf->removable = true;
|
||||
diff --git a/gdb/nat/ppc-linux.c b/gdb/nat/ppc-linux.c
|
||||
index 0957d1b58a7..74549754806 100644
|
||||
--- a/gdb/nat/ppc-linux.c
|
||||
+++ b/gdb/nat/ppc-linux.c
|
||||
@@ -78,6 +78,8 @@ ppc64_64bit_inferior_p (long msr)
|
||||
int
|
||||
ppc_linux_target_wordsize (int tid)
|
||||
{
|
||||
+ gdb_assert (tid != 0);
|
||||
+
|
||||
int wordsize = 4;
|
||||
|
||||
/* Check for 64-bit inferior process. This is the case when the host is
|
||||
diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c
|
||||
index d14aba694e5..817505ea73e 100644
|
||||
--- a/gdb/ppc-linux-nat.c
|
||||
+++ b/gdb/ppc-linux-nat.c
|
||||
@@ -1914,6 +1914,8 @@ ppc_linux_nat_target::auxv_parse (const gdb_byte **readptr,
|
||||
const gdb_byte *endptr, CORE_ADDR *typep,
|
||||
CORE_ADDR *valp)
|
||||
{
|
||||
+ gdb_assert (inferior_ptid != null_ptid);
|
||||
+
|
||||
int tid = inferior_ptid.lwp ();
|
||||
if (tid == 0)
|
||||
tid = inferior_ptid.pid ();
|
||||
diff --git a/gdb/s390-linux-nat.c b/gdb/s390-linux-nat.c
|
||||
index 8f54e9f6322..54167f49480 100644
|
||||
--- a/gdb/s390-linux-nat.c
|
||||
+++ b/gdb/s390-linux-nat.c
|
||||
@@ -949,10 +949,12 @@ s390_target_wordsize (void)
|
||||
/* Check for 64-bit inferior process. This is the case when the host is
|
||||
64-bit, and in addition bit 32 of the PSW mask is set. */
|
||||
#ifdef __s390x__
|
||||
+ int tid = s390_inferior_tid ();
|
||||
+ gdb_assert (tid != 0);
|
||||
long pswm;
|
||||
|
||||
errno = 0;
|
||||
- pswm = (long) ptrace (PTRACE_PEEKUSER, s390_inferior_tid (), PT_PSWMASK, 0);
|
||||
+ pswm = (long) ptrace (PTRACE_PEEKUSER, tid, PT_PSWMASK, 0);
|
||||
if (errno == 0 && (pswm & 0x100000000ul) != 0)
|
||||
wordsize = 8;
|
||||
#endif
|
||||
@@ -965,6 +967,7 @@ s390_linux_nat_target::auxv_parse (const gdb_byte **readptr,
|
||||
const gdb_byte *endptr, CORE_ADDR *typep,
|
||||
CORE_ADDR *valp)
|
||||
{
|
||||
+ gdb_assert (inferior_ptid != null_ptid);
|
||||
int sizeof_auxv_field = s390_target_wordsize ();
|
||||
enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
|
||||
const gdb_byte *ptr = *readptr;
|
||||
|
||||
base-commit: 1d02ba0f4adcba2595a67e88fb1ba6d35c7f8e5b
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,42 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Buettner <kevinb@redhat.com>
|
||||
Date: Wed, 17 Jan 2024 12:53:53 -0700
|
||||
Subject: gdb-ftbs-swapped-calloc-args.patch
|
||||
|
||||
Backport upstream commit 54195469c18ec9873cc5ba6907f768509473fa9b
|
||||
which fixes a build problem in which arguments to calloc were swapped.
|
||||
|
||||
[opcodes] ARC + PPC: Fix -Walloc-size warnings
|
||||
|
||||
Recently, -Walloc-size warnings started to kick in. Fix these two
|
||||
calloc() calls to match the intended usage pattern.
|
||||
|
||||
opcodes/ChangeLog:
|
||||
|
||||
* arc-dis.c (init_arc_disasm_info): Fix calloc() call.
|
||||
* ppc-dis.c (powerpc_init_dialect): Ditto.
|
||||
|
||||
diff --git a/opcodes/arc-dis.c b/opcodes/arc-dis.c
|
||||
--- a/opcodes/arc-dis.c
|
||||
+++ b/opcodes/arc-dis.c
|
||||
@@ -147,7 +147,7 @@ static bool
|
||||
init_arc_disasm_info (struct disassemble_info *info)
|
||||
{
|
||||
struct arc_disassemble_info *arc_infop
|
||||
- = calloc (sizeof (*arc_infop), 1);
|
||||
+ = calloc (1, sizeof (*arc_infop));
|
||||
|
||||
if (arc_infop == NULL)
|
||||
return false;
|
||||
diff --git a/opcodes/ppc-dis.c b/opcodes/ppc-dis.c
|
||||
--- a/opcodes/ppc-dis.c
|
||||
+++ b/opcodes/ppc-dis.c
|
||||
@@ -348,7 +348,7 @@ powerpc_init_dialect (struct disassemble_info *info)
|
||||
{
|
||||
ppc_cpu_t dialect = 0;
|
||||
ppc_cpu_t sticky = 0;
|
||||
- struct dis_private *priv = calloc (sizeof (*priv), 1);
|
||||
+ struct dis_private *priv = calloc (1, sizeof (*priv));
|
||||
|
||||
if (priv == NULL)
|
||||
return;
|
@@ -6,5 +6,5 @@ index b9770ea415..3149f6e1fe 100644
|
||||
-#!/usr/bin/env bash
|
||||
+#!/bin/bash
|
||||
|
||||
# Copyright (C) 2003-2023 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2003-2024 Free Software Foundation, Inc.
|
||||
|
||||
|
@@ -1,132 +0,0 @@
|
||||
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"}
|
68
gdb-guile-use-scm_debug_typing_strictness-0.patch
Normal file
68
gdb-guile-use-scm_debug_typing_strictness-0.patch
Normal file
@@ -0,0 +1,68 @@
|
||||
From fe0e6edbcb65ab5eca50c1a0ad8ddc9844f8ea98 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Mon, 27 Jan 2025 09:23:18 +0100
|
||||
Subject: [PATCH] [gdb/guile] Use SCM_DEBUG_TYPING_STRICTNESS 0
|
||||
|
||||
I build gdb with libguile v2.0.9, and ran into:
|
||||
...
|
||||
In file included from /usr/include/guile/2.0/libguile.h:56,
|
||||
from ../../gdb/guile/guile-internal.h:30,
|
||||
from ../../gdb/guile/scm-arch.c:26:
|
||||
/usr/include/guile/2.0/libguile/inline.h: In function 'int scm_is_pair(SCM)':
|
||||
/usr/include/guile/2.0/libguile/tags.h:97:53: error: \
|
||||
operation on '*0' may be undefined [-Werror=sequence-point]
|
||||
# define SCM_UNPACK(x) ((scm_t_bits) (0? (*(SCM*)0=(x)): x))
|
||||
~~~~~~~~~^~~~~
|
||||
...
|
||||
|
||||
Fix this by using SCM_DEBUG_TYPING_STRICTNESS 0.
|
||||
|
||||
We were already using this for c++20 due to a Werror=volatile in SCM_UNPACK
|
||||
when using libguile v2.0.10.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
---
|
||||
gdb/guile/guile-internal.h | 22 +++++++++++++++++++++-
|
||||
1 file changed, 21 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/guile/guile-internal.h b/gdb/guile/guile-internal.h
|
||||
index be16fee0dd2..6665bfc7813 100644
|
||||
--- a/gdb/guile/guile-internal.h
|
||||
+++ b/gdb/guile/guile-internal.h
|
||||
@@ -27,10 +27,30 @@
|
||||
#include "hashtab.h"
|
||||
#include "extension-priv.h"
|
||||
#include "symtab.h"
|
||||
-#include "libguile.h"
|
||||
#include "objfiles.h"
|
||||
#include "top.h"
|
||||
|
||||
+/* For libguile v2.0.9 and SCM_DEBUG_TYPING_STRICTNESS == 1, SCM_UNPACK(x) is
|
||||
+ defined as:
|
||||
+
|
||||
+ ((scm_t_bits) (0? (*(SCM*)0=(x)): x))
|
||||
+
|
||||
+ and for v2.0.10 it's defined as:
|
||||
+
|
||||
+ ((scm_t_bits) (0? (*(volatile SCM *)0=(x)): x))
|
||||
+
|
||||
+ The volatile was added to avoid a clang warning.
|
||||
+
|
||||
+ The latter form causes a Werror=volatile with C++20.
|
||||
+ This was reported upstream (
|
||||
+ https://debbugs.gnu.org/cgi/bugreport.cgi?bug=65333 ).
|
||||
+
|
||||
+ The former form causes a Werror=sequence-point with gcc 7-14.
|
||||
+
|
||||
+ Work around these problem by using SCM_DEBUG_TYPING_STRICTNESS == 0. */
|
||||
+#define SCM_DEBUG_TYPING_STRICTNESS 0
|
||||
+#include "libguile.h"
|
||||
+
|
||||
struct block;
|
||||
struct frame_info;
|
||||
struct objfile;
|
||||
|
||||
base-commit: 94df6741bbabaa9a51960446b2af4c0bed01b54b
|
||||
--
|
||||
2.43.0
|
||||
|
@@ -1,226 +0,0 @@
|
||||
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
|
130
gdb-prune-inferior-after-switching-inferior.patch
Normal file
130
gdb-prune-inferior-after-switching-inferior.patch
Normal file
@@ -0,0 +1,130 @@
|
||||
From 22d05b4879b8608e3768483735140a729952b565 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Sun, 18 Aug 2024 20:51:29 +0200
|
||||
Subject: [PATCH 39/46] [gdb] Prune inferior after switching inferior
|
||||
|
||||
Usually with test-case gdb.python/py-progspace-events.exp I get:
|
||||
...
|
||||
(gdb) inferior 1^M
|
||||
[Switching to inferior 1 [process 4116] (py-progspace-events)]^M
|
||||
[Switching to thread 1.1 (Thread 0xf77d0ce0 (LWP 4116))]^M
|
||||
28 { /* Nothing. */ }^M
|
||||
(gdb) PASS: gdb.python/py-progspace-events.exp: inferior 1
|
||||
step^M
|
||||
FreeProgspaceEvent: <gdb.Progspace object at 0xabf4f850>^M
|
||||
do_parent_stuff () at py-progspace-events.c:41^M
|
||||
41 ++global_var;^M
|
||||
(gdb) PASS: gdb.python/py-progspace-events.exp: step
|
||||
...
|
||||
|
||||
But occasionally I run into the following FAIL:
|
||||
...
|
||||
(gdb) inferior 1^M
|
||||
[Switching to inferior 1 [process 5199] (py-progspace-events)]^M
|
||||
[Switching to thread 1.1 (Thread 0xf77d0ce0 (LWP 5199))]^M
|
||||
28 { /* Nothing. */ }^M
|
||||
(gdb) FreeProgspaceEvent: <gdb.Progspace object at 0xabaf03a0>^M
|
||||
FAIL: gdb.python/py-progspace-events.exp: inferior 1 (timeout)
|
||||
...
|
||||
|
||||
This is caused by a race between the handling of an event, and the
|
||||
"inferior 1" command.
|
||||
|
||||
In the passing case, the event is handled first. During which prune_inferiors
|
||||
is called, but it can't remove inferior 2, because it's still the current one.
|
||||
|
||||
In the failing case, the "inferior 1" command is handled first. Then during
|
||||
handling of the event, prune_inferiors is called, and it can remove inferior 2
|
||||
because it's no longer the current one.
|
||||
|
||||
This looks like a test-case issue to me, but ISTM that we can do better: by
|
||||
calling prune_inferiors asap, at the end of the "inferior 1" command, we
|
||||
stabilize the moment when the inferior is removed:
|
||||
...
|
||||
(gdb) inferior 1^M
|
||||
[Switching to inferior 1 [process 5199] (py-progspace-events)]^M
|
||||
[Switching to thread 1.1 (Thread 0xf77d0ce0 (LWP 5199))]^M
|
||||
28 { /* Nothing. */ }^M
|
||||
FreeProgspaceEvent: <gdb.Progspace object at 0xabaf03a0>^M
|
||||
(gdb) PASS: gdb.python/py-progspace-events.exp: inferior 1
|
||||
...
|
||||
|
||||
This also allows us to simplify the test-case by removing the step command,
|
||||
which is no longer required to trigger the pruning of the inferior.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
|
||||
Approved-by: Kevin Buettner <kevinb@redhat.com>
|
||||
|
||||
PR gdb/31440
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31440
|
||||
---
|
||||
gdb/inferior.c | 4 +++
|
||||
.../gdb.python/py-progspace-events.exp | 31 +++----------------
|
||||
2 files changed, 9 insertions(+), 26 deletions(-)
|
||||
|
||||
diff --git a/gdb/inferior.c b/gdb/inferior.c
|
||||
index 0522cb5c14d..2a19c5b19a1 100644
|
||||
--- a/gdb/inferior.c
|
||||
+++ b/gdb/inferior.c
|
||||
@@ -790,6 +790,10 @@ inferior_command (const char *args, int from_tty)
|
||||
notify_user_selected_context_changed
|
||||
(USER_SELECTED_INFERIOR);
|
||||
}
|
||||
+
|
||||
+ /* Switching current inferior may have made one of the inferiors
|
||||
+ prunable, so prune it. */
|
||||
+ prune_inferiors ();
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.python/py-progspace-events.exp b/gdb/testsuite/gdb.python/py-progspace-events.exp
|
||||
index 95e4ca8da0b..9dfc7573d40 100644
|
||||
--- a/gdb/testsuite/gdb.python/py-progspace-events.exp
|
||||
+++ b/gdb/testsuite/gdb.python/py-progspace-events.exp
|
||||
@@ -79,37 +79,16 @@ gdb_test "continue" \
|
||||
"\\\[Inferior $decimal \[^\r\n\]+ exited normally\\\]"] \
|
||||
"continue until inferior 2 exits"
|
||||
|
||||
-gdb_test "inferior 1" "\\\[Switching to inferior 1 .*"
|
||||
-
|
||||
-# Step the inferior. During this process GDB will prune the now
|
||||
+# Switch to inferior 1. During this process GDB will prune the now
|
||||
# defunct inferior, which deletes its program space, which should
|
||||
# trigger the FreeProgspaceEvent.
|
||||
#
|
||||
-# However, there is a slight problem. When the target is remote, and
|
||||
-# GDB is accessing files using remote fileio, then GDB will attempt to
|
||||
-# prune the inferior at a point in time when the remote target is
|
||||
-# waiting for a stop reply. Pruning an inferior causes GDB to close
|
||||
-# files associated with that inferior.
|
||||
-#
|
||||
-# In non-async mode we can't send fileio packets while waiting for a
|
||||
-# stop reply, so the attempts to close files fails, and this shows up
|
||||
-# as an error.
|
||||
-#
|
||||
-# As this error has nothing to do with the feature being tested here,
|
||||
-# we just accept the error message, the important part is the
|
||||
-# 'FreeProgspaceEvent' string, so long as that appears (just once)
|
||||
-# then the test is a success.
|
||||
-set warning_msg \
|
||||
- [multi_line \
|
||||
- "warning: cannot close \"\[^\r\n\]+\": Cannot execute this command while the target is running\\." \
|
||||
- "Use the \"interrupt\" command to stop the target" \
|
||||
- "and then try again\\."]
|
||||
|
||||
-gdb_test "step" \
|
||||
+gdb_test "inferior 1" \
|
||||
[multi_line \
|
||||
- "^FreeProgspaceEvent.*: <gdb.Progspace object at $hex>(?:\r\n$warning_msg)*" \
|
||||
- "do_parent_stuff \\(\\) at \[^\r\n\]+" \
|
||||
- "$decimal\\s+\[^\r\n\]+"]
|
||||
+ "\\\[Switching to inferior 1 .*" \
|
||||
+ ".*" \
|
||||
+ "FreeProgspaceEvent.*: <gdb.Progspace object at $hex>"]
|
||||
|
||||
# Let this inferior run to completion.
|
||||
gdb_continue_to_end
|
||||
--
|
||||
2.43.0
|
||||
|
@@ -1,7 +1,7 @@
|
||||
From adfcabe4cc43766996a61bdf08ce1e9db7f18dcc Mon Sep 17 00:00:00 2001
|
||||
From 086a725aa02b1195f63b2df4c2a2b4516788b2c6 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Thu, 18 Apr 2024 14:27:04 +0200
|
||||
Subject: [PATCH] gdb-python-finishbreakpoint-update
|
||||
Subject: [PATCH 42/46] gdb-python-finishbreakpoint-update
|
||||
|
||||
[gdb/python] FinishBreakPoint update
|
||||
|
||||
@@ -337,10 +337,10 @@ and running the test-cases:
|
||||
4 files changed, 35 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
|
||||
index db7d2e6a8e5..01f187ca4fe 100644
|
||||
index 5653842ce76..6e10914a316 100644
|
||||
--- a/gdb/breakpoint.c
|
||||
+++ b/gdb/breakpoint.c
|
||||
@@ -14683,6 +14683,10 @@ breakpoint_free_objfile (struct objfile *objfile)
|
||||
@@ -14693,6 +14693,10 @@ breakpoint_free_objfile (struct objfile *objfile)
|
||||
|
||||
static struct cmd_list_element *enablebreaklist = NULL;
|
||||
|
||||
@@ -351,7 +351,7 @@ index db7d2e6a8e5..01f187ca4fe 100644
|
||||
/* See breakpoint.h. */
|
||||
|
||||
cmd_list_element *commands_cmd_element = nullptr;
|
||||
@@ -15243,8 +15247,14 @@ This is useful for formatted output in user-defined commands."));
|
||||
@@ -15255,8 +15259,14 @@ This is useful for formatted output in user-defined commands."));
|
||||
|
||||
gdb::observers::about_to_proceed.attach (breakpoint_about_to_proceed,
|
||||
"breakpoint");
|
||||
@@ -367,10 +367,10 @@ index db7d2e6a8e5..01f187ca4fe 100644
|
||||
"breakpoint");
|
||||
}
|
||||
diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
|
||||
index 99670cca025..ba414b4e2c3 100644
|
||||
index 86ccc140c6d..e49cc580b1b 100644
|
||||
--- a/gdb/doc/python.texi
|
||||
+++ b/gdb/doc/python.texi
|
||||
@@ -6648,7 +6648,7 @@ is not writable.
|
||||
@@ -6882,7 +6882,7 @@ is not writable.
|
||||
@tindex gdb.FinishBreakpoint
|
||||
|
||||
A finish breakpoint is a temporary breakpoint set at the return address of
|
||||
@@ -379,7 +379,7 @@ index 99670cca025..ba414b4e2c3 100644
|
||||
extends @code{gdb.Breakpoint}. The underlying breakpoint will be disabled
|
||||
and deleted when the execution will run out of the breakpoint scope (i.e.@:
|
||||
@code{Breakpoint.stop} or @code{FinishBreakpoint.out_of_scope} triggered).
|
||||
@@ -6667,7 +6667,9 @@ details about this argument.
|
||||
@@ -6901,7 +6901,9 @@ details about this argument.
|
||||
In some circumstances (e.g.@: @code{longjmp}, C@t{++} exceptions, @value{GDBN}
|
||||
@code{return} command, @dots{}), a function may not properly terminate, and
|
||||
thus never hit the finish breakpoint. When @value{GDBN} notices such a
|
||||
@@ -391,7 +391,7 @@ index 99670cca025..ba414b4e2c3 100644
|
||||
You may want to sub-class @code{gdb.FinishBreakpoint} and override this
|
||||
method:
|
||||
diff --git a/gdb/python/py-finishbreakpoint.c b/gdb/python/py-finishbreakpoint.c
|
||||
index 42a7e0706d2..fa7ec43fbb4 100644
|
||||
index c74a2473a81..957d4ebc142 100644
|
||||
--- a/gdb/python/py-finishbreakpoint.c
|
||||
+++ b/gdb/python/py-finishbreakpoint.c
|
||||
@@ -433,6 +433,24 @@ bpfinishpy_handle_exit (struct inferior *inf)
|
||||
@@ -402,9 +402,9 @@ index 42a7e0706d2..fa7ec43fbb4 100644
|
||||
+ scope notifications. */
|
||||
+
|
||||
+static void
|
||||
+bpfinishpy_handle_thread_exit (struct thread_info *tp, gdb::optional<ULONGEST>, bool)
|
||||
+bpfinishpy_handle_thread_exit (struct thread_info *tp, std::optional<ULONGEST>, bool)
|
||||
+{
|
||||
+ gdbpy_enter enter_py (target_gdbarch (), current_language);
|
||||
+ gdbpy_enter enter_py (target_thread_architecture (tp->ptid), current_language);
|
||||
+
|
||||
+ for (breakpoint &bp : all_breakpoints_safe ())
|
||||
+ {
|
||||
@@ -429,7 +429,7 @@ index 42a7e0706d2..fa7ec43fbb4 100644
|
||||
return 0;
|
||||
}
|
||||
diff --git a/gdb/testsuite/gdb.python/py-finish-breakpoint2.exp b/gdb/testsuite/gdb.python/py-finish-breakpoint2.exp
|
||||
index 66587b8b9a0..31479a05e6f 100644
|
||||
index b837bb3a108..7d99aad2fd2 100644
|
||||
--- a/gdb/testsuite/gdb.python/py-finish-breakpoint2.exp
|
||||
+++ b/gdb/testsuite/gdb.python/py-finish-breakpoint2.exp
|
||||
@@ -87,6 +87,7 @@ if { $need_continue } {
|
||||
@@ -440,8 +440,6 @@ index 66587b8b9a0..31479a05e6f 100644
|
||||
gdb_test "python ExceptionFinishBreakpoint(gdb.newest_frame())" \
|
||||
"init ExceptionFinishBreakpoint" "set FinishBP after the exception again"
|
||||
|
||||
|
||||
base-commit: 6de9111c512de99fd8cb3ea89f9890b1d72f6ef0
|
||||
--
|
||||
2.35.3
|
||||
2.43.0
|
||||
|
||||
|
@@ -1,125 +0,0 @@
|
||||
From 4c7dab250c3581e691c2da87395e80244074d8bf Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Mon, 10 Jun 2024 17:53:30 +0200
|
||||
Subject: [PATCH] [gdb/python] Fix gdb.python/py-disasm.exp on arm-linux
|
||||
|
||||
After fixing test-case gdb.python/py-disasm.exp to recognize the arm nop:
|
||||
...
|
||||
nop {0}
|
||||
...
|
||||
we run into:
|
||||
...
|
||||
disassemble test^M
|
||||
Dump of assembler code for function test:^M
|
||||
0x004004d8 <+0>: push {r11} @ (str r11, [sp, #-4]!)^M
|
||||
0x004004dc <+4>: add r11, sp, #0^M
|
||||
0x004004e0 <+8>: nop {0}^M
|
||||
=> 0x004004e4 <+12>: Python Exception <class 'ValueError'>: Buffer \
|
||||
returned from read_memory is sized 0 instead of the expected 4^M
|
||||
^M
|
||||
unknown disassembler error (error = -1)^M
|
||||
(gdb) FAIL: $exp: global_disassembler=ShowInfoRepr: disassemble test
|
||||
...
|
||||
|
||||
This is caused by this code in gdbpy_disassembler::read_memory_func:
|
||||
...
|
||||
gdbpy_ref<> result_obj (PyObject_CallMethod ((PyObject *) obj,
|
||||
"read_memory",
|
||||
"KL", len, offset));
|
||||
...
|
||||
where len has type "unsigned int", while "K" means "unsigned long long" [1].
|
||||
|
||||
Fix this by using "I" instead, meaning "unsigned int".
|
||||
|
||||
Also, offset has type LONGEST, which is typedef'ed to int64_t, while "L" means
|
||||
"long long".
|
||||
|
||||
Fix this by using type gdb_py_longest for offset, in combination with format
|
||||
character "GDB_PY_LL_ARG". Likewise in disasmpy_info_read_memory.
|
||||
|
||||
Tested on arm-linux.
|
||||
|
||||
Reviewed-By: Alexandra Petlanova Hajkova <ahajkova@redhat.com>
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
PR python/31845
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31845
|
||||
|
||||
[1] https://docs.python.org/3/c-api/arg.html
|
||||
|
||||
(cherry picked from commit 4cd214dce4579f86a85a96c882e0fc8c4d94601c)
|
||||
---
|
||||
gdb/python/py-disasm.c | 12 +++++++-----
|
||||
gdb/testsuite/gdb.python/py-disasm.exp | 2 +-
|
||||
gdb/testsuite/gdb.python/py-disasm.py | 2 +-
|
||||
3 files changed, 9 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/gdb/python/py-disasm.c b/gdb/python/py-disasm.c
|
||||
index 6f0fed137e6..b2e95b3cba6 100644
|
||||
--- a/gdb/python/py-disasm.c
|
||||
+++ b/gdb/python/py-disasm.c
|
||||
@@ -668,12 +668,13 @@ disasmpy_info_read_memory (PyObject *self, PyObject *args, PyObject *kw)
|
||||
disasm_info_object *obj = (disasm_info_object *) self;
|
||||
DISASMPY_DISASM_INFO_REQUIRE_VALID (obj);
|
||||
|
||||
- LONGEST length, offset = 0;
|
||||
+ gdb_py_longest length, offset = 0;
|
||||
gdb::unique_xmalloc_ptr<gdb_byte> buffer;
|
||||
static const char *keywords[] = { "length", "offset", nullptr };
|
||||
|
||||
- if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "L|L", keywords,
|
||||
- &length, &offset))
|
||||
+ if (!gdb_PyArg_ParseTupleAndKeywords (args, kw,
|
||||
+ GDB_PY_LL_ARG "|" GDB_PY_LL_ARG,
|
||||
+ keywords, &length, &offset))
|
||||
return nullptr;
|
||||
|
||||
/* The apparent address from which we are reading memory. Note that in
|
||||
@@ -850,13 +851,14 @@ gdbpy_disassembler::read_memory_func (bfd_vma memaddr, gdb_byte *buff,
|
||||
/* The DisassembleInfo.read_memory method expects an offset from the
|
||||
address stored within the DisassembleInfo object; calculate that
|
||||
offset here. */
|
||||
- LONGEST offset = (LONGEST) memaddr - (LONGEST) obj->address;
|
||||
+ gdb_py_longest offset
|
||||
+ = (gdb_py_longest) memaddr - (gdb_py_longest) obj->address;
|
||||
|
||||
/* Now call the DisassembleInfo.read_memory method. This might have been
|
||||
overridden by the user. */
|
||||
gdbpy_ref<> result_obj (PyObject_CallMethod ((PyObject *) obj,
|
||||
"read_memory",
|
||||
- "KL", len, offset));
|
||||
+ "I" GDB_PY_LL_ARG, len, offset));
|
||||
|
||||
/* Handle any exceptions. */
|
||||
if (result_obj == nullptr)
|
||||
diff --git a/gdb/testsuite/gdb.python/py-disasm.exp b/gdb/testsuite/gdb.python/py-disasm.exp
|
||||
index f2f9225168a..9d0f6ec1d01 100644
|
||||
--- a/gdb/testsuite/gdb.python/py-disasm.exp
|
||||
+++ b/gdb/testsuite/gdb.python/py-disasm.exp
|
||||
@@ -65,7 +65,7 @@ proc py_remove_all_disassemblers {} {
|
||||
#
|
||||
# Each different disassembler tests some different feature of the
|
||||
# Python disassembler API.
|
||||
-set nop "(nop|nop\t0)"
|
||||
+set nop "(nop|nop\t0|[string_to_regexp nop\t{0}])"
|
||||
set unknown_error_pattern "unknown disassembler error \\(error = -1\\)"
|
||||
set addr_pattern "\r\n=> ${curr_pc_pattern} <\[^>\]+>:\\s+"
|
||||
set base_pattern "${addr_pattern}${nop}"
|
||||
diff --git a/gdb/testsuite/gdb.python/py-disasm.py b/gdb/testsuite/gdb.python/py-disasm.py
|
||||
index 67ba6756ea9..6a39b0764e6 100644
|
||||
--- a/gdb/testsuite/gdb.python/py-disasm.py
|
||||
+++ b/gdb/testsuite/gdb.python/py-disasm.py
|
||||
@@ -46,7 +46,7 @@ def check_building_disassemble_result():
|
||||
|
||||
|
||||
def is_nop(s):
|
||||
- return s == "nop" or s == "nop\t0"
|
||||
+ return s == "nop" or s == "nop\t0" or s == "nop\t{0}"
|
||||
|
||||
|
||||
# Remove all currently registered disassemblers.
|
||||
|
||||
base-commit: 22383ac8031b0e626e8ecd62e4378266065d067c
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,70 +0,0 @@
|
||||
From fc73000faa1798573090994167b7e2d451c211db Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Fri, 10 May 2024 08:46:21 +0200
|
||||
Subject: [PATCH] [gdb/python] Make gdb.UnwindInfo.add_saved_register more
|
||||
robust (fixup)
|
||||
|
||||
In commit 2236c5e384d ("[gdb/python] Make gdb.UnwindInfo.add_saved_register
|
||||
more robust") I added this code in unwind_infopy_add_saved_register:
|
||||
...
|
||||
if (value->optimized_out () || !value->entirely_available ())
|
||||
...
|
||||
which may throw c++ exceptions.
|
||||
|
||||
This needs to be caught and transformed into a python exception.
|
||||
|
||||
Fix this by using GDB_PY_HANDLE_EXCEPTION.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
Fixes: 2236c5e384d ("[gdb/python] Make gdb.UnwindInfo.add_saved_register more robust")
|
||||
(cherry picked from commit 408bc9c5fc757bd4b8adb1c3d54ecd672beaedb7)
|
||||
---
|
||||
gdb/python/py-unwind.c | 26 +++++++++++++++++---------
|
||||
1 file changed, 17 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/gdb/python/py-unwind.c b/gdb/python/py-unwind.c
|
||||
index 471eb851674..e57c8c1adcf 100644
|
||||
--- a/gdb/python/py-unwind.c
|
||||
+++ b/gdb/python/py-unwind.c
|
||||
@@ -354,16 +354,24 @@ unwind_infopy_add_saved_register (PyObject *self, PyObject *args, PyObject *kw)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
- if (value->optimized_out () || !value->entirely_available ())
|
||||
+
|
||||
+ try
|
||||
+ {
|
||||
+ if (value->optimized_out () || !value->entirely_available ())
|
||||
+ {
|
||||
+ /* If we allow this value to be registered here, pyuw_sniffer is going
|
||||
+ to run into an exception when trying to access its contents.
|
||||
+ Throwing an exception here just puts a burden on the user to
|
||||
+ implement the same checks on the user side. We could return False
|
||||
+ here and True otherwise, but again that might require changes in
|
||||
+ user code. So, handle this with minimal impact for the user, while
|
||||
+ improving robustness: silently ignore the register/value pair. */
|
||||
+ Py_RETURN_NONE;
|
||||
+ }
|
||||
+ }
|
||||
+ catch (const gdb_exception &except)
|
||||
{
|
||||
- /* If we allow this value to be registered here, pyuw_sniffer is going
|
||||
- to run into an exception when trying to access its contents.
|
||||
- Throwing an exception here just puts a burden on the user to
|
||||
- implement the same checks on the user side. We could return False
|
||||
- here and True otherwise, but again that might require changes in user
|
||||
- code. So, handle this with minimal impact for the user, while
|
||||
- improving robustness: silently ignore the register/value pair. */
|
||||
- Py_RETURN_NONE;
|
||||
+ GDB_PY_HANDLE_EXCEPTION (except);
|
||||
}
|
||||
|
||||
gdbpy_ref<> new_value = gdbpy_ref<>::new_reference (pyo_reg_value);
|
||||
|
||||
base-commit: a6f598be3d0477c5c59bd490573a5d457949658e
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,61 +0,0 @@
|
||||
From eafca1ce3d589c731927e5481199db715bcbeff3 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Sat, 2 Mar 2024 09:35:22 +0100
|
||||
Subject: [PATCH 2/2] [gdb/python] Make gdb.UnwindInfo.add_saved_register more
|
||||
robust
|
||||
|
||||
On arm-linux, until commit bbb12eb9c84 ("gdb/arm: Remove tpidruro register
|
||||
from non-FreeBSD target descriptions") I ran into:
|
||||
...
|
||||
FAIL: gdb.base/inline-frame-cycle-unwind.exp: cycle at level 5: \
|
||||
backtrace when the unwind is broken at frame 5
|
||||
...
|
||||
|
||||
What happens is the following:
|
||||
- the TestUnwinder from inline-frame-cycle-unwind.py calls
|
||||
gdb.UnwindInfo.add_saved_register with reg == tpidruro and value
|
||||
"<unavailable>",
|
||||
- pyuw_sniffer calls value->contents ().data () to access the value of the
|
||||
register, which throws an UNAVAILABLE_ERROR,
|
||||
- this causes the TestUnwinder unwinder to fail, after which another unwinder
|
||||
succeeds and returns the correct frame, and
|
||||
- the test-case fails because it's counting on the TestUnwinder to succeed and
|
||||
return an incorrect frame.
|
||||
|
||||
Fix this by checking for !value::entirely_available as well as
|
||||
valued::optimized_out in unwind_infopy_add_saved_register.
|
||||
|
||||
Tested on x86_64-linux and arm-linux.
|
||||
|
||||
PR python/31437
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31437
|
||||
---
|
||||
gdb/python/py-unwind.c | 12 ++++++++++++
|
||||
1 file changed, 12 insertions(+)
|
||||
|
||||
diff --git a/gdb/python/py-unwind.c b/gdb/python/py-unwind.c
|
||||
index 1856e41e2a1..471eb851674 100644
|
||||
--- a/gdb/python/py-unwind.c
|
||||
+++ b/gdb/python/py-unwind.c
|
||||
@@ -354,6 +354,18 @@ unwind_infopy_add_saved_register (PyObject *self, PyObject *args, PyObject *kw)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
+ if (value->optimized_out () || !value->entirely_available ())
|
||||
+ {
|
||||
+ /* If we allow this value to be registered here, pyuw_sniffer is going
|
||||
+ to run into an exception when trying to access its contents.
|
||||
+ Throwing an exception here just puts a burden on the user to
|
||||
+ implement the same checks on the user side. We could return False
|
||||
+ here and True otherwise, but again that might require changes in user
|
||||
+ code. So, handle this with minimal impact for the user, while
|
||||
+ improving robustness: silently ignore the register/value pair. */
|
||||
+ Py_RETURN_NONE;
|
||||
+ }
|
||||
+
|
||||
gdbpy_ref<> new_value = gdbpy_ref<>::new_reference (pyo_reg_value);
|
||||
bool found = false;
|
||||
for (saved_reg ® : *unwind_info->saved_regs)
|
||||
--
|
||||
2.35.3
|
||||
|
89
gdb-record-fix-out-of-bounds-write-in-aarch64_record.patch
Normal file
89
gdb-record-fix-out-of-bounds-write-in-aarch64_record.patch
Normal file
@@ -0,0 +1,89 @@
|
||||
From 9b1fc55c1887675923d4ddeda4b38ab05e6bb44c Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Thu, 13 Mar 2025 11:15:05 +0100
|
||||
Subject: [PATCH 1/2] [gdb/record] Fix out-of-bounds write in
|
||||
aarch64_record_asimd_load_store
|
||||
|
||||
After compiling gdb with -fstack-protector-all, and running test-case
|
||||
gdb.reverse/getrandom.exp on aarch64-linux, we run into
|
||||
"Stack smashing detected" in function aarch64_record_asimd_load_store.
|
||||
|
||||
This is reported in PR record/32784.
|
||||
|
||||
This happens due to an out-of-bounds write to local array record_buf_mem:
|
||||
...
|
||||
uint64_t record_buf_mem[24];
|
||||
...
|
||||
when recording insn:
|
||||
...
|
||||
B+>0xfffff7ff4d10 st1 {v0.16b-v3.16b}, [x0]
|
||||
...
|
||||
|
||||
We can fix this by increasing the array size to 128, but rather than again
|
||||
hardcoding a size, reimplement record_buf_mem as std::vector.
|
||||
|
||||
Tested on aarch64-linux.
|
||||
|
||||
Approved-By: Guinevere Larsen <guinevere@redhat.com>
|
||||
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32784
|
||||
(cherry picked from commit 51729ea0905d1f688b7fd2ea769e69b29daa1b7c)
|
||||
---
|
||||
gdb/aarch64-tdep.c | 16 ++++++++--------
|
||||
1 file changed, 8 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
|
||||
index e4bca6c6632..92daaa75b1c 100644
|
||||
--- a/gdb/aarch64-tdep.c
|
||||
+++ b/gdb/aarch64-tdep.c
|
||||
@@ -5030,9 +5030,9 @@ aarch64_record_asimd_load_store (aarch64_insn_decode_record *aarch64_insn_r)
|
||||
CORE_ADDR address;
|
||||
uint64_t addr_offset = 0;
|
||||
uint32_t record_buf[24];
|
||||
- uint64_t record_buf_mem[24];
|
||||
+ std::vector<uint64_t> record_buf_mem;
|
||||
uint32_t reg_rn, reg_rt;
|
||||
- uint32_t reg_index = 0, mem_index = 0;
|
||||
+ uint32_t reg_index = 0;
|
||||
uint8_t opcode_bits, size_bits;
|
||||
|
||||
reg_rt = bits (aarch64_insn_r->aarch64_insn, 0, 4);
|
||||
@@ -5095,8 +5095,8 @@ aarch64_record_asimd_load_store (aarch64_insn_decode_record *aarch64_insn_r)
|
||||
record_buf[reg_index++] = reg_rt + AARCH64_V0_REGNUM;
|
||||
else
|
||||
{
|
||||
- record_buf_mem[mem_index++] = esize / 8;
|
||||
- record_buf_mem[mem_index++] = address + addr_offset;
|
||||
+ record_buf_mem.push_back (esize / 8);
|
||||
+ record_buf_mem.push_back (address + addr_offset);
|
||||
}
|
||||
addr_offset = addr_offset + (esize / 8);
|
||||
reg_rt = (reg_rt + 1) % 32;
|
||||
@@ -5167,8 +5167,8 @@ aarch64_record_asimd_load_store (aarch64_insn_decode_record *aarch64_insn_r)
|
||||
record_buf[reg_index++] = reg_tt + AARCH64_V0_REGNUM;
|
||||
else
|
||||
{
|
||||
- record_buf_mem[mem_index++] = esize / 8;
|
||||
- record_buf_mem[mem_index++] = address + addr_offset;
|
||||
+ record_buf_mem.push_back (esize / 8);
|
||||
+ record_buf_mem.push_back (address + addr_offset);
|
||||
}
|
||||
addr_offset = addr_offset + (esize / 8);
|
||||
reg_tt = (reg_tt + 1) % 32;
|
||||
@@ -5180,9 +5180,9 @@ aarch64_record_asimd_load_store (aarch64_insn_decode_record *aarch64_insn_r)
|
||||
record_buf[reg_index++] = reg_rn;
|
||||
|
||||
aarch64_insn_r->reg_rec_count = reg_index;
|
||||
- aarch64_insn_r->mem_rec_count = mem_index / 2;
|
||||
+ aarch64_insn_r->mem_rec_count = record_buf_mem.size () / 2;
|
||||
MEM_ALLOC (aarch64_insn_r->aarch64_mems, aarch64_insn_r->mem_rec_count,
|
||||
- record_buf_mem);
|
||||
+ record_buf_mem.data ());
|
||||
REG_ALLOC (aarch64_insn_r->aarch64_regs, aarch64_insn_r->reg_rec_count,
|
||||
record_buf);
|
||||
return AARCH64_RECORD_SUCCESS;
|
||||
|
||||
base-commit: 96a340e789f714156bbac7f78f340e06659b5e70
|
||||
--
|
||||
2.43.0
|
||||
|
@@ -1,229 +0,0 @@
|
||||
From 0ad71e3088f345101085a1f72e81a000a100db18 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Sat, 27 Apr 2024 17:48:22 +0200
|
||||
Subject: [PATCH 25/48] [gdb/remote] Fix abort on REMOTE_CLOSE_ERROR
|
||||
|
||||
When running test-case gdb.server/connect-with-no-symbol-file.exp on
|
||||
aarch64-linux (specifically, an opensuse leap 15.5 container on a
|
||||
fedora asahi 39 system), I run into:
|
||||
...
|
||||
(gdb) detach^M
|
||||
Detaching from program: target:connect-with-no-symbol-file, process 185104^M
|
||||
Ending remote debugging.^M
|
||||
terminate called after throwing an instance of 'gdb_exception_error'^M
|
||||
...
|
||||
|
||||
The detailed backtrace of the corefile is:
|
||||
...
|
||||
(gdb) bt
|
||||
#0 0x0000ffff75504f54 in raise () from /lib64/libpthread.so.0
|
||||
#1 0x00000000007a86b4 in handle_fatal_signal (sig=6)
|
||||
at gdb/event-top.c:926
|
||||
#2 <signal handler called>
|
||||
#3 0x0000ffff74b977b4 in raise () from /lib64/libc.so.6
|
||||
#4 0x0000ffff74b98c18 in abort () from /lib64/libc.so.6
|
||||
#5 0x0000ffff74ea26f4 in __gnu_cxx::__verbose_terminate_handler() ()
|
||||
from /usr/lib64/libstdc++.so.6
|
||||
#6 0x0000ffff74ea011c in ?? () from /usr/lib64/libstdc++.so.6
|
||||
#7 0x0000ffff74ea0180 in std::terminate() () from /usr/lib64/libstdc++.so.6
|
||||
#8 0x0000ffff74ea0464 in __cxa_throw () from /usr/lib64/libstdc++.so.6
|
||||
#9 0x0000000001548870 in throw_it (reason=RETURN_ERROR,
|
||||
error=TARGET_CLOSE_ERROR, fmt=0x16c7810 "Remote connection closed", ap=...)
|
||||
at gdbsupport/common-exceptions.cc:203
|
||||
#10 0x0000000001548920 in throw_verror (error=TARGET_CLOSE_ERROR,
|
||||
fmt=0x16c7810 "Remote connection closed", ap=...)
|
||||
at gdbsupport/common-exceptions.cc:211
|
||||
#11 0x0000000001548a00 in throw_error (error=TARGET_CLOSE_ERROR,
|
||||
fmt=0x16c7810 "Remote connection closed")
|
||||
at gdbsupport/common-exceptions.cc:226
|
||||
#12 0x0000000000ac8f2c in remote_target::readchar (this=0x233d3d90, timeout=2)
|
||||
at gdb/remote.c:9856
|
||||
#13 0x0000000000ac9f04 in remote_target::getpkt (this=0x233d3d90,
|
||||
buf=0x233d40a8, forever=false, is_notif=0x0) at gdb/remote.c:10326
|
||||
#14 0x0000000000acf3d0 in remote_target::remote_hostio_send_command
|
||||
(this=0x233d3d90, command_bytes=13, which_packet=17,
|
||||
remote_errno=0xfffff1a3cf38, attachment=0xfffff1a3ce88,
|
||||
attachment_len=0xfffff1a3ce90) at gdb/remote.c:12567
|
||||
#15 0x0000000000ad03bc in remote_target::fileio_fstat (this=0x233d3d90, fd=3,
|
||||
st=0xfffff1a3d020, remote_errno=0xfffff1a3cf38)
|
||||
at gdb/remote.c:12979
|
||||
#16 0x0000000000c39878 in target_fileio_fstat (fd=0, sb=0xfffff1a3d020,
|
||||
target_errno=0xfffff1a3cf38) at gdb/target.c:3315
|
||||
#17 0x00000000007eee5c in target_fileio_stream::stat (this=0x233d4400,
|
||||
abfd=0x2323fc40, sb=0xfffff1a3d020) at gdb/gdb_bfd.c:467
|
||||
#18 0x00000000007f012c in <lambda(bfd*, void*, stat*)>::operator()(bfd *,
|
||||
void *, stat *) const (__closure=0x0, abfd=0x2323fc40, stream=0x233d4400,
|
||||
sb=0xfffff1a3d020) at gdb/gdb_bfd.c:955
|
||||
#19 0x00000000007f015c in <lambda(bfd*, void*, stat*)>::_FUN(bfd *, void *,
|
||||
stat *) () at gdb/gdb_bfd.c:956
|
||||
#20 0x0000000000f9b838 in opncls_bstat (abfd=0x2323fc40, sb=0xfffff1a3d020)
|
||||
at bfd/opncls.c:665
|
||||
#21 0x0000000000f90adc in bfd_stat (abfd=0x2323fc40, statbuf=0xfffff1a3d020)
|
||||
at bfd/bfdio.c:431
|
||||
#22 0x000000000065fe20 in reopen_exec_file () at gdb/corefile.c:52
|
||||
#23 0x0000000000c3a3e8 in generic_mourn_inferior ()
|
||||
at gdb/target.c:3642
|
||||
#24 0x0000000000abf3f0 in remote_unpush_target (target=0x233d3d90)
|
||||
at gdb/remote.c:6067
|
||||
#25 0x0000000000aca8b0 in remote_target::mourn_inferior (this=0x233d3d90)
|
||||
at gdb/remote.c:10587
|
||||
#26 0x0000000000c387cc in target_mourn_inferior (
|
||||
ptid=<error reading variable: Cannot access memory at address 0x2d310>)
|
||||
at gdb/target.c:2738
|
||||
#27 0x0000000000abfff0 in remote_target::remote_detach_1 (this=0x233d3d90,
|
||||
inf=0x22fce540, from_tty=1) at gdb/remote.c:6421
|
||||
#28 0x0000000000ac0094 in remote_target::detach (this=0x233d3d90,
|
||||
inf=0x22fce540, from_tty=1) at gdb/remote.c:6436
|
||||
#29 0x0000000000c37c3c in target_detach (inf=0x22fce540, from_tty=1)
|
||||
at gdb/target.c:2526
|
||||
#30 0x0000000000860424 in detach_command (args=0x0, from_tty=1)
|
||||
at gdb/infcmd.c:2817
|
||||
#31 0x000000000060b594 in do_simple_func (args=0x0, from_tty=1, c=0x231431a0)
|
||||
at gdb/cli/cli-decode.c:94
|
||||
#32 0x00000000006108c8 in cmd_func (cmd=0x231431a0, args=0x0, from_tty=1)
|
||||
at gdb/cli/cli-decode.c:2741
|
||||
#33 0x0000000000c65a94 in execute_command (p=0x232e52f6 "", from_tty=1)
|
||||
at gdb/top.c:570
|
||||
#34 0x00000000007a7d2c in command_handler (command=0x232e52f0 "")
|
||||
at gdb/event-top.c:566
|
||||
#35 0x00000000007a8290 in command_line_handler (rl=...)
|
||||
at gdb/event-top.c:802
|
||||
#36 0x0000000000c9092c in tui_command_line_handler (rl=...)
|
||||
at gdb/tui/tui-interp.c:103
|
||||
#37 0x00000000007a750c in gdb_rl_callback_handler (rl=0x23385330 "detach")
|
||||
at gdb/event-top.c:258
|
||||
#38 0x0000000000d910f4 in rl_callback_read_char ()
|
||||
at readline/readline/callback.c:290
|
||||
#39 0x00000000007a7338 in gdb_rl_callback_read_char_wrapper_noexcept ()
|
||||
at gdb/event-top.c:194
|
||||
#40 0x00000000007a73f0 in gdb_rl_callback_read_char_wrapper
|
||||
(client_data=0x22fbf640) at gdb/event-top.c:233
|
||||
#41 0x0000000000cbee1c in stdin_event_handler (error=0, client_data=0x22fbf640)
|
||||
at gdb/ui.c:154
|
||||
#42 0x000000000154ed60 in handle_file_event (file_ptr=0x232be730, ready_mask=1)
|
||||
at gdbsupport/event-loop.cc:572
|
||||
#43 0x000000000154f21c in gdb_wait_for_event (block=1)
|
||||
at gdbsupport/event-loop.cc:693
|
||||
#44 0x000000000154dec4 in gdb_do_one_event (mstimeout=-1)
|
||||
at gdbsupport/event-loop.cc:263
|
||||
#45 0x0000000000910f98 in start_event_loop () at gdb/main.c:400
|
||||
#46 0x0000000000911130 in captured_command_loop () at gdb/main.c:464
|
||||
#47 0x0000000000912b5c in captured_main (data=0xfffff1a3db58)
|
||||
at gdb/main.c:1338
|
||||
#48 0x0000000000912bf4 in gdb_main (args=0xfffff1a3db58)
|
||||
at gdb/main.c:1357
|
||||
#49 0x00000000004170f4 in main (argc=10, argv=0xfffff1a3dcc8)
|
||||
at gdb/gdb.c:38
|
||||
(gdb)
|
||||
...
|
||||
|
||||
The abort happens because a c++ exception escapes to c code, specifically
|
||||
opncls_bstat in bfd/opncls.c. Compiling with -fexceptions works around this.
|
||||
|
||||
Fix this by catching the exception just before it escapes, in stat_trampoline
|
||||
and likewise in few similar spot.
|
||||
|
||||
Add a new template catch_exceptions to do so in a consistent way.
|
||||
|
||||
Tested on aarch64-linux.
|
||||
|
||||
Approved-by: Pedro Alves <pedro@palves.net>
|
||||
|
||||
PR remote/31577
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31577
|
||||
---
|
||||
gdb/gdb_bfd.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++---
|
||||
1 file changed, 56 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/gdb/gdb_bfd.c b/gdb/gdb_bfd.c
|
||||
index 217753cf914..3c34cc5693f 100644
|
||||
--- a/gdb/gdb_bfd.c
|
||||
+++ b/gdb/gdb_bfd.c
|
||||
@@ -887,6 +887,29 @@ gdb_bfd_openw (const char *filename, const char *target)
|
||||
return gdb_bfd_ref_ptr::new_reference (result);
|
||||
}
|
||||
|
||||
+/* Wrap f (args) and handle exceptions by:
|
||||
+ - returning val, and
|
||||
+ - calling set_quit_flag or set_force_quit_flag, if needed. */
|
||||
+
|
||||
+template <typename R, R val, typename F, typename... Args>
|
||||
+static R
|
||||
+catch_exceptions (F &&f, Args&&... args)
|
||||
+{
|
||||
+ try
|
||||
+ {
|
||||
+ return f (std::forward<Args> (args)...);
|
||||
+ }
|
||||
+ catch (const gdb_exception &ex)
|
||||
+ {
|
||||
+ if (ex.reason == RETURN_QUIT)
|
||||
+ set_quit_flag ();
|
||||
+ else if (ex.reason == RETURN_FORCED_QUIT)
|
||||
+ set_force_quit_flag ();
|
||||
+ }
|
||||
+
|
||||
+ return val;
|
||||
+}
|
||||
+
|
||||
/* See gdb_bfd.h. */
|
||||
|
||||
gdb_bfd_ref_ptr
|
||||
@@ -896,21 +919,51 @@ gdb_bfd_openr_iovec (const char *filename, const char *target,
|
||||
auto do_open = [] (bfd *nbfd, void *closure) -> void *
|
||||
{
|
||||
auto real_opener = static_cast<gdb_iovec_opener_ftype *> (closure);
|
||||
- return (*real_opener) (nbfd);
|
||||
+ /* Prevent exceptions from escaping to C code and triggering an abort. */
|
||||
+ auto res = catch_exceptions<gdb_bfd_iovec_base *, nullptr> ([&]
|
||||
+ {
|
||||
+ return (*real_opener) (nbfd);
|
||||
+ });
|
||||
+ if (res == nullptr)
|
||||
+ {
|
||||
+ errno = EIO;
|
||||
+ bfd_set_error (bfd_error_system_call);
|
||||
+ }
|
||||
+ return res;
|
||||
};
|
||||
|
||||
auto read_trampoline = [] (bfd *nbfd, void *stream, void *buf,
|
||||
file_ptr nbytes, file_ptr offset) -> file_ptr
|
||||
{
|
||||
gdb_bfd_iovec_base *obj = static_cast<gdb_bfd_iovec_base *> (stream);
|
||||
- return obj->read (nbfd, buf, nbytes, offset);
|
||||
+ /* Prevent exceptions from escaping to C code and triggering an abort. */
|
||||
+ auto res = catch_exceptions<long int, -1> ([&]
|
||||
+ {
|
||||
+ return obj->read (nbfd, buf, nbytes, offset);
|
||||
+ });
|
||||
+ if (res == -1)
|
||||
+ {
|
||||
+ errno = EIO;
|
||||
+ bfd_set_error (bfd_error_system_call);
|
||||
+ }
|
||||
+ return res;
|
||||
};
|
||||
|
||||
auto stat_trampoline = [] (struct bfd *abfd, void *stream,
|
||||
struct stat *sb) -> int
|
||||
{
|
||||
gdb_bfd_iovec_base *obj = static_cast<gdb_bfd_iovec_base *> (stream);
|
||||
- return obj->stat (abfd, sb);
|
||||
+ /* Prevent exceptions from escaping to C code and triggering an abort. */
|
||||
+ auto res = catch_exceptions<int, -1> ([&]
|
||||
+ {
|
||||
+ return obj->stat (abfd, sb);
|
||||
+ });
|
||||
+ if (res == -1)
|
||||
+ {
|
||||
+ errno = EIO;
|
||||
+ bfd_set_error (bfd_error_system_call);
|
||||
+ }
|
||||
+ return res;
|
||||
};
|
||||
|
||||
auto close_trampoline = [] (struct bfd *nbfd, void *stream) -> int
|
||||
--
|
||||
2.35.3
|
||||
|
2923
gdb-remove-qnx-neutrino-support.patch
Normal file
2923
gdb-remove-qnx-neutrino-support.patch
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,264 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Burgess <aburgess@redhat.com>
|
||||
Date: Sat, 25 Nov 2023 10:35:37 +0000
|
||||
Subject: gdb-rhbz-2232086-cpp-ify-mapped-symtab.patch
|
||||
|
||||
;; Back-port upstream commit acc117b57f7 as part of a fix for
|
||||
;; non-deterministic gdb-index generation (RH BZ 2232086).
|
||||
|
||||
gdb: C++-ify mapped_symtab from dwarf2/index-write.c
|
||||
|
||||
Make static the functions add_index_entry, find_slot, and hash_expand,
|
||||
member functions of the mapped_symtab class.
|
||||
|
||||
Fold an additional snippet of code from write_gdbindex into
|
||||
mapped_symtab::minimize, this code relates to minimisation, so this
|
||||
seems like a good home for it.
|
||||
|
||||
Make the n_elements, data, and m_string_obstack member variables of
|
||||
mapped_symtab private. Provide a new obstack() member function to
|
||||
provide access to the obstack when needed, and also add member
|
||||
functions begin(), end(), cbegin(), and cend() so that the
|
||||
mapped_symtab class can be treated like a contained and iterated
|
||||
over.
|
||||
|
||||
I've also taken this opportunity to split out the logic for whether
|
||||
the hash table (m_data) needs expanding, this is the new function
|
||||
hash_needs_expanding. This will be useful in a later commit.
|
||||
|
||||
There should be no user visible changes after this commit.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
diff --git a/gdb/dwarf2/index-write.c b/gdb/dwarf2/index-write.c
|
||||
--- a/gdb/dwarf2/index-write.c
|
||||
+++ b/gdb/dwarf2/index-write.c
|
||||
@@ -187,86 +187,135 @@ struct mapped_symtab
|
||||
{
|
||||
mapped_symtab ()
|
||||
{
|
||||
- data.resize (1024);
|
||||
+ m_data.resize (1024);
|
||||
}
|
||||
|
||||
- /* Minimize each entry in the symbol table, removing duplicates. */
|
||||
+ /* If there are no elements in the symbol table, then reduce the table
|
||||
+ size to zero. Otherwise call symtab_index_entry::minimize each entry
|
||||
+ in the symbol table. */
|
||||
+
|
||||
void minimize ()
|
||||
{
|
||||
- for (symtab_index_entry &item : data)
|
||||
+ if (m_element_count == 0)
|
||||
+ m_data.resize (0);
|
||||
+
|
||||
+ for (symtab_index_entry &item : m_data)
|
||||
item.minimize ();
|
||||
}
|
||||
|
||||
- offset_type n_elements = 0;
|
||||
- std::vector<symtab_index_entry> data;
|
||||
+ /* Add an entry to SYMTAB. NAME is the name of the symbol. CU_INDEX is
|
||||
+ the index of the CU in which the symbol appears. IS_STATIC is one if
|
||||
+ the symbol is static, otherwise zero (global). */
|
||||
+
|
||||
+ void add_index_entry (const char *name, int is_static,
|
||||
+ gdb_index_symbol_kind kind, offset_type cu_index);
|
||||
+
|
||||
+ /* Access the obstack. */
|
||||
+ struct obstack *obstack ()
|
||||
+ { return &m_string_obstack; }
|
||||
+
|
||||
+private:
|
||||
+
|
||||
+ /* Find a slot in SYMTAB for the symbol NAME. Returns a reference to
|
||||
+ the slot.
|
||||
+
|
||||
+ Function is used only during write_hash_table so no index format
|
||||
+ backward compatibility is needed. */
|
||||
+
|
||||
+ symtab_index_entry &find_slot (const char *name);
|
||||
+
|
||||
+ /* Expand SYMTAB's hash table. */
|
||||
+
|
||||
+ void hash_expand ();
|
||||
+
|
||||
+ /* Return true if the hash table in data needs to grow. */
|
||||
+
|
||||
+ bool hash_needs_expanding () const
|
||||
+ { return 4 * m_element_count / 3 >= m_data.size (); }
|
||||
+
|
||||
+ /* A vector that is used as a hash table. */
|
||||
+ std::vector<symtab_index_entry> m_data;
|
||||
+
|
||||
+ /* The number of elements stored in the m_data hash. */
|
||||
+ offset_type m_element_count = 0;
|
||||
|
||||
/* Temporary storage for names. */
|
||||
auto_obstack m_string_obstack;
|
||||
-};
|
||||
|
||||
-/* Find a slot in SYMTAB for the symbol NAME. Returns a reference to
|
||||
- the slot.
|
||||
+public:
|
||||
+ using iterator = decltype (m_data)::iterator;
|
||||
+ using const_iterator = decltype (m_data)::const_iterator;
|
||||
|
||||
- Function is used only during write_hash_table so no index format backward
|
||||
- compatibility is needed. */
|
||||
+ iterator begin ()
|
||||
+ { return m_data.begin (); }
|
||||
|
||||
-static symtab_index_entry &
|
||||
-find_slot (struct mapped_symtab *symtab, const char *name)
|
||||
+ iterator end ()
|
||||
+ { return m_data.end (); }
|
||||
+
|
||||
+ const_iterator cbegin ()
|
||||
+ { return m_data.cbegin (); }
|
||||
+
|
||||
+ const_iterator cend ()
|
||||
+ { return m_data.cend (); }
|
||||
+};
|
||||
+
|
||||
+/* See class definition. */
|
||||
+
|
||||
+symtab_index_entry &
|
||||
+mapped_symtab::find_slot (const char *name)
|
||||
{
|
||||
offset_type index, step, hash = mapped_index_string_hash (INT_MAX, name);
|
||||
|
||||
- index = hash & (symtab->data.size () - 1);
|
||||
- step = ((hash * 17) & (symtab->data.size () - 1)) | 1;
|
||||
+ index = hash & (m_data.size () - 1);
|
||||
+ step = ((hash * 17) & (m_data.size () - 1)) | 1;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
- if (symtab->data[index].name == NULL
|
||||
- || strcmp (name, symtab->data[index].name) == 0)
|
||||
- return symtab->data[index];
|
||||
- index = (index + step) & (symtab->data.size () - 1);
|
||||
+ if (m_data[index].name == NULL
|
||||
+ || strcmp (name, m_data[index].name) == 0)
|
||||
+ return m_data[index];
|
||||
+ index = (index + step) & (m_data.size () - 1);
|
||||
}
|
||||
}
|
||||
|
||||
-/* Expand SYMTAB's hash table. */
|
||||
+/* See class definition. */
|
||||
|
||||
-static void
|
||||
-hash_expand (struct mapped_symtab *symtab)
|
||||
+void
|
||||
+mapped_symtab::hash_expand ()
|
||||
{
|
||||
- auto old_entries = std::move (symtab->data);
|
||||
+ auto old_entries = std::move (m_data);
|
||||
|
||||
- symtab->data.clear ();
|
||||
- symtab->data.resize (old_entries.size () * 2);
|
||||
+ gdb_assert (m_data.size () == 0);
|
||||
+ m_data.resize (old_entries.size () * 2);
|
||||
|
||||
for (auto &it : old_entries)
|
||||
if (it.name != NULL)
|
||||
{
|
||||
- auto &ref = find_slot (symtab, it.name);
|
||||
+ auto &ref = this->find_slot (it.name);
|
||||
ref = std::move (it);
|
||||
}
|
||||
}
|
||||
|
||||
-/* Add an entry to SYMTAB. NAME is the name of the symbol.
|
||||
- CU_INDEX is the index of the CU in which the symbol appears.
|
||||
- IS_STATIC is one if the symbol is static, otherwise zero (global). */
|
||||
+/* See class definition. */
|
||||
|
||||
-static void
|
||||
-add_index_entry (struct mapped_symtab *symtab, const char *name,
|
||||
- int is_static, gdb_index_symbol_kind kind,
|
||||
- offset_type cu_index)
|
||||
+void
|
||||
+mapped_symtab::add_index_entry (const char *name, int is_static,
|
||||
+ gdb_index_symbol_kind kind,
|
||||
+ offset_type cu_index)
|
||||
{
|
||||
- symtab_index_entry *slot = &find_slot (symtab, name);
|
||||
+ symtab_index_entry *slot = &this->find_slot (name);
|
||||
if (slot->name == NULL)
|
||||
{
|
||||
/* This is a new element in the hash table. */
|
||||
- ++symtab->n_elements;
|
||||
+ ++this->m_element_count;
|
||||
|
||||
/* We might need to grow the hash table. */
|
||||
- if (4 * symtab->n_elements / 3 >= symtab->data.size ())
|
||||
+ if (this->hash_needs_expanding ())
|
||||
{
|
||||
- hash_expand (symtab);
|
||||
+ this->hash_expand ();
|
||||
|
||||
/* This element will have a different slot in the new table. */
|
||||
- slot = &find_slot (symtab, name);
|
||||
+ slot = &this->find_slot (name);
|
||||
|
||||
/* But it should still be a new element in the hash table. */
|
||||
gdb_assert (slot->name == nullptr);
|
||||
@@ -387,7 +436,7 @@ write_hash_table (mapped_symtab *symtab, data_buf &output, data_buf &cpool)
|
||||
|
||||
/* We add all the index vectors to the constant pool first, to
|
||||
ensure alignment is ok. */
|
||||
- for (symtab_index_entry &entry : symtab->data)
|
||||
+ for (symtab_index_entry &entry : *symtab)
|
||||
{
|
||||
if (entry.name == NULL)
|
||||
continue;
|
||||
@@ -416,7 +465,7 @@ write_hash_table (mapped_symtab *symtab, data_buf &output, data_buf &cpool)
|
||||
|
||||
/* Now write out the hash table. */
|
||||
std::unordered_map<c_str_view, offset_type, c_str_view_hasher> str_table;
|
||||
- for (const auto &entry : symtab->data)
|
||||
+ for (const auto &entry : *symtab)
|
||||
{
|
||||
offset_type str_off, vec_off;
|
||||
|
||||
@@ -1151,7 +1200,7 @@ write_cooked_index (cooked_index *table,
|
||||
const auto it = cu_index_htab.find (entry->per_cu);
|
||||
gdb_assert (it != cu_index_htab.cend ());
|
||||
|
||||
- const char *name = entry->full_name (&symtab->m_string_obstack);
|
||||
+ const char *name = entry->full_name (symtab->obstack ());
|
||||
|
||||
if (entry->per_cu->lang () == language_ada)
|
||||
{
|
||||
@@ -1159,7 +1208,7 @@ write_cooked_index (cooked_index *table,
|
||||
gdb, it has to use the encoded name, with any
|
||||
suffixes stripped. */
|
||||
std::string encoded = ada_encode (name, false);
|
||||
- name = obstack_strdup (&symtab->m_string_obstack,
|
||||
+ name = obstack_strdup (symtab->obstack (),
|
||||
encoded.c_str ());
|
||||
}
|
||||
else if (entry->per_cu->lang () == language_cplus
|
||||
@@ -1191,8 +1240,8 @@ write_cooked_index (cooked_index *table,
|
||||
else
|
||||
kind = GDB_INDEX_SYMBOL_KIND_TYPE;
|
||||
|
||||
- add_index_entry (symtab, name, (entry->flags & IS_STATIC) != 0,
|
||||
- kind, it->second);
|
||||
+ symtab->add_index_entry (name, (entry->flags & IS_STATIC) != 0,
|
||||
+ kind, it->second);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1267,8 +1316,6 @@ write_gdbindex (dwarf2_per_bfd *per_bfd, cooked_index *table,
|
||||
symtab.minimize ();
|
||||
|
||||
data_buf symtab_vec, constant_pool;
|
||||
- if (symtab.n_elements == 0)
|
||||
- symtab.data.resize (0);
|
||||
|
||||
write_hash_table (&symtab, symtab_vec, constant_pool);
|
||||
|
@@ -1,101 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Burgess <aburgess@redhat.com>
|
||||
Date: Mon, 27 Nov 2023 13:19:39 +0000
|
||||
Subject: gdb-rhbz-2232086-generate-dwarf-5-index-consistently.patch
|
||||
|
||||
;; Back-port upstream commit 3644f41dc80 as part of a fix for
|
||||
;; non-deterministic gdb-index generation (RH BZ 2232086).
|
||||
|
||||
gdb: generate dwarf-5 index identically as worker-thread count changes
|
||||
|
||||
Similar to the previous commit, this commit ensures that the dwarf-5
|
||||
index files are generated identically as the number of worker-threads
|
||||
changes.
|
||||
|
||||
Building the dwarf-5 index makes use of a closed hash table, the
|
||||
bucket_hash local within debug_names::build(). Entries are added to
|
||||
bucket_hash from m_name_to_value_set, which, in turn, is populated
|
||||
by calls to debug_names::insert() in write_debug_names. The insert
|
||||
calls are ordered based on the entries within the cooked_index, and
|
||||
the ordering within cooked_index depends on the number of worker
|
||||
threads that GDB is using.
|
||||
|
||||
My proposal is to sort each chain within the bucket_hash closed hash
|
||||
table prior to using this to build the dwarf-5 index.
|
||||
|
||||
The buckets within bucket_hash will always have the same ordering (for
|
||||
a given GDB build with a given executable), and by sorting the chains
|
||||
within each bucket, we can be sure that GDB will see each entry in a
|
||||
deterministic order.
|
||||
|
||||
I've extended the index creation test to cover this case.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
diff --git a/gdb/dwarf2/index-write.c b/gdb/dwarf2/index-write.c
|
||||
--- a/gdb/dwarf2/index-write.c
|
||||
+++ b/gdb/dwarf2/index-write.c
|
||||
@@ -452,6 +452,11 @@ class c_str_view
|
||||
return strcmp (m_cstr, other.m_cstr) == 0;
|
||||
}
|
||||
|
||||
+ bool operator< (const c_str_view &other) const
|
||||
+ {
|
||||
+ return strcmp (m_cstr, other.m_cstr) < 0;
|
||||
+ }
|
||||
+
|
||||
/* Return the underlying C string. Note, the returned string is
|
||||
only a reference with lifetime of this object. */
|
||||
const char *c_str () const
|
||||
@@ -771,10 +776,18 @@ class debug_names
|
||||
}
|
||||
for (size_t bucket_ix = 0; bucket_ix < bucket_hash.size (); ++bucket_ix)
|
||||
{
|
||||
- const std::forward_list<hash_it_pair> &hashitlist
|
||||
- = bucket_hash[bucket_ix];
|
||||
+ std::forward_list<hash_it_pair> &hashitlist = bucket_hash[bucket_ix];
|
||||
if (hashitlist.empty ())
|
||||
continue;
|
||||
+
|
||||
+ /* Sort the items within each bucket. This ensures that the
|
||||
+ generated index files will be the same no matter the order in
|
||||
+ which symbols were added into the index. */
|
||||
+ hashitlist.sort ([] (const hash_it_pair &a, const hash_it_pair &b)
|
||||
+ {
|
||||
+ return a.it->first < b.it->first;
|
||||
+ });
|
||||
+
|
||||
uint32_t &bucket_slot = m_bucket_table[bucket_ix];
|
||||
/* The hashes array is indexed starting at 1. */
|
||||
store_unsigned_integer (reinterpret_cast<gdb_byte *> (&bucket_slot),
|
||||
diff --git a/gdb/testsuite/gdb.gdb/index-file.exp b/gdb/testsuite/gdb.gdb/index-file.exp
|
||||
--- a/gdb/testsuite/gdb.gdb/index-file.exp
|
||||
+++ b/gdb/testsuite/gdb.gdb/index-file.exp
|
||||
@@ -47,6 +47,9 @@ remote_exec host "mkdir -p ${dir1}"
|
||||
with_timeout_factor $timeout_factor {
|
||||
gdb_test_no_output "save gdb-index $dir1" \
|
||||
"create gdb-index file"
|
||||
+
|
||||
+ gdb_test_no_output "save gdb-index -dwarf-5 $dir1" \
|
||||
+ "create dwarf-index files"
|
||||
}
|
||||
|
||||
# Close GDB.
|
||||
@@ -143,13 +146,16 @@ if { $worker_threads > 1 } {
|
||||
with_timeout_factor $timeout_factor {
|
||||
gdb_test_no_output "save gdb-index $dir2" \
|
||||
"create second gdb-index file"
|
||||
+
|
||||
+ gdb_test_no_output "save gdb-index -dwarf-5 $dir2" \
|
||||
+ "create second dwarf-index files"
|
||||
}
|
||||
|
||||
# Close GDB.
|
||||
gdb_exit
|
||||
|
||||
# Now check that the index files are identical.
|
||||
- foreach suffix { gdb-index } {
|
||||
+ foreach suffix { gdb-index debug_names debug_str } {
|
||||
set result \
|
||||
[remote_exec host \
|
||||
"cmp -s \"$dir1/${index_filename_base}.${suffix}\" \"$dir2/${index_filename_base}.${suffix}\""]
|
@@ -1,230 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Burgess <aburgess@redhat.com>
|
||||
Date: Fri, 24 Nov 2023 12:04:36 +0000
|
||||
Subject: gdb-rhbz-2232086-generate-gdb-index-consistently.patch
|
||||
|
||||
;; Back-port upstream commit aff250145af as part of a fix for
|
||||
;; non-deterministic gdb-index generation (RH BZ 2232086).
|
||||
|
||||
gdb: generate gdb-index identically regardless of work thread count
|
||||
|
||||
It was observed that changing the number of worker threads that GDB
|
||||
uses (maintenance set worker-threads NUM) would have an impact on the
|
||||
layout of the generated gdb-index.
|
||||
|
||||
The cause seems to be how the CU are distributed between threads, and
|
||||
then symbols that appear in multiple CU can be encountered earlier or
|
||||
later depending on whether a particular CU moves between threads.
|
||||
|
||||
I certainly found this behaviour was reproducible when generating an
|
||||
index for GDB itself, like:
|
||||
|
||||
gdb -q -nx -nh -batch \
|
||||
-eiex 'maint set worker-threads NUM' \
|
||||
-ex 'save gdb-index /tmp/'
|
||||
|
||||
And then setting different values for NUM will change the generated
|
||||
index.
|
||||
|
||||
Now, the question is: does this matter?
|
||||
|
||||
I would like to suggest that yes, this does matter. At Red Hat we
|
||||
generate a gdb-index as part of the build process, and we would
|
||||
ideally like to have reproducible builds: for the same source,
|
||||
compiled with the same tool-chain, we should get the exact same output
|
||||
binary. And we do .... except for the index.
|
||||
|
||||
Now we could simply force GDB to only use a single worker thread when
|
||||
we build the index, but, I don't think the idea of reproducible builds
|
||||
is that strange, so I think we should ensure that our generated
|
||||
indexes are always reproducible.
|
||||
|
||||
To achieve this, I propose that we add an extra step when building the
|
||||
gdb-index file. After constructing the initial symbol hash table
|
||||
contents, we will pull all the symbols out of the hash, sort them,
|
||||
then re-insert them in sorted order. This will ensure that the
|
||||
structure of the generated hash will remain consistent (given the same
|
||||
set of symbols).
|
||||
|
||||
I've extended the existing index-file test to check that the generated
|
||||
index doesn't change if we adjust the number of worker threads used.
|
||||
Given that this test is already rather slow, I've only made one change
|
||||
to the worker-thread count. Maybe this test should be changed to use
|
||||
a smaller binary, which is quicker to load, and for which we could
|
||||
then try many different worker thread counts.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
diff --git a/gdb/dwarf2/index-write.c b/gdb/dwarf2/index-write.c
|
||||
--- a/gdb/dwarf2/index-write.c
|
||||
+++ b/gdb/dwarf2/index-write.c
|
||||
@@ -210,6 +210,13 @@ struct mapped_symtab
|
||||
void add_index_entry (const char *name, int is_static,
|
||||
gdb_index_symbol_kind kind, offset_type cu_index);
|
||||
|
||||
+ /* When entries are originally added into the data hash the order will
|
||||
+ vary based on the number of worker threads GDB is configured to use.
|
||||
+ This function will rebuild the hash such that the final layout will be
|
||||
+ deterministic regardless of the number of worker threads used. */
|
||||
+
|
||||
+ void sort ();
|
||||
+
|
||||
/* Access the obstack. */
|
||||
struct obstack *obstack ()
|
||||
{ return &m_string_obstack; }
|
||||
@@ -296,6 +303,65 @@ mapped_symtab::hash_expand ()
|
||||
}
|
||||
}
|
||||
|
||||
+/* See mapped_symtab class declaration. */
|
||||
+
|
||||
+void mapped_symtab::sort ()
|
||||
+{
|
||||
+ /* Move contents out of this->data vector. */
|
||||
+ std::vector<symtab_index_entry> original_data = std::move (m_data);
|
||||
+
|
||||
+ /* Restore the size of m_data, this will avoid having to expand the hash
|
||||
+ table (and rehash all elements) when we reinsert after sorting.
|
||||
+ However, we do reset the element count, this allows for some sanity
|
||||
+ checking asserts during the reinsert phase. */
|
||||
+ gdb_assert (m_data.size () == 0);
|
||||
+ m_data.resize (original_data.size ());
|
||||
+ m_element_count = 0;
|
||||
+
|
||||
+ /* Remove empty entries from ORIGINAL_DATA, this makes sorting quicker. */
|
||||
+ auto it = std::remove_if (original_data.begin (), original_data.end (),
|
||||
+ [] (const symtab_index_entry &entry) -> bool
|
||||
+ {
|
||||
+ return entry.name == nullptr;
|
||||
+ });
|
||||
+ original_data.erase (it, original_data.end ());
|
||||
+
|
||||
+ /* Sort the existing contents. */
|
||||
+ std::sort (original_data.begin (), original_data.end (),
|
||||
+ [] (const symtab_index_entry &a,
|
||||
+ const symtab_index_entry &b) -> bool
|
||||
+ {
|
||||
+ /* Return true if A is before B. */
|
||||
+ gdb_assert (a.name != nullptr);
|
||||
+ gdb_assert (b.name != nullptr);
|
||||
+
|
||||
+ return strcmp (a.name, b.name) < 0;
|
||||
+ });
|
||||
+
|
||||
+ /* Re-insert each item from the sorted list. */
|
||||
+ for (auto &entry : original_data)
|
||||
+ {
|
||||
+ /* We know that ORIGINAL_DATA contains no duplicates, this data was
|
||||
+ taken from a hash table that de-duplicated entries for us, so
|
||||
+ count this as a new item.
|
||||
+
|
||||
+ As we retained the original size of m_data (see above) then we
|
||||
+ should never need to grow m_data_ during this re-insertion phase,
|
||||
+ assert that now. */
|
||||
+ ++m_element_count;
|
||||
+ gdb_assert (!this->hash_needs_expanding ());
|
||||
+
|
||||
+ /* Lookup a slot. */
|
||||
+ symtab_index_entry &slot = this->find_slot (entry.name);
|
||||
+
|
||||
+ /* As discussed above, we should not find duplicates. */
|
||||
+ gdb_assert (slot.name == nullptr);
|
||||
+
|
||||
+ /* Move this item into the slot we found. */
|
||||
+ slot = std::move (entry);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/* See class definition. */
|
||||
|
||||
void
|
||||
@@ -1311,6 +1377,9 @@ write_gdbindex (dwarf2_per_bfd *per_bfd, cooked_index *table,
|
||||
for (auto map : table->get_addrmaps ())
|
||||
write_address_map (map, addr_vec, cu_index_htab);
|
||||
|
||||
+ /* Ensure symbol hash is built domestically. */
|
||||
+ symtab.sort ();
|
||||
+
|
||||
/* Now that we've processed all symbols we can shrink their cu_indices
|
||||
lists. */
|
||||
symtab.minimize ();
|
||||
diff --git a/gdb/testsuite/gdb.gdb/index-file.exp b/gdb/testsuite/gdb.gdb/index-file.exp
|
||||
--- a/gdb/testsuite/gdb.gdb/index-file.exp
|
||||
+++ b/gdb/testsuite/gdb.gdb/index-file.exp
|
||||
@@ -38,6 +38,9 @@ with_timeout_factor $timeout_factor {
|
||||
clean_restart $filename
|
||||
}
|
||||
|
||||
+# Record how many worker threads GDB is using.
|
||||
+set worker_threads [gdb_get_worker_threads]
|
||||
+
|
||||
# Generate an index file.
|
||||
set dir1 [standard_output_file "index_1"]
|
||||
remote_exec host "mkdir -p ${dir1}"
|
||||
@@ -116,3 +119,41 @@ proc check_symbol_table_usage { filename } {
|
||||
|
||||
set index_filename_base [file tail $filename]
|
||||
check_symbol_table_usage "$dir1/${index_filename_base}.gdb-index"
|
||||
+
|
||||
+# If GDB is using more than 1 worker thread then reduce the number of
|
||||
+# worker threads, regenerate the index, and check that we get the same
|
||||
+# index file back. At one point the layout of the index would vary
|
||||
+# based on the number of worker threads used.
|
||||
+if { $worker_threads > 1 } {
|
||||
+ # Start GDB, but don't load a file yet.
|
||||
+ clean_restart
|
||||
+
|
||||
+ # Adjust the number of threads to use.
|
||||
+ set reduced_threads [expr $worker_threads / 2]
|
||||
+ gdb_test_no_output "maint set worker-threads $reduced_threads"
|
||||
+
|
||||
+ with_timeout_factor $timeout_factor {
|
||||
+ # Now load the test binary.
|
||||
+ gdb_file_cmd $filename
|
||||
+ }
|
||||
+
|
||||
+ # Generate an index file.
|
||||
+ set dir2 [standard_output_file "index_2"]
|
||||
+ remote_exec host "mkdir -p ${dir2}"
|
||||
+ with_timeout_factor $timeout_factor {
|
||||
+ gdb_test_no_output "save gdb-index $dir2" \
|
||||
+ "create second gdb-index file"
|
||||
+ }
|
||||
+
|
||||
+ # Close GDB.
|
||||
+ gdb_exit
|
||||
+
|
||||
+ # Now check that the index files are identical.
|
||||
+ foreach suffix { gdb-index } {
|
||||
+ set result \
|
||||
+ [remote_exec host \
|
||||
+ "cmp -s \"$dir1/${index_filename_base}.${suffix}\" \"$dir2/${index_filename_base}.${suffix}\""]
|
||||
+ gdb_assert { [lindex $result 0] == 0 } \
|
||||
+ "$suffix files are identical"
|
||||
+ }
|
||||
+}
|
||||
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
|
||||
--- a/gdb/testsuite/lib/gdb.exp
|
||||
+++ b/gdb/testsuite/lib/gdb.exp
|
||||
@@ -10033,6 +10033,21 @@ proc is_target_non_stop { {testname ""} } {
|
||||
return $is_non_stop
|
||||
}
|
||||
|
||||
+# Return the number of worker threads that GDB is currently using.
|
||||
+
|
||||
+proc gdb_get_worker_threads { {testname ""} } {
|
||||
+ set worker_threads "UNKNOWN"
|
||||
+ gdb_test_multiple "maintenance show worker-threads" $testname {
|
||||
+ -wrap -re "The number of worker threads GDB can use is unlimited \\(currently ($::decimal)\\)\\." {
|
||||
+ set worker_threads $expect_out(1,string)
|
||||
+ }
|
||||
+ -wrap -re "The number of worker threads GDB can use is ($::decimal)\\." {
|
||||
+ set worker_threads $expect_out(1,string)
|
||||
+ }
|
||||
+ }
|
||||
+ return $worker_threads
|
||||
+}
|
||||
+
|
||||
# Check if the compiler emits epilogue information associated
|
||||
# with the closing brace or with the last statement line.
|
||||
#
|
@@ -1,222 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Burgess <aburgess@redhat.com>
|
||||
Date: Fri, 24 Nov 2023 11:50:35 +0000
|
||||
Subject: gdb-rhbz-2232086-reduce-size-of-gdb-index.patch
|
||||
|
||||
;; Back-port upstream commit aa19bc1d259 as part of a fix for
|
||||
;; non-deterministic gdb-index generation (RH BZ 2232086).
|
||||
|
||||
gdb: reduce size of generated gdb-index file
|
||||
|
||||
I noticed in passing that out algorithm for generating the gdb-index
|
||||
file is incorrect. When building the hash table in add_index_entry we
|
||||
count every incoming entry rehash when the number of entries gets too
|
||||
large. However, some of the incoming entries will be duplicates,
|
||||
which don't actually result in new items being added to the hash
|
||||
table.
|
||||
|
||||
As a result, we grow the gdb-index hash table far too often.
|
||||
|
||||
With an unmodified GDB, generating a gdb-index for GDB, I see a file
|
||||
size of 90M, with a hash usage (in the generated index file) of just
|
||||
2.6%.
|
||||
|
||||
With a patched GDB, generating a gdb-index for the _same_ GDB binary,
|
||||
I now see a gdb-index file size of 30M, with a hash usage of 41.9%.
|
||||
|
||||
This is a 67% reduction in gdb-index file size.
|
||||
|
||||
Obviously, not every gdb-index file is going to see such big savings,
|
||||
however, the larger a program, and the more symbols that are
|
||||
duplicated between compilation units, the more GDB would over count,
|
||||
and so, over-grow the index.
|
||||
|
||||
The gdb-index hash table we create has a minimum size of 1024, and
|
||||
then we grow the hash when it is 75% full, doubling the hash table at
|
||||
that time. Given this, then we expect that either:
|
||||
|
||||
a. The hash table is size 1024, and less than 75% full, or
|
||||
b. The hash table is between 37.5% and 75% full.
|
||||
|
||||
I've include a test that checks some of these constraints -- I've not
|
||||
bothered to check the upper limit, and over full hash table isn't
|
||||
really a problem here, but if the fill percentage is less than 37.5%
|
||||
then this indicates that we've done something wrong (obviously, I also
|
||||
check for the 1024 minimum size).
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
diff --git a/gdb/dwarf2/index-write.c b/gdb/dwarf2/index-write.c
|
||||
--- a/gdb/dwarf2/index-write.c
|
||||
+++ b/gdb/dwarf2/index-write.c
|
||||
@@ -254,20 +254,29 @@ add_index_entry (struct mapped_symtab *symtab, const char *name,
|
||||
int is_static, gdb_index_symbol_kind kind,
|
||||
offset_type cu_index)
|
||||
{
|
||||
- offset_type cu_index_and_attrs;
|
||||
+ symtab_index_entry *slot = &find_slot (symtab, name);
|
||||
+ if (slot->name == NULL)
|
||||
+ {
|
||||
+ /* This is a new element in the hash table. */
|
||||
+ ++symtab->n_elements;
|
||||
|
||||
- ++symtab->n_elements;
|
||||
- if (4 * symtab->n_elements / 3 >= symtab->data.size ())
|
||||
- hash_expand (symtab);
|
||||
+ /* We might need to grow the hash table. */
|
||||
+ if (4 * symtab->n_elements / 3 >= symtab->data.size ())
|
||||
+ {
|
||||
+ hash_expand (symtab);
|
||||
|
||||
- symtab_index_entry &slot = find_slot (symtab, name);
|
||||
- if (slot.name == NULL)
|
||||
- {
|
||||
- slot.name = name;
|
||||
+ /* This element will have a different slot in the new table. */
|
||||
+ slot = &find_slot (symtab, name);
|
||||
+
|
||||
+ /* But it should still be a new element in the hash table. */
|
||||
+ gdb_assert (slot->name == nullptr);
|
||||
+ }
|
||||
+
|
||||
+ slot->name = name;
|
||||
/* index_offset is set later. */
|
||||
}
|
||||
|
||||
- cu_index_and_attrs = 0;
|
||||
+ offset_type cu_index_and_attrs = 0;
|
||||
DW2_GDB_INDEX_CU_SET_VALUE (cu_index_and_attrs, cu_index);
|
||||
DW2_GDB_INDEX_SYMBOL_STATIC_SET_VALUE (cu_index_and_attrs, is_static);
|
||||
DW2_GDB_INDEX_SYMBOL_KIND_SET_VALUE (cu_index_and_attrs, kind);
|
||||
@@ -279,7 +288,7 @@ add_index_entry (struct mapped_symtab *symtab, const char *name,
|
||||
the last entry pushed), but a symbol could have multiple kinds in one CU.
|
||||
To keep things simple we don't worry about the duplication here and
|
||||
sort and uniquify the list after we've processed all symbols. */
|
||||
- slot.cu_indices.push_back (cu_index_and_attrs);
|
||||
+ slot->cu_indices.push_back (cu_index_and_attrs);
|
||||
}
|
||||
|
||||
/* See symtab_index_entry. */
|
||||
diff --git a/gdb/testsuite/gdb.gdb/index-file.exp b/gdb/testsuite/gdb.gdb/index-file.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.gdb/index-file.exp
|
||||
@@ -0,0 +1,118 @@
|
||||
+# Copyright 2023 Free Software Foundation, Inc.
|
||||
+
|
||||
+# This program is free software; you can redistribute it and/or modify
|
||||
+# it under the terms of the GNU General Public License as published by
|
||||
+# the Free Software Foundation; either version 3 of the License, or
|
||||
+# (at your option) any later version.
|
||||
+#
|
||||
+# This program is distributed in the hope that it will be useful,
|
||||
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+# GNU General Public License for more details.
|
||||
+#
|
||||
+# You should have received a copy of the GNU General Public License
|
||||
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
+
|
||||
+# Load the GDB executable, and then 'save gdb-index', and make some
|
||||
+# checks of the generated index file.
|
||||
+
|
||||
+load_lib selftest-support.exp
|
||||
+
|
||||
+# Can't save an index with readnow.
|
||||
+if {[readnow]} {
|
||||
+ untested "cannot create an index when readnow is in use"
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+# A multiplier used to ensure slow tasks are less likely to timeout.
|
||||
+set timeout_factor 20
|
||||
+
|
||||
+set filename [selftest_prepare]
|
||||
+if { $filename eq "" } {
|
||||
+ unsupported "${gdb_test_file_name}.exp"
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+with_timeout_factor $timeout_factor {
|
||||
+ # Start GDB, load FILENAME.
|
||||
+ clean_restart $filename
|
||||
+}
|
||||
+
|
||||
+# Generate an index file.
|
||||
+set dir1 [standard_output_file "index_1"]
|
||||
+remote_exec host "mkdir -p ${dir1}"
|
||||
+with_timeout_factor $timeout_factor {
|
||||
+ gdb_test_no_output "save gdb-index $dir1" \
|
||||
+ "create gdb-index file"
|
||||
+}
|
||||
+
|
||||
+# Close GDB.
|
||||
+gdb_exit
|
||||
+
|
||||
+# Validate that the index-file FILENAME has made efficient use of its
|
||||
+# symbol hash table. Calculate the number of symbols in the hash
|
||||
+# table and the total hash table size. The hash table starts with
|
||||
+# 1024 entries, and then doubles each time it is filled to 75%. At
|
||||
+# 75% filled, doubling the size takes it to 37.5% filled.
|
||||
+#
|
||||
+# Thus, the hash table is correctly filled if:
|
||||
+# 1. Its size is 1024 (i.e. it has not yet had its first doubling), or
|
||||
+# 2. Its filled percentage is over 37%
|
||||
+#
|
||||
+# We could check that it is not over filled, but I don't as that's not
|
||||
+# really an issue. But we did once have a bug where the table was
|
||||
+# doubled incorrectly, in which case we'd see a filled percentage of
|
||||
+# around 2% in some cases, which is a huge waste of disk space.
|
||||
+proc check_symbol_table_usage { filename } {
|
||||
+ # Open the file in binary mode and read-only mode.
|
||||
+ set fp [open $filename rb]
|
||||
+
|
||||
+ # Configure the channel to use binary translation.
|
||||
+ fconfigure $fp -translation binary
|
||||
+
|
||||
+ # Read the first 8 bytes of the file, which contain the header of
|
||||
+ # the index section.
|
||||
+ set header [read $fp [expr 7 * 4]]
|
||||
+
|
||||
+ # Scan the header to get the version, the CU list offset, and the
|
||||
+ # types CU list offset.
|
||||
+ binary scan $header iiiiii version \
|
||||
+ _ _ _ symbol_table_offset shortcut_offset
|
||||
+
|
||||
+ # The length of the symbol hash table (in entries).
|
||||
+ set len [expr ($shortcut_offset - $symbol_table_offset) / 8]
|
||||
+
|
||||
+ # Now walk the hash table and count how many entries are in use.
|
||||
+ set offset $symbol_table_offset
|
||||
+ set count 0
|
||||
+ while { $offset < $shortcut_offset } {
|
||||
+ seek $fp $offset
|
||||
+ set entry [read $fp 8]
|
||||
+ binary scan $entry ii name_ptr flags
|
||||
+ if { $name_ptr != 0 } {
|
||||
+ incr count
|
||||
+ }
|
||||
+
|
||||
+ incr offset 8
|
||||
+ }
|
||||
+
|
||||
+ # Close the file.
|
||||
+ close $fp
|
||||
+
|
||||
+ # Calculate how full the cache is.
|
||||
+ set pct [expr (100 * double($count)) / $len]
|
||||
+
|
||||
+ # Write our results out to the gdb.log.
|
||||
+ verbose -log "Hash table size: $len"
|
||||
+ verbose -log "Hash table entries: $count"
|
||||
+ verbose -log "Percentage usage: $pct%"
|
||||
+
|
||||
+ # The minimum fill percentage is actually 37.5%, but we give TCL a
|
||||
+ # little flexibility in case the FP maths give a result a little
|
||||
+ # off.
|
||||
+ gdb_assert { $len == 1024 || $pct > 37 } \
|
||||
+ "symbol hash table usage"
|
||||
+}
|
||||
+
|
||||
+set index_filename_base [file tail $filename]
|
||||
+check_symbol_table_usage "$dir1/${index_filename_base}.gdb-index"
|
@@ -1,170 +0,0 @@
|
||||
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 ()
|
@@ -1,104 +0,0 @@
|
||||
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
|
@@ -1,77 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Burgess <aburgess@redhat.com>
|
||||
Date: Fri, 24 Nov 2023 11:10:08 +0000
|
||||
Subject: gdb-rhbz2232086-refactor-selftest-support.patch
|
||||
|
||||
;; Back-port upstream commit 1f0fab7ff86 as part of a fix for
|
||||
;; non-deterministic gdb-index generation (RH BZ 2232086).
|
||||
|
||||
gdb/testsuite: small refactor in selftest-support.exp
|
||||
|
||||
Split out the code that makes a copy of the GDB executable ready for
|
||||
self testing into a new proc. A later commit in this series wants to
|
||||
load the GDB executable into GDB (for creating an on-disk debug
|
||||
index), but doesn't need to make use of the full do_self_tests proc.
|
||||
|
||||
There should be no changes in what is tested after this commit.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
diff --git a/gdb/testsuite/lib/selftest-support.exp b/gdb/testsuite/lib/selftest-support.exp
|
||||
--- a/gdb/testsuite/lib/selftest-support.exp
|
||||
+++ b/gdb/testsuite/lib/selftest-support.exp
|
||||
@@ -92,11 +92,13 @@ proc selftest_setup { executable function } {
|
||||
return 0
|
||||
}
|
||||
|
||||
-# A simple way to run some self-tests.
|
||||
-
|
||||
-proc do_self_tests {function body} {
|
||||
- global GDB tool
|
||||
-
|
||||
+# Prepare for running a self-test by moving the GDB executable to a
|
||||
+# location where we can use it as the inferior. Return the filename
|
||||
+# of the new location.
|
||||
+#
|
||||
+# If the current testing setup is not suitable for running a
|
||||
+# self-test, then return an empty string.
|
||||
+proc selftest_prepare {} {
|
||||
# Are we testing with a remote board? In that case, the target
|
||||
# won't have access to the GDB's auxilliary data files
|
||||
# (data-directory, etc.). It's simpler to just skip.
|
||||
@@ -120,19 +122,31 @@ proc do_self_tests {function body} {
|
||||
# Run the test with self. Copy the file executable file in case
|
||||
# this OS doesn't like to edit its own text space.
|
||||
|
||||
- set GDB_FULLPATH [find_gdb $GDB]
|
||||
+ set gdb_fullpath [find_gdb $::GDB]
|
||||
|
||||
if {[is_remote host]} {
|
||||
- set xgdb x$tool
|
||||
+ set xgdb x$::tool
|
||||
} else {
|
||||
- set xgdb [standard_output_file x$tool]
|
||||
+ set xgdb [standard_output_file x$::tool]
|
||||
}
|
||||
|
||||
# Remove any old copy lying around.
|
||||
remote_file host delete $xgdb
|
||||
|
||||
+ set filename [remote_download host $gdb_fullpath $xgdb]
|
||||
+
|
||||
+ return $filename
|
||||
+}
|
||||
+
|
||||
+# A simple way to run some self-tests.
|
||||
+
|
||||
+proc do_self_tests {function body} {
|
||||
+ set file [selftest_prepare]
|
||||
+ if { $file eq "" } {
|
||||
+ return
|
||||
+ }
|
||||
+
|
||||
gdb_start
|
||||
- set file [remote_download host $GDB_FULLPATH $xgdb]
|
||||
|
||||
# When debugging GDB with GDB, some operations can take a relatively long
|
||||
# time, especially if the build is non-optimized. Bump the timeout for the
|
@@ -1,48 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Alexandra=20H=C3=A1jkov=C3=A1?= <ahajkova@redhat.com>
|
||||
Date: Mon, 8 Jan 2024 13:24:05 +0100
|
||||
Subject: gdb-rhbz2250652-avoid-PyOS_ReadlineTState.patch
|
||||
|
||||
gdb/python: avoid use of _PyOS_ReadlineTState
|
||||
|
||||
In python/py-gdb-readline.c we make use of _PyOS_ReadlineTState,
|
||||
however, this variable is no longer public in Python 3.13, and so GDB
|
||||
no longer builds.
|
||||
|
||||
We are making use of _PyOS_ReadlineTState in order to re-acquire the
|
||||
Python Global Interpreter Lock (GIL). The _PyOS_ReadlineTState
|
||||
variable is set in Python's outer readline code prior to calling the
|
||||
user (GDB) supplied readline callback function, which for us is
|
||||
gdbpy_readline_wrapper. The gdbpy_readline_wrapper function is called
|
||||
without the GIL held.
|
||||
|
||||
Instead of using _PyOS_ReadlineTState, I propose that we switch to
|
||||
calling PyGILState_Ensure() and PyGILState_Release(). These functions
|
||||
will acquire the GIL based on the current thread. I think this should
|
||||
be sufficient; I can't imagine why we'd be running
|
||||
gdbpy_readline_wrapper on one thread on behalf of a different Python
|
||||
thread.... that would be unexpected I think.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
diff --git a/gdb/python/py-gdb-readline.c b/gdb/python/py-gdb-readline.c
|
||||
--- a/gdb/python/py-gdb-readline.c
|
||||
+++ b/gdb/python/py-gdb-readline.c
|
||||
@@ -56,13 +56,11 @@ gdbpy_readline_wrapper (FILE *sys_stdin, FILE *sys_stdout,
|
||||
if (except.reason == RETURN_QUIT)
|
||||
return NULL;
|
||||
|
||||
- /* The thread state is nulled during gdbpy_readline_wrapper,
|
||||
- with the original value saved in the following undocumented
|
||||
- variable (see Python's Parser/myreadline.c and
|
||||
- Modules/readline.c). */
|
||||
- PyEval_RestoreThread (_PyOS_ReadlineTState);
|
||||
+
|
||||
+ /* This readline callback is called without the GIL held. */
|
||||
+ gdbpy_gil gil;
|
||||
+
|
||||
gdbpy_convert_exception (except);
|
||||
- PyEval_SaveThread ();
|
||||
return NULL;
|
||||
}
|
||||
|
@@ -1,81 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Alexandra=20H=C3=A1jkov=C3=A1?= <ahajkova@redhat.com>
|
||||
Date: Mon, 8 Jan 2024 13:12:15 +0100
|
||||
Subject: gdb-rhbz2250652-gdbpy_gil.patch
|
||||
|
||||
gdb: move gdbpy_gil into python-internal.h
|
||||
|
||||
Move gdbpy_gil class into python-internal.h, the next
|
||||
commit wants to make use of this class from a file other
|
||||
than python.c.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
|
||||
--- a/gdb/python/python-internal.h
|
||||
+++ b/gdb/python/python-internal.h
|
||||
@@ -754,6 +754,30 @@ class gdbpy_allow_threads
|
||||
PyThreadState *m_save;
|
||||
};
|
||||
|
||||
+/* A helper class to save and restore the GIL, but without touching
|
||||
+ the other globals that are handled by gdbpy_enter. */
|
||||
+
|
||||
+class gdbpy_gil
|
||||
+{
|
||||
+public:
|
||||
+
|
||||
+ gdbpy_gil ()
|
||||
+ : m_state (PyGILState_Ensure ())
|
||||
+ {
|
||||
+ }
|
||||
+
|
||||
+ ~gdbpy_gil ()
|
||||
+ {
|
||||
+ PyGILState_Release (m_state);
|
||||
+ }
|
||||
+
|
||||
+ DISABLE_COPY_AND_ASSIGN (gdbpy_gil);
|
||||
+
|
||||
+private:
|
||||
+
|
||||
+ PyGILState_STATE m_state;
|
||||
+};
|
||||
+
|
||||
/* Use this after a TRY_EXCEPT to throw the appropriate Python
|
||||
exception. */
|
||||
#define GDB_PY_HANDLE_EXCEPTION(Exception) \
|
||||
diff --git a/gdb/python/python.c b/gdb/python/python.c
|
||||
--- a/gdb/python/python.c
|
||||
+++ b/gdb/python/python.c
|
||||
@@ -257,30 +257,6 @@ gdbpy_enter::finalize ()
|
||||
python_gdbarch = target_gdbarch ();
|
||||
}
|
||||
|
||||
-/* A helper class to save and restore the GIL, but without touching
|
||||
- the other globals that are handled by gdbpy_enter. */
|
||||
-
|
||||
-class gdbpy_gil
|
||||
-{
|
||||
-public:
|
||||
-
|
||||
- gdbpy_gil ()
|
||||
- : m_state (PyGILState_Ensure ())
|
||||
- {
|
||||
- }
|
||||
-
|
||||
- ~gdbpy_gil ()
|
||||
- {
|
||||
- PyGILState_Release (m_state);
|
||||
- }
|
||||
-
|
||||
- DISABLE_COPY_AND_ASSIGN (gdbpy_gil);
|
||||
-
|
||||
-private:
|
||||
-
|
||||
- PyGILState_STATE m_state;
|
||||
-};
|
||||
-
|
||||
/* Set the quit flag. */
|
||||
|
||||
static void
|
@@ -1,55 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Buettner <kevinb@redhat.com>
|
||||
Date: Mon, 29 Jan 2024 14:51:22 -0700
|
||||
Subject: gdb-rhbz2261580-intrusive_list-assertion-fix.patch
|
||||
|
||||
;; Backport upstream workaround for GCC 14 problem which cause assertion
|
||||
;; failures in GDB.
|
||||
|
||||
[gdb/build] Workaround gcc PR113599
|
||||
|
||||
Since gcc commit d3f48f68227 ("c++: non-dependent .* operand folding
|
||||
[PR112427]"), with gdb we run into PR gcc/113599 [1], a wrong-code bug, as
|
||||
reported in PR build/31281.
|
||||
|
||||
Work around this by flipping inherit order:
|
||||
...
|
||||
-class thread_info : public refcounted_object,
|
||||
- public intrusive_list_node<thread_info>
|
||||
+class thread_info : public intrusive_list_node<thread_info>,
|
||||
+ public refcounted_object
|
||||
...
|
||||
|
||||
An argument could be made that this isn't necessary, because this occurred in
|
||||
an unreleased gcc version.
|
||||
|
||||
However, I think it could be useful when bisecting gcc for other problems in
|
||||
building gdb. Having this workaround means the bisect won't reintroduce the
|
||||
problem. Furthermore, the workaround is harmless.
|
||||
|
||||
Tested on Fedora rawhide x86_64.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31281
|
||||
|
||||
[1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113599
|
||||
|
||||
diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
|
||||
--- a/gdb/gdbthread.h
|
||||
+++ b/gdb/gdbthread.h
|
||||
@@ -242,10 +242,11 @@ using private_thread_info_up = std::unique_ptr<private_thread_info>;
|
||||
strong reference, and is thus not accounted for in the thread's
|
||||
refcount.
|
||||
|
||||
- The intrusive_list_node base links threads in a per-inferior list. */
|
||||
+ The intrusive_list_node base links threads in a per-inferior list.
|
||||
+ We place it first in the inherit order to work around PR gcc/113599. */
|
||||
|
||||
-class thread_info : public refcounted_object,
|
||||
- public intrusive_list_node<thread_info>
|
||||
+class thread_info : public intrusive_list_node<thread_info>,
|
||||
+ public refcounted_object
|
||||
{
|
||||
public:
|
||||
explicit thread_info (inferior *inf, ptid_t ptid);
|
@@ -1,147 +0,0 @@
|
||||
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"
|
||||
+}
|
@@ -1,50 +0,0 @@
|
||||
From 6cfb7bf81be3ab6f131dbc6a27eefca516cf7517 Mon Sep 17 00:00:00 2001
|
||||
From: Andreas Arnez <arnez@linux.ibm.com>
|
||||
Date: Tue, 13 Feb 2024 18:55:29 +0100
|
||||
Subject: [PATCH 2/2] gdb: s390: Add arch14 record/replay support
|
||||
|
||||
Enable recording of the new "arch14" instructions on z/Architecture
|
||||
targets, except for the specialized-function-assist instruction NNPA.
|
||||
---
|
||||
gdb/s390-tdep.c | 13 +++++++++++++
|
||||
1 file changed, 13 insertions(+)
|
||||
|
||||
diff --git a/gdb/s390-tdep.c b/gdb/s390-tdep.c
|
||||
index 54b5c89e5e3..dcac407caef 100644
|
||||
--- a/gdb/s390-tdep.c
|
||||
+++ b/gdb/s390-tdep.c
|
||||
@@ -5534,6 +5534,14 @@ s390_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
|
||||
case 0xe635: /* VLRL - vector load rightmost with immed. length */
|
||||
case 0xe637: /* VLRLR - vector load rightmost with length */
|
||||
case 0xe649: /* VLIP - vector load immediate decimal */
|
||||
+ case 0xe656: /* VCLFNH - vector fp convert and lengthen from NNP high */
|
||||
+ case 0xe65e: /* VCLFNL - vector fp convert and lengthen from NNP low */
|
||||
+ case 0xe655: /* VCNF - vector fp convert to NNP */
|
||||
+ case 0xe65d: /* VCFN - vector fp convert from NNP */
|
||||
+ case 0xe674: /* VSCHP - decimal scale and convert to HFP */
|
||||
+ case 0xe675: /* VCRNF - vector fp convert and round to NNP */
|
||||
+ case 0xe67c: /* VSCSHP - decimal scale and convert and split to HFP */
|
||||
+ case 0xe67d: /* VCSPH - vector convert HFP to scaled decimal */
|
||||
case 0xe700: /* VLEB - vector load element */
|
||||
case 0xe701: /* VLEH - vector load element */
|
||||
case 0xe702: /* VLEG - vector load element */
|
||||
@@ -5791,11 +5799,16 @@ s390_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
|
||||
|
||||
/* 0xe747-0xe749 undefined */
|
||||
|
||||
+ case 0xe651: /* VCLZDP - vector count leading zero digits */
|
||||
+ case 0xe654: /* VUPKZH - vector unpack zoned high */
|
||||
case 0xe658: /* VCVD - vector convert to decimal 32 bit */
|
||||
case 0xe659: /* VSRP - vector shift and round decimal */
|
||||
case 0xe65a: /* VCVDG - vector convert to decimal 64 bit*/
|
||||
case 0xe65b: /* VPSOP - vector perform sign operation decimal */
|
||||
+ case 0xe65c: /* VUPKZL - vector unpack zoned low */
|
||||
+ case 0xe670: /* VPKZR - vector pack zoned register */
|
||||
case 0xe671: /* VAP - vector add decimal */
|
||||
+ case 0xe672: /* VSRPR - vector shift and round decimal register */
|
||||
case 0xe673: /* VSP - vector subtract decimal */
|
||||
case 0xe678: /* VMP - vector multiply decimal */
|
||||
case 0xe679: /* VMSP - vector multiply decimal */
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,162 +0,0 @@
|
||||
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"
|
@@ -1,125 +0,0 @@
|
||||
From aa8ba17b9a3fdfeeb65df4c3e0731a0e9e96cbf7 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Wed, 1 Nov 2023 00:33:12 +0100
|
||||
Subject: [PATCH 1/2] [gdb/symtab] Add producer_is_gas
|
||||
|
||||
Add producer_is_gas, a generic way to get the gas version from the
|
||||
producer string.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
---
|
||||
gdb/dwarf2/read.c | 4 ++--
|
||||
gdb/producer.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++
|
||||
gdb/producer.h | 5 +++++
|
||||
3 files changed, 63 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index 970dd54c7a5..472684a5817 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -13376,8 +13376,8 @@ check_producer (struct dwarf2_cu *cu)
|
||||
cu->producer_is_codewarrior = true;
|
||||
else if (producer_is_clang (cu->producer, &major, &minor))
|
||||
cu->producer_is_clang = true;
|
||||
- else if (startswith (cu->producer, "GNU AS 2.39.0"))
|
||||
- cu->producer_is_gas_2_39 = true;
|
||||
+ else if (producer_is_gas (cu->producer, &major, &minor))
|
||||
+ cu->producer_is_gas_2_39 = major == 2 && minor == 39;
|
||||
else
|
||||
{
|
||||
/* For other non-GCC compilers, expect their behavior is DWARF version
|
||||
diff --git a/gdb/producer.c b/gdb/producer.c
|
||||
index 9fcf749e3d4..cd83dfce128 100644
|
||||
--- a/gdb/producer.c
|
||||
+++ b/gdb/producer.c
|
||||
@@ -81,6 +81,45 @@ producer_is_gcc (const char *producer, int *major, int *minor)
|
||||
|
||||
/* See producer.h. */
|
||||
|
||||
+bool
|
||||
+producer_is_gas (const char *producer, int *major, int *minor)
|
||||
+{
|
||||
+ if (producer == nullptr)
|
||||
+ {
|
||||
+ /* No producer, don't know. */
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ /* Detect prefix. */
|
||||
+ const char prefix[] = "GNU AS ";
|
||||
+ if (!startswith (producer, prefix))
|
||||
+ {
|
||||
+ /* Producer is not gas. */
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ /* Skip prefix. */
|
||||
+ const char *cs = &producer[strlen (prefix)];
|
||||
+
|
||||
+ /* Ensure that major/minor are not nullptrs. */
|
||||
+ int maj, min;
|
||||
+ if (major == nullptr)
|
||||
+ major = &maj;
|
||||
+ if (minor == nullptr)
|
||||
+ minor = &min;
|
||||
+
|
||||
+ int scanned = sscanf (cs, "%d.%d", major, minor);
|
||||
+ if (scanned != 2)
|
||||
+ {
|
||||
+ /* Unable to scan major/minor version. */
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+ /* See producer.h. */
|
||||
+
|
||||
bool
|
||||
producer_is_icc_ge_19 (const char *producer)
|
||||
{
|
||||
@@ -251,6 +290,23 @@ Version 18.0 Beta";
|
||||
SELF_CHECK (!producer_is_gcc (flang_llvm_exp, &major, &minor));
|
||||
SELF_CHECK (producer_is_llvm (flang_llvm_exp));
|
||||
}
|
||||
+
|
||||
+ {
|
||||
+ static const char gas_exp[] = "GNU AS 2.39.0";
|
||||
+ int major = 0, minor = 0;
|
||||
+ SELF_CHECK (!producer_is_gcc (gas_exp, &major, &minor));
|
||||
+ SELF_CHECK (producer_is_gas (gas_exp, &major, &minor));
|
||||
+ SELF_CHECK (major == 2 && minor == 39);
|
||||
+
|
||||
+ static const char gas_incomplete_exp[] = "GNU AS ";
|
||||
+ SELF_CHECK (!producer_is_gas (gas_incomplete_exp, &major, &minor));
|
||||
+ SELF_CHECK (!producer_is_gcc (gas_incomplete_exp, &major, &minor));
|
||||
+
|
||||
+ static const char gas_incomplete_exp_2[] = "GNU AS 2";
|
||||
+ SELF_CHECK (!producer_is_gas (gas_incomplete_exp_2, &major, &minor));
|
||||
+ SELF_CHECK (!producer_is_gcc (gas_incomplete_exp_2, &major, &minor));
|
||||
+ }
|
||||
+
|
||||
}
|
||||
}
|
||||
}
|
||||
diff --git a/gdb/producer.h b/gdb/producer.h
|
||||
index c915979b122..00718511775 100644
|
||||
--- a/gdb/producer.h
|
||||
+++ b/gdb/producer.h
|
||||
@@ -30,6 +30,11 @@ extern int producer_is_gcc_ge_4 (const char *producer);
|
||||
is NULL or it isn't GCC. */
|
||||
extern int producer_is_gcc (const char *producer, int *major, int *minor);
|
||||
|
||||
+/* Returns nonzero if the given PRODUCER string is GAS and sets the MAJOR
|
||||
+ and MINOR versions when not NULL. Returns zero if the given PRODUCER
|
||||
+ is NULL or it isn't GAS. */
|
||||
+bool producer_is_gas (const char *producer, int *major, int *minor);
|
||||
+
|
||||
/* Check for Intel compilers >= 19.0. */
|
||||
extern bool producer_is_icc_ge_19 (const char *producer);
|
||||
|
||||
|
||||
base-commit: 39553c1e285c426946188ec2a890c1c1cb933060
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,74 +0,0 @@
|
||||
From 0218e033b415df76be0a14871447bbd94dce62a3 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Sat, 16 Sep 2023 04:07:22 +0200
|
||||
Subject: [PATCH 10/13] [gdb/symtab] Don't defer backward refs, inter-cu
|
||||
intra-shard case
|
||||
|
||||
In patch "[gdb/symtab] Resolve deferred entries, inter-shard case" we've
|
||||
solved the generic case of handling deferred entries.
|
||||
|
||||
Add an optimization that doesn't defer inter-CU intra-shard dependencies that
|
||||
are present in the shard's parent map.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
---
|
||||
gdb/dwarf2/read.c | 29 ++++++++++++++++++++++++++++-
|
||||
1 file changed, 28 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index a97f738a54e..e7904532434 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -4709,6 +4709,12 @@ class cooked_index_storage
|
||||
m_index->set_parent_valid (start, end);
|
||||
}
|
||||
|
||||
+ /* Return true if find_parents can be relied upon. */
|
||||
+ bool parent_valid (CORE_ADDR addr)
|
||||
+ {
|
||||
+ return m_index->parent_valid (addr);
|
||||
+ }
|
||||
+
|
||||
private:
|
||||
|
||||
/* Hash function for a cutu_reader. */
|
||||
@@ -4857,6 +4863,12 @@ class cooked_indexer
|
||||
{
|
||||
m_index_storage->set_parent_valid (start, end);
|
||||
}
|
||||
+
|
||||
+ /* Return true if find_parents can be relied upon. */
|
||||
+ bool parent_valid (CORE_ADDR addr)
|
||||
+ {
|
||||
+ return m_index_storage->parent_valid (addr);
|
||||
+ }
|
||||
};
|
||||
|
||||
/* Subroutine of dwarf2_build_psymtabs_hard to simplify it.
|
||||
@@ -16482,7 +16494,22 @@ cooked_indexer::scan_attributes (dwarf2_per_cu_data *scanning_per_cu,
|
||||
else
|
||||
{
|
||||
/* Inter-CU case. */
|
||||
- *maybe_defer = addr;
|
||||
+ if (parent_valid (addr))
|
||||
+ {
|
||||
+ auto tmp = find_parent (addr);
|
||||
+ if (tmp == &parent_map::deferred)
|
||||
+ {
|
||||
+ /* Defer because origin is deferred. */
|
||||
+ *maybe_defer = addr;
|
||||
+ }
|
||||
+ else
|
||||
+ *parent_entry = tmp;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /* Defer because origin is in other shard. */
|
||||
+ *maybe_defer = addr;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,76 +0,0 @@
|
||||
From 8a444a93d4bd78355fc4e6ecb1935cc2b0a6a997 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Fri, 15 Sep 2023 08:38:00 +0200
|
||||
Subject: [PATCH 04/13] [gdb/symtab] Factor out m_deferred_entries usage
|
||||
|
||||
Factor out usage of cooked_indexer::m_deferred_entries in new member
|
||||
functions defer_entry, handle_deferred_entries and resolve_deferred_entry.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
---
|
||||
gdb/dwarf2/read.c | 35 ++++++++++++++++++++++++++++-------
|
||||
1 file changed, 28 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index d48f3010063..afdf9e870a8 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -4822,6 +4822,32 @@ class cooked_indexer
|
||||
we'll know the containing context of all the DIEs that we might
|
||||
have scanned. This vector stores these deferred entries. */
|
||||
std::vector<deferred_entry> m_deferred_entries;
|
||||
+
|
||||
+ /* Defer creating a cooked_index_entry corresponding to deferred_entry DE. */
|
||||
+ void defer_entry (const deferred_entry &de)
|
||||
+ {
|
||||
+ m_deferred_entries.push_back (de);
|
||||
+ }
|
||||
+
|
||||
+ /* Create a cooked_index_entry corresponding to deferred_entry DE with
|
||||
+ parent PARENT_ENTRY. */
|
||||
+ const cooked_index_entry *resolve_deferred_entry
|
||||
+ (const deferred_entry &de, const cooked_index_entry *parent_entry)
|
||||
+ {
|
||||
+ return m_index_storage->add (de.die_offset, de.tag, de.flags, de.name,
|
||||
+ parent_entry, m_per_cu);
|
||||
+ }
|
||||
+
|
||||
+ /* Create cooked_index_entries for the deferred entries. */
|
||||
+ void handle_deferred_entries ()
|
||||
+ {
|
||||
+ for (const auto &entry : m_deferred_entries)
|
||||
+ {
|
||||
+ const cooked_index_entry *parent_entry
|
||||
+ = find_parent (entry.spec_offset);
|
||||
+ resolve_deferred_entry (entry, parent_entry);
|
||||
+ }
|
||||
+ }
|
||||
};
|
||||
|
||||
/* Subroutine of dwarf2_build_psymtabs_hard to simplify it.
|
||||
@@ -16611,7 +16637,7 @@ cooked_indexer::index_dies (cutu_reader *reader,
|
||||
if (name != nullptr)
|
||||
{
|
||||
if (defer != 0)
|
||||
- m_deferred_entries.push_back ({
|
||||
+ defer_entry ({
|
||||
this_die, name, defer, abbrev->tag, flags
|
||||
});
|
||||
else
|
||||
@@ -16716,12 +16742,7 @@ cooked_indexer::make_index (cutu_reader *reader)
|
||||
return;
|
||||
index_dies (reader, reader->info_ptr, nullptr, false);
|
||||
|
||||
- for (const auto &entry : m_deferred_entries)
|
||||
- {
|
||||
- const cooked_index_entry *parent = find_parent (entry.spec_offset);
|
||||
- m_index_storage->add (entry.die_offset, entry.tag, entry.flags,
|
||||
- entry.name, parent, m_per_cu);
|
||||
- }
|
||||
+ handle_deferred_entries ();
|
||||
}
|
||||
|
||||
/* An implementation of quick_symbol_functions for the cooked DWARF
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,151 +0,0 @@
|
||||
From b2f260d117dc11b8e90d4e9bf7f4b2cbd63d1d49 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Tue, 22 Aug 2023 13:17:47 +0200
|
||||
Subject: [PATCH 02/13] [gdb/symtab] Factor out m_die_range_map usage
|
||||
|
||||
Factor out usage of cooked_indexer::m_die_range_map into new class parent_map
|
||||
with member functions find_parent and set_parent, and static member function
|
||||
form_addr.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
---
|
||||
gdb/dwarf2/cooked-index.h | 32 +++++++++++++++++++++++++++
|
||||
gdb/dwarf2/read.c | 46 ++++++++++++++++++++-------------------
|
||||
2 files changed, 56 insertions(+), 22 deletions(-)
|
||||
|
||||
diff --git a/gdb/dwarf2/cooked-index.h b/gdb/dwarf2/cooked-index.h
|
||||
index 5aacb321c91..979541fbf60 100644
|
||||
--- a/gdb/dwarf2/cooked-index.h
|
||||
+++ b/gdb/dwarf2/cooked-index.h
|
||||
@@ -239,6 +239,38 @@ struct cooked_index_entry : public allocate_on_obstack
|
||||
bool for_name) const;
|
||||
};
|
||||
|
||||
+class parent_map
|
||||
+{
|
||||
+public:
|
||||
+ /* A helper function to turn a section offset into an address that
|
||||
+ can be used in a parent_map. */
|
||||
+ static CORE_ADDR form_addr (sect_offset offset, bool is_dwz)
|
||||
+ {
|
||||
+ CORE_ADDR value = to_underlying (offset);
|
||||
+ if (is_dwz)
|
||||
+ value |= ((CORE_ADDR) 1) << (8 * sizeof (CORE_ADDR) - 1);
|
||||
+ return value;
|
||||
+ }
|
||||
+
|
||||
+ /* Find the parent of DIE LOOKUP. */
|
||||
+ const cooked_index_entry *find_parent (CORE_ADDR lookup) const
|
||||
+ {
|
||||
+ const void *obj = m_parent_map.find (lookup);
|
||||
+ return static_cast<const cooked_index_entry *> (obj);
|
||||
+ }
|
||||
+
|
||||
+ /* Set the parent of DIES in range [START, END] to PARENT_ENTRY. */
|
||||
+ void set_parent (CORE_ADDR start, CORE_ADDR end,
|
||||
+ const cooked_index_entry *parent_entry)
|
||||
+ {
|
||||
+ m_parent_map.set_empty (start, end, (void *)parent_entry);
|
||||
+ }
|
||||
+
|
||||
+private:
|
||||
+ /* An addrmap that maps from section offsets to cooked_index_entry *. */
|
||||
+ addrmap_mutable m_parent_map;
|
||||
+};
|
||||
+
|
||||
class cooked_index;
|
||||
|
||||
/* An index of interesting DIEs. This is "cooked", in contrast to a
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index 466d3e59878..d48f3010063 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -4722,16 +4722,6 @@ class cooked_indexer
|
||||
|
||||
private:
|
||||
|
||||
- /* A helper function to turn a section offset into an address that
|
||||
- can be used in an addrmap. */
|
||||
- CORE_ADDR form_addr (sect_offset offset, bool is_dwz)
|
||||
- {
|
||||
- CORE_ADDR value = to_underlying (offset);
|
||||
- if (is_dwz)
|
||||
- value |= ((CORE_ADDR) 1) << (8 * sizeof (CORE_ADDR) - 1);
|
||||
- return value;
|
||||
- }
|
||||
-
|
||||
/* A helper function to scan the PC bounds of READER and record them
|
||||
in the storage's addrmap. */
|
||||
void check_bounds (cutu_reader *reader);
|
||||
@@ -4799,7 +4789,20 @@ class cooked_indexer
|
||||
/* An addrmap that maps from section offsets (see the form_addr
|
||||
method) to newly-created entries. See m_deferred_entries to
|
||||
understand this. */
|
||||
- addrmap_mutable m_die_range_map;
|
||||
+ parent_map m_die_range_map;
|
||||
+
|
||||
+ /* Find the parent of DIE LOOKUP. */
|
||||
+ const cooked_index_entry *find_parent (CORE_ADDR lookup) const
|
||||
+ {
|
||||
+ return m_die_range_map.find_parent (lookup);
|
||||
+ }
|
||||
+
|
||||
+ /* Set the parent of DIES in range [START, END] to PARENT_ENTRY. */
|
||||
+ void set_parent (CORE_ADDR start, CORE_ADDR end,
|
||||
+ const cooked_index_entry *parent_entry)
|
||||
+ {
|
||||
+ m_die_range_map.set_parent (start, end, parent_entry);
|
||||
+ }
|
||||
|
||||
/* A single deferred entry. */
|
||||
struct deferred_entry
|
||||
@@ -16412,15 +16415,13 @@ cooked_indexer::scan_attributes (dwarf2_per_cu_data *scanning_per_cu,
|
||||
|
||||
if (*parent_entry == nullptr)
|
||||
{
|
||||
- CORE_ADDR addr = form_addr (origin_offset, origin_is_dwz);
|
||||
+ CORE_ADDR addr
|
||||
+ = parent_map::form_addr (origin_offset, origin_is_dwz);
|
||||
if (new_reader->cu == reader->cu
|
||||
&& new_info_ptr > watermark_ptr)
|
||||
*maybe_defer = addr;
|
||||
else
|
||||
- {
|
||||
- void *obj = m_die_range_map.find (addr);
|
||||
- *parent_entry = static_cast <cooked_index_entry *> (obj);
|
||||
- }
|
||||
+ *parent_entry = find_parent (addr);
|
||||
}
|
||||
|
||||
unsigned int bytes_read;
|
||||
@@ -16538,11 +16539,13 @@ cooked_indexer::recurse (cutu_reader *reader,
|
||||
{
|
||||
/* Both start and end are inclusive, so use both "+ 1" and "- 1" to
|
||||
limit the range to the children of parent_entry. */
|
||||
- CORE_ADDR start = form_addr (parent_entry->die_offset + 1,
|
||||
- reader->cu->per_cu->is_dwz);
|
||||
- CORE_ADDR end = form_addr (sect_offset (info_ptr - 1 - reader->buffer),
|
||||
+ CORE_ADDR start
|
||||
+ = parent_map::form_addr (parent_entry->die_offset + 1,
|
||||
+ reader->cu->per_cu->is_dwz);
|
||||
+ CORE_ADDR end
|
||||
+ = parent_map::form_addr (sect_offset (info_ptr - 1 - reader->buffer),
|
||||
reader->cu->per_cu->is_dwz);
|
||||
- m_die_range_map.set_empty (start, end, (void *) parent_entry);
|
||||
+ set_parent (start, end, parent_entry);
|
||||
}
|
||||
|
||||
return info_ptr;
|
||||
@@ -16715,8 +16718,7 @@ cooked_indexer::make_index (cutu_reader *reader)
|
||||
|
||||
for (const auto &entry : m_deferred_entries)
|
||||
{
|
||||
- void *obj = m_die_range_map.find (entry.spec_offset);
|
||||
- cooked_index_entry *parent = static_cast<cooked_index_entry *> (obj);
|
||||
+ const cooked_index_entry *parent = find_parent (entry.spec_offset);
|
||||
m_index_storage->add (entry.die_offset, entry.tag, entry.flags,
|
||||
entry.name, parent, m_per_cu);
|
||||
}
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,112 +0,0 @@
|
||||
From c79ecacd3f75cfb0ec1a3afc49ca3f30b1759009 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Fri, 11 Aug 2023 01:36:50 +0200
|
||||
Subject: [PATCH 13/13] [gdb/symtab] Fix DW_TAG_inlined_subroutine entries in
|
||||
the cooked index
|
||||
|
||||
We get incorrect qualified names in the cooked index for
|
||||
DW_TAG_inlined_subroutine DIEs with abstract origin, due to the fact that the
|
||||
DIE parent is used instead of the abstract origin.
|
||||
|
||||
Fix this by preferring the abstract origin parent, if available.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
|
||||
PR symtab/30728
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30728
|
||||
---
|
||||
gdb/dwarf2/read.c | 67 ++++++++++++++++++++++-------------------------
|
||||
1 file changed, 32 insertions(+), 35 deletions(-)
|
||||
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index 93708ef11b9..a4f982962ae 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -16464,52 +16464,49 @@ cooked_indexer::scan_attributes (dwarf2_per_cu_data *scanning_per_cu,
|
||||
const gdb_byte *new_info_ptr = (new_reader->buffer
|
||||
+ to_underlying (origin_offset));
|
||||
|
||||
- if (*parent_entry == nullptr)
|
||||
+ gdb_assert (reader->cu->per_cu->is_debug_types
|
||||
+ == new_reader->cu->per_cu->is_debug_types);
|
||||
+ CORE_ADDR addr
|
||||
+ = parent_map::form_addr (origin_offset, origin_is_dwz,
|
||||
+ reader->cu->per_cu->is_debug_types);
|
||||
+ if (new_reader->cu == reader->cu)
|
||||
{
|
||||
- gdb_assert (reader->cu->per_cu->is_debug_types
|
||||
- == new_reader->cu->per_cu->is_debug_types);
|
||||
- CORE_ADDR addr
|
||||
- = parent_map::form_addr (origin_offset, origin_is_dwz,
|
||||
- reader->cu->per_cu->is_debug_types);
|
||||
- if (new_reader->cu == reader->cu)
|
||||
+ /* Intra-CU case. */
|
||||
+ if (new_info_ptr > watermark_ptr)
|
||||
{
|
||||
- /* Intra-CU case. */
|
||||
- if (new_info_ptr > watermark_ptr)
|
||||
- {
|
||||
- /* Defer because origin is not read yet. */
|
||||
- *maybe_defer = addr;
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- auto tmp = find_parent (addr);
|
||||
- if (tmp == &parent_map::deferred)
|
||||
- {
|
||||
- /* Defer because origin is deferred. */
|
||||
- *maybe_defer = addr;
|
||||
- }
|
||||
- else
|
||||
- *parent_entry = tmp;
|
||||
- }
|
||||
+ /* Defer because origin is not read yet. */
|
||||
+ *maybe_defer = addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
- /* Inter-CU case. */
|
||||
- if (parent_valid (addr))
|
||||
+ auto tmp = find_parent (addr);
|
||||
+ if (tmp == &parent_map::deferred)
|
||||
{
|
||||
- auto tmp = find_parent (addr);
|
||||
- if (tmp == &parent_map::deferred)
|
||||
- {
|
||||
- /* Defer because origin is deferred. */
|
||||
- *maybe_defer = addr;
|
||||
- }
|
||||
- else
|
||||
- *parent_entry = tmp;
|
||||
+ /* Defer because origin is deferred. */
|
||||
+ *maybe_defer = addr;
|
||||
}
|
||||
else
|
||||
+ *parent_entry = tmp;
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /* Inter-CU case. */
|
||||
+ if (parent_valid (addr))
|
||||
+ {
|
||||
+ auto tmp = find_parent (addr);
|
||||
+ if (tmp == &parent_map::deferred)
|
||||
{
|
||||
- /* Defer because origin is in other shard. */
|
||||
+ /* Defer because origin is deferred. */
|
||||
*maybe_defer = addr;
|
||||
}
|
||||
+ else
|
||||
+ *parent_entry = tmp;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /* Defer because origin is in other shard. */
|
||||
+ *maybe_defer = addr;
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.35.3
|
||||
|
337
gdb-symtab-fix-target-type-of-complex-long-double-on.patch
Normal file
337
gdb-symtab-fix-target-type-of-complex-long-double-on.patch
Normal file
@@ -0,0 +1,337 @@
|
||||
From e485fec626c14303a31bf7eab35c4288f9710c9d Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Wed, 19 Jun 2024 17:32:55 +0200
|
||||
Subject: [PATCH 07/46] [gdb/symtab] Fix target type of complex long double on
|
||||
arm
|
||||
|
||||
When running test-case gdb.base/complex-parts.exp on arm-linux, I get:
|
||||
...
|
||||
(gdb) p $_cimag (z3)^M
|
||||
$6 = 6.5^M
|
||||
(gdb) PASS: gdb.base/complex-parts.exp: long double imaginary: p $_cimag (z3)
|
||||
ptype $^M
|
||||
type = double^M
|
||||
(gdb) FAIL: gdb.base/complex-parts.exp: long double imaginary: ptype $
|
||||
...
|
||||
|
||||
Given that z3 is a complex long double, the test-case expects the type of the
|
||||
imaginary part of z3 to be long double, but it's double instead.
|
||||
|
||||
This is due to the fact that the dwarf info doesn't specify an explicit target
|
||||
type:
|
||||
...
|
||||
<5b> DW_AT_name : z3
|
||||
<60> DW_AT_type : <0xa4>
|
||||
...
|
||||
<1><a4>: Abbrev Number: 2 (DW_TAG_base_type)
|
||||
<a5> DW_AT_byte_size : 16
|
||||
<a6> DW_AT_encoding : 3 (complex float)
|
||||
<a7> DW_AT_name : complex long double
|
||||
...
|
||||
and consequently we're guessing in dwarf2_init_complex_target_type based on
|
||||
the size:
|
||||
...
|
||||
case 64:
|
||||
tt = builtin_type (gdbarch)->builtin_double;
|
||||
break;
|
||||
case 96: /* The x86-32 ABI specifies 96-bit long double. */
|
||||
case 128:
|
||||
tt = builtin_type (gdbarch)->builtin_long_double;
|
||||
break;
|
||||
...
|
||||
|
||||
For arm-linux, complex long double is 16 bytes, so the target type is assumed
|
||||
to be 8 bytes, which is handled by the "case 64", which gets us double
|
||||
instead of long double.
|
||||
|
||||
Fix this by searching for "long" in the name_hint parameter, and using long
|
||||
double instead.
|
||||
|
||||
Note that base types in dwarf are not allowed to contain references to other
|
||||
types, and the complex types are base types, so the missing explicit target
|
||||
type is standard-conformant.
|
||||
|
||||
A gcc PR was filed to add this as a dwarf extension (
|
||||
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115272 ).
|
||||
|
||||
Tested on arm-linux.
|
||||
---
|
||||
gdb/dwarf2/read.c | 10 +-
|
||||
.../gdb.dwarf2/dw2-complex-parts.exp | 244 ++++++++++++++++++
|
||||
2 files changed, 253 insertions(+), 1 deletion(-)
|
||||
create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-complex-parts.exp
|
||||
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index 7cd1d2b4c4e..18054d0070d 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -15123,7 +15123,15 @@ dwarf2_init_complex_target_type (struct dwarf2_cu *cu,
|
||||
tt = builtin_type (gdbarch)->builtin_float;
|
||||
break;
|
||||
case 64:
|
||||
- tt = builtin_type (gdbarch)->builtin_double;
|
||||
+ if (builtin_type (gdbarch)->builtin_long_double->length () == 8
|
||||
+ && name_hint != nullptr
|
||||
+ && strstr (name_hint, "long") != nullptr)
|
||||
+ {
|
||||
+ /* Use "long double" for "complex long double". */
|
||||
+ tt = builtin_type (gdbarch)->builtin_long_double;
|
||||
+ }
|
||||
+ else
|
||||
+ tt = builtin_type (gdbarch)->builtin_double;
|
||||
break;
|
||||
case 96: /* The x86-32 ABI specifies 96-bit long double. */
|
||||
case 128:
|
||||
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-complex-parts.exp b/gdb/testsuite/gdb.dwarf2/dw2-complex-parts.exp
|
||||
new file mode 100644
|
||||
index 00000000000..281e87d2fc8
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.dwarf2/dw2-complex-parts.exp
|
||||
@@ -0,0 +1,244 @@
|
||||
+# 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/>.
|
||||
+
|
||||
+# Test complex types, and their parts. Dwarf assembly counterpart of
|
||||
+# gdb.base/complex-parts.exp.
|
||||
+#
|
||||
+# In dwarf, base types are not allowed to have references to other types. And
|
||||
+# because complex types are modeled as base types, gdb has to figure out what
|
||||
+# the part type is.
|
||||
+#
|
||||
+# It would be easier for gdb if compilers would add a dwarf extension and
|
||||
+# supply this information, but that may or may not happen
|
||||
+# ( https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115272 ).
|
||||
+
|
||||
+load_lib dwarf.exp
|
||||
+
|
||||
+# This test can only be run on targets which support DWARF-2 and use gas.
|
||||
+require dwarf2_support
|
||||
+
|
||||
+standard_testfile main.c -debug.S
|
||||
+
|
||||
+if [prepare_for_testing "failed to prepare" $testfile \
|
||||
+ "${srcfile}" {}] {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+set float_size [get_sizeof float 0]
|
||||
+set double_size [get_sizeof double 0]
|
||||
+set long_double_size [get_sizeof "long double" 0]
|
||||
+
|
||||
+set int_size [get_sizeof int 0]
|
||||
+
|
||||
+# Create the DWARF.
|
||||
+set asm_file [standard_output_file $srcfile2]
|
||||
+Dwarf::assemble $asm_file {
|
||||
+ cu { version 2 } {
|
||||
+ compile_unit {} {
|
||||
+ # Main.
|
||||
+
|
||||
+ declare_labels int_type
|
||||
+
|
||||
+ int_type: DW_TAG_base_type {
|
||||
+ {DW_AT_byte_size $::int_size DW_FORM_sdata}
|
||||
+ {DW_AT_encoding @DW_ATE_signed}
|
||||
+ {DW_AT_name int}
|
||||
+ }
|
||||
+
|
||||
+ DW_TAG_subprogram {
|
||||
+ {MACRO_AT_func {main}}
|
||||
+ {type :$int_type}
|
||||
+ }
|
||||
+
|
||||
+ # GCC complex float.
|
||||
+
|
||||
+ declare_labels cf_type cd_type cld_type
|
||||
+
|
||||
+ cf_type: DW_TAG_base_type {
|
||||
+ {DW_AT_byte_size [expr 2 * $::float_size] DW_FORM_sdata}
|
||||
+ {DW_AT_encoding @DW_ATE_complex_float}
|
||||
+ {DW_AT_name "complex float"}
|
||||
+ }
|
||||
+
|
||||
+ cd_type: DW_TAG_base_type {
|
||||
+ {DW_AT_byte_size [expr 2 * $::double_size] DW_FORM_sdata}
|
||||
+ {DW_AT_encoding @DW_ATE_complex_float}
|
||||
+ {DW_AT_name "complex double"}
|
||||
+ }
|
||||
+
|
||||
+ cld_type: DW_TAG_base_type {
|
||||
+ {DW_AT_byte_size [expr 2 * $::long_double_size] DW_FORM_sdata}
|
||||
+ {DW_AT_encoding @DW_ATE_complex_float}
|
||||
+ {DW_AT_name "complex long double"}
|
||||
+ }
|
||||
+
|
||||
+ DW_TAG_variable {
|
||||
+ {name var_complex_float}
|
||||
+ {DW_AT_type :$cf_type}
|
||||
+ }
|
||||
+
|
||||
+ DW_TAG_variable {
|
||||
+ {name var_complex_double}
|
||||
+ {DW_AT_type :$cd_type}
|
||||
+ }
|
||||
+
|
||||
+ DW_TAG_variable {
|
||||
+ {name var_complex_long_double}
|
||||
+ {DW_AT_type :$cld_type}
|
||||
+ }
|
||||
+
|
||||
+ # GCC complex int.
|
||||
+ # This is what gcc currently generates, see gcc PR debug/93988.
|
||||
+
|
||||
+ declare_labels ci_type
|
||||
+
|
||||
+ ci_type: DW_TAG_base_type {
|
||||
+ {DW_AT_byte_size [expr 2 * $::int_size] DW_FORM_sdata}
|
||||
+ {DW_AT_encoding @DW_ATE_lo_user}
|
||||
+ {DW_AT_name "complex int"}
|
||||
+ }
|
||||
+
|
||||
+ DW_TAG_variable {
|
||||
+ {name var_complex_int}
|
||||
+ {DW_AT_type :$ci_type}
|
||||
+ }
|
||||
+
|
||||
+ # Clang complex float.
|
||||
+ # This is what clang currently generates, see this issue (
|
||||
+ # https://github.com/llvm/llvm-project/issues/52996 ).
|
||||
+
|
||||
+ declare_labels clang_cf_type clang_cd_type clang_cld_type
|
||||
+
|
||||
+ clang_cf_type: DW_TAG_base_type {
|
||||
+ {DW_AT_byte_size [expr 2 * $::float_size] DW_FORM_sdata}
|
||||
+ {DW_AT_encoding @DW_ATE_complex_float}
|
||||
+ {DW_AT_name "complex"}
|
||||
+ }
|
||||
+
|
||||
+ DW_TAG_variable {
|
||||
+ {name var_complex_clang_float}
|
||||
+ {DW_AT_type :$clang_cf_type}
|
||||
+ }
|
||||
+
|
||||
+ clang_cd_type: DW_TAG_base_type {
|
||||
+ {DW_AT_byte_size [expr 2 * $::double_size] DW_FORM_sdata}
|
||||
+ {DW_AT_encoding @DW_ATE_complex_float}
|
||||
+ {DW_AT_name "complex"}
|
||||
+ }
|
||||
+
|
||||
+ DW_TAG_variable {
|
||||
+ {name var_complex_clang_double}
|
||||
+ {DW_AT_type :$clang_cd_type}
|
||||
+ }
|
||||
+
|
||||
+ clang_cld_type: DW_TAG_base_type {
|
||||
+ {DW_AT_byte_size [expr 2 * $::long_double_size] DW_FORM_sdata}
|
||||
+ {DW_AT_encoding @DW_ATE_complex_float}
|
||||
+ {DW_AT_name "complex"}
|
||||
+ }
|
||||
+
|
||||
+ DW_TAG_variable {
|
||||
+ {name var_complex_clang_long_double}
|
||||
+ {DW_AT_type :$clang_cld_type}
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+if [prepare_for_testing "failed to prepare" $testfile \
|
||||
+ "${asm_file} ${srcfile}" {}] {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+if ![runto_main] {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+proc do_test { type {clang 0}} {
|
||||
+ with_test_prefix $type {
|
||||
+ with_test_prefix clang=$clang {
|
||||
+
|
||||
+ if { $clang } {
|
||||
+ set type_id [regsub -all " " $type _]
|
||||
+ set var "var_complex_clang_$type_id"
|
||||
+
|
||||
+ # Gdb could try to synthesize better names, see enhancement
|
||||
+ # PR symtab/31858.
|
||||
+ set ctype "complex"
|
||||
+ set ctype_id "complex"
|
||||
+ } else {
|
||||
+ set ctype "complex $type"
|
||||
+ set type_id [regsub -all " " $type _]
|
||||
+ set ctype_id [regsub -all " " $ctype _]
|
||||
+ set var "var_$ctype_id"
|
||||
+ }
|
||||
+
|
||||
+ gdb_test "ptype '$type'" \
|
||||
+ "type = $type"
|
||||
+
|
||||
+ gdb_test "ptype '$ctype'" \
|
||||
+ "type = $ctype"
|
||||
+
|
||||
+ eval set type_size \$::${type_id}_size
|
||||
+
|
||||
+ gdb_test "p sizeof ('$type')" \
|
||||
+ " = $type_size"
|
||||
+
|
||||
+ if { ! $clang } {
|
||||
+ # With clang, the ctype name does not uniquely map to a type,
|
||||
+ # so the size is unpredictable.
|
||||
+ gdb_test "p sizeof ('$ctype')" \
|
||||
+ " = [expr 2 * $type_size]"
|
||||
+ }
|
||||
+
|
||||
+ set re_kfail \
|
||||
+ [string_to_regexp \
|
||||
+ "'var_complex_int' has unknown type; cast it to its declared type"]
|
||||
+
|
||||
+ foreach f { {$_cimag} {$_creal} } {
|
||||
+ gdb_test_multiple "p $f ($var)" "" {
|
||||
+ -re -wrap " = <optimized out>" {
|
||||
+ pass $gdb_test_name
|
||||
+ }
|
||||
+ -re -wrap $re_kfail {
|
||||
+ kfail gdb/31857 $gdb_test_name
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if { $clang } {
|
||||
+ # Without a specific complex type name, it's
|
||||
+ # unpredictable which type name the part will have.
|
||||
+ gdb_test {ptype $} \
|
||||
+ "type = (float|double|long double)" \
|
||||
+ "ptype $f"
|
||||
+ } else {
|
||||
+ gdb_test {ptype $} \
|
||||
+ "type = $type" \
|
||||
+ "ptype $f"
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+do_test "float"
|
||||
+do_test "double"
|
||||
+do_test "long double"
|
||||
+
|
||||
+do_test "int"
|
||||
+
|
||||
+do_test "float" 1
|
||||
+do_test "double" 1
|
||||
+do_test "long double" 1
|
||||
--
|
||||
2.43.0
|
||||
|
@@ -1,37 +0,0 @@
|
||||
From bc970668f83cf142c4955d1cbeaa24e8bcc4b238 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Fri, 25 Aug 2023 09:30:54 +0200
|
||||
Subject: [PATCH 03/13] [gdb/symtab] Handle nullptr parent in
|
||||
parent_map::set_parent
|
||||
|
||||
Set_parent uses m_die_range_map.set_empty, which doesn't allow
|
||||
parent_entry == nullptr.
|
||||
|
||||
So it may be necessary to guard calls to set_parent with
|
||||
"if (parent_entry != nullptr)".
|
||||
|
||||
Fix this by handling the parent_entry == nullptr case in set_parent.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
---
|
||||
gdb/dwarf2/cooked-index.h | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/dwarf2/cooked-index.h b/gdb/dwarf2/cooked-index.h
|
||||
index 979541fbf60..79fbfe88c03 100644
|
||||
--- a/gdb/dwarf2/cooked-index.h
|
||||
+++ b/gdb/dwarf2/cooked-index.h
|
||||
@@ -263,7 +263,9 @@ class parent_map
|
||||
void set_parent (CORE_ADDR start, CORE_ADDR end,
|
||||
const cooked_index_entry *parent_entry)
|
||||
{
|
||||
- m_parent_map.set_empty (start, end, (void *)parent_entry);
|
||||
+ /* Calling set_empty with nullptr is currently not allowed. */
|
||||
+ if (parent_entry != nullptr)
|
||||
+ m_parent_map.set_empty (start, end, (void *)parent_entry);
|
||||
}
|
||||
|
||||
private:
|
||||
--
|
||||
2.35.3
|
||||
|
@@ -1,38 +0,0 @@
|
||||
From 0e706742f37ee90629350780263b573f326f1a5f Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Thu, 7 Dec 2023 10:38:05 +0100
|
||||
Subject: [PATCH 12/13] [gdb/symtab] Keep track of all parents for cooked index
|
||||
|
||||
Keep track of all parents for cooked index.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
---
|
||||
gdb/dwarf2/read.c | 12 +++++++++---
|
||||
1 file changed, 9 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index de7b655d26c..93708ef11b9 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -16718,9 +16718,15 @@ cooked_indexer::index_dies (cutu_reader *reader,
|
||||
});
|
||||
}
|
||||
else
|
||||
- this_entry = m_index_storage->add (this_die, abbrev->tag, flags,
|
||||
- name, this_parent_entry,
|
||||
- m_per_cu);
|
||||
+ {
|
||||
+ CORE_ADDR addr
|
||||
+ = parent_map::form_addr (this_die, reader->cu->per_cu->is_dwz,
|
||||
+ reader->cu->per_cu->is_debug_types);
|
||||
+ set_parent (addr, addr, this_parent_entry);
|
||||
+ this_entry = m_index_storage->add (this_die, abbrev->tag, flags,
|
||||
+ name, this_parent_entry,
|
||||
+ m_per_cu);
|
||||
+ }
|
||||
}
|
||||
|
||||
if (linkage_name != nullptr)
|
||||
--
|
||||
2.35.3
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user