[v2,1/1] gdb: abort start command if there is no symbol for 'main_name ()'

Message ID 20241209130528.312719-2-stephan.rohr@intel.com
State New
Headers
Series gdb: Fix start command for Windows |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_gdb_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_gdb_check--master-arm success Test passed
linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 success Test passed

Commit Message

Rohr, Stephan Dec. 9, 2024, 1:05 p.m. UTC
  From: "Rohr, Stephan" <stephan.rohr@intel.com>

GDB aborts the 'start' command if the minimal symbols cannot be
resolved.  On Windows, GDB reads the minimal symbols from the COFF
header of the PE file.  The symbol table is deprecated and the
number of symbols in the COFF header may be zero [1].  For example,
the LLVM clang compiler for Windows MSVC can be instructed to generate
DWARF:

  clang++ -g -O0 -gdwarf -fuse-ld=lld test.cpp -o test_clang

The corresponding COFF file header shows:

  FILE HEADER VALUES
        8664 machine (x64)
           E number of sections
    66E889EC time date stamp Mon Sep 16 21:41:32 2024
       FB400 file pointer to symbol table
           0 number of symbols
          F0 size of optional header
          22 characteristics

GDB is not able to read the minimal symbols; the `start' command fails
with an error:

  (gdb) start
  No symbol table loaded.  Use the "file" command.

Manually inserting a breakpoint in main works fine:

  (gdb) tbreak main
  Temporary breakpoint 1 at 0x14000100c: file test.cpp, line 6.
  (gdb) run
  Starting program: C:\test-clang

  Temporary breakpoint 1, main () at test.cpp:6
  6         std::cout << "Hello World.\n";

Fix this by testing if a symbol for `main' is available instead of checking
the minimal symbol table:

  (gdb) start
  Temporary breakpoint 1 at 0x14000100c: file test.cpp, line 6.
  Starting program: C:\test-clang

  Temporary breakpoint 1, main () at test.cpp:6
  6         std::cout << "Hello World.\n";
  (gdb)

[1]: https://learn.microsoft.com/en-us/windows/win32/debug/pe-format
---
 gdb/infcmd.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)
  

Comments

Eli Zaretskii Dec. 9, 2024, 3:17 p.m. UTC | #1
> From: Stephan Rohr <stephan.rohr@intel.com>
> Cc: guinevere@redhat.com
> Date: Mon,  9 Dec 2024 05:05:28 -0800
> 
> --- a/gdb/infcmd.c
> +++ b/gdb/infcmd.c
> @@ -516,10 +516,15 @@ run_command (const char *args, int from_tty)
>  static void
>  start_command (const char *args, int from_tty)
>  {
> -  /* Some languages such as Ada need to search inside the program
> -     minimal symbols for the location where to put the temporary
> -     breakpoint before starting.  */
> -  if (!have_minimal_symbols (current_program_space))
> +  /* Abort the start command if `main` cannot be resolved, e.g., there

Thanks, but please don't quote `like this` in comments and doc
strings; instead, quote 'like this'.
  
Guinevere Larsen Dec. 10, 2024, 2:50 p.m. UTC | #2
On 12/9/24 10:05 AM, Stephan Rohr wrote:
> From: "Rohr, Stephan" <stephan.rohr@intel.com>
>
> GDB aborts the 'start' command if the minimal symbols cannot be
> resolved.  On Windows, GDB reads the minimal symbols from the COFF
> header of the PE file.  The symbol table is deprecated and the
> number of symbols in the COFF header may be zero [1].  For example,
> the LLVM clang compiler for Windows MSVC can be instructed to generate
> DWARF:
>
>    clang++ -g -O0 -gdwarf -fuse-ld=lld test.cpp -o test_clang
>
> The corresponding COFF file header shows:
>
>    FILE HEADER VALUES
>          8664 machine (x64)
>             E number of sections
>      66E889EC time date stamp Mon Sep 16 21:41:32 2024
>         FB400 file pointer to symbol table
>             0 number of symbols
>            F0 size of optional header
>            22 characteristics
>
> GDB is not able to read the minimal symbols; the `start' command fails
> with an error:
>
>    (gdb) start
>    No symbol table loaded.  Use the "file" command.
>
> Manually inserting a breakpoint in main works fine:
>
>    (gdb) tbreak main
>    Temporary breakpoint 1 at 0x14000100c: file test.cpp, line 6.
>    (gdb) run
>    Starting program: C:\test-clang
>
>    Temporary breakpoint 1, main () at test.cpp:6
>    6         std::cout << "Hello World.\n";
>
> Fix this by testing if a symbol for `main' is available instead of checking
> the minimal symbol table:
>
>    (gdb) start
>    Temporary breakpoint 1 at 0x14000100c: file test.cpp, line 6.
>    Starting program: C:\test-clang
>
>    Temporary breakpoint 1, main () at test.cpp:6
>    6         std::cout << "Hello World.\n";
>    (gdb)
>
> [1]: https://learn.microsoft.com/en-us/windows/win32/debug/pe-format
> ---
>   gdb/infcmd.c | 13 +++++++++----
>   1 file changed, 9 insertions(+), 4 deletions(-)
>
> diff --git a/gdb/infcmd.c b/gdb/infcmd.c
> index 5c0e3f51162..7e18a8de3a8 100644
> --- a/gdb/infcmd.c
> +++ b/gdb/infcmd.c
> @@ -516,10 +516,15 @@ run_command (const char *args, int from_tty)
>   static void
>   start_command (const char *args, int from_tty)
>   {
> -  /* Some languages such as Ada need to search inside the program
> -     minimal symbols for the location where to put the temporary
> -     breakpoint before starting.  */
> -  if (!have_minimal_symbols (current_program_space))
> +  /* Abort the start command if `main` cannot be resolved, e.g., there
> +     is no symbol for main.  Some languages such as Ada need to search
> +     inside the program minimal symbols for the location where to put
> +     the temporary breakpoint before starting.  */

I think the old comment can be entirely removed, now that we make a full 
search through all symbols, instead of just looking at minsyms.

It took me a moment to reconcile why that comment was there, since the 
code doesn't do anything with minimal symbols, and I think keeping it 
will make things even more confusing the next time someone looks at this 
command.

With that removed, I'm happy with this solution :)

Reviewed-By: Guinevere Larsen <guinevere@redhat.com>

Hope this gets approved soon.
  

Patch

diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 5c0e3f51162..7e18a8de3a8 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -516,10 +516,15 @@  run_command (const char *args, int from_tty)
 static void
 start_command (const char *args, int from_tty)
 {
-  /* Some languages such as Ada need to search inside the program
-     minimal symbols for the location where to put the temporary
-     breakpoint before starting.  */
-  if (!have_minimal_symbols (current_program_space))
+  /* Abort the start command if `main` cannot be resolved, e.g., there
+     is no symbol for main.  Some languages such as Ada need to search
+     inside the program minimal symbols for the location where to put
+     the temporary breakpoint before starting.  */
+  struct symbol *sym
+    = lookup_symbol_search_name (main_name (), nullptr,
+				 SEARCH_FUNCTION_DOMAIN).symbol;
+
+  if (sym == nullptr)
     error (_("No symbol table loaded.  Use the \"file\" command."));
 
   /* Run the program until reaching the main procedure...  */