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