]>
Commit | Line | Data |
---|---|---|
e1b16eb4 JK |
1 | /* Virtual tail call frames unwinder for GDB. |
2 | ||
1d506c26 | 3 | Copyright (C) 2010-2024 Free Software Foundation, Inc. |
e1b16eb4 JK |
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 | #include "defs.h" | |
4de283e4 | 21 | #include "frame.h" |
82ca8957 TT |
22 | #include "dwarf2/frame-tailcall.h" |
23 | #include "dwarf2/loc.h" | |
e1b16eb4 | 24 | #include "frame-unwind.h" |
4de283e4 | 25 | #include "block.h" |
d55e5aa6 | 26 | #include "hashtab.h" |
4de283e4 | 27 | #include "gdbtypes.h" |
e1b16eb4 JK |
28 | #include "regcache.h" |
29 | #include "value.h" | |
82ca8957 | 30 | #include "dwarf2/frame.h" |
0d12e84c | 31 | #include "gdbarch.h" |
e1b16eb4 JK |
32 | |
33 | /* Contains struct tailcall_cache indexed by next_bottom_frame. */ | |
34 | static htab_t cache_htab; | |
35 | ||
36 | /* Associate structure of the unwinder to call_site_chain. Lifetime of this | |
37 | structure is maintained by REFC decremented by dealloc_cache, all of them | |
38 | get deleted during reinit_frame_cache. */ | |
39 | struct tailcall_cache | |
40 | { | |
41 | /* It must be the first one of this struct. It is the furthest callee. */ | |
bd2b40ac | 42 | frame_info *next_bottom_frame; |
e1b16eb4 JK |
43 | |
44 | /* Reference count. The whole chain of virtual tail call frames shares one | |
45 | tailcall_cache. */ | |
46 | int refc; | |
47 | ||
85102364 | 48 | /* Associated found virtual tail call frames chain, it is never NULL. */ |
e1b16eb4 JK |
49 | struct call_site_chain *chain; |
50 | ||
51 | /* Cached pretended_chain_levels result. */ | |
52 | int chain_levels; | |
53 | ||
54 | /* Unwound PC from the top (caller) frame, as it is not contained | |
55 | in CHAIN. */ | |
56 | CORE_ADDR prev_pc; | |
57 | ||
58 | /* Compensate SP in caller frames appropriately. prev_sp and | |
59 | entry_cfa_sp_offset are valid only if PREV_SP_P. PREV_SP is SP at the top | |
60 | (caller) frame. ENTRY_CFA_SP_OFFSET is shift of SP in tail call frames | |
61 | against next_bottom_frame SP. */ | |
62 | unsigned prev_sp_p : 1; | |
63 | CORE_ADDR prev_sp; | |
64 | LONGEST entry_cfa_sp_offset; | |
65 | }; | |
66 | ||
67 | /* hash_f for htab_create_alloc of cache_htab. */ | |
68 | ||
69 | static hashval_t | |
70 | cache_hash (const void *arg) | |
71 | { | |
9a3c8263 | 72 | const struct tailcall_cache *cache = (const struct tailcall_cache *) arg; |
e1b16eb4 JK |
73 | |
74 | return htab_hash_pointer (cache->next_bottom_frame); | |
75 | } | |
76 | ||
77 | /* eq_f for htab_create_alloc of cache_htab. */ | |
78 | ||
79 | static int | |
80 | cache_eq (const void *arg1, const void *arg2) | |
81 | { | |
9a3c8263 SM |
82 | const struct tailcall_cache *cache1 = (const struct tailcall_cache *) arg1; |
83 | const struct tailcall_cache *cache2 = (const struct tailcall_cache *) arg2; | |
e1b16eb4 JK |
84 | |
85 | return cache1->next_bottom_frame == cache2->next_bottom_frame; | |
86 | } | |
87 | ||
88 | /* Create new tailcall_cache for NEXT_BOTTOM_FRAME, NEXT_BOTTOM_FRAME must not | |
89 | yet have been indexed by cache_htab. Caller holds one reference of the new | |
90 | tailcall_cache. */ | |
91 | ||
92 | static struct tailcall_cache * | |
bd2b40ac | 93 | cache_new_ref1 (frame_info_ptr next_bottom_frame) |
e1b16eb4 | 94 | { |
8d749320 | 95 | struct tailcall_cache *cache = XCNEW (struct tailcall_cache); |
e1b16eb4 JK |
96 | void **slot; |
97 | ||
bd2b40ac | 98 | cache->next_bottom_frame = next_bottom_frame.get (); |
e1b16eb4 JK |
99 | cache->refc = 1; |
100 | ||
101 | slot = htab_find_slot (cache_htab, cache, INSERT); | |
102 | gdb_assert (*slot == NULL); | |
103 | *slot = cache; | |
104 | ||
105 | return cache; | |
106 | } | |
107 | ||
108 | /* Create new reference to CACHE. */ | |
109 | ||
110 | static void | |
111 | cache_ref (struct tailcall_cache *cache) | |
112 | { | |
113 | gdb_assert (cache->refc > 0); | |
114 | ||
115 | cache->refc++; | |
116 | } | |
117 | ||
118 | /* Drop reference to CACHE, possibly fully freeing it and unregistering it from | |
119 | cache_htab. */ | |
120 | ||
121 | static void | |
122 | cache_unref (struct tailcall_cache *cache) | |
123 | { | |
124 | gdb_assert (cache->refc > 0); | |
125 | ||
126 | if (!--cache->refc) | |
127 | { | |
128 | gdb_assert (htab_find_slot (cache_htab, cache, NO_INSERT) != NULL); | |
129 | htab_remove_elt (cache_htab, cache); | |
130 | ||
131 | xfree (cache->chain); | |
132 | xfree (cache); | |
133 | } | |
134 | } | |
135 | ||
136 | /* Return 1 if FI is a non-bottom (not the callee) tail call frame. Otherwise | |
137 | return 0. */ | |
138 | ||
139 | static int | |
bd2b40ac | 140 | frame_is_tailcall (frame_info_ptr fi) |
e1b16eb4 JK |
141 | { |
142 | return frame_unwinder_is (fi, &dwarf2_tailcall_frame_unwind); | |
143 | } | |
144 | ||
145 | /* Try to find tailcall_cache in cache_htab if FI is a part of its virtual tail | |
146 | call chain. Otherwise return NULL. No new reference is created. */ | |
147 | ||
148 | static struct tailcall_cache * | |
bd2b40ac | 149 | cache_find (frame_info_ptr fi) |
e1b16eb4 JK |
150 | { |
151 | struct tailcall_cache *cache; | |
bd2b40ac | 152 | struct tailcall_cache search; |
e1b16eb4 JK |
153 | void **slot; |
154 | ||
155 | while (frame_is_tailcall (fi)) | |
156 | { | |
157 | fi = get_next_frame (fi); | |
158 | gdb_assert (fi != NULL); | |
159 | } | |
160 | ||
bd2b40ac TT |
161 | search.next_bottom_frame = fi.get(); |
162 | search.refc = 1; | |
163 | slot = htab_find_slot (cache_htab, &search, NO_INSERT); | |
e1b16eb4 JK |
164 | if (slot == NULL) |
165 | return NULL; | |
166 | ||
9a3c8263 | 167 | cache = (struct tailcall_cache *) *slot; |
e1b16eb4 JK |
168 | gdb_assert (cache != NULL); |
169 | return cache; | |
170 | } | |
171 | ||
172 | /* Number of virtual frames between THIS_FRAME and CACHE->NEXT_BOTTOM_FRAME. | |
173 | If THIS_FRAME is CACHE-> NEXT_BOTTOM_FRAME return -1. */ | |
174 | ||
175 | static int | |
bd2b40ac | 176 | existing_next_levels (frame_info_ptr this_frame, |
e1b16eb4 JK |
177 | struct tailcall_cache *cache) |
178 | { | |
179 | int retval = (frame_relative_level (this_frame) | |
bd2b40ac | 180 | - frame_relative_level (frame_info_ptr (cache->next_bottom_frame)) - 1); |
e1b16eb4 JK |
181 | |
182 | gdb_assert (retval >= -1); | |
183 | ||
184 | return retval; | |
185 | } | |
186 | ||
187 | /* The number of virtual tail call frames in CHAIN. With no virtual tail call | |
188 | frames the function would return 0 (but CHAIN does not exist in such | |
189 | case). */ | |
190 | ||
191 | static int | |
192 | pretended_chain_levels (struct call_site_chain *chain) | |
193 | { | |
194 | int chain_levels; | |
195 | ||
196 | gdb_assert (chain != NULL); | |
197 | ||
198 | if (chain->callers == chain->length && chain->callees == chain->length) | |
199 | return chain->length; | |
200 | ||
201 | chain_levels = chain->callers + chain->callees; | |
e0619de6 | 202 | gdb_assert (chain_levels <= chain->length); |
e1b16eb4 JK |
203 | |
204 | return chain_levels; | |
205 | } | |
206 | ||
207 | /* Implementation of frame_this_id_ftype. THIS_CACHE must be already | |
208 | initialized with tailcall_cache, THIS_FRAME must be a part of THIS_CACHE. | |
209 | ||
210 | Specific virtual tail call frames are tracked by INLINE_DEPTH. */ | |
211 | ||
212 | static void | |
bd2b40ac | 213 | tailcall_frame_this_id (frame_info_ptr this_frame, void **this_cache, |
e1b16eb4 JK |
214 | struct frame_id *this_id) |
215 | { | |
9a3c8263 | 216 | struct tailcall_cache *cache = (struct tailcall_cache *) *this_cache; |
bd2b40ac | 217 | frame_info_ptr next_frame; |
e1b16eb4 JK |
218 | |
219 | /* Tail call does not make sense for a sentinel frame. */ | |
220 | next_frame = get_next_frame (this_frame); | |
221 | gdb_assert (next_frame != NULL); | |
222 | ||
223 | *this_id = get_frame_id (next_frame); | |
224 | (*this_id).code_addr = get_frame_pc (this_frame); | |
97916bfe | 225 | (*this_id).code_addr_p = true; |
193facb3 JK |
226 | (*this_id).artificial_depth = (cache->chain_levels |
227 | - existing_next_levels (this_frame, cache)); | |
228 | gdb_assert ((*this_id).artificial_depth > 0); | |
e1b16eb4 JK |
229 | } |
230 | ||
231 | /* Find PC to be unwound from THIS_FRAME. THIS_FRAME must be a part of | |
232 | CACHE. */ | |
233 | ||
234 | static CORE_ADDR | |
bd2b40ac | 235 | pretend_pc (frame_info_ptr this_frame, struct tailcall_cache *cache) |
e1b16eb4 JK |
236 | { |
237 | int next_levels = existing_next_levels (this_frame, cache); | |
238 | struct call_site_chain *chain = cache->chain; | |
e1b16eb4 JK |
239 | |
240 | gdb_assert (chain != NULL); | |
241 | ||
242 | next_levels++; | |
243 | gdb_assert (next_levels >= 0); | |
244 | ||
245 | if (next_levels < chain->callees) | |
b84aaada | 246 | return chain->call_site[chain->length - next_levels - 1]->pc (); |
e1b16eb4 JK |
247 | next_levels -= chain->callees; |
248 | ||
249 | /* Otherwise CHAIN->CALLEES are already covered by CHAIN->CALLERS. */ | |
250 | if (chain->callees != chain->length) | |
251 | { | |
252 | if (next_levels < chain->callers) | |
b84aaada | 253 | return chain->call_site[chain->callers - next_levels - 1]->pc (); |
e1b16eb4 JK |
254 | next_levels -= chain->callers; |
255 | } | |
256 | ||
257 | gdb_assert (next_levels == 0); | |
258 | return cache->prev_pc; | |
259 | } | |
260 | ||
261 | /* Implementation of frame_prev_register_ftype. If no specific register | |
262 | override is supplied NULL is returned (this is incompatible with | |
263 | frame_prev_register_ftype semantics). next_bottom_frame and tail call | |
264 | frames unwind the NULL case differently. */ | |
265 | ||
266 | struct value * | |
bd2b40ac | 267 | dwarf2_tailcall_prev_register_first (frame_info_ptr this_frame, |
e1b16eb4 JK |
268 | void **tailcall_cachep, int regnum) |
269 | { | |
270 | struct gdbarch *this_gdbarch = get_frame_arch (this_frame); | |
9a3c8263 | 271 | struct tailcall_cache *cache = (struct tailcall_cache *) *tailcall_cachep; |
e1b16eb4 JK |
272 | CORE_ADDR addr; |
273 | ||
274 | if (regnum == gdbarch_pc_regnum (this_gdbarch)) | |
275 | addr = pretend_pc (this_frame, cache); | |
276 | else if (cache->prev_sp_p && regnum == gdbarch_sp_regnum (this_gdbarch)) | |
277 | { | |
278 | int next_levels = existing_next_levels (this_frame, cache); | |
279 | ||
280 | if (next_levels == cache->chain_levels - 1) | |
281 | addr = cache->prev_sp; | |
282 | else | |
13294f7d | 283 | addr = dwarf2_frame_cfa (this_frame) - cache->entry_cfa_sp_offset; |
e1b16eb4 JK |
284 | } |
285 | else | |
286 | return NULL; | |
287 | ||
288 | return frame_unwind_got_address (this_frame, regnum, addr); | |
289 | } | |
290 | ||
291 | /* Implementation of frame_prev_register_ftype for tail call frames. Register | |
292 | set of virtual tail call frames is assumed to be the one of the top (caller) | |
293 | frame - assume unchanged register value for NULL from | |
294 | dwarf2_tailcall_prev_register_first. */ | |
295 | ||
296 | static struct value * | |
bd2b40ac | 297 | tailcall_frame_prev_register (frame_info_ptr this_frame, |
e1b16eb4 JK |
298 | void **this_cache, int regnum) |
299 | { | |
9a3c8263 | 300 | struct tailcall_cache *cache = (struct tailcall_cache *) *this_cache; |
e1b16eb4 JK |
301 | struct value *val; |
302 | ||
303 | gdb_assert (this_frame != cache->next_bottom_frame); | |
304 | ||
305 | val = dwarf2_tailcall_prev_register_first (this_frame, this_cache, regnum); | |
306 | if (val) | |
307 | return val; | |
308 | ||
309 | return frame_unwind_got_register (this_frame, regnum, regnum); | |
310 | } | |
311 | ||
312 | /* Implementation of frame_sniffer_ftype. It will never find a new chain, use | |
313 | dwarf2_tailcall_sniffer_first for the bottom (callee) frame. It will find | |
314 | all the predecessing virtual tail call frames, it will return false when | |
315 | there exist no more tail call frames in this chain. */ | |
316 | ||
317 | static int | |
318 | tailcall_frame_sniffer (const struct frame_unwind *self, | |
bd2b40ac | 319 | frame_info_ptr this_frame, void **this_cache) |
e1b16eb4 | 320 | { |
bd2b40ac | 321 | frame_info_ptr next_frame; |
e1b16eb4 JK |
322 | int next_levels; |
323 | struct tailcall_cache *cache; | |
324 | ||
3c3bb058 AB |
325 | if (!dwarf2_frame_unwinders_enabled_p) |
326 | return 0; | |
327 | ||
e1b16eb4 JK |
328 | /* Inner tail call element does not make sense for a sentinel frame. */ |
329 | next_frame = get_next_frame (this_frame); | |
330 | if (next_frame == NULL) | |
331 | return 0; | |
332 | ||
333 | cache = cache_find (next_frame); | |
334 | if (cache == NULL) | |
335 | return 0; | |
336 | ||
337 | cache_ref (cache); | |
338 | ||
339 | next_levels = existing_next_levels (this_frame, cache); | |
340 | ||
341 | /* NEXT_LEVELS is -1 only in dwarf2_tailcall_sniffer_first. */ | |
342 | gdb_assert (next_levels >= 0); | |
343 | gdb_assert (next_levels <= cache->chain_levels); | |
344 | ||
345 | if (next_levels == cache->chain_levels) | |
346 | { | |
347 | cache_unref (cache); | |
348 | return 0; | |
349 | } | |
350 | ||
351 | *this_cache = cache; | |
352 | return 1; | |
353 | } | |
354 | ||
355 | /* The initial "sniffer" whether THIS_FRAME is a bottom (callee) frame of a new | |
356 | chain to create. Keep TAILCALL_CACHEP NULL if it did not find any chain, | |
357 | initialize it otherwise. No tail call chain is created if there are no | |
358 | unambiguous virtual tail call frames to report. | |
359 | ||
360 | ENTRY_CFA_SP_OFFSETP is NULL if no special SP handling is possible, | |
361 | otherwise *ENTRY_CFA_SP_OFFSETP is the number of bytes to subtract from tail | |
362 | call frames frame base to get the SP value there - to simulate return | |
363 | address pushed on the stack. */ | |
364 | ||
365 | void | |
bd2b40ac | 366 | dwarf2_tailcall_sniffer_first (frame_info_ptr this_frame, |
e1b16eb4 JK |
367 | void **tailcall_cachep, |
368 | const LONGEST *entry_cfa_sp_offsetp) | |
369 | { | |
370 | CORE_ADDR prev_pc = 0, prev_sp = 0; /* GCC warning. */ | |
371 | int prev_sp_p = 0; | |
22e048c9 | 372 | CORE_ADDR this_pc; |
e1b16eb4 | 373 | struct gdbarch *prev_gdbarch; |
8084e579 | 374 | gdb::unique_xmalloc_ptr<call_site_chain> chain; |
e1b16eb4 | 375 | struct tailcall_cache *cache; |
e1b16eb4 JK |
376 | |
377 | gdb_assert (*tailcall_cachep == NULL); | |
378 | ||
05c56a9d JK |
379 | /* PC may be after the function if THIS_FRAME calls noreturn function, |
380 | get_frame_address_in_block will decrease it by 1 in such case. */ | |
381 | this_pc = get_frame_address_in_block (this_frame); | |
e1b16eb4 | 382 | |
a70b8144 | 383 | try |
e1b16eb4 | 384 | { |
13294f7d | 385 | int sp_regnum; |
e1b16eb4 JK |
386 | |
387 | prev_gdbarch = frame_unwind_arch (this_frame); | |
e1b16eb4 JK |
388 | |
389 | /* Simulate frame_unwind_pc without setting this_frame->prev_pc.p. */ | |
9fc501fd | 390 | prev_pc = gdbarch_unwind_pc (prev_gdbarch, this_frame); |
e1b16eb4 JK |
391 | |
392 | /* call_site_find_chain can throw an exception. */ | |
393 | chain = call_site_find_chain (prev_gdbarch, prev_pc, this_pc); | |
394 | ||
9c6595ab PA |
395 | if (entry_cfa_sp_offsetp != NULL) |
396 | { | |
397 | sp_regnum = gdbarch_sp_regnum (prev_gdbarch); | |
398 | if (sp_regnum != -1) | |
399 | { | |
400 | prev_sp = frame_unwind_register_unsigned (this_frame, sp_regnum); | |
401 | prev_sp_p = 1; | |
402 | } | |
403 | } | |
e1b16eb4 | 404 | } |
230d2906 | 405 | catch (const gdb_exception_error &except) |
e1b16eb4 JK |
406 | { |
407 | if (entry_values_debug) | |
408 | exception_print (gdb_stdout, except); | |
6d7aa592 PA |
409 | |
410 | switch (except.error) | |
411 | { | |
412 | case NO_ENTRY_VALUE_ERROR: | |
413 | /* Thrown by call_site_find_chain. */ | |
414 | case MEMORY_ERROR: | |
415 | case OPTIMIZED_OUT_ERROR: | |
416 | case NOT_AVAILABLE_ERROR: | |
417 | /* These can normally happen when we try to access an | |
418 | optimized out or unavailable register, either in a | |
419 | physical register or spilled to memory. */ | |
420 | return; | |
421 | } | |
422 | ||
423 | /* Let unexpected errors propagate. */ | |
424 | throw; | |
e1b16eb4 JK |
425 | } |
426 | ||
427 | /* Ambiguous unwind or unambiguous unwind verified as matching. */ | |
428 | if (chain == NULL || chain->length == 0) | |
8084e579 | 429 | return; |
e1b16eb4 JK |
430 | |
431 | cache = cache_new_ref1 (this_frame); | |
432 | *tailcall_cachep = cache; | |
8084e579 | 433 | cache->chain = chain.release (); |
e1b16eb4 | 434 | cache->prev_pc = prev_pc; |
8084e579 | 435 | cache->chain_levels = pretended_chain_levels (cache->chain); |
e1b16eb4 JK |
436 | cache->prev_sp_p = prev_sp_p; |
437 | if (cache->prev_sp_p) | |
438 | { | |
439 | cache->prev_sp = prev_sp; | |
440 | cache->entry_cfa_sp_offset = *entry_cfa_sp_offsetp; | |
441 | } | |
442 | gdb_assert (cache->chain_levels > 0); | |
443 | } | |
444 | ||
445 | /* Implementation of frame_dealloc_cache_ftype. It can be called even for the | |
446 | bottom chain frame from dwarf2_frame_dealloc_cache which is not a real | |
447 | TAILCALL_FRAME. */ | |
448 | ||
449 | static void | |
bd2b40ac | 450 | tailcall_frame_dealloc_cache (frame_info *self, void *this_cache) |
e1b16eb4 | 451 | { |
9a3c8263 | 452 | struct tailcall_cache *cache = (struct tailcall_cache *) this_cache; |
e1b16eb4 JK |
453 | |
454 | cache_unref (cache); | |
455 | } | |
456 | ||
457 | /* Implementation of frame_prev_arch_ftype. We assume all the virtual tail | |
458 | call frames have gdbarch of the bottom (callee) frame. */ | |
459 | ||
460 | static struct gdbarch * | |
bd2b40ac | 461 | tailcall_frame_prev_arch (frame_info_ptr this_frame, |
e1b16eb4 JK |
462 | void **this_prologue_cache) |
463 | { | |
9a3c8263 | 464 | struct tailcall_cache *cache = (struct tailcall_cache *) *this_prologue_cache; |
e1b16eb4 | 465 | |
bd2b40ac | 466 | return get_frame_arch (frame_info_ptr (cache->next_bottom_frame)); |
e1b16eb4 JK |
467 | } |
468 | ||
469 | /* Virtual tail call frame unwinder if dwarf2_tailcall_sniffer_first finds | |
470 | a chain to create. */ | |
471 | ||
472 | const struct frame_unwind dwarf2_tailcall_frame_unwind = | |
473 | { | |
a154d838 | 474 | "dwarf2 tailcall", |
e1b16eb4 JK |
475 | TAILCALL_FRAME, |
476 | default_frame_unwind_stop_reason, | |
477 | tailcall_frame_this_id, | |
478 | tailcall_frame_prev_register, | |
479 | NULL, | |
480 | tailcall_frame_sniffer, | |
481 | tailcall_frame_dealloc_cache, | |
482 | tailcall_frame_prev_arch | |
483 | }; | |
484 | ||
6c265988 | 485 | void _initialize_tailcall_frame (); |
e1b16eb4 | 486 | void |
6c265988 | 487 | _initialize_tailcall_frame () |
e1b16eb4 JK |
488 | { |
489 | cache_htab = htab_create_alloc (50, cache_hash, cache_eq, NULL, xcalloc, | |
490 | xfree); | |
491 | } |