HPCToolkit
stack_troll.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 /*
48  * Troll the stack for potential valid return addresses
49 
50  * The algorithm is simple, given a stack pointer (address), look thru the
51  * stack for a value that is an address in some function (and therefore is
52  * a valid return address). If such a value is found, then the address (eg the
53  * stack pointer) is returned.
54  *
55  * Valid return address is determined by using the enclosing_function_bounds
56  * routine.
57  *
58  * NOTE: This is a secondary heuristic: when the normal binary analysis interval
59  * builder does not yield a useful interval, the unwinder can use this stack trolling
60  * method.
61  */
62 
63 #include <stdlib.h>
64 #include <inttypes.h>
65 
66 #include <include/uint.h>
67 
68 #include "stack_troll.h"
69 #include "fnbounds_interface.h"
70 #include "validate_return_addr.h"
71 
72 #include <messages/messages.h>
73 
74 static const int TROLL_LIMIT = 16;
75 
77 stack_troll(void **start_sp, uint *ra_pos, validate_addr_fn_t validate_addr, void *generic_arg)
78 {
79  void **sp = start_sp;
80 
81  for (int i = 0; i < TROLL_LIMIT; i++) {
82  switch (validate_addr(*sp, generic_arg)){
83  case UNW_ADDR_CONFIRMED:
84  TMSG(TROLL,"found a confirmed valid return address %p at sp = %p", \
85  *sp, sp);
86  *ra_pos = (uintptr_t)sp - (uintptr_t)start_sp;
87  return TROLL_VALID; // success
88 
89  case UNW_ADDR_PROBABLE_INDIRECT:
90  TMSG(TROLL,"found a likely (from indirect call) valid return address %p at sp = %p", \
91  *sp, sp);
92  *ra_pos = (uintptr_t)sp - (uintptr_t)start_sp;
93  return TROLL_LIKELY; // success
94 
95  case UNW_ADDR_PROBABLE_TAIL:
96  TMSG(TROLL,"found a likely (from tail call) valid return address %p at sp = %p", \
97  *sp, sp);
98  *ra_pos = (uintptr_t)sp - (uintptr_t)start_sp;
99  return TROLL_LIKELY; // success
100 
101  case UNW_ADDR_PROBABLE:
102  TMSG(TROLL,"found a likely valid return address %p at sp = %p", \
103  *sp, sp);
104  *ra_pos = (uintptr_t)sp - (uintptr_t)start_sp;
105  return TROLL_LIKELY; // success
106 
107  case UNW_ADDR_CYCLE:
108  TMSG(TROLL_CHK,"infinite loop detected with return address %p at sp = %p", \
109  *sp, sp);
110  break;
111 
112  case UNW_ADDR_WRONG:
113  TMSG(TROLL_CHK,"provably invalid return address %p at sp = %p", \
114  *sp, sp);
115  break;
116 
117  default:
118  EMSG("UNKNOWN return code from validate_addr in Trolling code %p at sp = %p",
119  *sp, sp);
120  break;
121  }
122  sp++;
123  }
124 
125  TMSG(TROLL,"(sp=%p): failed using limit %d", start_sp, TROLL_LIMIT);
126  *ra_pos = -1;
127  return TROLL_INVALID; // error
128 }
static const int TROLL_LIMIT
Definition: stack_troll.c:74
validation_status(* validate_addr_fn_t)(void *addr, void *generic_arg)
unsigned int uint
Definition: uint.h:124
#define EMSG
Definition: messages.h:70
troll_status
Definition: stack_troll.h:56
troll_status stack_troll(void **start_sp, uint *ra_pos, validate_addr_fn_t validate_addr, void *generic_arg)
Definition: stack_troll.c:77
#define TMSG(f,...)
Definition: messages.h:93