/* * Copyright (C) 2008 The Android Open Source Project * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include <unwind.h> #include <sys/types.h> // ============================================================================= // stack trace functions // ============================================================================= typedef struct { size_t count; intptr_t* addrs; } stack_crawl_state_t; /* depends how the system includes define this */ #ifdef HAVE_UNWIND_CONTEXT_STRUCT typedef struct _Unwind_Context __unwind_context; #else typedef _Unwind_Context __unwind_context; #endif static _Unwind_Reason_Code trace_function(__unwind_context *context, void *arg) { stack_crawl_state_t* state = (stack_crawl_state_t*)arg; if (state->count) { intptr_t ip = (intptr_t)_Unwind_GetIP(context); if (ip) { state->addrs[0] = ip; state->addrs++; state->count--; return _URC_NO_REASON; } } /* * If we run out of space to record the address or 0 has been seen, stop * unwinding the stack. */ return _URC_END_OF_STACK; } int heaptracker_stacktrace(intptr_t* addrs, size_t max_entries) { stack_crawl_state_t state; state.count = max_entries; state.addrs = (intptr_t*)addrs; _Unwind_Backtrace(trace_function, (void*)&state); return max_entries - state.count; }