stacktrace_unittest.cc 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. // Copyright (c) 2005, Google Inc.
  2. // All rights reserved.
  3. //
  4. // Redistribution and use in source and binary forms, with or without
  5. // modification, are permitted provided that the following conditions are
  6. // met:
  7. //
  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
  13. // distribution.
  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.
  17. //
  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.
  29. #include "config_for_unittests.h"
  30. #ifdef HAVE_EXECINFO_H
  31. #include <execinfo.h>
  32. #endif
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include "base/commandlineflags.h"
  36. #include "base/logging.h"
  37. #include <gperftools/stacktrace.h>
  38. namespace {
  39. // Obtain a backtrace, verify that the expected callers are present in the
  40. // backtrace, and maybe print the backtrace to stdout.
  41. // The sequence of functions whose return addresses we expect to see in the
  42. // backtrace.
  43. const int BACKTRACE_STEPS = 6;
  44. struct AddressRange {
  45. const void *start, *end;
  46. };
  47. // Expected function [start,end] range.
  48. AddressRange expected_range[BACKTRACE_STEPS];
  49. #if __GNUC__
  50. // Using GCC extension: address of a label can be taken with '&&label'.
  51. // Start should be a label somewhere before recursive call, end somewhere
  52. // after it.
  53. #define INIT_ADDRESS_RANGE(fn, start_label, end_label, prange) \
  54. do { \
  55. (prange)->start = &&start_label; \
  56. (prange)->end = &&end_label; \
  57. CHECK_LT((prange)->start, (prange)->end); \
  58. } while (0)
  59. // This macro expands into "unmovable" code (opaque to GCC), and that
  60. // prevents GCC from moving a_label up or down in the code.
  61. // Without it, there is no code following the 'end' label, and GCC
  62. // (4.3.1, 4.4.0) thinks it safe to assign &&end an address that is before
  63. // the recursive call.
  64. #define DECLARE_ADDRESS_LABEL(a_label) \
  65. a_label: do { __asm__ __volatile__(""); } while (0)
  66. // Gcc 4.4.0 may split function into multiple chunks, and the chunk
  67. // performing recursive call may end up later in the code then the return
  68. // instruction (this actually happens with FDO).
  69. // Adjust function range from __builtin_return_address.
  70. #define ADJUST_ADDRESS_RANGE_FROM_RA(prange) \
  71. do { \
  72. void *ra = __builtin_return_address(0); \
  73. CHECK_LT((prange)->start, ra); \
  74. if (ra > (prange)->end) { \
  75. printf("Adjusting range from %p..%p to %p..%p\n", \
  76. (prange)->start, (prange)->end, \
  77. (prange)->start, ra); \
  78. (prange)->end = ra; \
  79. } \
  80. } while (0)
  81. #else
  82. // Assume the Check* functions below are not longer than 256 bytes.
  83. #define INIT_ADDRESS_RANGE(fn, start_label, end_label, prange) \
  84. do { \
  85. (prange)->start = reinterpret_cast<const void *>(&fn); \
  86. (prange)->end = reinterpret_cast<const char *>(&fn) + 256; \
  87. } while (0)
  88. #define DECLARE_ADDRESS_LABEL(a_label) do { } while (0)
  89. #define ADJUST_ADDRESS_RANGE_FROM_RA(prange) do { } while (0)
  90. #endif // __GNUC__
  91. //-----------------------------------------------------------------------//
  92. void CheckRetAddrIsInFunction(void *ret_addr, const AddressRange &range)
  93. {
  94. CHECK_GE(ret_addr, range.start);
  95. CHECK_LE(ret_addr, range.end);
  96. }
  97. //-----------------------------------------------------------------------//
  98. void ATTRIBUTE_NOINLINE CheckStackTrace(int);
  99. void ATTRIBUTE_NOINLINE CheckStackTraceLeaf(void) {
  100. const int STACK_LEN = 10;
  101. void *stack[STACK_LEN];
  102. int size;
  103. ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[1]);
  104. INIT_ADDRESS_RANGE(CheckStackTraceLeaf, start, end, &expected_range[0]);
  105. DECLARE_ADDRESS_LABEL(start);
  106. size = GetStackTrace(stack, STACK_LEN, 0);
  107. printf("Obtained %d stack frames.\n", size);
  108. CHECK_GE(size, 1);
  109. CHECK_LE(size, STACK_LEN);
  110. #ifdef HAVE_EXECINFO_H
  111. {
  112. char **strings = backtrace_symbols(stack, size);
  113. printf("Obtained %d stack frames.\n", size);
  114. for (int i = 0; i < size; i++)
  115. printf("%s %p\n", strings[i], stack[i]);
  116. printf("CheckStackTrace() addr: %p\n", &CheckStackTrace);
  117. free(strings);
  118. }
  119. #endif
  120. for (int i = 0; i < BACKTRACE_STEPS; i++) {
  121. printf("Backtrace %d: expected: %p..%p actual: %p ... ",
  122. i, expected_range[i].start, expected_range[i].end, stack[i]);
  123. fflush(stdout);
  124. CheckRetAddrIsInFunction(stack[i], expected_range[i]);
  125. printf("OK\n");
  126. }
  127. DECLARE_ADDRESS_LABEL(end);
  128. }
  129. //-----------------------------------------------------------------------//
  130. /* Dummy functions to make the backtrace more interesting. */
  131. void ATTRIBUTE_NOINLINE CheckStackTrace4(int i) {
  132. ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[2]);
  133. INIT_ADDRESS_RANGE(CheckStackTrace4, start, end, &expected_range[1]);
  134. DECLARE_ADDRESS_LABEL(start);
  135. for (int j = i; j >= 0; j--)
  136. CheckStackTraceLeaf();
  137. DECLARE_ADDRESS_LABEL(end);
  138. }
  139. void ATTRIBUTE_NOINLINE CheckStackTrace3(int i) {
  140. ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[3]);
  141. INIT_ADDRESS_RANGE(CheckStackTrace3, start, end, &expected_range[2]);
  142. DECLARE_ADDRESS_LABEL(start);
  143. for (int j = i; j >= 0; j--)
  144. CheckStackTrace4(j);
  145. DECLARE_ADDRESS_LABEL(end);
  146. }
  147. void ATTRIBUTE_NOINLINE CheckStackTrace2(int i) {
  148. ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[4]);
  149. INIT_ADDRESS_RANGE(CheckStackTrace2, start, end, &expected_range[3]);
  150. DECLARE_ADDRESS_LABEL(start);
  151. for (int j = i; j >= 0; j--)
  152. CheckStackTrace3(j);
  153. DECLARE_ADDRESS_LABEL(end);
  154. }
  155. void ATTRIBUTE_NOINLINE CheckStackTrace1(int i) {
  156. ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[5]);
  157. INIT_ADDRESS_RANGE(CheckStackTrace1, start, end, &expected_range[4]);
  158. DECLARE_ADDRESS_LABEL(start);
  159. for (int j = i; j >= 0; j--)
  160. CheckStackTrace2(j);
  161. DECLARE_ADDRESS_LABEL(end);
  162. }
  163. void ATTRIBUTE_NOINLINE CheckStackTrace(int i) {
  164. INIT_ADDRESS_RANGE(CheckStackTrace, start, end, &expected_range[5]);
  165. DECLARE_ADDRESS_LABEL(start);
  166. for (int j = i; j >= 0; j--)
  167. CheckStackTrace1(j);
  168. DECLARE_ADDRESS_LABEL(end);
  169. }
  170. } // namespace
  171. //-----------------------------------------------------------------------//
  172. int main(int argc, char ** argv) {
  173. CheckStackTrace(0);
  174. printf("PASS\n");
  175. return 0;
  176. }