HPCToolkit
x86-unwind.c
Go to the documentation of this file.
1 // -*-Mode: C++;-*- // technically C99
2 
3 // * BeginRiceCopyright *****************************************************
4 //
5 // $HeadURL$
6 // $Id$
7 //
8 // --------------------------------------------------------------------------
9 // Part of HPCToolkit (hpctoolkit.org)
10 //
11 // Information about sources of support for research and development of
12 // HPCToolkit is at 'hpctoolkit.org' and in 'README.Acknowledgments'.
13 // --------------------------------------------------------------------------
14 //
15 // Copyright ((c)) 2002-2019, Rice University
16 // All rights reserved.
17 //
18 // Redistribution and use in source and binary forms, with or without
19 // modification, are permitted provided that the following conditions are
20 // met:
21 //
22 // * Redistributions of source code must retain the above copyright
23 // notice, this list of conditions and the following disclaimer.
24 //
25 // * Redistributions in binary form must reproduce the above copyright
26 // notice, this list of conditions and the following disclaimer in the
27 // documentation and/or other materials provided with the distribution.
28 //
29 // * Neither the name of Rice University (RICE) nor the names of its
30 // contributors may be used to endorse or promote products derived from
31 // this software without specific prior written permission.
32 //
33 // This software is provided by RICE and contributors "as is" and any
34 // express or implied warranties, including, but not limited to, the
35 // implied warranties of merchantability and fitness for a particular
36 // purpose are disclaimed. In no event shall RICE or contributors be
37 // liable for any direct, indirect, incidental, special, exemplary, or
38 // consequential damages (including, but not limited to, procurement of
39 // substitute goods or services; loss of use, data, or profits; or
40 // business interruption) however caused and on any theory of liability,
41 // whether in contract, strict liability, or tort (including negligence
42 // or otherwise) arising in any way out of the use of this software, even
43 // if advised of the possibility of such damage.
44 //
45 // ******************************************************* EndRiceCopyright *
46 
47 // note:
48 // when cross compiling, this version MUST BE compiled for
49 // the target system, as the include file that defines the
50 // structure for the contexts may be different for the
51 // target system vs the build system.
52 
53 //***************************************************************************
54 // system include files
55 //***************************************************************************
56 
57 #include <stdio.h>
58 #include <setjmp.h>
59 #include <stdbool.h>
60 #include <assert.h>
61 
62 #include <sys/types.h>
63 #include <unistd.h> // for getpid
64 
65 //***************************************************************************
66 // external includes
67 //***************************************************************************
68 
69 #include <monitor.h>
70 #define UNW_LOCAL_ONLY
71 #include <libunwind.h>
72 
73 //***************************************************************************
74 // local include files
75 //***************************************************************************
76 
77 #include <include/gcc-attr.h>
78 #include <x86-decoder.h>
79 
80 #include <hpcrun/epoch.h>
81 #include <hpcrun/main.h>
82 #include "stack_troll.h"
83 #include "thread_use.h"
84 
85 #include <unwind/common/unwind.h>
95 
96 #include <hpcrun/main.h>
97 #include <hpcrun/thread_data.h>
98 #include "x86-build-intervals.h"
99 #include "x86-unwind-interval.h"
100 #include "x86-validate-retn-addr.h"
101 
102 #include <messages/messages.h>
103 #include <messages/debug-flag.h>
104 
105 
106 //****************************************************************************
107 // global data
108 //****************************************************************************
109 
110 int debug_unw = 0;
111 
112 
113 
114 //****************************************************************************
115 // local data
116 //****************************************************************************
117 
118 // flag value won't matter environment var set
120 
121 static int DEBUG_NO_LONGJMP = 0;
122 
123 
124 
125 //****************************************************************************
126 // forward declarations
127 //****************************************************************************
128 
129 #define MYDBG 0
130 
131 
132 static void
133 update_cursor_with_troll(hpcrun_unw_cursor_t* cursor, int offset);
134 
135 static step_state
137 
138 static step_state
140 
141 static step_state
143 
144 static step_state
146 
148 
149 //************************************************
150 // private functions
151 //************************************************
152 
153 static void
154 save_registers(hpcrun_unw_cursor_t* cursor, void **pc, void **bp, void *sp,
155  void **ra_loc)
156 {
157  cursor->pc_unnorm = pc;
158  cursor->bp = bp;
159  cursor->sp = sp;
160  cursor->ra_loc = ra_loc;
161 }
162 
163 static void
165 {
166  void *func_start_pc = (void*) cursor->unwr_info.interval.start;
167  load_module_t* lm = cursor->unwr_info.lm;
168 
169  cursor->pc_norm = hpcrun_normalize_ip(cursor->pc_unnorm, lm);
170  cursor->the_function = hpcrun_normalize_ip(func_start_pc, lm);
171 }
172 
173 
174 
175 //************************************************
176 // interface functions
177 //************************************************
178 
179 void
181 {
184 }
185 
186 typedef unw_frame_regnum_t unw_reg_code_t;
187 
188 static int
190  void** reg_value)
191 {
192  //
193  // only implement 1 reg for the moment.
194  // add more if necessary
195  //
196  switch (reg_id) {
197  case UNW_REG_IP:
198  *reg_value = cursor->pc_unnorm;
199  break;
200  default:
201  return ~0;
202  }
203  return 0;
204 }
205 
206 static int
208  ip_normalized_t* reg_value)
209 {
210  //
211  // only implement 1 reg for the moment.
212  // add more if necessary
213  //
214  switch (reg_id) {
215  case UNW_REG_IP:
216  *reg_value = cursor->pc_norm;
217  break;
218  default:
219  return ~0;
220  }
221  return 0;
222 }
223 
224 int
226 {
227  return hpcrun_unw_get_norm_reg(c, UNW_REG_IP, reg_value);
228 }
229 
230 int
232 {
233  return hpcrun_unw_get_unnorm_reg(c, UNW_REG_IP, reg_value);
234 }
235 
236 void
238 {
239  libunw_unw_init_cursor(cursor, context);
240 
241  void *pc, **bp, **sp;
242  unw_get_reg(&cursor->uc, UNW_REG_IP, (unw_word_t *)&pc);
243  unw_get_reg(&cursor->uc, UNW_REG_SP, (unw_word_t *)&sp);
244  unw_get_reg(&cursor->uc, UNW_TDEP_BP, (unw_word_t *)&bp);
245  save_registers(cursor, pc, bp, sp, NULL);
246 
247  if (cursor->libunw_status == LIBUNW_READY)
248  return;
249 
250  bool found = uw_recipe_map_lookup(pc, NATIVE_UNWINDER, &cursor->unwr_info);
251 
252  if (!found) {
253  EMSG("unw_init: cursor could NOT build an interval for initial pc = %p",
254  cursor->pc_unnorm);
255  }
256 
257  compute_normalized_ips(cursor);
258 
259  if (MYDBG) { dump_ui(cursor->unwr_info.btuwi, 0); }
260 }
261 
262 //
263 // Unwinder support for trampolines augments the
264 // cursor with 'ra_loc' field.
265 //
266 // This is NOT part of libunwind interface, so
267 // it does not use the unw_get_reg.
268 //
269 // Instead, we use the following procedure to abstractly
270 // fetch the ra_loc
271 //
272 
273 void*
275 {
276  return cursor->ra_loc;
277 }
278 
280 build_intervals(char *ins, unsigned int len, unwinder_t uw)
281 {
282  if (uw == NATIVE_UNWINDER)
283  return x86_build_intervals(ins, len, 0);
284  return libunw_build_intervals(ins, len);
285 }
286 
287 
288 static step_state
290 {
291  void *pc = cursor->pc_unnorm;
292  cursor->fence = (monitor_unwind_process_bottom_frame(pc) ? FENCE_MAIN :
293  monitor_unwind_thread_bottom_frame(pc)? FENCE_THREAD : FENCE_NONE);
294 
295  if (cursor->fence != FENCE_NONE) {
296  if (ENABLED(FENCE_UNW))
297  TMSG(FENCE_UNW, "%s", fence_enum_name(cursor->fence));
298 
299  //-----------------------------------------------------------
300  // check if we have reached the end of our unwind, which is
301  // demarcated with a fence.
302  //-----------------------------------------------------------
303  TMSG(UNW,"unw_step: STEP_STOP, current pc in monitor fence pc=%p\n", pc);
304  return STEP_STOP;
305  }
306 
307  // current frame
308  void** bp = cursor->bp;
309  void* sp = cursor->sp;
310  unwind_interval* uw = cursor->unwr_info.btuwi;
311 
312  if (!uw) {
313  TMSG(UNW, "unw_step: invalid unw interval for cursor, trolling ...");
314  TMSG(TROLL, "Troll due to Invalid interval for pc %p", pc);
315  update_cursor_with_troll(cursor, 0);
316  return STEP_TROLL;
317  }
318 
319  step_state unw_res;
320  switch (UWI_RECIPE(uw)->ra_status) {
321  case RA_SP_RELATIVE:
322  unw_res = unw_step_sp(cursor);
323  break;
324 
325  case RA_BP_FRAME:
326  unw_res = unw_step_bp(cursor);
327  break;
328 
329  case RA_STD_FRAME:
330  unw_res = unw_step_std(cursor);
331  break;
332 
333  default:
334  EMSG("unw_step: ILLEGAL UNWIND INTERVAL");
335  dump_ui(cursor->unwr_info.btuwi, 0);
336  assert(0);
337  }
338  if (unw_res == STEP_STOP_WEAK) unw_res = STEP_STOP;
339 
340  if (unw_res != STEP_ERROR) {
341  return unw_res;
342  }
343 
344  TMSG(TROLL,"unw_step: STEP_ERROR, pc=%p, bp=%p, sp=%p", pc, bp, sp);
345  dump_ui_troll(uw);
346 
347  if (ENABLED(TROLL_WAIT)) {
348  fprintf(stderr,"Hit troll point: attach w gdb to %d\n"
349  "Maybe call dbg_set_flag(DBG_TROLL_WAIT,0) after attached\n",
350  getpid());
351 
352  // spin wait for developer to attach a debugger and clear the flag
354  }
355 
356  update_cursor_with_troll(cursor, 1);
357 
358  return STEP_TROLL;
359 }
360 
362 #define _MM(a) [UNW_ADDR_ ## a] = 0,
364 #undef _MM
365 };
366 
367 void
369 {
370  AMSG("VALIDATION: Confirmed: %ld, Probable: %ld (indirect: %ld, tail: %ld, etc: %ld), Wrong: %ld",
371  hpcrun_validation_counts[UNW_ADDR_CONFIRMED],
372  hpcrun_validation_counts[UNW_ADDR_PROBABLE_INDIRECT] +
373  hpcrun_validation_counts[UNW_ADDR_PROBABLE_TAIL] +
374  hpcrun_validation_counts[UNW_ADDR_PROBABLE],
375  hpcrun_validation_counts[UNW_ADDR_PROBABLE_INDIRECT],
376  hpcrun_validation_counts[UNW_ADDR_PROBABLE_TAIL],
377  hpcrun_validation_counts[UNW_ADDR_PROBABLE],
378  hpcrun_validation_counts[UNW_ADDR_WRONG]);
379 }
380 
381 
382 static void
383 vrecord(void *from, void *to, validation_status vstat)
384 {
385  hpcrun_validation_counts[vstat]++;
386 
387  if ( ENABLED(VALID_RECORD_ALL) || (vstat == UNW_ADDR_WRONG) ){
388  TMSG(UNW_VALID,"%p->%p (%s)", from, to, vstat2s(vstat));
389  }
390 }
391 
392 
393 static bool
395  void *pc, void **sp, void **bp)
396 {
397  ucontext_t uc;
398  memcpy(&uc, &cursor->uc, sizeof(uc));
399  LV_MCONTEXT_PC(&uc.uc_mcontext) = (intptr_t)pc;
400  LV_MCONTEXT_SP(&uc.uc_mcontext) = (intptr_t)sp;
401  LV_MCONTEXT_BP(&uc.uc_mcontext) = (intptr_t)bp;
402  unw_init_local(&cursor->uc, &uc);
403  return libunw_finalize_cursor(cursor);
404 }
405 
408 {
409  step_state unw_res;
410 
411  if (cursor->libunw_status == LIBUNW_READY) {
412  unw_res = libunw_take_step(cursor);
413 
414  void *pc, **bp, **sp;
415  unw_get_reg(&cursor->uc, UNW_REG_IP, (unw_word_t *)&pc);
416  unw_get_reg(&cursor->uc, UNW_REG_SP, (unw_word_t *)&sp);
417  unw_get_reg(&cursor->uc, UNW_TDEP_BP, (unw_word_t *)&bp);
418  // sanity check to avoid infinite unwind loop
419  if (sp <= cursor->sp) {
420  cursor->libunw_status = LIBUNW_UNAVAIL;
421  unw_res = STEP_ERROR;
422  }
423  else
424  save_registers(cursor, pc, bp, sp, (void **)(sp - 1));
425 
426  if (unw_res == STEP_OK) {
427  libunw_finalize_cursor(cursor);
428  }
429 
430  if (unw_res == STEP_STOP || unw_res == STEP_OK) {
431  return unw_res;
432  }
433  bool found = uw_recipe_map_lookup(((char *)pc) - 1, NATIVE_UNWINDER, &cursor->unwr_info);
434 
435  if (!found) {
436  EMSG("hpcrun_unw_step: cursor could NOT build an interval for last libunwind pc = %p",
437  cursor->pc_unnorm);
438  return unw_res;
439  }
440  compute_normalized_ips(cursor);
441  }
442 
443  if ( ENABLED(DBG_UNW_STEP) ){
444  return dbg_unw_step(cursor);
445  }
446 
447  hpcrun_unw_cursor_t saved = *cursor;
448  step_state rv = hpcrun_unw_step_real(cursor);
449  if ( ENABLED(UNW_VALID) ) {
450  if (rv == STEP_OK) {
451  // try to validate all calls, except the one at the base of the call stack from libmonitor.
452  // rather than recording that as a valid call, it is preferable to ignore it.
453  if (!monitor_in_start_func_wide(cursor->pc_unnorm)) {
455  (void *) &saved);
456  vrecord(saved.pc_unnorm,cursor->pc_unnorm,vstat);
457  }
458  }
459  }
460  return rv;
461 }
462 
463 //****************************************************************************
464 // hpcrun_unw_step helpers
465 //****************************************************************************
466 
467 static step_state
469 {
470  TMSG(UNW_STRATEGY,"Using SP step");
471 
472  // void *stack_bottom = monitor_stack_bottom();
473 
474  // current frame
475  void** bp = cursor->bp;
476  void* sp = cursor->sp;
477  void* pc = cursor->pc_unnorm;
478  unwind_interval* uw = cursor->unwr_info.btuwi;
479  x86recipe_t *xr = UWI_RECIPE(uw);
480 
481  if (xr == NULL) {
482  return STEP_ERROR;
483  }
484 
485  TMSG(UNW,"step_sp: cursor { bp=%p, sp=%p, pc=%p }", bp, sp, pc);
486  if (MYDBG) { dump_ui(uw, 0); }
487 
488  void** next_bp = xr->reg.bp_status == BP_UNCHANGED ? bp :
489  //-----------------------------------------------------------
490  // reload the candidate value for the caller's BP from the
491  // save area in the activation frame according to the unwind
492  // information produced by binary analysis
493  //-----------------------------------------------------------
494  *(void **)(sp + xr->reg.sp_bp_pos);
495  void** next_sp = (void **)(sp + xr->reg.sp_ra_pos);
496  void* ra_loc = (void*) next_sp;
497  void* next_pc = *next_sp++;
498 
499  if ((RA_BP_FRAME == xr->ra_status) ||
500  (RA_STD_FRAME == xr->ra_status)) { // Makes sense to sanity check BP, do it
501  //-----------------------------------------------------------
502  // if value of BP reloaded from the save area does not point
503  // into the stack, then it cannot possibly be useful as a frame
504  // pointer in the caller or any of its ancesters.
505  //
506  // if the value in the BP register points into the stack, then
507  // it might be useful as a frame pointer. in this case, we have
508  // nothing to lose by assuming that our binary analysis for
509  // unwinding might have been mistaken and that the value in
510  // the register is the one we might want.
511  //
512  // 19 December 2007 - John Mellor-Crummey
513  //-----------------------------------------------------------
514 
515  if (((unsigned long) next_bp < (unsigned long) sp) &&
516  ((unsigned long) bp > (unsigned long) sp)){
517  next_bp = bp;
518  TMSG(UNW," step_sp: unwind bp sanity check fails."
519  " Resetting next_bp to current bp = %p", next_bp);
520  }
521  }
522 
523  if (hpcrun_retry_libunw_find_step(cursor, next_pc, next_sp, next_bp))
524  return STEP_OK;
525 
526 
527  TMSG(UNW," step_sp: potential next cursor next_sp=%p ==> next_pc = %p",
528  next_sp, next_pc);
529 
530  unwindr_info_t unwr_info;
531  bool found = uw_recipe_map_lookup(((char *)next_pc) - 1, NATIVE_UNWINDER, &unwr_info);
532  if (!found){
533  if (((void *)next_sp) >= monitor_stack_bottom()){
534  TMSG(UNW," step_sp: STEP_STOP_WEAK, no next interval and next_sp >= stack bottom,"
535  " so stop unwind ...");
536  return STEP_STOP_WEAK;
537  }
538  TMSG(UNW," sp STEP_ERROR: no next interval, step fails");
539  return STEP_ERROR;
540  }
541 
542  // sanity check to avoid infinite unwind loop
543  if (next_sp <= cursor->sp){
544  TMSG(INTV_ERR,"@ pc = %p. sp unwind does not advance stack."
545  " New sp = %p, old sp = %p", cursor->pc_unnorm, next_sp,
546  cursor->sp);
547 
548  return STEP_ERROR;
549  }
550  TMSG(UNW," step_sp: STEP_OK, has_intvl=%d, bp=%p, sp=%p, pc=%p",
551  cursor->unwr_info.btuwi != NULL, next_bp, next_sp, next_pc);
552 
553  cursor->unwr_info = unwr_info;
554  save_registers(cursor, next_pc, next_bp, next_sp, ra_loc);
555  compute_normalized_ips(cursor);
556  return STEP_OK;
557 }
558 
559 
560 static step_state
562 {
563  TMSG(UNW_STRATEGY,"Using BP step");
564  // current frame
565  void **bp = cursor->bp;
566  void *sp = cursor->sp;
567  void *pc = cursor->pc_unnorm;
568  unwind_interval *uw = cursor->unwr_info.btuwi;
569  x86recipe_t *xr = UWI_RECIPE(uw);
570 
571  TMSG(UNW,"step_bp: cursor { bp=%p, sp=%p, pc=%p }", bp, sp, pc);
572  if (MYDBG) { dump_ui(uw, 0); }
573 
574  if (!(sp <= (void*) bp)) {
575  TMSG(UNW," step_bp: STEP_ERROR, unwind attempted, but incoming bp(%p) was not"
576  " >= sp(%p)", bp, sp);
577  return STEP_ERROR;
578  }
579  if (DISABLED(OMP_SKIP_MSB)) {
580  if (!((void *)bp < monitor_stack_bottom())) {
581  TMSG(UNW," step_bp: STEP_ERROR, unwind attempted, but incoming bp(%p) was not"
582  " between sp (%p) and monitor stack bottom (%p)",
583  bp, sp, monitor_stack_bottom());
584  return STEP_ERROR;
585  }
586  }
587  // bp relative
588  void **next_bp = *(void **)((void *)bp + xr->reg.bp_bp_pos);
589  void **next_sp = (void **)((void *)bp + xr->reg.bp_ra_pos);
590  void* ra_loc = (void*) next_sp;
591  void *next_pc = *next_sp++;
592 
593 
594  if (hpcrun_retry_libunw_find_step(cursor, next_pc, next_sp, next_bp))
595  return STEP_OK;
596 
597  // this condition is a weak correctness check. only
598  // try building an interval for the return address again if it succeeds
599  if ((void *)next_sp <= sp) {
600  TMSG(UNW_STRATEGY,"BP unwind fails: bp (%p) < sp (%p)", bp, sp);
601  return STEP_ERROR;
602  }
603 
604  unwindr_info_t unwr_info;
605  bool found = uw_recipe_map_lookup(((char *)next_pc) - 1, NATIVE_UNWINDER, &unwr_info);
606  if (!found){
607  if (((void *)next_sp) >= monitor_stack_bottom()) {
608  TMSG(UNW," step_bp: STEP_STOP_WEAK, next_sp >= monitor_stack_bottom,"
609  " next_sp = %p", next_sp);
610  return STEP_STOP_WEAK;
611  }
612  TMSG(UNW," step_bp: STEP_ERROR, cannot build interval for next_pc(%p)", next_pc);
613  return STEP_ERROR;
614  }
615  TMSG(UNW," step_bp: STEP_OK, has_intvl=%d, bp=%p, sp=%p, pc=%p",
616  unwr_info.btuwi != NULL, next_bp, next_sp, next_pc);
617  assert(ra_loc == (void *)(next_sp - 1));
618  cursor->unwr_info = unwr_info;
619  save_registers(cursor, next_pc, next_bp, next_sp, ra_loc);
620  compute_normalized_ips(cursor);
621 
622  return STEP_OK;
623 }
624 
625 static step_state
627 {
628  int unw_res;
629 
630  if (ENABLED(PREFER_SP)) {
631  TMSG(UNW_STRATEGY,"--STD_FRAME: STARTing with SP");
632  unw_res = unw_step_sp(cursor);
633  if (unw_res == STEP_ERROR || unw_res == STEP_STOP_WEAK) {
634  TMSG(UNW_STRATEGY,"--STD_FRAME: SP failed, RETRY w BP");
635  unw_res = unw_step_bp(cursor);
636  if (unw_res == STEP_STOP_WEAK) unw_res = STEP_STOP;
637  }
638  }
639  else {
640  TMSG(UNW_STRATEGY,"--STD_FRAME: STARTing with BP");
641  unw_res = unw_step_bp(cursor);
642  if (unw_res == STEP_ERROR || unw_res == STEP_STOP_WEAK) {
643  TMSG(UNW_STRATEGY,"--STD_FRAME: BP failed, RETRY w SP");
644  unw_res = unw_step_sp(cursor);
645  }
646  }
647  return unw_res;
648 }
649 
650 
651 
652 // special steppers to artificially introduce error conditions
653 static step_state
655 {
656  if (!DEBUG_NO_LONGJMP) {
657 
659  hpcrun_bt_dump(TD_GET(btbuf_cur), "DROP");
660  }
661 
663 
664  sigjmp_buf_t *it = &(TD_GET(bad_unwind));
665  (*hpcrun_get_real_siglongjmp())(it->jb, 9);
666  }
667 
668  return STEP_ERROR;
669 }
670 
671 
674 {
675  static int s = 0;
676  step_state rv;
677  if (s == 0){
678  update_cursor_with_troll(cursor, 1);
679  rv = STEP_TROLL;
680  }
681  else {
682  rv = STEP_STOP;
683  }
684  s =(s+1) %2;
685  return rv;
686 }
687 
688 
689 //****************************************************************************
690 // private operations
691 //****************************************************************************
692 
693 static void
695 {
696  if (ENABLED(NO_TROLLING)){
697  TMSG(TROLL, "Trolling disabled");
699  }
700 
701  unsigned int tmp_ra_offset;
702 
703  int ret = stack_troll(cursor->sp, &tmp_ra_offset, &deep_validate_return_addr,
704  (void *)cursor);
705 
706  if (ret != TROLL_INVALID) {
707  void **next_sp = ((void **)((unsigned long) cursor->sp + tmp_ra_offset));
708  void *next_pc = *next_sp;
709  void *ra_loc = (void*) next_sp;
710 
711  // the current base pointer is a good assumption for the caller's BP
712  void **next_bp = (void **) cursor->bp;
713 
714  next_sp += 1;
715  if ( next_sp <= cursor->sp){
716  TMSG(TROLL,"Something weird happened! trolling from %p"
717  " resulted in sp not advancing", cursor->pc_unnorm);
719  }
720 
721  bool found = uw_recipe_map_lookup(((char *)next_pc) + offset, NATIVE_UNWINDER, &(cursor->unwr_info));
722  if (found) {
723  TMSG(TROLL,"Trolling advances cursor to pc = %p, sp = %p",
724  next_pc, next_sp);
725  TMSG(TROLL,"TROLL SUCCESS pc = %p", cursor->pc_unnorm);
726 
727  assert(ra_loc == (void *)(next_sp - 1));
728  save_registers(cursor, next_pc, next_bp, next_sp, ra_loc);
729  compute_normalized_ips(cursor);
730  return; // success!
731  }
732  TMSG(TROLL, "No interval found for trolled pc, dropping sample,"
733  " cursor pc = %p", cursor->pc_unnorm);
734  // fall through for error handling
735  }
736  else {
737  TMSG(TROLL, "Troll failed: dropping sample, cursor pc = %p",
738  cursor->pc_unnorm);
739  TMSG(TROLL,"TROLL FAILURE pc = %p", cursor->pc_unnorm);
740  // fall through for error handling
741  }
742  // assert(0);
744 }
ip_normalized_t hpcrun_normalize_ip(void *unnormalized_ip, load_module_t *lm)
Definition: ip-normalized.c:70
static step_state t1_dbg_unw_step(hpcrun_unw_cursor_t *cursor)
Definition: x86-unwind.c:654
unw_frame_regnum_t unw_reg_code_t
Definition: x86-unwind.c:186
void hpcrun_unw_init(void)
Definition: x86-unwind.c:180
static int hpcrun_unw_get_norm_reg(hpcrun_unw_cursor_t *cursor, unw_reg_code_t reg_id, ip_normalized_t *reg_value)
Definition: x86-unwind.c:207
void dump_ui_troll(unwind_interval *u)
void * hpcrun_unw_get_ra_loc(hpcrun_unw_cursor_t *cursor)
Definition: x86-unwind.c:274
static int DEBUG_WAIT_BEFORE_TROLLING
Definition: x86-unwind.c:119
validation_status
static step_state(* dbg_unw_step)(hpcrun_unw_cursor_t *cursor)
Definition: x86-unwind.c:147
void hpcrun_validation_summary(void)
Definition: x86-unwind.c:368
fence_enum_t fence
static void update_cursor_with_troll(hpcrun_unw_cursor_t *cursor, int offset)
Definition: x86-unwind.c:694
static step_state GCC_ATTR_UNUSED t2_dbg_unw_step(hpcrun_unw_cursor_t *cursor)
Definition: x86-unwind.c:673
static step_state unw_step_bp(hpcrun_unw_cursor_t *cursor)
Definition: x86-unwind.c:561
int hpcrun_below_pmsg_threshold(void)
interval_t interval
Definition: unwindr_info.h:100
#define LV_MCONTEXT_PC(mctxt)
Definition: _mcontext.h:83
static step_state unw_step_std(hpcrun_unw_cursor_t *cursor)
Definition: x86-unwind.c:626
static bool hpcrun_retry_libunw_find_step(hpcrun_unw_cursor_t *cursor, void *pc, void **sp, void **bp)
Definition: x86-unwind.c:394
#define UWI_RECIPE(btuwi)
enum libunw_state libunw_status
static void save_registers(hpcrun_unw_cursor_t *cursor, void **pc, void **bp, void *sp, void **ra_loc)
Definition: x86-unwind.c:154
bitree_uwi_t * btuwi
Definition: unwindr_info.h:103
bool uw_recipe_map_lookup(void *addr, unwinder_t uw, unwindr_info_t *unwr_info)
x86registers_t reg
void hpcrun_unw_init_cursor(hpcrun_unw_cursor_t *cursor, void *context)
Definition: x86-unwind.c:237
step_state hpcrun_unw_step(hpcrun_unw_cursor_t *cursor)
Definition: x86-unwind.c:407
static step_state unw_step_sp(hpcrun_unw_cursor_t *cursor)
Definition: x86-unwind.c:468
ip_normalized_t pc_norm
void hpcrun_up_pmsg_count(void)
int hpcrun_unw_get_ip_unnorm_reg(hpcrun_unw_cursor_t *c, void **reg_value)
Definition: x86-unwind.c:231
#define MYDBG
Definition: x86-unwind.c:129
void hpcrun_unw_throw(void)
Definition: unw-throw.c:97
#define EMSG
Definition: messages.h:70
static step_state hpcrun_unw_step_real(hpcrun_unw_cursor_t *cursor)
Definition: x86-unwind.c:289
btuwi_status_t x86_build_intervals(void *ins, unsigned int len, int noisy)
troll_status stack_troll(void **start_sp, uint *ra_pos, validate_addr_fn_t validate_addr, void *generic_arg)
Definition: stack_troll.c:77
static char * vstat2s(validation_status v)
#define TD_GET(field)
Definition: thread_data.h:256
void dump_ui(unwind_interval *u, int dump_to_stderr)
static void compute_normalized_ips(hpcrun_unw_cursor_t *cursor)
Definition: x86-unwind.c:164
#define DISABLED(f)
Definition: debug-flag.h:77
#define LV_MCONTEXT_SP(mctxt)
Definition: _mcontext.h:85
bool found
Definition: cct.c:129
btuwi_status_t libunw_build_intervals(char *beg_insn, unsigned int len)
#define TMSG(f,...)
Definition: messages.h:93
unw_frame_regnum_t unw_reg_code_t
Definition: ppc64-unwind.c:104
ip_normalized_t the_function
#define LV_MCONTEXT_BP(mctxt)
Definition: _mcontext.h:84
step_state libunw_take_step(hpcrun_unw_cursor_t *cursor)
#define AMSG
Definition: messages.h:71
#define NULL
Definition: ElfHelper.cpp:85
load_module_t * lm
Definition: unwindr_info.h:101
int hpcrun_unw_get_ip_norm_reg(hpcrun_unw_cursor_t *c, ip_normalized_t *reg_value)
Definition: x86-unwind.c:225
bitree_uwi_t unwind_interval
enum unwinder_e unwinder_t
unsigned char uc
Definition: amd-xop.c:3
void x86_family_decoder_init()
Definition: x86-decoder.c:80
void hpcrun_bt_dump(frame_t *unwind, const char *tag)
Definition: backtrace.c:90
uintptr_t start
Definition: interval_t.h:27
int debug_unw
Definition: x86-unwind.c:110
#define GCC_ATTR_UNUSED
Definition: gcc-attr.h:80
siglongjmp_fcn * hpcrun_get_real_siglongjmp(void)
Definition: main.c:1142
static char * fence_enum_name(fence_enum_t f)
Definition: fence_enum.h:24
bool libunw_finalize_cursor(hpcrun_unw_cursor_t *cursor)
validation_status deep_validate_return_addr(void *addr, void *generic)
size_t hpcrun_validation_counts[]
Definition: x86-unwind.c:361
sigjmp_buf jb
Definition: thread_data.h:74
static void vrecord(void *from, void *to, validation_status vstat)
Definition: x86-unwind.c:383
step_state
Definition: unwind.h:124
void libunw_unw_init_cursor(hpcrun_unw_cursor_t *cursor, void *context)
unwindr_info_t unwr_info
static int hpcrun_unw_get_unnorm_reg(hpcrun_unw_cursor_t *cursor, unw_reg_code_t reg_id, void **reg_value)
Definition: x86-unwind.c:189
static int DEBUG_NO_LONGJMP
Definition: x86-unwind.c:121
#define ENABLED(f)
Definition: debug-flag.h:76
void uw_recipe_map_init(void)
btuwi_status_t build_intervals(char *ins, unsigned int len, unwinder_t uw)
Definition: x86-unwind.c:280