1 // Copyright (c) 2005, Google Inc.
2 // All rights reserved.
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
14 // * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include "config_for_unittests.h"
31 #ifdef HAVE_EXECINFO_H
36 #include "base/commandlineflags.h"
37 #include "base/logging.h"
38 #include <gperftools/stacktrace.h>
42 // Obtain a backtrace, verify that the expected callers are present in the
43 // backtrace, and maybe print the backtrace to stdout.
45 // The sequence of functions whose return addresses we expect to see in the
47 const int BACKTRACE_STEPS
= 6;
50 const void *start
, *end
;
53 // Expected function [start,end] range.
54 AddressRange expected_range
[BACKTRACE_STEPS
];
57 // Using GCC extension: address of a label can be taken with '&&label'.
58 // Start should be a label somewhere before recursive call, end somewhere
60 #define INIT_ADDRESS_RANGE(fn, start_label, end_label, prange) \
62 (prange)->start = &&start_label; \
63 (prange)->end = &&end_label; \
64 CHECK_LT((prange)->start, (prange)->end); \
66 // This macro expands into "unmovable" code (opaque to GCC), and that
67 // prevents GCC from moving a_label up or down in the code.
68 // Without it, there is no code following the 'end' label, and GCC
69 // (4.3.1, 4.4.0) thinks it safe to assign &&end an address that is before
70 // the recursive call.
71 #define DECLARE_ADDRESS_LABEL(a_label) \
72 a_label: do { __asm__ __volatile__(""); } while (0)
73 // Gcc 4.4.0 may split function into multiple chunks, and the chunk
74 // performing recursive call may end up later in the code then the return
75 // instruction (this actually happens with FDO).
76 // Adjust function range from __builtin_return_address.
77 #define ADJUST_ADDRESS_RANGE_FROM_RA(prange) \
79 void *ra = __builtin_return_address(0); \
80 CHECK_LT((prange)->start, ra); \
81 if (ra > (prange)->end) { \
82 printf("Adjusting range from %p..%p to %p..%p\n", \
83 (prange)->start, (prange)->end, \
84 (prange)->start, ra); \
89 // Assume the Check* functions below are not longer than 256 bytes.
90 #define INIT_ADDRESS_RANGE(fn, start_label, end_label, prange) \
92 (prange)->start = reinterpret_cast<const void *>(&fn); \
93 (prange)->end = reinterpret_cast<const char *>(&fn) + 256; \
95 #define DECLARE_ADDRESS_LABEL(a_label) do { } while (0)
96 #define ADJUST_ADDRESS_RANGE_FROM_RA(prange) do { } while (0)
99 //-----------------------------------------------------------------------//
101 void CheckRetAddrIsInFunction(void *ret_addr
, const AddressRange
&range
)
103 CHECK_GE(ret_addr
, range
.start
);
104 CHECK_LE(ret_addr
, range
.end
);
107 //-----------------------------------------------------------------------//
109 void ATTRIBUTE_NOINLINE
CheckStackTrace(int);
110 void ATTRIBUTE_NOINLINE
CheckStackTraceLeaf(void) {
111 const int STACK_LEN
= 10;
112 void *stack
[STACK_LEN
];
115 ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range
[1]);
116 INIT_ADDRESS_RANGE(CheckStackTraceLeaf
, start
, end
, &expected_range
[0]);
117 DECLARE_ADDRESS_LABEL(start
);
118 size
= GetStackTrace(stack
, STACK_LEN
, 0);
119 printf("Obtained %d stack frames.\n", size
);
121 CHECK_LE(size
, STACK_LEN
);
123 #ifdef HAVE_EXECINFO_H
125 char **strings
= backtrace_symbols(stack
, size
);
126 printf("Obtained %d stack frames.\n", size
);
127 for (int i
= 0; i
< size
; i
++)
128 printf("%s %p\n", strings
[i
], stack
[i
]);
129 printf("CheckStackTrace() addr: %p\n", &CheckStackTrace
);
134 for (int i
= 0; i
< BACKTRACE_STEPS
; i
++) {
135 printf("Backtrace %d: expected: %p..%p actual: %p ... ",
136 i
, expected_range
[i
].start
, expected_range
[i
].end
, stack
[i
]);
138 CheckRetAddrIsInFunction(stack
[i
], expected_range
[i
]);
141 DECLARE_ADDRESS_LABEL(end
);
144 //-----------------------------------------------------------------------//
146 /* Dummy functions to make the backtrace more interesting. */
147 void ATTRIBUTE_NOINLINE
CheckStackTrace4(int i
) {
148 ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range
[2]);
149 INIT_ADDRESS_RANGE(CheckStackTrace4
, start
, end
, &expected_range
[1]);
150 DECLARE_ADDRESS_LABEL(start
);
151 for (int j
= i
; j
>= 0; j
--)
152 CheckStackTraceLeaf();
153 DECLARE_ADDRESS_LABEL(end
);
155 void ATTRIBUTE_NOINLINE
CheckStackTrace3(int i
) {
156 ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range
[3]);
157 INIT_ADDRESS_RANGE(CheckStackTrace3
, start
, end
, &expected_range
[2]);
158 DECLARE_ADDRESS_LABEL(start
);
159 for (int j
= i
; j
>= 0; j
--)
161 DECLARE_ADDRESS_LABEL(end
);
163 void ATTRIBUTE_NOINLINE
CheckStackTrace2(int i
) {
164 ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range
[4]);
165 INIT_ADDRESS_RANGE(CheckStackTrace2
, start
, end
, &expected_range
[3]);
166 DECLARE_ADDRESS_LABEL(start
);
167 for (int j
= i
; j
>= 0; j
--)
169 DECLARE_ADDRESS_LABEL(end
);
171 void ATTRIBUTE_NOINLINE
CheckStackTrace1(int i
) {
172 ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range
[5]);
173 INIT_ADDRESS_RANGE(CheckStackTrace1
, start
, end
, &expected_range
[4]);
174 DECLARE_ADDRESS_LABEL(start
);
175 for (int j
= i
; j
>= 0; j
--)
177 DECLARE_ADDRESS_LABEL(end
);
179 void ATTRIBUTE_NOINLINE
CheckStackTrace(int i
) {
180 INIT_ADDRESS_RANGE(CheckStackTrace
, start
, end
, &expected_range
[5]);
181 DECLARE_ADDRESS_LABEL(start
);
182 for (int j
= i
; j
>= 0; j
--)
184 DECLARE_ADDRESS_LABEL(end
);
188 //-----------------------------------------------------------------------//
190 int main(int argc
, char ** argv
) {