1 /* Convert symbols from GDB to GCC
3 Copyright (C) 2014-2023 Free Software Foundation, Inc.
5 This file is part of GDB.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
22 #include "compile-internal.h"
23 #include "compile-c.h"
25 #include "parser-defs.h"
30 #include "exceptions.h"
32 #include "dwarf2/loc.h"
36 /* Compute the name of the pointer representing a local symbol's
39 gdb::unique_xmalloc_ptr
<char>
40 c_symbol_substitution_name (struct symbol
*sym
)
42 return gdb::unique_xmalloc_ptr
<char>
43 (concat ("__", sym
->natural_name (), "_ptr", (char *) NULL
));
46 /* Convert a given symbol, SYM, to the compiler's representation.
47 CONTEXT is the compiler instance. IS_GLOBAL is true if the
48 symbol came from the global scope. IS_LOCAL is true if the symbol
49 came from a local scope. (Note that the two are not strictly
50 inverses because the symbol might have come from the static
54 convert_one_symbol (compile_c_instance
*context
,
55 struct block_symbol sym
,
60 const char *filename
= sym
.symbol
->symtab ()->filename
;
61 unsigned int line
= sym
.symbol
->line ();
63 context
->error_symbol_once (sym
.symbol
);
65 if (sym
.symbol
->aclass () == LOC_LABEL
)
68 sym_type
= context
->convert_type (sym
.symbol
->type ());
70 if (sym
.symbol
->domain () == STRUCT_DOMAIN
)
72 /* Binding a tag, so we don't need to build a decl. */
73 context
->plugin ().tagbind (sym
.symbol
->natural_name (),
74 sym_type
, filename
, line
);
79 enum gcc_c_symbol_kind kind
;
81 gdb::unique_xmalloc_ptr
<char> symbol_name
;
83 switch (sym
.symbol
->aclass ())
86 kind
= GCC_C_SYMBOL_TYPEDEF
;
90 kind
= GCC_C_SYMBOL_LABEL
;
91 addr
= sym
.symbol
->value_address ();
95 kind
= GCC_C_SYMBOL_FUNCTION
;
96 addr
= sym
.symbol
->value_block ()->entry_pc ();
97 if (is_global
&& sym
.symbol
->type ()->is_gnu_ifunc ())
98 addr
= gnu_ifunc_resolve_addr (current_inferior ()->arch (), addr
);
102 if (sym
.symbol
->type ()->code () == TYPE_CODE_ENUM
)
104 /* Already handled by convert_enum. */
107 context
->plugin ().build_constant
108 (sym_type
, sym
.symbol
->natural_name (),
109 sym
.symbol
->value_longest (),
113 case LOC_CONST_BYTES
:
114 error (_("Unsupported LOC_CONST_BYTES for symbol \"%s\"."),
115 sym
.symbol
->print_name ());
118 internal_error (_("LOC_UNDEF found for \"%s\"."),
119 sym
.symbol
->print_name ());
121 case LOC_COMMON_BLOCK
:
122 error (_("Fortran common block is unsupported for compilation "
123 "evaluaton of symbol \"%s\"."),
124 sym
.symbol
->print_name ());
126 case LOC_OPTIMIZED_OUT
:
127 error (_("Symbol \"%s\" cannot be used for compilation evaluation "
128 "as it is optimized out."),
129 sym
.symbol
->print_name ());
134 /* Probably TLS here. */
135 warning (_("Symbol \"%s\" is thread-local and currently can only "
136 "be referenced from the current thread in "
138 sym
.symbol
->print_name ());
141 /* 'symbol_name' cannot be used here as that one is used only for
142 local variables from compile_dwarf_expr_to_c.
143 Global variables can be accessed by GCC only by their address, not
147 frame_info_ptr frame
= NULL
;
149 if (symbol_read_needs_frame (sym
.symbol
))
151 frame
= get_selected_frame (NULL
);
153 error (_("Symbol \"%s\" cannot be used because "
154 "there is no selected frame"),
155 sym
.symbol
->print_name ());
158 val
= read_var_value (sym
.symbol
, sym
.block
, frame
);
159 if (val
->lval () != lval_memory
)
160 error (_("Symbol \"%s\" cannot be used for compilation "
161 "evaluation as its address has not been found."),
162 sym
.symbol
->print_name ());
164 kind
= GCC_C_SYMBOL_VARIABLE
;
165 addr
= val
->address ();
173 case LOC_REGPARM_ADDR
:
176 kind
= GCC_C_SYMBOL_VARIABLE
;
177 symbol_name
= c_symbol_substitution_name (sym
.symbol
);
181 kind
= GCC_C_SYMBOL_VARIABLE
;
182 addr
= sym
.symbol
->value_address ();
185 case LOC_FINAL_VALUE
:
187 gdb_assert_not_reached ("Unreachable case in convert_one_symbol.");
191 /* Don't emit local variable decls for a raw expression. */
192 if (context
->scope () != COMPILE_I_RAW_SCOPE
193 || symbol_name
== NULL
)
195 decl
= context
->plugin ().build_decl
196 (sym
.symbol
->natural_name (),
199 symbol_name
.get (), addr
,
202 context
->plugin ().bind (decl
, is_global
);
207 /* Convert a full symbol to its gcc form. CONTEXT is the compiler to
208 use, IDENTIFIER is the name of the symbol, SYM is the symbol
209 itself, and DOMAIN is the domain which was searched. */
212 convert_symbol_sym (compile_c_instance
*context
, const char *identifier
,
213 struct block_symbol sym
, domain_enum domain
)
217 /* If we found a symbol and it is not in the static or global
218 scope, then we should first convert any static or global scope
219 symbol of the same name. This lets this unusual case work:
225 // At this spot, evaluate "extern int x; x"
229 const struct block
*static_block
= nullptr;
230 if (sym
.block
!= nullptr)
231 static_block
= sym
.block
->static_block ();
232 /* STATIC_BLOCK is NULL if FOUND_BLOCK is the global block. */
233 is_local_symbol
= (sym
.block
!= static_block
&& static_block
!= NULL
);
236 struct block_symbol global_sym
;
238 global_sym
= lookup_symbol (identifier
, NULL
, domain
, NULL
);
239 /* If the outer symbol is in the static block, we ignore it, as
240 it cannot be referenced. */
241 if (global_sym
.symbol
!= NULL
242 && global_sym
.block
!= global_sym
.block
->static_block ())
245 gdb_printf (gdb_stdlog
,
246 "gcc_convert_symbol \"%s\": global symbol\n",
248 convert_one_symbol (context
, global_sym
, 1, 0);
253 gdb_printf (gdb_stdlog
,
254 "gcc_convert_symbol \"%s\": local symbol\n",
256 convert_one_symbol (context
, sym
, 0, is_local_symbol
);
259 /* Convert a minimal symbol to its gcc form. CONTEXT is the compiler
260 to use and BMSYM is the minimal symbol to convert. */
263 convert_symbol_bmsym (compile_c_instance
*context
,
264 struct bound_minimal_symbol bmsym
)
266 struct minimal_symbol
*msym
= bmsym
.minsym
;
267 struct objfile
*objfile
= bmsym
.objfile
;
269 enum gcc_c_symbol_kind kind
;
274 addr
= msym
->value_address (objfile
);
276 /* Conversion copied from write_exp_msymbol. */
277 switch (msym
->type ())
281 case mst_solib_trampoline
:
282 type
= builtin_type (objfile
)->nodebug_text_symbol
;
283 kind
= GCC_C_SYMBOL_FUNCTION
;
286 case mst_text_gnu_ifunc
:
287 type
= builtin_type (objfile
)->nodebug_text_gnu_ifunc_symbol
;
288 kind
= GCC_C_SYMBOL_FUNCTION
;
289 addr
= gnu_ifunc_resolve_addr (current_inferior ()->arch (), addr
);
296 type
= builtin_type (objfile
)->nodebug_data_symbol
;
297 kind
= GCC_C_SYMBOL_VARIABLE
;
300 case mst_slot_got_plt
:
301 type
= builtin_type (objfile
)->nodebug_got_plt_symbol
;
302 kind
= GCC_C_SYMBOL_FUNCTION
;
306 type
= builtin_type (objfile
)->nodebug_unknown_symbol
;
307 kind
= GCC_C_SYMBOL_VARIABLE
;
311 sym_type
= context
->convert_type (type
);
312 decl
= context
->plugin ().build_decl (msym
->natural_name (),
313 kind
, sym_type
, NULL
, addr
,
315 context
->plugin ().bind (decl
, 1 /* is_global */);
318 /* See compile-internal.h. */
321 gcc_convert_symbol (void *datum
,
322 struct gcc_c_context
*gcc_context
,
323 enum gcc_c_oracle_request request
,
324 const char *identifier
)
326 compile_c_instance
*context
327 = static_cast<compile_c_instance
*> (datum
);
333 case GCC_C_ORACLE_SYMBOL
:
336 case GCC_C_ORACLE_TAG
:
337 domain
= STRUCT_DOMAIN
;
339 case GCC_C_ORACLE_LABEL
:
340 domain
= LABEL_DOMAIN
;
343 gdb_assert_not_reached ("Unrecognized oracle request.");
346 /* We can't allow exceptions to escape out of this callback. Safest
347 is to simply emit a gcc error. */
350 struct block_symbol sym
;
352 sym
= lookup_symbol (identifier
, context
->block (), domain
, NULL
);
353 if (sym
.symbol
!= NULL
)
355 convert_symbol_sym (context
, identifier
, sym
, domain
);
358 else if (domain
== VAR_DOMAIN
)
360 struct bound_minimal_symbol bmsym
;
362 bmsym
= lookup_minimal_symbol (identifier
, NULL
, NULL
);
363 if (bmsym
.minsym
!= NULL
)
365 convert_symbol_bmsym (context
, bmsym
);
371 catch (const gdb_exception
&e
)
373 context
->plugin ().error (e
.what ());
376 if (compile_debug
&& !found
)
377 gdb_printf (gdb_stdlog
,
378 "gcc_convert_symbol \"%s\": lookup_symbol failed\n",
383 /* See compile-internal.h. */
386 gcc_symbol_address (void *datum
, struct gcc_c_context
*gcc_context
,
387 const char *identifier
)
389 compile_c_instance
*context
390 = static_cast<compile_c_instance
*> (datum
);
391 gcc_address result
= 0;
394 /* We can't allow exceptions to escape out of this callback. Safest
395 is to simply emit a gcc error. */
400 /* We only need global functions here. */
401 sym
= lookup_symbol (identifier
, NULL
, VAR_DOMAIN
, NULL
).symbol
;
402 if (sym
!= NULL
&& sym
->aclass () == LOC_BLOCK
)
405 gdb_printf (gdb_stdlog
,
406 "gcc_symbol_address \"%s\": full symbol\n",
408 result
= sym
->value_block ()->entry_pc ();
409 if (sym
->type ()->is_gnu_ifunc ())
410 result
= gnu_ifunc_resolve_addr (current_inferior ()->arch (),
416 struct bound_minimal_symbol msym
;
418 msym
= lookup_bound_minimal_symbol (identifier
);
419 if (msym
.minsym
!= NULL
)
422 gdb_printf (gdb_stdlog
,
423 "gcc_symbol_address \"%s\": minimal "
426 result
= msym
.value_address ();
427 if (msym
.minsym
->type () == mst_text_gnu_ifunc
)
428 result
= gnu_ifunc_resolve_addr (current_inferior ()->arch (),
435 catch (const gdb_exception_error
&e
)
437 context
->plugin ().error (e
.what ());
440 if (compile_debug
&& !found
)
441 gdb_printf (gdb_stdlog
,
442 "gcc_symbol_address \"%s\": failed\n",
449 /* A hash function for symbol names. */
452 hash_symname (const void *a
)
454 const struct symbol
*sym
= (const struct symbol
*) a
;
456 return htab_hash_string (sym
->natural_name ());
459 /* A comparison function for hash tables that just looks at symbol
463 eq_symname (const void *a
, const void *b
)
465 const struct symbol
*syma
= (const struct symbol
*) a
;
466 const struct symbol
*symb
= (const struct symbol
*) b
;
468 return strcmp (syma
->natural_name (), symb
->natural_name ()) == 0;
471 /* If a symbol with the same name as SYM is already in HASHTAB, return
472 1. Otherwise, add SYM to HASHTAB and return 0. */
475 symbol_seen (htab_t hashtab
, struct symbol
*sym
)
479 slot
= htab_find_slot (hashtab
, sym
, INSERT
);
487 /* Generate C code to compute the length of a VLA. */
490 generate_vla_size (compile_instance
*compiler
,
492 struct gdbarch
*gdbarch
,
493 std::vector
<bool> ®isters_used
,
498 type
= check_typedef (type
);
500 if (TYPE_IS_REFERENCE (type
))
501 type
= check_typedef (type
->target_type ());
503 switch (type
->code ())
505 case TYPE_CODE_RANGE
:
507 if (type
->bounds ()->high
.kind () == PROP_LOCEXPR
508 || type
->bounds ()->high
.kind () == PROP_LOCLIST
)
510 const struct dynamic_prop
*prop
= &type
->bounds ()->high
;
511 std::string name
= c_get_range_decl_name (prop
);
513 dwarf2_compile_property_to_c (stream
, name
.c_str (),
514 gdbarch
, registers_used
,
520 case TYPE_CODE_ARRAY
:
521 generate_vla_size (compiler
, stream
, gdbarch
, registers_used
, pc
,
522 type
->index_type (), sym
);
523 generate_vla_size (compiler
, stream
, gdbarch
, registers_used
, pc
,
524 type
->target_type (), sym
);
527 case TYPE_CODE_UNION
:
528 case TYPE_CODE_STRUCT
:
532 for (i
= 0; i
< type
->num_fields (); ++i
)
533 if (!type
->field (i
).is_static ())
534 generate_vla_size (compiler
, stream
, gdbarch
, registers_used
, pc
,
535 type
->field (i
).type (), sym
);
541 /* Generate C code to compute the address of SYM. */
544 generate_c_for_for_one_variable (compile_instance
*compiler
,
546 struct gdbarch
*gdbarch
,
547 std::vector
<bool> ®isters_used
,
554 if (is_dynamic_type (sym
->type ()))
556 /* We need to emit to a temporary buffer in case an error
557 occurs in the middle. */
558 string_file local_file
;
560 generate_vla_size (compiler
, &local_file
, gdbarch
, registers_used
, pc
,
563 stream
->write (local_file
.c_str (), local_file
.size ());
566 if (SYMBOL_COMPUTED_OPS (sym
) != NULL
)
568 gdb::unique_xmalloc_ptr
<char> generated_name
569 = c_symbol_substitution_name (sym
);
570 /* We need to emit to a temporary buffer in case an error
571 occurs in the middle. */
572 string_file local_file
;
574 SYMBOL_COMPUTED_OPS (sym
)->generate_c_location (sym
, &local_file
,
578 generated_name
.get ());
579 stream
->write (local_file
.c_str (), local_file
.size ());
583 switch (sym
->aclass ())
588 case LOC_REGPARM_ADDR
:
590 error (_("Local symbol unhandled when generating C code."));
593 gdb_assert_not_reached ("LOC_COMPUTED variable "
594 "missing a method.");
597 /* Nothing to do for all other cases, as they don't represent
604 catch (const gdb_exception_error
&e
)
606 compiler
->insert_symbol_error (sym
, e
.what ());
610 /* See compile-c.h. */
613 generate_c_for_variable_locations (compile_instance
*compiler
,
615 struct gdbarch
*gdbarch
,
616 const struct block
*block
,
619 if (block
== nullptr)
622 const struct block
*static_block
= block
->static_block ();
624 /* If we're already in the static or global block, there is nothing
626 if (static_block
== NULL
|| block
== static_block
)
629 std::vector
<bool> registers_used (gdbarch_num_regs (gdbarch
));
631 /* Ensure that a given name is only entered once. This reflects the
632 reality of shadowing. */
633 htab_up
symhash (htab_create_alloc (1, hash_symname
, eq_symname
, NULL
,
638 /* Iterate over symbols in this block, generating code to
639 compute the location of each local variable. */
640 for (struct symbol
*sym
: block_iterator_range (block
))
642 if (!symbol_seen (symhash
.get (), sym
))
643 generate_c_for_for_one_variable (compiler
, stream
, gdbarch
,
644 registers_used
, pc
, sym
);
647 /* If we just finished the outermost block of a function, we're
649 if (block
->function () != NULL
)
651 block
= block
->superblock ();
654 return registers_used
;