* [PATCH] gdb/dwarf: filter discarded zero-address variables after relocation
@ 2026-10-09 17:46 Longjun Luo
2026-10-16 4:00 ` [PATCH v2] " Longjun Luo
0 siblings, 1 reply; 4+ messages in thread
From: Longjun Luo @ 2026-10-09 17:46 UTC (permalink / raw)
To: gdb-patches; +Cc: Tom Tromey, Simon Marchi
A variable discarded by section GC can retain a DIE with a zero DWARF
address. var_decode_location adds the section offset before new_symbol
checks that address. If the objfile has already been relocated, the
symbol survives the zero-address check and can read the ELF header as
data.
This affects PIE executables when the CU is first expanded after
starting the program. It also affects normally loaded shared libraries,
including with --readnow, because their objfiles already have a load
offset.
Have var_decode_location return the address it decoded before
relocation, and check that address in new_symbol, as the DWARF reader
already does for discarded functions and address ranges. Preserve the
existing exception for objects with allocated sections at zero.
Extend gdb.dwarf2/dw2-var-zero-addr.exp with a PIE whose CU is first
expanded after starting the program, and with a loaded shared library,
with and without --readnow.
Tested on x86_64 GNU/Linux with GCC. Without the fix, the three new
cases fail; with it, the test passes. GDB selftests pass.
Signed-off-by: Longjun Luo <luolongjuna@gmail.com>
---
I do not have an FSF copyright assignment for GDB. I contribute to
GCC under the DCO and have signed off this patch. Please let me know
if any additional paperwork is needed for GDB.
This came up while working on a DWARF proposal about post-link
addresses [1]. The fix does not depend on the proposal.
Tested on x86_64 GNU/Linux with Python enabled and --enable-werror.
The revised regression passes with GCC, Clang and cc-with-gdb-index;
all three new cases fail on the GCC baseline. Earlier full gdb.dwarf2
testing of the same implementation found no new unexpected failures;
the existing debug-frame Tcl errors were unchanged. All 195
selftests passed.
[1] https://lists.dwarfstd.org/pipermail/dwarf-discuss/2026-September/002859.html
gdb/dwarf2/read.c | 27 +++++----
.../gdb.dwarf2/dw2-var-zero-addr.exp | 55 ++++++++++++++++++-
2 files changed, 71 insertions(+), 11 deletions(-)
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 1fc6d7ffb4f..48c1100b645 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -514,9 +514,8 @@ show_dwarf_synchronous (struct ui_file *file, int from_tty,
\f
/* local function prototypes */
-static void var_decode_location (struct attribute *attr,
- struct symbol *sym,
- struct dwarf2_cu *cu);
+static std::optional<unrelocated_addr> var_decode_location
+ (struct attribute *attr, struct symbol *sym, struct dwarf2_cu *cu);
static unsigned int peek_abbrev_code (bfd *, const gdb_byte *);
@@ -15160,7 +15159,11 @@ dwarf_decode_line_header (sect_offset sect_off, struct dwarf2_cu *cu,
&cu->header, comp_dir);
}
-static void
+/* Decode the DW_AT_location attribute ATTR of SYM. If ATTR is a single
+ DW_OP_addr, DW_OP_addrx or DW_OP_GNU_addr_index, return its address
+ before relocation. */
+
+static std::optional<unrelocated_addr>
var_decode_location (struct attribute *attr, struct symbol *sym,
struct dwarf2_cu *cu)
{
@@ -15182,7 +15185,7 @@ var_decode_location (struct attribute *attr, struct symbol *sym,
if (attr->form_is_block () && attr->as_block ()->size == 0)
{
sym->set_loc_class_index (LOC_OPTIMIZED_OUT);
- return;
+ return {};
}
/* Handle one degenerate form of location expression specially, to
@@ -15216,7 +15219,7 @@ var_decode_location (struct attribute *attr, struct symbol *sym,
sym->set_value_address
(sym->value_address ()
+ objfile->section_offsets[sym->section_index ()]);
- return;
+ return tem;
}
}
@@ -15231,6 +15234,8 @@ var_decode_location (struct attribute *attr, struct symbol *sym,
if (sym->computed_ops ()->location_has_loclist)
cu->has_loclist = true;
+
+ return {};
}
/* A helper function to add an "export" symbol. The new symbol starts
@@ -15482,7 +15487,8 @@ new_symbol (struct die_info *die, struct dwarf2_cu *cu, struct symbol *sym,
attr = dwarf2_attr (die, DW_AT_location, cu);
if (attr != nullptr)
{
- var_decode_location (attr, sym, cu);
+ std::optional<unrelocated_addr> unrelocated
+ = var_decode_location (attr, sym, cu);
attr2 = dwarf2_attr (die, DW_AT_external, cu);
/* Fortran explicitly imports any global symbols to the local
@@ -15491,14 +15497,15 @@ new_symbol (struct die_info *die, struct dwarf2_cu *cu, struct symbol *sym,
&& die->parent->tag == DW_TAG_common_block)
attr2 = nullptr;
- if (sym->loc_class () == LOC_STATIC
- && sym->value_address () == 0
+ if (unrelocated == (unrelocated_addr) 0
&& !per_objfile->per_bfd->has_section_at_zero)
{
/* When a static variable is eliminated by the linker,
the corresponding debug information is not stripped
out, but the variable address is set to null;
- do not add such variables into symbol table. */
+ do not add such variables into symbol table. Check
+ the address before relocation, which adds the load
+ offset of a PIE or shared library. */
}
else if (attr2 != nullptr && attr2->as_boolean ())
{
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-var-zero-addr.exp b/gdb/testsuite/gdb.dwarf2/dw2-var-zero-addr.exp
index 04a2aa06ea9..027a073d7e0 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-var-zero-addr.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-var-zero-addr.exp
@@ -25,7 +25,7 @@ if {[prepare_for_testing "failed to prepare" ${testfile} \
}
proc test { } {
- # FAIL was: = (int *) 0x0
+ # FAIL was: = (int *) 0x0, or the load address in a relocated objfile.
# Such DIE record can be produced using: gcc -fdata-sections -Wl,-gc-sections
gdb_test "print &var" {No symbol "var" in current context\.}
}
@@ -40,3 +40,56 @@ save_vars { GDBFLAGS } {
with_test_prefix "readnow" {
test
}
+
+# Expand the CU for the first time after the PIE has been relocated.
+proc_with_prefix test_pie_after_run {} {
+ set executable ${::testfile}-pie
+ if {[build_executable "failed to prepare" $executable \
+ [list $::srcfile $::srcfile2] {nodebug pie}]} {
+ return
+ }
+
+ clean_restart $executable
+ if {[runto_main]} {
+ test
+ }
+}
+
+# A shared library is relocated before its CUs are expanded, even with
+# --readnow.
+proc_with_prefix test_shlib {} {
+ set lib_path [standard_output_file ${::testfile}-shlib.so]
+ if {[gdb_compile_shlib $::srcdir/$::subdir/$::srcfile $lib_path \
+ {nodebug}] != ""} {
+ untested "failed to compile shared library"
+ return
+ }
+
+ set executable ${::testfile}-shlib
+ if {[build_executable "failed to prepare" $executable $::srcfile2 \
+ [list debug shlib=$lib_path]]} {
+ return
+ }
+
+ foreach_with_prefix readnow {false true} {
+ save_vars { ::GDBFLAGS } {
+ if {$readnow} {
+ append ::GDBFLAGS " --readnow"
+ }
+ clean_restart $executable
+ }
+ gdb_load_shlib $lib_path
+ if {[runto_main]} {
+ set lib_name [file tail $lib_path]
+ gdb_test "info sharedlibrary $lib_name" \
+ ".*Yes.*[string_to_regexp $lib_name]" \
+ "shared library is loaded"
+ test
+ }
+ }
+}
+
+test_pie_after_run
+
+require allow_shlib_tests
+test_shlib
--
2.53.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v2] gdb/dwarf: filter discarded zero-address variables after relocation
2026-10-09 17:46 [PATCH] gdb/dwarf: filter discarded zero-address variables after relocation Longjun Luo
@ 2026-10-16 4:00 ` Longjun Luo
2026-10-18 23:29 ` Kevin Buettner
2026-10-27 8:27 ` [PATCH v3] " Longjun Luo
0 siblings, 2 replies; 4+ messages in thread
From: Longjun Luo @ 2026-10-16 4:00 UTC (permalink / raw)
To: gdb-patches; +Cc: Longjun Luo
A variable discarded by section GC can retain a DIE with a zero DWARF
address. var_decode_location adds the section offset before new_symbol
checks that address. If the objfile has already been relocated, the
symbol survives the zero-address check and can read the ELF header as
data.
This affects PIE executables when the CU is first expanded after
starting the program. It also affects normally loaded shared libraries,
including with --readnow, because their objfiles already have a load
offset.
Have var_decode_location return the address it decoded before
relocation, and check that address in new_symbol, as the DWARF reader
already does for discarded functions and address ranges. Preserve the
existing exception for objects with allocated sections at zero.
Extend gdb.dwarf2/dw2-var-zero-addr.exp with a PIE whose CU is first
expanded after starting the program, and with a loaded shared library,
with and without --readnow. Use a distinctive variable name to avoid
clashes with shared-library debug symbols after the program starts.
Tested on x86_64 GNU/Linux with GCC. Without the fix, the three new
cases fail; with it, the test passes. GDB selftests pass.
Signed-off-by: Longjun Luo <luolongjuna@gmail.com>
---
v1: https://inbox.sourceware.org/gdb-patches/20261009174623.2894733-1-luolongjuna@gmail.com/
Changes in v2:
- Use a test-specific variable name to avoid clashes with symbols from
shared-library debug information. No reader changes.
Linaro CI on ARM and AArch64 reported failures in the three new cases:
(gdb) print &var
Can't take address of "var" which isn't an lvalue.
After the discarded test variable is filtered out, the lookup can
find an unrelated symbol with the same name. I reproduced this on
x86_64 with a same-named enumerator in shared-library debug
information. The renamed test passes with and without those symbols.
Re-tested on x86_64 GNU/Linux with GCC, Clang and cc-with-gdb-index
(7 PASS each). The three added cases still fail without the fix.
All 195 selftests pass. A full native testsuite comparison, with
differing cases rechecked, found no new regressions; existing failures
and test-driver errors remained in both variants.
As in v1, I do not have an FSF copyright assignment for GDB and have
signed off this patch under the DCO.
gdb/dwarf2/read.c | 27 +++++----
gdb/testsuite/gdb.dwarf2/dw2-var-zero-addr.S | 2 +-
.../gdb.dwarf2/dw2-var-zero-addr.exp | 60 ++++++++++++++++++-
3 files changed, 76 insertions(+), 13 deletions(-)
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 1fc6d7ffb4f..48c1100b645 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -514,9 +514,8 @@ show_dwarf_synchronous (struct ui_file *file, int from_tty,
\f
/* local function prototypes */
-static void var_decode_location (struct attribute *attr,
- struct symbol *sym,
- struct dwarf2_cu *cu);
+static std::optional<unrelocated_addr> var_decode_location
+ (struct attribute *attr, struct symbol *sym, struct dwarf2_cu *cu);
static unsigned int peek_abbrev_code (bfd *, const gdb_byte *);
@@ -15160,7 +15159,11 @@ dwarf_decode_line_header (sect_offset sect_off, struct dwarf2_cu *cu,
&cu->header, comp_dir);
}
-static void
+/* Decode the DW_AT_location attribute ATTR of SYM. If ATTR is a single
+ DW_OP_addr, DW_OP_addrx or DW_OP_GNU_addr_index, return its address
+ before relocation. */
+
+static std::optional<unrelocated_addr>
var_decode_location (struct attribute *attr, struct symbol *sym,
struct dwarf2_cu *cu)
{
@@ -15182,7 +15185,7 @@ var_decode_location (struct attribute *attr, struct symbol *sym,
if (attr->form_is_block () && attr->as_block ()->size == 0)
{
sym->set_loc_class_index (LOC_OPTIMIZED_OUT);
- return;
+ return {};
}
/* Handle one degenerate form of location expression specially, to
@@ -15216,7 +15219,7 @@ var_decode_location (struct attribute *attr, struct symbol *sym,
sym->set_value_address
(sym->value_address ()
+ objfile->section_offsets[sym->section_index ()]);
- return;
+ return tem;
}
}
@@ -15231,6 +15234,8 @@ var_decode_location (struct attribute *attr, struct symbol *sym,
if (sym->computed_ops ()->location_has_loclist)
cu->has_loclist = true;
+
+ return {};
}
/* A helper function to add an "export" symbol. The new symbol starts
@@ -15482,7 +15487,8 @@ new_symbol (struct die_info *die, struct dwarf2_cu *cu, struct symbol *sym,
attr = dwarf2_attr (die, DW_AT_location, cu);
if (attr != nullptr)
{
- var_decode_location (attr, sym, cu);
+ std::optional<unrelocated_addr> unrelocated
+ = var_decode_location (attr, sym, cu);
attr2 = dwarf2_attr (die, DW_AT_external, cu);
/* Fortran explicitly imports any global symbols to the local
@@ -15491,14 +15497,15 @@ new_symbol (struct die_info *die, struct dwarf2_cu *cu, struct symbol *sym,
&& die->parent->tag == DW_TAG_common_block)
attr2 = nullptr;
- if (sym->loc_class () == LOC_STATIC
- && sym->value_address () == 0
+ if (unrelocated == (unrelocated_addr) 0
&& !per_objfile->per_bfd->has_section_at_zero)
{
/* When a static variable is eliminated by the linker,
the corresponding debug information is not stripped
out, but the variable address is set to null;
- do not add such variables into symbol table. */
+ do not add such variables into symbol table. Check
+ the address before relocation, which adds the load
+ offset of a PIE or shared library. */
}
else if (attr2 != nullptr && attr2->as_boolean ())
{
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-var-zero-addr.S b/gdb/testsuite/gdb.dwarf2/dw2-var-zero-addr.S
index f7394f33946..233bd6ce79e 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-var-zero-addr.S
+++ b/gdb/testsuite/gdb.dwarf2/dw2-var-zero-addr.S
@@ -39,7 +39,7 @@
.byte 5 /* DW_AT_encoding */
.uleb128 3 /* Abbrev: DW_TAG_variable (location) */
- .ascii "var\0" /* DW_AT_name */
+ .ascii "dw2_discarded_zero_addr_var\0" /* DW_AT_name */
.byte 2f - 1f /* DW_AT_location */
1: .byte 3 /* DW_OP_addr */
.4byte 0 /* <addr> */
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-var-zero-addr.exp b/gdb/testsuite/gdb.dwarf2/dw2-var-zero-addr.exp
index 04a2aa06ea9..360894661e5 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-var-zero-addr.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-var-zero-addr.exp
@@ -25,9 +25,12 @@ if {[prepare_for_testing "failed to prepare" ${testfile} \
}
proc test { } {
- # FAIL was: = (int *) 0x0
+ # FAIL was: = (int *) 0x0, or the load address in a relocated objfile.
# Such DIE record can be produced using: gcc -fdata-sections -Wl,-gc-sections
- gdb_test "print &var" {No symbol "var" in current context\.}
+ # Use a distinctive name to avoid clashes with shared-library debug
+ # symbols once the program runs.
+ gdb_test "print &dw2_discarded_zero_addr_var" \
+ {No symbol "dw2_discarded_zero_addr_var" in current context\.}
}
test
@@ -40,3 +43,56 @@ save_vars { GDBFLAGS } {
with_test_prefix "readnow" {
test
}
+
+# Expand the CU for the first time after the PIE has been relocated.
+proc_with_prefix test_pie_after_run {} {
+ set executable ${::testfile}-pie
+ if {[build_executable "failed to prepare" $executable \
+ [list $::srcfile $::srcfile2] {nodebug pie}]} {
+ return
+ }
+
+ clean_restart $executable
+ if {[runto_main]} {
+ test
+ }
+}
+
+# A shared library is relocated before its CUs are expanded, even with
+# --readnow.
+proc_with_prefix test_shlib {} {
+ set lib_path [standard_output_file ${::testfile}-shlib.so]
+ if {[gdb_compile_shlib $::srcdir/$::subdir/$::srcfile $lib_path \
+ {nodebug}] != ""} {
+ untested "failed to compile shared library"
+ return
+ }
+
+ set executable ${::testfile}-shlib
+ if {[build_executable "failed to prepare" $executable $::srcfile2 \
+ [list debug shlib=$lib_path]]} {
+ return
+ }
+
+ foreach_with_prefix readnow {false true} {
+ save_vars { ::GDBFLAGS } {
+ if {$readnow} {
+ append ::GDBFLAGS " --readnow"
+ }
+ clean_restart $executable
+ }
+ gdb_load_shlib $lib_path
+ if {[runto_main]} {
+ set lib_name [file tail $lib_path]
+ gdb_test "info sharedlibrary $lib_name" \
+ ".*Yes.*[string_to_regexp $lib_name]" \
+ "shared library is loaded"
+ test
+ }
+ }
+}
+
+test_pie_after_run
+
+require allow_shlib_tests
+test_shlib
--
2.55.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v2] gdb/dwarf: filter discarded zero-address variables after relocation
2026-10-16 4:00 ` [PATCH v2] " Longjun Luo
@ 2026-10-18 23:29 ` Kevin Buettner
2026-10-27 8:27 ` [PATCH v3] " Longjun Luo
1 sibling, 0 replies; 4+ messages in thread
From: Kevin Buettner @ 2026-10-18 23:29 UTC (permalink / raw)
To: Longjun Luo, gdb-patches
Hi Longjun,
This looks pretty good. I just have a few nits...
On 10/15/26 9:00 PM, Longjun Luo wrote:
> A variable discarded by section GC can retain a DIE with a zero DWARF
> address. var_decode_location adds the section offset before new_symbol
> checks that address. If the objfile has already been relocated, the
> symbol survives the zero-address check and can read the ELF header as
> data.
>
> This affects PIE executables when the CU is first expanded after
> starting the program. It also affects normally loaded shared libraries,
> including with --readnow, because their objfiles already have a load
> offset.
>
> Have var_decode_location return the address it decoded before
> relocation, and check that address in new_symbol, as the DWARF reader
> already does for discarded functions and address ranges. Preserve the
> existing exception for objects with allocated sections at zero.
>
> Extend gdb.dwarf2/dw2-var-zero-addr.exp with a PIE whose CU is first
> expanded after starting the program, and with a loaded shared library,
> with and without --readnow. Use a distinctive variable name to avoid
> clashes with shared-library debug symbols after the program starts.
>
> Tested on x86_64 GNU/Linux with GCC. Without the fix, the three new
> cases fail; with it, the test passes. GDB selftests pass.
>
> Signed-off-by: Longjun Luo <luolongjuna@gmail.com>
> ---
> v1: https://inbox.sourceware.org/gdb-patches/20261009174623.2894733-1-luolongjuna@gmail.com/
>
> Changes in v2:
> - Use a test-specific variable name to avoid clashes with symbols from
> shared-library debug information. No reader changes.
>
> Linaro CI on ARM and AArch64 reported failures in the three new cases:
>
> (gdb) print &var
> Can't take address of "var" which isn't an lvalue.
>
> After the discarded test variable is filtered out, the lookup can
> find an unrelated symbol with the same name. I reproduced this on
> x86_64 with a same-named enumerator in shared-library debug
> information. The renamed test passes with and without those symbols.
>
> Re-tested on x86_64 GNU/Linux with GCC, Clang and cc-with-gdb-index
> (7 PASS each). The three added cases still fail without the fix.
> All 195 selftests pass. A full native testsuite comparison, with
> differing cases rechecked, found no new regressions; existing failures
> and test-driver errors remained in both variants.
>
> As in v1, I do not have an FSF copyright assignment for GDB and have
> signed off this patch under the DCO.
The GDB project does not yet accept contributions under the DCO. (It's
something which is under discussion though; I'd very much like to see it
happen.)
IMO, this fix is of a size that is "legally significant". We'll need a
copyright assignment, I think.
> gdb/dwarf2/read.c | 27 +++++----
> gdb/testsuite/gdb.dwarf2/dw2-var-zero-addr.S | 2 +-
> .../gdb.dwarf2/dw2-var-zero-addr.exp | 60 ++++++++++++++++++-
> 3 files changed, 76 insertions(+), 13 deletions(-)
>
> diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
> index 1fc6d7ffb4f..48c1100b645 100644
> --- a/gdb/dwarf2/read.c
> +++ b/gdb/dwarf2/read.c
> @@ -514,9 +514,8 @@ show_dwarf_synchronous (struct ui_file *file, int from_tty,
> \f
> /* local function prototypes */
>
> -static void var_decode_location (struct attribute *attr,
> - struct symbol *sym,
> - struct dwarf2_cu *cu);
> +static std::optional<unrelocated_addr> var_decode_location
> + (struct attribute *attr, struct symbol *sym, struct dwarf2_cu *cu);
>
> static unsigned int peek_abbrev_code (bfd *, const gdb_byte *);
>
> @@ -15160,7 +15159,11 @@ dwarf_decode_line_header (sect_offset sect_off, struct dwarf2_cu *cu,
> &cu->header, comp_dir);
> }
>
> -static void
> +/* Decode the DW_AT_location attribute ATTR of SYM. If ATTR is a single
> + DW_OP_addr, DW_OP_addrx or DW_OP_GNU_addr_index, return its address
> + before relocation. */
Thanks for adding this comment. Could you also mention what the
return value is when ATTR isn't one of the mentioned ATTRs? E.g.,
something like "Otherwise, return std::nullopt."
I noticed, too, that two of the three callers discard the return
value. This might be worth a one line comment at the call site,
though there are plenty of cases where this is not done. I'll leave it
to you to decide whether those sites deserve a comment.
Kevin
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v3] gdb/dwarf: filter discarded zero-address variables after relocation
2026-10-16 4:00 ` [PATCH v2] " Longjun Luo
2026-10-18 23:29 ` Kevin Buettner
@ 2026-10-27 8:27 ` Longjun Luo
1 sibling, 0 replies; 4+ messages in thread
From: Longjun Luo @ 2026-10-27 8:27 UTC (permalink / raw)
To: gdb-patches; +Cc: Kevin Buettner, Longjun Luo
A variable discarded by section GC can retain a DIE with a zero DWARF
address. var_decode_location adds the section offset before new_symbol
checks that address. If the objfile has already been relocated, the
symbol survives the zero-address check and can read the ELF header as
data.
This affects PIE executables when the CU is first expanded after
starting the program. It also affects normally loaded shared libraries,
including with --readnow, because their objfiles already have a load
offset.
Have var_decode_location return the address it decoded before
relocation, and check that address in new_symbol, as the DWARF reader
already does for discarded functions and address ranges. Preserve the
existing exception for objects with allocated sections at zero.
Extend gdb.dwarf2/dw2-var-zero-addr.exp with a PIE whose CU is first
expanded after starting the program, and with a loaded shared library,
with and without --readnow. Use a distinctive variable name to avoid
clashes with shared-library debug symbols after the program starts.
Tested on x86_64 GNU/Linux with GCC. Without the fix, the three new
cases fail; with it, the test passes. GDB selftests pass.
Signed-off-by: Longjun Luo <luolongjuna@gmail.com>
---
Changes in v3:
- Document the std::nullopt return value in the comment above
var_decode_location. Leave the two callers that ignore the return
value as-is, as they only populate the symbol's location.
Regarding the copyright assignment: I looked into the process, but I am
currently unable to complete the paperwork. I understand the full patch
(especially with the new test cases) exceeds the ~15-line threshold for
legally significant changes.
Would it be acceptable to take only the minimal fix in gdb/dwarf2/read.c
under the small-change rule, or should we hold off on this patch until
GDB's DCO policy is finalized? I will hold off on sending further patches
in the meantime.
v2: https://sourceware.org/pipermail/gdb-patches/2026-October/231127.html
gdb/dwarf2/read.c | 27 +++++----
gdb/testsuite/gdb.dwarf2/dw2-var-zero-addr.S | 2 +-
.../gdb.dwarf2/dw2-var-zero-addr.exp | 60 ++++++++++++++++++-
3 files changed, 76 insertions(+), 13 deletions(-)
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 1fc6d7ffb4f..77a74c49b35 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -514,9 +514,8 @@ show_dwarf_synchronous (struct ui_file *file, int from_tty,
\f
/* local function prototypes */
-static void var_decode_location (struct attribute *attr,
- struct symbol *sym,
- struct dwarf2_cu *cu);
+static std::optional<unrelocated_addr> var_decode_location
+ (struct attribute *attr, struct symbol *sym, struct dwarf2_cu *cu);
static unsigned int peek_abbrev_code (bfd *, const gdb_byte *);
@@ -15160,7 +15159,11 @@ dwarf_decode_line_header (sect_offset sect_off, struct dwarf2_cu *cu,
&cu->header, comp_dir);
}
-static void
+/* Decode the DW_AT_location attribute ATTR of SYM. If ATTR is a single
+ DW_OP_addr, DW_OP_addrx or DW_OP_GNU_addr_index, return its address
+ before relocation. Otherwise, return std::nullopt. */
+
+static std::optional<unrelocated_addr>
var_decode_location (struct attribute *attr, struct symbol *sym,
struct dwarf2_cu *cu)
{
@@ -15182,7 +15185,7 @@ var_decode_location (struct attribute *attr, struct symbol *sym,
if (attr->form_is_block () && attr->as_block ()->size == 0)
{
sym->set_loc_class_index (LOC_OPTIMIZED_OUT);
- return;
+ return {};
}
/* Handle one degenerate form of location expression specially, to
@@ -15216,7 +15219,7 @@ var_decode_location (struct attribute *attr, struct symbol *sym,
sym->set_value_address
(sym->value_address ()
+ objfile->section_offsets[sym->section_index ()]);
- return;
+ return tem;
}
}
@@ -15231,6 +15234,8 @@ var_decode_location (struct attribute *attr, struct symbol *sym,
if (sym->computed_ops ()->location_has_loclist)
cu->has_loclist = true;
+
+ return {};
}
/* A helper function to add an "export" symbol. The new symbol starts
@@ -15482,7 +15487,8 @@ new_symbol (struct die_info *die, struct dwarf2_cu *cu, struct symbol *sym,
attr = dwarf2_attr (die, DW_AT_location, cu);
if (attr != nullptr)
{
- var_decode_location (attr, sym, cu);
+ std::optional<unrelocated_addr> unrelocated
+ = var_decode_location (attr, sym, cu);
attr2 = dwarf2_attr (die, DW_AT_external, cu);
/* Fortran explicitly imports any global symbols to the local
@@ -15491,14 +15497,15 @@ new_symbol (struct die_info *die, struct dwarf2_cu *cu, struct symbol *sym,
&& die->parent->tag == DW_TAG_common_block)
attr2 = nullptr;
- if (sym->loc_class () == LOC_STATIC
- && sym->value_address () == 0
+ if (unrelocated == (unrelocated_addr) 0
&& !per_objfile->per_bfd->has_section_at_zero)
{
/* When a static variable is eliminated by the linker,
the corresponding debug information is not stripped
out, but the variable address is set to null;
- do not add such variables into symbol table. */
+ do not add such variables into symbol table. Check
+ the address before relocation, which adds the load
+ offset of a PIE or shared library. */
}
else if (attr2 != nullptr && attr2->as_boolean ())
{
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-var-zero-addr.S b/gdb/testsuite/gdb.dwarf2/dw2-var-zero-addr.S
index f7394f33946..233bd6ce79e 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-var-zero-addr.S
+++ b/gdb/testsuite/gdb.dwarf2/dw2-var-zero-addr.S
@@ -39,7 +39,7 @@
.byte 5 /* DW_AT_encoding */
.uleb128 3 /* Abbrev: DW_TAG_variable (location) */
- .ascii "var\0" /* DW_AT_name */
+ .ascii "dw2_discarded_zero_addr_var\0" /* DW_AT_name */
.byte 2f - 1f /* DW_AT_location */
1: .byte 3 /* DW_OP_addr */
.4byte 0 /* <addr> */
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-var-zero-addr.exp b/gdb/testsuite/gdb.dwarf2/dw2-var-zero-addr.exp
index 04a2aa06ea9..360894661e5 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-var-zero-addr.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-var-zero-addr.exp
@@ -25,9 +25,12 @@ if {[prepare_for_testing "failed to prepare" ${testfile} \
}
proc test { } {
- # FAIL was: = (int *) 0x0
+ # FAIL was: = (int *) 0x0, or the load address in a relocated objfile.
# Such DIE record can be produced using: gcc -fdata-sections -Wl,-gc-sections
- gdb_test "print &var" {No symbol "var" in current context\.}
+ # Use a distinctive name to avoid clashes with shared-library debug
+ # symbols once the program runs.
+ gdb_test "print &dw2_discarded_zero_addr_var" \
+ {No symbol "dw2_discarded_zero_addr_var" in current context\.}
}
test
@@ -40,3 +43,56 @@ save_vars { GDBFLAGS } {
with_test_prefix "readnow" {
test
}
+
+# Expand the CU for the first time after the PIE has been relocated.
+proc_with_prefix test_pie_after_run {} {
+ set executable ${::testfile}-pie
+ if {[build_executable "failed to prepare" $executable \
+ [list $::srcfile $::srcfile2] {nodebug pie}]} {
+ return
+ }
+
+ clean_restart $executable
+ if {[runto_main]} {
+ test
+ }
+}
+
+# A shared library is relocated before its CUs are expanded, even with
+# --readnow.
+proc_with_prefix test_shlib {} {
+ set lib_path [standard_output_file ${::testfile}-shlib.so]
+ if {[gdb_compile_shlib $::srcdir/$::subdir/$::srcfile $lib_path \
+ {nodebug}] != ""} {
+ untested "failed to compile shared library"
+ return
+ }
+
+ set executable ${::testfile}-shlib
+ if {[build_executable "failed to prepare" $executable $::srcfile2 \
+ [list debug shlib=$lib_path]]} {
+ return
+ }
+
+ foreach_with_prefix readnow {false true} {
+ save_vars { ::GDBFLAGS } {
+ if {$readnow} {
+ append ::GDBFLAGS " --readnow"
+ }
+ clean_restart $executable
+ }
+ gdb_load_shlib $lib_path
+ if {[runto_main]} {
+ set lib_name [file tail $lib_path]
+ gdb_test "info sharedlibrary $lib_name" \
+ ".*Yes.*[string_to_regexp $lib_name]" \
+ "shared library is loaded"
+ test
+ }
+ }
+}
+
+test_pie_after_run
+
+require allow_shlib_tests
+test_shlib
--
2.53.0
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-10-27 8:28 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-09 17:46 [PATCH] gdb/dwarf: filter discarded zero-address variables after relocation Longjun Luo
2026-10-16 4:00 ` [PATCH v2] " Longjun Luo
2026-10-18 23:29 ` Kevin Buettner
2026-10-27 8:27 ` [PATCH v3] " Longjun Luo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox