t_backtrace.c revision 276478
1155131Srwatson/* $NetBSD: t_backtrace.c,v 1.16 2014/11/04 00:20:19 justin Exp $ */ 2155131Srwatson 3155131Srwatson/*- 4155131Srwatson * Copyright (c) 2012 The NetBSD Foundation, Inc. 5155131Srwatson * All rights reserved. 6155131Srwatson * 7155131Srwatson * This code is derived from software contributed to The NetBSD Foundation 8155131Srwatson * by Christos Zoulas. 9155131Srwatson * 10155131Srwatson * Redistribution and use in source and binary forms, with or without 11155131Srwatson * modification, are permitted provided that the following conditions 12155131Srwatson * are met: 13168777Srwatson * 1. Redistributions of source code must retain the above copyright 14155131Srwatson * notice, this list of conditions and the following disclaimer. 15155131Srwatson * 2. Redistributions in binary form must reproduce the above copyright 16155131Srwatson * notice, this list of conditions and the following disclaimer in the 17155131Srwatson * documentation and/or other materials provided with the distribution. 18155131Srwatson * 19155131Srwatson * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20155131Srwatson * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21155131Srwatson * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22155131Srwatson * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23155131Srwatson * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24155131Srwatson * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25155131Srwatson * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26155131Srwatson * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27155131Srwatson * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28155131Srwatson * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29155131Srwatson * POSSIBILITY OF SUCH DAMAGE. 30155131Srwatson */ 31155131Srwatson#include <sys/cdefs.h> 32155131Srwatson__RCSID("$NetBSD: t_backtrace.c,v 1.16 2014/11/04 00:20:19 justin Exp $"); 33155131Srwatson 34155131Srwatson#include <atf-c.h> 35155131Srwatson#include <string.h> 36155131Srwatson#include <stdio.h> 37155131Srwatson#include <stdlib.h> 38168777Srwatson#include <execinfo.h> 39155131Srwatson#include <unistd.h> 40155131Srwatson 41155131Srwatson#ifndef __arraycount 42168777Srwatson#define __arraycount(a) (sizeof(a) / sizeof(a[0])) 43155131Srwatson#endif 44168777Srwatson 45155131Srwatsonvoid myfunc3(size_t ncalls); 46168777Srwatsonvoid myfunc2(size_t ncalls); 47168777Srwatsonvoid myfunc1(size_t origcalls, volatile size_t ncalls); 48168777Srwatsonvoid myfunc(size_t ncalls); 49168777Srwatson 50168777Srwatsonvolatile int prevent_inline; 51168777Srwatson 52155131Srwatsonvoid 53168777Srwatsonmyfunc3(size_t ncalls) 54155131Srwatson{ 55155131Srwatson static const struct { 56155131Srwatson const char *name; 57155131Srwatson bool is_optional; 58168777Srwatson } frames[] = { 59168777Srwatson { "myfunc", false }, 60168777Srwatson { "atfu_backtrace_fmt_basic_body", false }, 61155131Srwatson { "atf_tc_run", false }, 62155131Srwatson { "atf_tp_run", true }, 63155131Srwatson { "run_tc", true }, 64155131Srwatson { "controlled_main", true }, 65155131Srwatson { "atf_tp_main", false }, 66155131Srwatson { "main", true }, 67155131Srwatson { "___start", true }, 68168777Srwatson }; 69155131Srwatson size_t j, nptrs, min_frames, max_frames; 70168777Srwatson void *buffer[ncalls + 10]; 71155131Srwatson char **strings; 72168777Srwatson 73155131Srwatson min_frames = 0; 74168777Srwatson max_frames = 0; 75155131Srwatson for (j = 0; j < __arraycount(frames); ++j) { 76168777Srwatson if (!frames[j].is_optional) 77155364Srwatson ++min_frames; 78155131Srwatson ++max_frames; 79155131Srwatson } 80155131Srwatson nptrs = backtrace(buffer, __arraycount(buffer)); 81155131Srwatson ATF_REQUIRE(nptrs != (size_t)-1); 82155131Srwatson strings = backtrace_symbols_fmt(buffer, nptrs, "%n"); 83168777Srwatson 84155131Srwatson ATF_CHECK(strings != NULL); 85168777Srwatson 86155131Srwatson printf("got nptrs=%zu ncalls=%zu (min_frames: %zu, max_frames: %zu)\n", 87155131Srwatson nptrs, ncalls, min_frames, max_frames); 88155131Srwatson printf("backtrace is:\n"); 89155131Srwatson for (j = 0; j < nptrs; j++) { 90168777Srwatson printf("#%zu: %s\n", j, strings[j]); 91155131Srwatson } 92168777Srwatson 93155131Srwatson ATF_REQUIRE(nptrs >= ncalls + 2 + min_frames); 94155131Srwatson ATF_REQUIRE(nptrs <= ncalls + 2 + max_frames); 95155131Srwatson ATF_CHECK_STREQ(strings[0], "myfunc3"); 96155131Srwatson ATF_CHECK_STREQ(strings[1], "myfunc2"); 97155131Srwatson 98155131Srwatson for (j = 2; j < ncalls + 2; j++) 99168777Srwatson ATF_CHECK_STREQ(strings[j], "myfunc1"); 100155131Srwatson 101168777Srwatson for (size_t i = 0; j < nptrs; i++, j++) { 102155131Srwatson if (frames[i].is_optional && 103155131Srwatson strcmp(strings[j], frames[i].name)) { 104155131Srwatson --i; 105155131Srwatson continue; 106168777Srwatson } 107168777Srwatson ATF_CHECK_STREQ(strings[j], frames[i].name); 108168777Srwatson } 109155364Srwatson 110168777Srwatson free(strings); 111155131Srwatson 112168777Srwatson if (prevent_inline) 113155131Srwatson vfork(); 114155131Srwatson} 115168777Srwatson 116168777Srwatsonvoid 117155131Srwatsonmyfunc2(size_t ncalls) 118168777Srwatson{ 119155131Srwatson myfunc3(ncalls); 120155131Srwatson 121168777Srwatson if (prevent_inline) 122168777Srwatson vfork(); 123168777Srwatson} 124168777Srwatson 125155131Srwatsonvoid 126168777Srwatsonmyfunc1(size_t origcalls, volatile size_t ncalls) 127168777Srwatson{ 128155131Srwatson if (ncalls > 1) 129155131Srwatson myfunc1(origcalls, ncalls - 1); 130168777Srwatson else 131168777Srwatson myfunc2(origcalls); 132168777Srwatson 133168777Srwatson if (prevent_inline) 134168777Srwatson vfork(); 135155131Srwatson} 136168777Srwatson 137168777Srwatsonvoid 138168777Srwatsonmyfunc(size_t ncalls) 139168777Srwatson{ 140168777Srwatson myfunc1(ncalls, ncalls); 141168777Srwatson 142168777Srwatson if (prevent_inline) 143155131Srwatson vfork(); 144155131Srwatson} 145155131Srwatson 146155131SrwatsonATF_TC(backtrace_fmt_basic); 147155131SrwatsonATF_TC_HEAD(backtrace_fmt_basic, tc) 148155131Srwatson{ 149155131Srwatson atf_tc_set_md_var(tc, "descr", "Test backtrace_fmt(3)"); 150155131Srwatson atf_tc_set_md_var(tc, "require.files", "/proc/self"); 151155131Srwatson} 152155131Srwatson 153155131SrwatsonATF_TC_BODY(backtrace_fmt_basic, tc) 154155131Srwatson{ 155 myfunc(12); 156 157 if (prevent_inline) 158 vfork(); 159} 160 161ATF_TP_ADD_TCS(tp) 162{ 163 164 ATF_TP_ADD_TC(tp, backtrace_fmt_basic); 165 166 return atf_no_error(); 167} 168