15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2005, Google Inc. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// All rights reserved. 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Redistribution and use in source and binary forms, with or without 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// modification, are permitted provided that the following conditions are 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// met: 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * Redistributions of source code must retain the above copyright 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// notice, this list of conditions and the following disclaimer. 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * Redistributions in binary form must reproduce the above 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// copyright notice, this list of conditions and the following disclaimer 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the documentation and/or other materials provided with the 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// distribution. 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * Neither the name of Google Inc. nor the names of its 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// contributors may be used to endorse or promote products derived from 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this software without specific prior written permission. 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "config_for_unittests.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_EXECINFO_H 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <execinfo.h> 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h> 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h> 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/commandlineflags.h" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gperftools/stacktrace.h> 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Obtain a backtrace, verify that the expected callers are present in the 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// backtrace, and maybe print the backtrace to stdout. 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The sequence of functions whose return addresses we expect to see in the 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// backtrace. 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int BACKTRACE_STEPS = 6; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct AddressRange { 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const void *start, *end; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Expected function [start,end] range. 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AddressRange expected_range[BACKTRACE_STEPS]; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if __GNUC__ 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Using GCC extension: address of a label can be taken with '&&label'. 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Start should be a label somewhere before recursive call, end somewhere 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// after it. 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define INIT_ADDRESS_RANGE(fn, start_label, end_label, prange) \ 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { \ 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (prange)->start = &&start_label; \ 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (prange)->end = &&end_label; \ 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_LT((prange)->start, (prange)->end); \ 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (0) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This macro expands into "unmovable" code (opaque to GCC), and that 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// prevents GCC from moving a_label up or down in the code. 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Without it, there is no code following the 'end' label, and GCC 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (4.3.1, 4.4.0) thinks it safe to assign &&end an address that is before 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the recursive call. 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DECLARE_ADDRESS_LABEL(a_label) \ 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) a_label: do { __asm__ __volatile__(""); } while (0) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Gcc 4.4.0 may split function into multiple chunks, and the chunk 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// performing recursive call may end up later in the code then the return 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// instruction (this actually happens with FDO). 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Adjust function range from __builtin_return_address. 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ADJUST_ADDRESS_RANGE_FROM_RA(prange) \ 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { \ 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *ra = __builtin_return_address(0); \ 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_LT((prange)->start, ra); \ 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ra > (prange)->end) { \ 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("Adjusting range from %p..%p to %p..%p\n", \ 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (prange)->start, (prange)->end, \ 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (prange)->start, ra); \ 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (prange)->end = ra; \ 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } \ 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (0) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Assume the Check* functions below are not longer than 256 bytes. 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define INIT_ADDRESS_RANGE(fn, start_label, end_label, prange) \ 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { \ 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (prange)->start = reinterpret_cast<const void *>(&fn); \ 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (prange)->end = reinterpret_cast<const char *>(&fn) + 256; \ 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (0) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DECLARE_ADDRESS_LABEL(a_label) do { } while (0) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ADJUST_ADDRESS_RANGE_FROM_RA(prange) do { } while (0) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // __GNUC__ 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------// 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CheckRetAddrIsInFunction(void *ret_addr, const AddressRange &range) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_GE(ret_addr, range.start); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_LE(ret_addr, range.end); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------// 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ATTRIBUTE_NOINLINE CheckStackTrace(int); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ATTRIBUTE_NOINLINE CheckStackTraceLeaf(void) { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int STACK_LEN = 10; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *stack[STACK_LEN]; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int size; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[1]); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INIT_ADDRESS_RANGE(CheckStackTraceLeaf, start, end, &expected_range[0]); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DECLARE_ADDRESS_LABEL(start); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size = GetStackTrace(stack, STACK_LEN, 0); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("Obtained %d stack frames.\n", size); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_GE(size, 1); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_LE(size, STACK_LEN); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_EXECINFO_H 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char **strings = backtrace_symbols(stack, size); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("Obtained %d stack frames.\n", size); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < size; i++) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("%s %p\n", strings[i], stack[i]); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("CheckStackTrace() addr: %p\n", &CheckStackTrace); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(strings); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < BACKTRACE_STEPS; i++) { 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("Backtrace %d: expected: %p..%p actual: %p ... ", 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i, expected_range[i].start, expected_range[i].end, stack[i]); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fflush(stdout); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckRetAddrIsInFunction(stack[i], expected_range[i]); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("OK\n"); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DECLARE_ADDRESS_LABEL(end); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------// 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Dummy functions to make the backtrace more interesting. */ 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ATTRIBUTE_NOINLINE CheckStackTrace4(int i) { 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[2]); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INIT_ADDRESS_RANGE(CheckStackTrace4, start, end, &expected_range[1]); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DECLARE_ADDRESS_LABEL(start); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int j = i; j >= 0; j--) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckStackTraceLeaf(); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DECLARE_ADDRESS_LABEL(end); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ATTRIBUTE_NOINLINE CheckStackTrace3(int i) { 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[3]); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INIT_ADDRESS_RANGE(CheckStackTrace3, start, end, &expected_range[2]); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DECLARE_ADDRESS_LABEL(start); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int j = i; j >= 0; j--) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckStackTrace4(j); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DECLARE_ADDRESS_LABEL(end); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ATTRIBUTE_NOINLINE CheckStackTrace2(int i) { 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[4]); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INIT_ADDRESS_RANGE(CheckStackTrace2, start, end, &expected_range[3]); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DECLARE_ADDRESS_LABEL(start); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int j = i; j >= 0; j--) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckStackTrace3(j); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DECLARE_ADDRESS_LABEL(end); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ATTRIBUTE_NOINLINE CheckStackTrace1(int i) { 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[5]); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INIT_ADDRESS_RANGE(CheckStackTrace1, start, end, &expected_range[4]); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DECLARE_ADDRESS_LABEL(start); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int j = i; j >= 0; j--) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckStackTrace2(j); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DECLARE_ADDRESS_LABEL(end); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ATTRIBUTE_NOINLINE CheckStackTrace(int i) { 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INIT_ADDRESS_RANGE(CheckStackTrace, start, end, &expected_range[5]); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DECLARE_ADDRESS_LABEL(start); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int j = i; j >= 0; j--) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckStackTrace1(j); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DECLARE_ADDRESS_LABEL(end); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------// 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int main(int argc, char ** argv) { 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckStackTrace(0); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("PASS\n"); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 195