xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/compile/compile-cplus-symbols.c (revision 6881a4007f077b54e5f51159c52b9b25f57deb0d)
1 /* Convert symbols from GDB to GCC
2 
3    Copyright (C) 2014-2023 Free Software Foundation, Inc.
4 
5    This file is part of GDB.
6 
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.
11 
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.
16 
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/>.  */
19 
20 
21 #include "defs.h"
22 #include "compile-internal.h"
23 #include "compile-cplus.h"
24 #include "gdbsupport/gdb_assert.h"
25 #include "symtab.h"
26 #include "parser-defs.h"
27 #include "block.h"
28 #include "objfiles.h"
29 #include "compile.h"
30 #include "value.h"
31 #include "exceptions.h"
32 #include "gdbtypes.h"
33 #include "dwarf2/loc.h"
34 #include "cp-support.h"
35 #include "gdbcmd.h"
36 #include "compile-c.h"
37 
38 /* Convert a given symbol, SYM, to the compiler's representation.
39    INSTANCE is the compiler instance.  IS_GLOBAL is true if the
40    symbol came from the global scope.  IS_LOCAL is true if the symbol
41    came from a local scope.  (Note that the two are not strictly
42    inverses because the symbol might have come from the static
43    scope.)  */
44 
45 static void
46 convert_one_symbol (compile_cplus_instance *instance,
47 		    struct block_symbol sym, bool is_global, bool is_local)
48 {
49   /* Squash compiler warning.  */
50   gcc_type sym_type = 0;
51   const char *filename = sym.symbol->symtab ()->filename;
52   unsigned short line = sym.symbol->line ();
53 
54   instance->error_symbol_once (sym.symbol);
55 
56   if (sym.symbol->aclass () == LOC_LABEL)
57     sym_type = 0;
58   else
59     sym_type = instance->convert_type (sym.symbol->type ());
60 
61   if (sym.symbol->domain () == STRUCT_DOMAIN)
62     {
63       /* Nothing to do.  */
64     }
65   else
66     {
67       /* Squash compiler warning.  */
68       gcc_cp_symbol_kind_flags kind = GCC_CP_FLAG_BASE;
69       CORE_ADDR addr = 0;
70       std::string name;
71       gdb::unique_xmalloc_ptr<char> symbol_name;
72 
73       switch (sym.symbol->aclass ())
74 	{
75 	case LOC_TYPEDEF:
76 	  if (sym.symbol->type ()->code () == TYPE_CODE_TYPEDEF)
77 	    kind = GCC_CP_SYMBOL_TYPEDEF;
78 	  else  if (sym.symbol->type ()->code () == TYPE_CODE_NAMESPACE)
79 	    return;
80 	  break;
81 
82 	case LOC_LABEL:
83 	  kind = GCC_CP_SYMBOL_LABEL;
84 	  addr = sym.symbol->value_address ();
85 	  break;
86 
87 	case LOC_BLOCK:
88 	  {
89 	    kind = GCC_CP_SYMBOL_FUNCTION;
90 	    addr = sym.symbol->value_block()->start ();
91 	    if (is_global && sym.symbol->type ()->is_gnu_ifunc ())
92 	      addr = gnu_ifunc_resolve_addr (target_gdbarch (), addr);
93 	  }
94 	  break;
95 
96 	case LOC_CONST:
97 	  if (sym.symbol->type ()->code () == TYPE_CODE_ENUM)
98 	    {
99 	      /* Already handled by convert_enum.  */
100 	      return;
101 	    }
102 	  instance->plugin ().build_constant
103 	    (sym_type, sym.symbol->natural_name (),
104 	     sym.symbol->value_longest (), filename, line);
105 	  return;
106 
107 	case LOC_CONST_BYTES:
108 	  error (_("Unsupported LOC_CONST_BYTES for symbol \"%s\"."),
109 		 sym.symbol->print_name ());
110 
111 	case LOC_UNDEF:
112 	  internal_error (_("LOC_UNDEF found for \"%s\"."),
113 			  sym.symbol->print_name ());
114 
115 	case LOC_COMMON_BLOCK:
116 	  error (_("Fortran common block is unsupported for compilation "
117 		   "evaluaton of symbol \"%s\"."),
118 		 sym.symbol->print_name ());
119 
120 	case LOC_OPTIMIZED_OUT:
121 	  error (_("Symbol \"%s\" cannot be used for compilation evaluation "
122 		   "as it is optimized out."),
123 		 sym.symbol->print_name ());
124 
125 	case LOC_COMPUTED:
126 	  if (is_local)
127 	    goto substitution;
128 	  /* Probably TLS here.  */
129 	  warning (_("Symbol \"%s\" is thread-local and currently can only "
130 		     "be referenced from the current thread in "
131 		     "compiled code."),
132 		   sym.symbol->print_name ());
133 	  /* FALLTHROUGH */
134 	case LOC_UNRESOLVED:
135 	  /* 'symbol_name' cannot be used here as that one is used only for
136 	     local variables from compile_dwarf_expr_to_c.
137 	     Global variables can be accessed by GCC only by their address, not
138 	     by their name.  */
139 	  {
140 	    struct value *val;
141 	    frame_info_ptr frame = nullptr;
142 
143 	    if (symbol_read_needs_frame (sym.symbol))
144 	      {
145 		frame = get_selected_frame (nullptr);
146 		if (frame == nullptr)
147 		  error (_("Symbol \"%s\" cannot be used because "
148 			   "there is no selected frame"),
149 			 sym.symbol->print_name ());
150 	      }
151 
152 	    val = read_var_value (sym.symbol, sym.block, frame);
153 	    if (VALUE_LVAL (val) != lval_memory)
154 	      error (_("Symbol \"%s\" cannot be used for compilation "
155 		       "evaluation as its address has not been found."),
156 		     sym.symbol->print_name ());
157 
158 	    kind = GCC_CP_SYMBOL_VARIABLE;
159 	    addr = value_address (val);
160 	  }
161 	  break;
162 
163 
164 	case LOC_REGISTER:
165 	case LOC_ARG:
166 	case LOC_REF_ARG:
167 	case LOC_REGPARM_ADDR:
168 	case LOC_LOCAL:
169 	substitution:
170 	  kind = GCC_CP_SYMBOL_VARIABLE;
171 	  symbol_name = c_symbol_substitution_name (sym.symbol);
172 	  break;
173 
174 	case LOC_STATIC:
175 	  kind = GCC_CP_SYMBOL_VARIABLE;
176 	  addr = sym.symbol->value_address ();
177 	  break;
178 
179 	case LOC_FINAL_VALUE:
180 	default:
181 	  gdb_assert_not_reached ("Unreachable case in convert_one_symbol.");
182 	}
183 
184       /* Don't emit local variable decls for a raw expression.  */
185       if (instance->scope () != COMPILE_I_RAW_SCOPE || symbol_name == nullptr)
186 	{
187 	  /* For non-local symbols, create/push a new scope so that the
188 	     symbol is properly scoped to the plug-in.  */
189 	  if (!is_local)
190 	    {
191 	      compile_scope scope
192 		= instance->new_scope (sym.symbol->natural_name (),
193 				       sym.symbol->type ());
194 	      if (scope.nested_type () != GCC_TYPE_NONE)
195 		{
196 		  /* We found a symbol for this type that was defined inside
197 		     some other symbol, e.g., a class typedef defined.  */
198 		  return;
199 		}
200 
201 	      instance->enter_scope (std::move (scope));
202 	    }
203 
204 	  /* Get the `raw' name of the symbol.  */
205 	  if (name.empty () && sym.symbol->natural_name () != nullptr)
206 	    name = compile_cplus_instance::decl_name
207 	      (sym.symbol->natural_name ()).get ();
208 
209 	  /* Define the decl.  */
210 	  instance->plugin ().build_decl
211 	    ("variable", name.c_str (), kind.raw (), sym_type,
212 	     symbol_name.get (), addr, filename, line);
213 
214 	  /* Pop scope for non-local symbols.  */
215 	  if (!is_local)
216 	    instance->leave_scope ();
217 	}
218     }
219 }
220 
221 /* Convert a full symbol to its gcc form.  CONTEXT is the compiler to
222    use, IDENTIFIER is the name of the symbol, SYM is the symbol
223    itself, and DOMAIN is the domain which was searched.  */
224 
225 static void
226 convert_symbol_sym (compile_cplus_instance *instance,
227 		    const char *identifier, struct block_symbol sym,
228 		    domain_enum domain)
229 {
230   /* If we found a symbol and it is not in the  static or global
231      scope, then we should first convert any static or global scope
232      symbol of the same name.  This lets this unusual case work:
233 
234      int x; // Global.
235      int func(void)
236      {
237      int x;
238      // At this spot, evaluate "extern int x; x"
239      }
240   */
241 
242   const struct block *static_block = block_static_block (sym.block);
243   /* STATIC_BLOCK is NULL if FOUND_BLOCK is the global block.  */
244   bool is_local_symbol = (sym.block != static_block && static_block != nullptr);
245   if (is_local_symbol)
246     {
247       struct block_symbol global_sym;
248 
249       global_sym = lookup_symbol (identifier, nullptr, domain, nullptr);
250       /* If the outer symbol is in the static block, we ignore it, as
251 	 it cannot be referenced.  */
252       if (global_sym.symbol != nullptr
253 	  && global_sym.block != block_static_block (global_sym.block))
254 	{
255 	  if (compile_debug)
256 	    gdb_printf (gdb_stdlog,
257 			"gcc_convert_symbol \"%s\": global symbol\n",
258 			identifier);
259 	  convert_one_symbol (instance, global_sym, true, false);
260 	}
261     }
262 
263   if (compile_debug)
264     gdb_printf (gdb_stdlog,
265 		"gcc_convert_symbol \"%s\": local symbol\n",
266 		identifier);
267   convert_one_symbol (instance, sym, false, is_local_symbol);
268 }
269 
270 /* Convert a minimal symbol to its gcc form.  CONTEXT is the compiler
271    to use and BMSYM is the minimal symbol to convert.  */
272 
273 static void
274 convert_symbol_bmsym (compile_cplus_instance *instance,
275 		      struct bound_minimal_symbol bmsym)
276 {
277   struct minimal_symbol *msym = bmsym.minsym;
278   struct objfile *objfile = bmsym.objfile;
279   struct type *type;
280   gcc_cp_symbol_kind_flags kind;
281   gcc_type sym_type;
282   CORE_ADDR addr;
283 
284   addr = msym->value_address (objfile);
285 
286   /* Conversion copied from write_exp_msymbol.  */
287   switch (msym->type ())
288     {
289     case mst_text:
290     case mst_file_text:
291     case mst_solib_trampoline:
292       type = objfile_type (objfile)->nodebug_text_symbol;
293       kind = GCC_CP_SYMBOL_FUNCTION;
294       break;
295 
296     case mst_text_gnu_ifunc:
297       /* nodebug_text_gnu_ifunc_symbol would cause:
298 	 function return type cannot be function  */
299       type = objfile_type (objfile)->nodebug_text_symbol;
300       kind = GCC_CP_SYMBOL_FUNCTION;
301       addr = gnu_ifunc_resolve_addr (target_gdbarch (), addr);
302       break;
303 
304     case mst_data:
305     case mst_file_data:
306     case mst_bss:
307     case mst_file_bss:
308       type = objfile_type (objfile)->nodebug_data_symbol;
309       kind = GCC_CP_SYMBOL_VARIABLE;
310       break;
311 
312     case mst_slot_got_plt:
313       type = objfile_type (objfile)->nodebug_got_plt_symbol;
314       kind = GCC_CP_SYMBOL_FUNCTION;
315       break;
316 
317     default:
318       type = objfile_type (objfile)->nodebug_unknown_symbol;
319       kind = GCC_CP_SYMBOL_VARIABLE;
320       break;
321     }
322 
323   sym_type = instance->convert_type (type);
324   instance->plugin ().push_namespace ("");
325   instance->plugin ().build_decl
326     ("minsym", msym->natural_name (), kind.raw (), sym_type, nullptr, addr,
327      nullptr, 0);
328   instance->plugin ().pop_binding_level ("");
329 }
330 
331 /* See compile-cplus.h.  */
332 
333 void
334 gcc_cplus_convert_symbol (void *datum,
335 			  struct gcc_cp_context *gcc_context,
336 			  enum gcc_cp_oracle_request request,
337 			  const char *identifier)
338 {
339   if (compile_debug)
340     gdb_printf (gdb_stdlog,
341 		"got oracle request for \"%s\"\n", identifier);
342 
343   bool found = false;
344   compile_cplus_instance *instance = (compile_cplus_instance *) datum;
345 
346   try
347     {
348       /* Symbol searching is a three part process unfortunately.  */
349 
350       /* First do a "standard" lookup, converting any found symbols.
351 	 This will find variables in the current scope.  */
352 
353       struct block_symbol sym
354 	= lookup_symbol (identifier, instance->block (), VAR_DOMAIN, nullptr);
355 
356       if (sym.symbol != nullptr)
357 	{
358 	  found = true;
359 	  convert_symbol_sym (instance, identifier, sym, VAR_DOMAIN);
360 	}
361 
362       /* Then use linespec.c's multi-symbol search.  This should find
363 	 all non-variable symbols for which we have debug info.  */
364 
365       symbol_searcher searcher;
366       searcher.find_all_symbols (identifier, current_language,
367 				 ALL_DOMAIN, nullptr, nullptr);
368 
369       /* Convert any found symbols.  */
370       for (const auto &it : searcher.matching_symbols ())
371 	{
372 	  /* Don't convert the symbol found above, if any, twice!  */
373 	  if (it.symbol != sym.symbol)
374 	    {
375 	      found = true;
376 	      convert_symbol_sym (instance, identifier, it,
377 				  it.symbol->domain ());
378 	    }
379 	}
380 
381       /* Finally, if no symbols have been found, fall back to minsyms.  */
382       if (!found)
383 	{
384 	  for (const auto &it : searcher.matching_msymbols ())
385 	    {
386 	      found = true;
387 	      convert_symbol_bmsym (instance, it);
388 	    }
389 	}
390     }
391   catch (const gdb_exception &e)
392     {
393       /* We can't allow exceptions to escape out of this callback.  Safest
394 	 is to simply emit a gcc error.  */
395       instance->plugin ().error (e.what ());
396     }
397 
398   if (compile_debug && !found)
399     gdb_printf (gdb_stdlog,
400 		"gcc_convert_symbol \"%s\": lookup_symbol failed\n",
401 		identifier);
402 
403   if (compile_debug)
404     {
405       if (found)
406 	gdb_printf (gdb_stdlog, "found type for %s\n", identifier);
407       else
408 	{
409 	  gdb_printf (gdb_stdlog, "did not find type for %s\n",
410 		      identifier);
411 	}
412     }
413 
414   return;
415 }
416 
417 /* See compile-cplus.h.  */
418 
419 gcc_address
420 gcc_cplus_symbol_address (void *datum, struct gcc_cp_context *gcc_context,
421 			  const char *identifier)
422 {
423   compile_cplus_instance *instance = (compile_cplus_instance *) datum;
424   gcc_address result = 0;
425   int found = 0;
426 
427   if (compile_debug)
428     gdb_printf (gdb_stdlog,
429 		"got oracle request for address of %s\n", identifier);
430 
431   /* We can't allow exceptions to escape out of this callback.  Safest
432      is to simply emit a gcc error.  */
433   try
434     {
435       struct symbol *sym
436 	= lookup_symbol (identifier, nullptr, VAR_DOMAIN, nullptr).symbol;
437 
438       if (sym != nullptr && sym->aclass () == LOC_BLOCK)
439 	{
440 	  if (compile_debug)
441 	    gdb_printf (gdb_stdlog,
442 			"gcc_symbol_address \"%s\": full symbol\n",
443 			identifier);
444 	  result = sym->value_block ()->start ();
445 	  if (sym->type ()->is_gnu_ifunc ())
446 	    result = gnu_ifunc_resolve_addr (target_gdbarch (), result);
447 	  found = 1;
448 	}
449       else
450 	{
451 	  struct bound_minimal_symbol msym;
452 
453 	  msym = lookup_bound_minimal_symbol (identifier);
454 	  if (msym.minsym != nullptr)
455 	    {
456 	      if (compile_debug)
457 		gdb_printf (gdb_stdlog,
458 			    "gcc_symbol_address \"%s\": minimal "
459 			    "symbol\n",
460 			    identifier);
461 	      result = msym.value_address ();
462 	      if (msym.minsym->type () == mst_text_gnu_ifunc)
463 		result = gnu_ifunc_resolve_addr (target_gdbarch (), result);
464 	      found = 1;
465 	    }
466 	}
467     }
468 
469   catch (const gdb_exception_error &e)
470     {
471       instance->plugin ().error (e.what ());
472     }
473 
474   if (compile_debug && !found)
475     gdb_printf (gdb_stdlog,
476 		"gcc_symbol_address \"%s\": failed\n",
477 		identifier);
478 
479   if (compile_debug)
480     {
481       if (found)
482 	gdb_printf (gdb_stdlog, "found address for %s!\n", identifier);
483       else
484 	gdb_printf (gdb_stdlog,
485 		    "did not find address for %s\n", identifier);
486     }
487 
488   return result;
489 }
490