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