Commit | Line | Data |
---|---|---|
078a0207 KS |
1 | /* Convert symbols from GDB to GCC |
2 | ||
42a4f53d | 3 | Copyright (C) 2014-2019 Free Software Foundation, Inc. |
078a0207 KS |
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" | |
0747795c | 24 | #include "common/gdb_assert.h" |
078a0207 KS |
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 "dwarf2loc.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 = symbol_symtab (sym.symbol)->filename; | |
52 | unsigned short line = SYMBOL_LINE (sym.symbol); | |
53 | ||
54 | instance->error_symbol_once (sym.symbol); | |
55 | ||
56 | if (SYMBOL_CLASS (sym.symbol) == LOC_LABEL) | |
57 | sym_type = 0; | |
58 | else | |
59 | sym_type = instance->convert_type (SYMBOL_TYPE (sym.symbol)); | |
60 | ||
61 | if (SYMBOL_DOMAIN (sym.symbol) == 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 (SYMBOL_CLASS (sym.symbol)) | |
74 | { | |
75 | case LOC_TYPEDEF: | |
76 | if (TYPE_CODE (SYMBOL_TYPE (sym.symbol)) == TYPE_CODE_TYPEDEF) | |
77 | kind = GCC_CP_SYMBOL_TYPEDEF; | |
78 | else if (TYPE_CODE (SYMBOL_TYPE (sym.symbol)) == TYPE_CODE_NAMESPACE) | |
79 | return; | |
80 | break; | |
81 | ||
82 | case LOC_LABEL: | |
83 | kind = GCC_CP_SYMBOL_LABEL; | |
84 | addr = SYMBOL_VALUE_ADDRESS (sym.symbol); | |
85 | break; | |
86 | ||
87 | case LOC_BLOCK: | |
88 | { | |
89 | kind = GCC_CP_SYMBOL_FUNCTION; | |
90 | addr = BLOCK_START (SYMBOL_BLOCK_VALUE (sym.symbol)); | |
91 | if (is_global && TYPE_GNU_IFUNC (SYMBOL_TYPE (sym.symbol))) | |
92 | addr = gnu_ifunc_resolve_addr (target_gdbarch (), addr); | |
93 | } | |
94 | break; | |
95 | ||
96 | case LOC_CONST: | |
97 | if (TYPE_CODE (SYMBOL_TYPE (sym.symbol)) == TYPE_CODE_ENUM) | |
98 | { | |
99 | /* Already handled by convert_enum. */ | |
100 | return; | |
101 | } | |
102 | instance->plugin ().build_constant | |
103 | (sym_type, SYMBOL_NATURAL_NAME (sym.symbol), | |
104 | SYMBOL_VALUE (sym.symbol), filename, line); | |
105 | return; | |
106 | ||
107 | case LOC_CONST_BYTES: | |
108 | error (_("Unsupported LOC_CONST_BYTES for symbol \"%s\"."), | |
109 | SYMBOL_PRINT_NAME (sym.symbol)); | |
110 | ||
111 | case LOC_UNDEF: | |
112 | internal_error (__FILE__, __LINE__, _("LOC_UNDEF found for \"%s\"."), | |
113 | SYMBOL_PRINT_NAME (sym.symbol)); | |
114 | ||
115 | case LOC_COMMON_BLOCK: | |
116 | error (_("Fortran common block is unsupported for compilation " | |
117 | "evaluaton of symbol \"%s\"."), | |
118 | SYMBOL_PRINT_NAME (sym.symbol)); | |
119 | ||
120 | case LOC_OPTIMIZED_OUT: | |
121 | error (_("Symbol \"%s\" cannot be used for compilation evaluation " | |
122 | "as it is optimized out."), | |
123 | SYMBOL_PRINT_NAME (sym.symbol)); | |
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 | SYMBOL_PRINT_NAME (sym.symbol)); | |
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 | struct frame_info *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 | SYMBOL_PRINT_NAME (sym.symbol)); | |
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 | SYMBOL_PRINT_NAME (sym.symbol)); | |
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 = SYMBOL_VALUE_ADDRESS (sym.symbol); | |
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 | { | |
078a0207 KS |
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 | { | |
d82b3862 | 191 | compile_scope scope |
078a0207 KS |
192 | = instance->new_scope (SYMBOL_NATURAL_NAME (sym.symbol), |
193 | SYMBOL_TYPE (sym.symbol)); | |
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 tyepdef defined. */ | |
198 | return; | |
199 | } | |
200 | ||
d82b3862 | 201 | instance->enter_scope (std::move (scope)); |
078a0207 KS |
202 | } |
203 | ||
204 | /* Get the `raw' name of the symbol. */ | |
205 | if (name.empty () && SYMBOL_NATURAL_NAME (sym.symbol) != nullptr) | |
206 | name = compile_cplus_instance::decl_name | |
207 | (SYMBOL_NATURAL_NAME (sym.symbol)).get (); | |
208 | ||
209 | /* Define the decl. */ | |
210 | instance->plugin ().build_decl | |
211 | ("variable", name.c_str (), kind, 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 | fprintf_unfiltered (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 | fprintf_unfiltered (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 = MSYMBOL_VALUE_ADDRESS (objfile, msym); | |
285 | ||
286 | /* Conversion copied from write_exp_msymbol. */ | |
287 | switch (MSYMBOL_TYPE (msym)) | |
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", MSYMBOL_NATURAL_NAME (msym), kind, 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, | |
5c889512 | 336 | enum gcc_cp_oracle_request request, |
078a0207 KS |
337 | const char *identifier) |
338 | { | |
339 | if (compile_debug) | |
340 | fprintf_unfiltered (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 | SYMBOL_DOMAIN (it.symbol)); | |
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 (e, RETURN_MASK_ALL) | |
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.message); | |
396 | } | |
397 | END_CATCH | |
398 | ||
399 | if (compile_debug && !found) | |
400 | fprintf_unfiltered (gdb_stdlog, | |
401 | "gcc_convert_symbol \"%s\": lookup_symbol failed\n", | |
402 | identifier); | |
403 | ||
404 | if (compile_debug) | |
405 | { | |
406 | if (found) | |
407 | fprintf_unfiltered (gdb_stdlog, "found type for %s\n", identifier); | |
408 | else | |
409 | { | |
410 | fprintf_unfiltered (gdb_stdlog, "did not find type for %s\n", | |
411 | identifier); | |
412 | } | |
413 | } | |
414 | ||
415 | return; | |
416 | } | |
417 | ||
418 | /* See compile-cplus.h. */ | |
419 | ||
420 | gcc_address | |
421 | gcc_cplus_symbol_address (void *datum, struct gcc_cp_context *gcc_context, | |
422 | const char *identifier) | |
423 | { | |
424 | compile_cplus_instance *instance = (compile_cplus_instance *) datum; | |
425 | gcc_address result = 0; | |
426 | int found = 0; | |
427 | ||
428 | if (compile_debug) | |
429 | fprintf_unfiltered (gdb_stdlog, | |
430 | "got oracle request for address of %s\n", identifier); | |
431 | ||
432 | /* We can't allow exceptions to escape out of this callback. Safest | |
433 | is to simply emit a gcc error. */ | |
434 | TRY | |
435 | { | |
436 | struct symbol *sym | |
437 | = lookup_symbol (identifier, nullptr, VAR_DOMAIN, nullptr).symbol; | |
438 | ||
439 | if (sym != nullptr && SYMBOL_CLASS (sym) == LOC_BLOCK) | |
440 | { | |
441 | if (compile_debug) | |
442 | fprintf_unfiltered (gdb_stdlog, | |
443 | "gcc_symbol_address \"%s\": full symbol\n", | |
444 | identifier); | |
445 | result = BLOCK_START (SYMBOL_BLOCK_VALUE (sym)); | |
446 | if (TYPE_GNU_IFUNC (SYMBOL_TYPE (sym))) | |
447 | result = gnu_ifunc_resolve_addr (target_gdbarch (), result); | |
448 | found = 1; | |
449 | } | |
450 | else | |
451 | { | |
452 | struct bound_minimal_symbol msym; | |
453 | ||
454 | msym = lookup_bound_minimal_symbol (identifier); | |
455 | if (msym.minsym != nullptr) | |
456 | { | |
457 | if (compile_debug) | |
458 | fprintf_unfiltered (gdb_stdlog, | |
459 | "gcc_symbol_address \"%s\": minimal " | |
460 | "symbol\n", | |
461 | identifier); | |
462 | result = BMSYMBOL_VALUE_ADDRESS (msym); | |
463 | if (MSYMBOL_TYPE (msym.minsym) == mst_text_gnu_ifunc) | |
464 | result = gnu_ifunc_resolve_addr (target_gdbarch (), result); | |
465 | found = 1; | |
466 | } | |
467 | } | |
468 | } | |
469 | ||
470 | CATCH (e, RETURN_MASK_ERROR) | |
471 | { | |
472 | instance->plugin ().error (e.message); | |
473 | } | |
474 | END_CATCH | |
475 | ||
476 | if (compile_debug && !found) | |
477 | fprintf_unfiltered (gdb_stdlog, | |
478 | "gcc_symbol_address \"%s\": failed\n", | |
479 | identifier); | |
480 | ||
481 | if (compile_debug) | |
482 | { | |
483 | if (found) | |
484 | fprintf_unfiltered (gdb_stdlog, "found address for %s!\n", identifier); | |
485 | else | |
486 | fprintf_unfiltered (gdb_stdlog, | |
487 | "did not find address for %s\n", identifier); | |
488 | } | |
489 | ||
490 | return result; | |
491 | } |