diff --git a/gdb/symfile.c b/gdb/symfile.c
index d583960d430..0413f7f7ce1 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -806,7 +806,6 @@ init_entry_point_info (struct objfile *objfile)
if (ei->entry_point_p)
{
CORE_ADDR entry_point = ei->entry_point;
- int found;
/* Make certain that the address points at real code, and not a
function descriptor. */
@@ -818,7 +817,7 @@ init_entry_point_info (struct objfile *objfile)
ei->entry_point
= gdbarch_addr_bits_remove (objfile->arch (), entry_point);
- found = 0;
+ bool found = false;
for (obj_section &osect : objfile->sections ())
{
struct bfd_section *sect = osect.the_bfd_section;
@@ -829,13 +828,17 @@ init_entry_point_info (struct objfile *objfile)
{
ei->the_bfd_section_index
= gdb_bfd_section_index (objfile->obfd.get (), sect);
- found = 1;
+ found = true;
break;
}
}
+ /* We store the section index so that the entry address can be
+ relocated when used. If the entry address is outside of any
+ section then we cannot relocate it. Just claim that there is no
+ entry address in this case. */
if (!found)
- ei->the_bfd_section_index = SECT_OFF_TEXT (objfile);
+ ei->entry_point_p = false;
}
}
diff --git a/gdb/testsuite/gdb.base/solib-bad-entry-addr-lib.s b/gdb/testsuite/gdb.base/solib-bad-entry-addr-lib.s
new file mode 100644
index 00000000000..595a5c5e132
--- /dev/null
+++ b/gdb/testsuite/gdb.base/solib-bad-entry-addr-lib.s
@@ -0,0 +1,33 @@
+/* Copyright 2026 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 . */
+
+ .section .rodata
+ .globl lib_var
+ .type lib_var, @object
+lib_var:
+ .long 42
+ .size lib_var, .-lib_var
+
+ /* This executable section exists solely to force the linker
+ to create an additional LOAD segment (with R+X permissions),
+ giving the library 3+ LOAD segments instead of the default 2.
+
+ This matters because GDB's symfile_find_segment_sections only
+ runs for objects with exactly 1 or 2 segments. When it runs,
+ it sets sect_index_text from the first section in segment 1,
+ which masks the bug we are testing for, see the .exp file for
+ details. */
+ .section .not_text, "ax", @progbits
+ .byte 0
diff --git a/gdb/testsuite/gdb.base/solib-bad-entry-addr.c b/gdb/testsuite/gdb.base/solib-bad-entry-addr.c
new file mode 100644
index 00000000000..9c5c7b491e0
--- /dev/null
+++ b/gdb/testsuite/gdb.base/solib-bad-entry-addr.c
@@ -0,0 +1,22 @@
+/* Copyright 2026 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 . */
+
+extern int lib_var;
+
+int
+main ()
+{
+ return lib_var;
+}
diff --git a/gdb/testsuite/gdb.base/solib-bad-entry-addr.exp b/gdb/testsuite/gdb.base/solib-bad-entry-addr.exp
new file mode 100644
index 00000000000..39694bffe63
--- /dev/null
+++ b/gdb/testsuite/gdb.base/solib-bad-entry-addr.exp
@@ -0,0 +1,99 @@
+# Copyright 2026 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 .
+
+# This test aims to exercise a specific situation which was seen
+# causing GDB to crash. An application has a shared library that
+# meets the following conditions:
+#
+# 1. No ".text" section,
+# 2. at least 3 LOAD segments, and
+# 3. a non-zero entry address that is outside of every section.
+#
+# When these 3 conditions are met then GDB would run into a problem in
+# init_entry_point_info for the shared library. The non-zero entry
+# address means GDB would try to find the section corresponding to the
+# address. As the address is outside of all sections then GDB would
+# try to use the .text section as a fall-back. But there is no text
+# section, so an internal error would be triggered.
+#
+# The 3 LOAD segments is important because, if there are only 1 or 2
+# segments GDB has a default in symfile_find_segment_sections where
+# it assumes the text section is the first section in the first
+# segment, which means init_entry_point_info will have a .text section
+# to use.
+#
+# This test has a very simple assembler file (which hopefully contains
+# no architecture specific content), which will compile to a couple of
+# sections, but no .text section. These sections force the creation
+# of more than 2 LOAD segments. The compiler flags then set the entry
+# address to 0x1, which (we hope) is outside all sections. This
+# assembler file is compiled into a shared library.
+
+require allow_shlib_tests
+require !use_gdb_stub
+require {istarget *-linux*}
+
+standard_testfile .c -lib.s
+
+# Build shared library.
+set lib_testfile ${testfile}-lib.so
+set lib_srcfile ${srcfile2}
+set lib_binfile [standard_output_file ${lib_testfile}]
+set lib_flags {shlib \
+ additional_flags=-nostartfiles \
+ additional_flags=-Wl,-e,0x1 \
+ additional_flags=-Wl,-z,separate-code}
+if { [build_executable "build solib" $lib_testfile $lib_srcfile \
+ $lib_flags] == -1 } {
+ return
+}
+
+# Build the test executable.
+if { [build_executable "build exec" $testfile $srcfile \
+ [list debug pie shlib=${lib_binfile}]] == -1 } {
+ return
+}
+
+# Confirm we have more than 2 LOAD segments in the shared library.
+set readelf_program [gdb_find_readelf]
+set command "exec $readelf_program -Wl $lib_binfile"
+verbose -log "command is $command"
+set result [catch {{*}$command} output]
+verbose -log "result is $result"
+verbose -log "output is $output"
+if {$result != 0} {
+ fail "read program headers from $lib_testfile"
+ return
+}
+if {![regexp {\nProgram Headers:\n *Type [^\n]* Align\n(.*?)\n\n} $output trash phdr]} {
+ fail "no Program Headers found"
+ return
+}
+set load_segment_count 0
+foreach line [regexp -line -all -inline {^ *LOAD .* 0x[0-9]+$} $phdr] {
+ incr load_segment_count
+}
+if { $load_segment_count <= 2 } {
+ fail "not enough LOAD segments"
+ return
+}
+
+# Start GDB and run to main. If the shared library is causing issues
+# then we will see an internal error once the inferior starts running.
+clean_restart $testfile
+
+if {![runto_main message]} {
+ return 0
+}