[PATCH v2 3/8] gdb: Remove stabs support from ELF files

Guinevere Larsen
2025-10-20T15:35:52Z

This commit makes it so that GDB won't read stabs information from ELF
files. If stabs is detected in an ELF file, the reader now warns the user
that stabs is not supported.

This test would cause two new failures in the test gdb.stabs/weird.exp
(that surprisingly didn't happen in the mips commit). Rather than fixing
the test that'll be removed soon, I just removed the test instead.

Approved-By: Tom Tromey <tom@tromey.com>
---
gdb/elfread.c | 146 +-------------
gdb/testsuite/gdb.stabs/weird.exp | 309 ------------------------------
2 files changed, 1 insertion(+), 454 deletions(-)
delete mode 100644 gdb/testsuite/gdb.stabs/weird.exp

diff --git a/gdb/elfread.c b/gdb/elfread.c
index 152576d3523..2302dcf1ae6 100644
--- a/gdb/elfread.c
+++ b/gdb/elfread.c
@@ -28,7 +28,6 @@
#include "symtab.h"
#include "symfile.h"
#include "objfiles.h"
-#include "stabsread.h"
#include "probe.h"
#include "arch-utils.h"
#include "gdbtypes.h"
@@ -45,7 +44,6 @@
#include <string_view>
#include "dwarf2/public.h"
#include "cli/cli-cmds.h"
-#include "gdb-stabs.h"

/* Whether ctf should always be read, or only if no dwarf is present. */
static bool always_read_ctf;
@@ -1207,134 +1205,6 @@ elf_symfile_read_dwarf2 (struct objfile *objfile,
return has_dwarf2;
}

-/* find_text_range --- find start and end of loadable code sections
-
- The find_text_range function finds the shortest address range that
- encloses all sections containing executable code, and stores it in
- objfile's text_addr and text_size members.
-
- dbx_symfile_read will use this to finish off the partial symbol
- table, in some cases. */
-
-static void
-find_text_range (bfd * sym_bfd, struct objfile *objfile)
-{
- asection *sec;
- int found_any = 0;
- CORE_ADDR start = 0;
- CORE_ADDR end = 0;
-
- for (sec = sym_bfd->sections; sec; sec = sec->next)
- if (bfd_section_flags (sec) & SEC_CODE)
- {
- CORE_ADDR sec_start = bfd_section_vma (sec);
- CORE_ADDR sec_end = sec_start + bfd_section_size (sec);
-
- if (found_any)
- {
- if (sec_start < start)
- start = sec_start;
- if (sec_end > end)
- end = sec_end;
- }
- else
- {
- start = sec_start;
- end = sec_end;
- }
-
- found_any = 1;
- }
-
- if (!found_any)
- error (_("Can't find any code sections in symbol file"));
-
- DBX_TEXT_ADDR (objfile) = start;
- DBX_TEXT_SIZE (objfile) = end - start;
-}
-
-/* Scan and build partial symbols for an ELF symbol file.
- This ELF file has already been processed to get its minimal symbols.
-
- This routine is the equivalent of dbx_symfile_init and dbx_symfile_read
- rolled into one.
-
- OBJFILE is the object file we are reading symbols from.
- ADDR is the address relative to which the symbols are (e.g.
- the base address of the text segment).
- STABSECT is the BFD section information for the .stab section.
- STABSTROFFSET and STABSTRSIZE define the location in OBJFILE where the
- .stabstr section exists.
-
- This routine is mostly copied from dbx_symfile_init and dbx_symfile_read,
- adjusted for elf details. */
-
-void
-elfstab_build_psymtabs (struct objfile *objfile, asection *stabsect,
- file_ptr stabstroffset, unsigned int stabstrsize)
-{
- int val;
- bfd *sym_bfd = objfile->obfd.get ();
- const char *name = bfd_get_filename (sym_bfd);
-
- stabsread_new_init ();
-
- /* Allocate struct to keep track of stab reading. */
- dbx_objfile_data_key.emplace (objfile);
- dbx_symfile_info *key = dbx_objfile_data_key.get (objfile);
-
- /* Find the first and last text address. dbx_symfile_read seems to
- want this. */
- find_text_range (sym_bfd, objfile);
-
-#define ELF_STABS_SYMBOL_SIZE 12 /* XXX FIXME XXX */
- DBX_SYMBOL_SIZE (objfile) = ELF_STABS_SYMBOL_SIZE;
- DBX_SYMCOUNT (objfile)
- = bfd_section_size (stabsect) / DBX_SYMBOL_SIZE (objfile);
- DBX_STRINGTAB_SIZE (objfile) = stabstrsize;
- DBX_SYMTAB_OFFSET (objfile) = stabsect->filepos;
- DBX_STAB_SECTION (objfile) = stabsect;
-
- if (stabstrsize > bfd_get_size (sym_bfd))
- error (_("ridiculous string table size: %d bytes"), stabstrsize);
- DBX_STRINGTAB (objfile) = (char *)
- obstack_alloc (&objfile->objfile_obstack, stabstrsize + 1);
- OBJSTAT (objfile, sz_strtab += stabstrsize + 1);
-
- /* Now read in the string table in one big gulp. */
-
- val = bfd_seek (sym_bfd, stabstroffset, SEEK_SET);
- if (val < 0)
- perror_with_name (name);
- val = bfd_read (DBX_STRINGTAB (objfile), stabstrsize, sym_bfd);
- if (val != stabstrsize)
- perror_with_name (name);
-
- stabsread_new_init ();
- free_header_files ();
- init_header_files ();
-
- key->ctx.processing_acc_compilation = 1;
-
- key->ctx.symbuf_read = 0;
- key->ctx.symbuf_left = bfd_section_size (stabsect);
-
- scoped_restore restore_stabs_data = make_scoped_restore (&key->ctx.stabs_data);
- gdb::unique_xmalloc_ptr<gdb_byte> data_holder;
-
- key->ctx.stabs_data = symfile_relocate_debug_section (objfile, stabsect, NULL);
- if (key->ctx.stabs_data)
- data_holder.reset (key->ctx.stabs_data);
-
- /* In an elf file, we've already installed the minimal symbols that came
- from the elf (non-stab) symbol table, so always act like an
- incremental load here. dbx_symfile_read should not generate any new
- minimal symbols, since we will have already read the ELF dynamic symbol
- table and normal symbol entries won't be in the ".stab" section; but in
- case it does, it will install them itself. */
- read_stabs_symtab (objfile, 0);
-}
-
/* Scan and build partial symbols for a symbol file.
We have been initialized by a call to elf_symfile_init, which
currently does nothing.
@@ -1350,7 +1220,6 @@ elfstab_build_psymtabs (struct objfile *objfile, asection *stabsect,
We look for sections with specific names, to tell us what debug
format to look for: FIXME!!!

- elfstab_build_psymtabs() handles STABS symbols;
mdebug_build_psymtabs() handles ECOFF debugging information.

Note that ELF files have a "minimal" symbol table, which looks a lot
@@ -1397,20 +1266,7 @@ elf_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
elfmdebug_build_psymtabs (objfile, swap, ei.mdebugsect);
}
if (ei.stabsect)
- {
- asection *str_sect;
-
- /* Stab sections have an associated string table that looks like
- a separate section. */
- str_sect = bfd_get_section_by_name (abfd, ".stabstr");
-
- /* FIXME should probably warn about a stab section without a stabstr. */
- if (str_sect)
- elfstab_build_psymtabs (objfile,
- ei.stabsect,
- str_sect->filepos,
- bfd_section_size (str_sect));
- }
+ warning ("stabs debug information is not supported.");

/* Read the CTF section only if there is no DWARF info. */
if (always_read_ctf && ei.ctfsect)
diff --git a/gdb/testsuite/gdb.stabs/weird.exp b/gdb/testsuite/gdb.stabs/weird.exp
deleted file mode 100644
index 3bc6e0d8ac9..00000000000
--- a/gdb/testsuite/gdb.stabs/weird.exp
+++ /dev/null
@@ -1,309 +0,0 @@
-# Copyright 1997-2025 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 GDB properly ignores invalid stabs.
-# Also test that GDB can debug a .o file, and that it doesn't mind
-# a file that's more minimal than what a compiler normally puts out.
-
-set testfile weird
-set srcfile [standard_output_file weird.s]
-set binfile [standard_output_file weirdx.o]
-
-proc do_tests {} {
- global binfile
- global gdb_prompt
-
- # Mips/alpha targets that use gcc with mips-tfile put out the stabs
- # assembler directives embedded in comments. If the assembler
- # file is then processed with native cc, all stabs directives
- # will be lost.
- # Skip the rest of the stabs tests for this case.
- send_gdb "ptype inttype\n"
- gdb_expect {
- -re "^ptype inttype\r*\ntype = inttype.*$gdb_prompt $" {
- pass "stabs found"
- }
- -re ".*$gdb_prompt $" {
- setup_xfail "mips-*-*"
- setup_xfail "alpha-*-*"
- fail "stabs not found"
- return
- }
- default { fail "checking for stabs" }
- }
-
- print_weird_var var0
- print_weird_var var1
- print_weird_var var2
- print_weird_var var3
-
- print_weird_var attr32
- print_weird_var attr33
- print_weird_var attr35
- print_weird_var attr36
- print_weird_var attr37
- print_weird_var attr38
- print_weird_var attr39
- print_weird_var attr41
- print_weird_var attr42
- print_weird_var attr43
- print_weird_var attr44
- print_weird_var attr46
- print_weird_var attr47
- print_weird_var attr58
- print_weird_var attr59
- print_weird_var attr60
- print_weird_var attr61
- print_weird_var attr62
- print_weird_var attr63
- print_weird_var attr64
- print_weird_var attr65
- print_weird_var attr66
- print_weird_var attr67
- print_weird_var attr68
- print_weird_var attr69
- print_weird_var attr70
- print_weird_var attr71
- print_weird_var attr72
- print_weird_var attr73
- print_weird_var attr74
- print_weird_var attr75
- print_weird_var attr76
- print_weird_var attr77
- print_weird_var attr78
- print_weird_var attr79
- print_weird_var attr80
- print_weird_var attr81
- print_weird_var attr82
- print_weird_var attr83
- print_weird_var attr84
- print_weird_var attr85
- print_weird_var attr86
- print_weird_var attr87
- print_weird_var attr88
- print_weird_var attr89
- print_weird_var attr90
- print_weird_var attr91
- print_weird_var attr92
- print_weird_var attr93
- print_weird_var attr94
- print_weird_var attr95
- print_weird_var attr96
- print_weird_var attr97
- print_weird_var attr98
- print_weird_var attr99
- print_weird_var attr100
- print_weird_var attr101
- print_weird_var attr102
- print_weird_var attr103
- print_weird_var attr104
- print_weird_var attr105
- print_weird_var attr106
- print_weird_var attr107
- print_weird_var attr108
- print_weird_var attr109
- print_weird_var attr110
- print_weird_var attr111
- print_weird_var attr112
- print_weird_var attr113
- print_weird_var attr114
- print_weird_var attr115
- print_weird_var attr116
- print_weird_var attr117
- print_weird_var attr118
- print_weird_var attr119
- print_weird_var attr120
- print_weird_var attr121
- print_weird_var attr122
- print_weird_var attr123
- print_weird_var attr124
- print_weird_var attr125
- print_weird_var attr126
-
- gdb_test "p const69" " = 69" "'e' constant on non-enum type"
- gdb_test "whatis const69" "type = (unsigned int|inttype)"
-
- gdb_test "p sizeof (const70)" " = 2" "'e' constant with embedded type"
-
- gdb_test "p constchar" " = 97 'a'" "char constant"
- gdb_test "p constString1" " = \"Single quote String1\"" "string constant 1"
- gdb_test "p constString2" " = \"Double quote String2\"" "string constant 2"
-
- gdb_test "p constString3" " = \"String3 with embedded quote ' in the middle\"" "string constant 3"
- gdb_test "p constString4" { = "String4 with embedded quote \\" in the middle"} "string constant 4"
- gdb_test "p bad_neg0" " = \{field0 = 42, field2 =.*field3 = 45\}"
-
- gdb_test "ptype inttype" "type = (unsigned int|inttype)" "ptype on inttype"
- gdb_test "p sizeof (float72type)" " = 9" "unrecognized floating point type"
-
- # This big number needs to be kept as one piece
- gdb_test "p/x int256var" " = 0x0*2a0000002b0000002c0000002d0000002d0000002c0000002b0000002a" "print very big integer"
-
- gdb_test "whatis consth" "type = inttype"
- gdb_test "whatis consth2" "type = inttype"
-
- # GDB does not yet understand S constants
- setup_xfail "*-*-*"
- gdb_test "p/x bad_neg0const" " = \{field0 = 0x11222211, field2 =.*\
-field3 = 0x77888877\}" "print struct constant"
-
- gdb_test "ptype bad_type0" "type = .*" "print bad_type0"
- gdb_test "ptype bad_type1" "type = .*" "print bad_type1"
-
- # GDB does not yet support arrays indexed by anything at all unusual
- setup_xfail "*-*-*"
- gdb_test "p array0" " = \\{42, 43, 44, 45, 46, 47\\}" "array0 with strange index"
- setup_xfail "*-*-*"
- gdb_test "p array1" " = \\{42, 43, 44\\}" "array1 with strange index"
-
- # GDB does not yet support this feature
- gdb_test "whatis one_var" "type = inttype_one" \
- "whatis one_var (known failure in gdb 4.10)"
- # But do make sure that it prints as something reasonable
- gdb_test "whatis one_var" "type = inttype(|_one)" \
- "whatis one_var test 2"
-
- gdb_test "whatis two_var" "type = inttype_two" \
- "whatis two_var (known failure in gdb 4.10)"
- # But do make sure that it prints as something reasonable
- gdb_test "whatis two_var" "type = inttype(|_two)" \
- "whatis two_var test 2"
-
- setup_xfail "*-*-*"
- gdb_test "whatis pointer_to_int_var" "type = int \[*\]"
- setup_xfail "*-*-*"
- gdb_test "whatis intp_var" "type = intp"
-
- gdb_test "p common0var0" "= 42"
- # GDB seems to only understand common blocks local to a function.
- # These variables never get relocated to be relative to the common
- # block.
- # I'm not sure whether it is valid to have a common block which
- # is not local to a function.
- setup_xfail "*-*-*"
- gdb_test "p common0var1" "= 24"
- setup_xfail "*-*-*"
- gdb_test "p common0var2" "= 22"
-}
-
-proc print_weird_var { var } {
- global gdb_prompt
-
- # Make sure that the variable gets printed out correctly, without
- # any sort of warning message.
- gdb_test_multiple "print $var" "variable $var printed property" {
- -re "^print $var\r*\n.\[0-9\]* = 42.*$gdb_prompt $" {
- pass "variable $var printed properly"
- }
- -re ".*$gdb_prompt $" {
- fail "variable $var printed properly"
- }
- }
-
- # Make sure that the stabs did get loaded in a sensible way.
- # If somehow the stabs got skipped, then the above test can
- # pass because GDB assumes int for variables without a stab.
-
- # This doesn't work because 32=45 doesn't preserve the name in
- # gdb (as of 14 Sep 93 anyway).
- #gdb_test "whatis $var" "type = (unsigned int|inttype)"
-
- # But the size should be right.
- gdb_test "print sizeof ($var)" "= 4"
-}
-
-
-# Don't use gdb_load; it doesn't bitch if the loading produced some
-# error messages during symbol reading.
-
-global target_os
-set sedscript ${srcdir}/${subdir}/aout.sed
-set sedoptions ""
-
-switch -glob ${target_triplet} {
- "hppa*-*-*" {
- set sedscript ${srcdir}/${subdir}/hppa.sed
- }
- "mips-*-ecoff" {
- set sedscript ${srcdir}/${subdir}/ecoff.sed
- }
- "powerpc-*-aix*" {
- set sedscript ${srcdir}/${subdir}/xcoff.sed
- set sedoptions "-r"
- }
- "rs6000-*-aix*" {
- set sedscript ${srcdir}/${subdir}/xcoff.sed
- set sedoptions "-r"
- }
- "*-*-aout" {
- set sedscript ${srcdir}/${subdir}/aout.sed
- }
- "*-*-xcoff" {
- set sedscript ${srcdir}/${subdir}/xcoff.sed
- set sedoptions "-r"
- }
- "alpha-*-*" {
- set sedscript ${srcdir}/${subdir}/ecoff.sed
- }
-}
-
-# Hope this is a Unix box.
-set exec_output [remote_exec build "sed" "${sedoptions} -f ${sedscript}" "${srcdir}/${subdir}/weird.def" "${srcfile}"]
-if { [lindex $exec_output 0] != 0 } {
- perror "Couldn't make test case. $exec_output"
- return -1
-}
-
-if { [gdb_compile "${srcfile}" "${binfile}" object ""] != "" } {
- untested "failed to compile"
- return -1
-}
-
-remote_file build delete ${srcfile}
-
-clean_restart
-
-set binfile_host [gdb_remote_download host $binfile]
-set binfile_re [string_to_regexp $binfile_host]
-send_gdb "file $binfile_host\n"
-# If $binfile is very long, a \r (but not a \n) will echo in the
-# middle of the echo of the command. So to match the echo, we
-# would like to match anything not containing \n
-# (we would prefer to be sure not to match any warning message).
-# But \[^\n\]* doesn't seem to work, so instead use the heuristic
-# that a filename won't contain a space and a warning message will.
-# But spaces following by backspaces aren't really spaces.
-gdb_expect 60 {
- -re "^file (\[^ \]| +\008)*\r*\n" {
- exp_continue
- }
- -re "A program is being debugged already.\[\r\n\]+Are you sure you want to change the file\\? \\(y or n\\)" {
- send_gdb "y\n"
- exp_continue
- }
- -re "^Reading symbols from .*$binfile_re\\.\\.\\.(|\r\nUsing host libthread_db library .*libthread_db.so.*\\.)\r\n(\[^\\n\]*\n)?$gdb_prompt $" {
- pass "weirdx.o read without error"
- }
- -re ".*$gdb_prompt $" {
- fail "errors reading weirdx.o"
- }
- timeout {
- perror "couldn't load $binfile into $GDB (timed out)."
- return -1
- }
- eof { fail "(eof) cannot read weirdx.o" }
-}
-
-do_tests
--
2.51.0