[v2] gdb/jit: add function symbols to global block

Message ID 20260106181539.154125-1-jan.vrany@labware.com
State New
Headers
Series [v2] gdb/jit: add function symbols to global block |

Commit Message

Jan Vrany Jan. 6, 2026, 6:15 p.m. UTC
  This V2 updates the code to use std::vector rather than pending list
as commit "gdb/buildsym: replace struct pending with std::vector" removed
the latter.

Also note that this needs to be applied after

https://inbox.sourceware.org/gdb-patches/20251211161826.2365983-1-jan.vrany@labware.com/

Thanks,
Jan
-- >8 --

While playing with JIT reader I realized that it is not possible to set
a breakpoint on jitted function:

    (gdb) b jit_function_stack_mangle
    Function "jit_function_stack_mangle" not defined.
    Make breakpoint pending on future shared library load? (y or [n])

The problem is that symbols for jitted functions (jit_function_stack_mangle
in the above example) are not added to jitted compunit's global block:

    (gdb) maint print symtabs
    ...
    Symtab for file  at 0x55d6f8c186c0
    Read from object file << JIT compiled code at 0x5555555592a0 >> (0x55d6f8cd4090)
    Language: unknown

    Line table:

     line 1 at 0x7ffff7fbc000	(stmt)
     line 0 at 0x7ffff7fbc001	(stmt)

    Blockvector:

    block #000, object at 0x55d6f8c188b0, 0 symbols in 0x7ffff7fbc000..0x7ffff7fbc011
      block #001, object at 0x55d6f8c18910 under 0x55d6f8c188b0, 0 symbols in 0x7ffff7fbc000..0x7ffff7fbc011
        block #002, object at 0x55d6f8c18730 under 0x55d6f8c18910, 0 symbols in 0x7ffff7fbc000..0x7ffff7fbc00a, function jit_function_stack_mangle
        block #003, object at 0x55d6f8c187f0 under 0x55d6f8c18910, 0 symbols in 0x7ffff7fbc00a..0x7ffff7fbc011, function jit_function_add

This commit changes JIT reader to add jitted functions to the global
block:

    ...
    Blockvector:

    block #000, object at 0x55ed6665b180, 2 symbols in 0x7ffff7fbc000..0x7ffff7fbc011
     void jit_function_stack_mangle(); block object 0x55ed6665b000, 0x7ffff7fbc000..0x7ffff7fbc00a
     void jit_function_add(); block object 0x55ed6665b0c0, 0x7ffff7fbc00a..0x7ffff7fbc011
      block #001, object at 0x55ed6665b230 under 0x55ed6665b180, 0 symbols in 0x7ffff7fbc000..0x7ffff7fbc011
        block #002, object at 0x55ed6665b000 under 0x55ed6665b230, 0 symbols in 0x7ffff7fbc000..0x7ffff7fbc00a, function jit_function_stack_mangle
        block #003, object at 0x55ed6665b0c0 under 0x55ed6665b230, 0 symbols in 0x7ffff7fbc00a..0x7ffff7fbc011, function jit_function_add
---
 gdb/jit.c                             | 17 +++++++++++++----
 gdb/testsuite/gdb.base/jit-reader.exp | 10 ++++++++++
 2 files changed, 23 insertions(+), 4 deletions(-)
  

Comments

Tom Tromey Jan. 13, 2026, 4:20 p.m. UTC | #1
>>>>> "Jan" == Jan Vrany <jan.vrany@labware.com> writes:

Jan> +	{
Jan> +	  new_block = new (&objfile->objfile_obstack) global_block;
Jan> +	  new_block->set_multidict (
Jan> +	    mdict_create_linear (&objfile->objfile_obstack, global_symbols));
Jan> +	}
Jan>        else
Jan> -	new_block = new (&objfile->objfile_obstack) block;
Jan> +	{
Jan> +	  new_block = new (&objfile->objfile_obstack) block;
Jan> +	  new_block->set_multidict (
Jan> +	    mdict_create_linear (&objfile->objfile_obstack, {}));
Jan> +	}

Does anything ever get added to the static block?
If not then making a dictionary doesn't seem necessary?

Also the formatting is wonky here, that "(" should not be at the end of
the line.  (Two instances of this.)

Kind of weird that this code doesn't use buildsym, but OTOH buildsym is
horrible.

Tom
  
Jan Vrany Jan. 13, 2026, 9:42 p.m. UTC | #2
On Tue, 2026-01-13 at 09:20 -0700, Tom Tromey wrote:
> > > > > > "Jan" == Jan Vrany <jan.vrany@labware.com> writes:
> 
> Jan> +	{
> Jan> +	  new_block = new (&objfile->objfile_obstack) global_block;
> Jan> +	  new_block->set_multidict (
> Jan> +	    mdict_create_linear (&objfile->objfile_obstack, global_symbols));
> Jan> +	}
> Jan>        else
> Jan> -	new_block = new (&objfile->objfile_obstack) block;
> Jan> +	{
> Jan> +	  new_block = new (&objfile->objfile_obstack) block;
> Jan> +	  new_block->set_multidict (
> Jan> +	    mdict_create_linear (&objfile->objfile_obstack, {}));
> Jan> +	}
> 
> Does anything ever get added to the static block?

No (at the moment). 

> If not then making a dictionary doesn't seem necessary?

As the code stands now, I think it has to - the rest of code expects it is
always there. For example, blockvector::~blockvector() just unconditionally
frees the dictionary. Or blpy_repr() that calls mdict_size().

> 
> Also the formatting is wonky here, that "(" should not be at the end of
> the line.  (Two instances of this.)

Sorry, will fix that.

Jan
> 
> Kind of weird that this code doesn't use buildsym, but OTOH buildsym is
> horrible.
> 
> Tom
  
Tom Tromey Jan. 13, 2026, 10:47 p.m. UTC | #3
>>>>> "Jan" == Jan Vraný <Jan.Vrany@labware.com> writes:

>> If not then making a dictionary doesn't seem necessary?

Jan> As the code stands now, I think it has to - the rest of code expects it is
Jan> always there. For example, blockvector::~blockvector() just unconditionally
Jan> frees the dictionary. Or blpy_repr() that calls mdict_size().

Gotcha, thanks for looking.

Maybe at someday we should let mdict_free take a null pointer and
then we could omit empty dictionaries for some blocks.

Tom
  

Patch

diff --git a/gdb/jit.c b/gdb/jit.c
index 489386393a1..214d984147e 100644
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -43,6 +43,7 @@ 
 #include "completer.h"
 #include <forward_list>
 #include "expanded-symbol.h"
+#include "buildsym.h"
 
 static std::string jit_reader_dir;
 
@@ -564,6 +565,7 @@  finalize_symtab (struct gdb_symtab *stab, struct objfile *objfile)
      object for each.  Simultaneously, keep setting the real_block
      fields.  */
   int block_idx = FIRST_LOCAL_BLOCK;
+  std::vector<symbol *> global_symbols;
   for (gdb_block &gdb_block_iter : stab->blocks)
     {
       struct block *new_block = new (&objfile->objfile_obstack) block;
@@ -585,6 +587,7 @@  finalize_symtab (struct gdb_symtab *stab, struct objfile *objfile)
 
       block_name->m_name = obstack_strdup (&objfile->objfile_obstack,
 					   gdb_block_iter.name.get ());
+      global_symbols.push_back (block_name);
 
       new_block->set_function (block_name);
 
@@ -606,12 +609,18 @@  finalize_symtab (struct gdb_symtab *stab, struct objfile *objfile)
       struct block *new_block;
 
       if (i == GLOBAL_BLOCK)
-	new_block = new (&objfile->objfile_obstack) global_block;
+	{
+	  new_block = new (&objfile->objfile_obstack) global_block;
+	  new_block->set_multidict (
+	    mdict_create_linear (&objfile->objfile_obstack, global_symbols));
+	}
       else
-	new_block = new (&objfile->objfile_obstack) block;
+	{
+	  new_block = new (&objfile->objfile_obstack) block;
+	  new_block->set_multidict (
+	    mdict_create_linear (&objfile->objfile_obstack, {}));
+	}
 
-      new_block->set_multidict
-	(mdict_create_linear (&objfile->objfile_obstack, {}));
       new_block->set_superblock (block_iter);
       block_iter = new_block;
 
diff --git a/gdb/testsuite/gdb.base/jit-reader.exp b/gdb/testsuite/gdb.base/jit-reader.exp
index 549859627f1..8b3f50d15b7 100644
--- a/gdb/testsuite/gdb.base/jit-reader.exp
+++ b/gdb/testsuite/gdb.base/jit-reader.exp
@@ -244,6 +244,16 @@  proc jit_reader_test {} {
 		    "<gdb.Objfile filename=<< JIT compiled code at $hex >>>" \
 		    "python gdb.Progspace.objfile_for_address"
 	    }
+
+	    # Check that jitted symbol completion works
+	    gdb_test "complete break jit_func" \
+		[multi_line "break jit_function_add" \
+		    "break jit_function_stack_mangle" ] \
+
+	    # Check that breakpoint can be set on jitted function
+	    gdb_test "break jit_function_add" \
+		"Breakpoint 1 at 0x\[0-9a-f\]+"
+	    gdb_test_no_output "del 1"
 	}
     }