Commit 0f26808e by Christopher Ferris Committed by Android Git Automerger

am 98f87d92: Merge "Rewrite libbacktrace using C++."

* commit '98f87d92':
  Rewrite libbacktrace using C++.
parents 5dadac50 98f87d92
......@@ -89,12 +89,12 @@ static void dump_thread(log_t* log, pid_t tid, bool attached,
wait_for_stop(tid, total_sleep_time_usec);
backtrace_t backtrace;
if (!backtrace_get_data(&backtrace, tid)) {
backtrace_context_t context;
if (!backtrace_create_context(&context, tid, -1, 0)) {
_LOG(log, SCOPE_AT_FAULT, "Could not create backtrace context.\n");
} else {
dump_backtrace_to_log(&backtrace, log, SCOPE_AT_FAULT, " ");
backtrace_free_data(&backtrace);
dump_backtrace_to_log(&context, log, SCOPE_AT_FAULT, " ");
backtrace_destroy_context(&context);
}
if (!attached && ptrace(PTRACE_DETACH, tid, 0, 0) != 0) {
......@@ -137,11 +137,11 @@ void dump_backtrace(int fd, int amfd, pid_t pid, pid_t tid, bool* detach_failed,
dump_process_footer(&log, pid);
}
void dump_backtrace_to_log(const backtrace_t* backtrace, log_t* log,
void dump_backtrace_to_log(const backtrace_context_t* context, log_t* log,
int scope_flags, const char* prefix) {
char buf[512];
for (size_t i = 0; i < backtrace->num_frames; i++) {
backtrace_format_frame_data(&backtrace->frames[i], i, buf, sizeof(buf));
for (size_t i = 0; i < context->backtrace->num_frames; i++) {
backtrace_format_frame_data(context, i, buf, sizeof(buf));
_LOG(log, scope_flags, "%s%s\n", prefix, buf);
}
}
......@@ -31,7 +31,7 @@ void dump_backtrace(int fd, int amfd, pid_t pid, pid_t tid, bool* detach_failed,
int* total_sleep_time_usec);
/* Dumps the backtrace in the backtrace data structure to the log. */
void dump_backtrace_to_log(const backtrace_t* backtrace, log_t* log,
void dump_backtrace_to_log(const backtrace_context_t* context, log_t* log,
int scope_flags, const char* prefix);
#endif // _DEBUGGERD_BACKTRACE_H
......@@ -228,39 +228,39 @@ static void dump_thread_info(log_t* log, pid_t pid, pid_t tid, int scope_flags)
}
}
static void dump_stack_segment(const backtrace_t* backtrace, log_t* log,
static void dump_stack_segment(const backtrace_context_t* context, log_t* log,
int scope_flags, uintptr_t *sp, size_t words, int label) {
for (size_t i = 0; i < words; i++) {
uint32_t stack_content;
if (!backtrace_read_word(backtrace, *sp, &stack_content)) {
if (!backtrace_read_word(context, *sp, &stack_content)) {
break;
}
const char* map_name = backtrace_get_map_info(backtrace, stack_content, NULL);
const char* map_name = backtrace_get_map_name(context, stack_content, NULL);
if (!map_name) {
map_name = "";
}
uintptr_t offset = 0;
char* proc_name = backtrace_get_proc_name(backtrace, stack_content, &offset);
if (proc_name) {
char* func_name = backtrace_get_func_name(context, stack_content, &offset);
if (func_name) {
if (!i && label >= 0) {
if (offset) {
_LOG(log, scope_flags, " #%02d %08x %08x %s (%s+%u)\n",
label, *sp, stack_content, map_name, proc_name, offset);
label, *sp, stack_content, map_name, func_name, offset);
} else {
_LOG(log, scope_flags, " #%02d %08x %08x %s (%s)\n",
label, *sp, stack_content, map_name, proc_name);
label, *sp, stack_content, map_name, func_name);
}
} else {
if (offset) {
_LOG(log, scope_flags, " %08x %08x %s (%s+%u)\n",
*sp, stack_content, map_name, proc_name, offset);
*sp, stack_content, map_name, func_name, offset);
} else {
_LOG(log, scope_flags, " %08x %08x %s (%s)\n",
*sp, stack_content, map_name, proc_name);
*sp, stack_content, map_name, func_name);
}
}
free(proc_name);
free(func_name);
} else {
if (!i && label >= 0) {
_LOG(log, scope_flags, " #%02d %08x %08x %s\n",
......@@ -275,7 +275,8 @@ static void dump_stack_segment(const backtrace_t* backtrace, log_t* log,
}
}
static void dump_stack(const backtrace_t* backtrace, log_t* log, int scope_flags) {
static void dump_stack(const backtrace_context_t* context, log_t* log, int scope_flags) {
const backtrace_t* backtrace = context->backtrace;
size_t first = 0, last;
for (size_t i = 0; i < backtrace->num_frames; i++) {
if (backtrace->frames[i].sp) {
......@@ -294,7 +295,7 @@ static void dump_stack(const backtrace_t* backtrace, log_t* log, int scope_flags
// Dump a few words before the first frame.
uintptr_t sp = backtrace->frames[first].sp - STACK_WORDS * sizeof(uint32_t);
dump_stack_segment(backtrace, log, scope_flags, &sp, STACK_WORDS, -1);
dump_stack_segment(context, log, scope_flags, &sp, STACK_WORDS, -1);
// Dump a few words from all successive frames.
// Only log the first 3 frames, put the rest in the tombstone.
......@@ -308,7 +309,7 @@ static void dump_stack(const backtrace_t* backtrace, log_t* log, int scope_flags
scope_flags &= (~SCOPE_AT_FAULT);
}
if (i == last) {
dump_stack_segment(backtrace, log, scope_flags, &sp, STACK_WORDS, i);
dump_stack_segment(context, log, scope_flags, &sp, STACK_WORDS, i);
if (sp < frame->sp + frame->stack_size) {
_LOG(log, scope_flags, " ........ ........\n");
}
......@@ -319,19 +320,19 @@ static void dump_stack(const backtrace_t* backtrace, log_t* log, int scope_flags
} else if (words > STACK_WORDS) {
words = STACK_WORDS;
}
dump_stack_segment(backtrace, log, scope_flags, &sp, words, i);
dump_stack_segment(context, log, scope_flags, &sp, words, i);
}
}
}
static void dump_backtrace_and_stack(const backtrace_t* backtrace, log_t* log,
int scope_flags) {
if (backtrace->num_frames) {
static void dump_backtrace_and_stack(const backtrace_context_t* context,
log_t* log, int scope_flags) {
if (context->backtrace->num_frames) {
_LOG(log, scope_flags, "\nbacktrace:\n");
dump_backtrace_to_log(backtrace, log, scope_flags, " ");
dump_backtrace_to_log(context, log, scope_flags, " ");
_LOG(log, scope_flags, "\nstack:\n");
dump_stack(backtrace, log, scope_flags);
dump_stack(context, log, scope_flags);
}
}
......@@ -399,12 +400,13 @@ static void dump_nearby_maps(const backtrace_map_info_t* map_info_list, log_t* l
dump_map(log, prev, "map above", scope_flags);
}
static void dump_thread(const backtrace_t* backtrace, log_t* log, int scope_flags,
int* total_sleep_time_usec) {
static void dump_thread(const backtrace_context_t* context, log_t* log,
int scope_flags, int* total_sleep_time_usec) {
const backtrace_t* backtrace = context->backtrace;
wait_for_stop(backtrace->tid, total_sleep_time_usec);
dump_registers(log, backtrace->tid, scope_flags);
dump_backtrace_and_stack(backtrace, log, scope_flags);
dump_backtrace_and_stack(context, log, scope_flags);
if (IS_AT_FAULT(scope_flags)) {
dump_memory_and_code(log, backtrace->tid, scope_flags);
dump_nearby_maps(backtrace->map_info_list, log, backtrace->tid, scope_flags);
......@@ -446,11 +448,11 @@ static bool dump_sibling_thread_report(
_LOG(log, 0, "--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---\n");
dump_thread_info(log, pid, new_tid, 0);
backtrace_t new_backtrace;
if (backtrace_get_data(&new_backtrace, new_tid)) {
dump_thread(&new_backtrace, log, 0, total_sleep_time_usec);
backtrace_context_t new_context;
if (backtrace_create_context(&new_context, pid, new_tid, 0)) {
dump_thread(&new_context, log, 0, total_sleep_time_usec);
backtrace_destroy_context(&new_context);
}
backtrace_free_data(&new_backtrace);
if (ptrace(PTRACE_DETACH, new_tid, 0, 0) != 0) {
LOG("ptrace detach from %d failed: %s\n", new_tid, strerror(errno));
......@@ -606,7 +608,7 @@ static void dump_logs(log_t* log, pid_t pid, bool tailOnly)
dump_log_file(log, pid, "/dev/log/main", tailOnly);
}
static void dump_abort_message(const backtrace_t* backtrace, log_t* log, uintptr_t address) {
static void dump_abort_message(const backtrace_context_t* context, log_t* log, uintptr_t address) {
if (address == 0) {
return;
}
......@@ -618,7 +620,7 @@ static void dump_abort_message(const backtrace_t* backtrace, log_t* log, uintptr
char* p = &msg[0];
while (p < &msg[sizeof(msg)]) {
uint32_t data;
if (!backtrace_read_word(backtrace, address, &data)) {
if (!backtrace_read_word(context, address, &data)) {
break;
}
address += sizeof(uint32_t);
......@@ -673,11 +675,11 @@ static bool dump_crash(log_t* log, pid_t pid, pid_t tid, int signal, uintptr_t a
dump_fault_addr(log, tid, signal);
}
backtrace_t backtrace;
if (backtrace_get_data(&backtrace, tid)) {
dump_abort_message(&backtrace, log, abort_msg_address);
dump_thread(&backtrace, log, SCOPE_AT_FAULT, total_sleep_time_usec);
backtrace_free_data(&backtrace);
backtrace_context_t context;
if (backtrace_create_context(&context, pid, tid, 0)) {
dump_abort_message(&context, log, abort_msg_address);
dump_thread(&context, log, SCOPE_AT_FAULT, total_sleep_time_usec);
backtrace_destroy_context(&context);
}
if (want_logs) {
......
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _BACKTRACE_BACKTRACE_H
#define _BACKTRACE_BACKTRACE_H
#include <backtrace/backtrace.h>
#include <string>
class BacktraceImpl;
class Backtrace {
public:
Backtrace(BacktraceImpl* impl);
virtual ~Backtrace();
// Get the current stack trace and store in the backtrace_ structure.
virtual bool Unwind(size_t num_ignore_frames);
// Get the function name and offset into the function given the pc.
// If the string is empty, then no valid function name was found.
virtual std::string GetFunctionName(uintptr_t pc, uintptr_t* offset);
// Get the name of the map associated with the given pc. If NULL is returned,
// then map_start is not set. Otherwise, map_start is the beginning of this
// map.
virtual const char* GetMapName(uintptr_t pc, uintptr_t* map_start);
// Finds the memory map associated with the given ptr.
virtual const backtrace_map_info_t* FindMapInfo(uintptr_t ptr);
// Read the data at a specific address.
virtual bool ReadWord(uintptr_t ptr, uint32_t* out_value) = 0;
// Create a string representing the formatted line of backtrace information
// for a single frame.
virtual std::string FormatFrameData(size_t frame_num);
pid_t Pid() { return backtrace_.pid; }
pid_t Tid() { return backtrace_.tid; }
size_t NumFrames() { return backtrace_.num_frames; }
const backtrace_t* GetBacktrace() { return &backtrace_; }
const backtrace_frame_data_t* GetFrame(size_t frame_num) {
return &backtrace_.frames[frame_num];
}
// Create the correct Backtrace object based on what is to be unwound.
// If pid < 0 or equals the current pid, then the Backtrace object
// corresponds to the current process.
// If pid < 0 or equals the current pid and tid >= 0, then the Backtrace
// object corresponds to a thread in the current process.
// If pid >= 0 and tid < 0, then the Backtrace object corresponds to a
// different process.
// Tracing a thread in a different process is not supported.
static Backtrace* Create(pid_t pid, pid_t tid);
protected:
virtual bool VerifyReadWordArgs(uintptr_t ptr, uint32_t* out_value);
BacktraceImpl* impl_;
backtrace_map_info_t* map_info_;
backtrace_t backtrace_;
friend class BacktraceImpl;
};
#endif // _BACKTRACE_BACKTRACE_H
......@@ -21,9 +21,7 @@
#include <stdbool.h>
#include <inttypes.h>
#ifdef __cplusplus
extern "C" {
#endif
__BEGIN_DECLS
#define MAX_BACKTRACE_FRAMES 64
......@@ -43,48 +41,58 @@ typedef struct {
size_t stack_size; /* The size of the stack, zero indicate an unknown stack size. */
const char* map_name; /* The name of the map to which this pc belongs, NULL indicates the pc doesn't belong to a known map. */
uintptr_t map_offset; /* pc relative to the start of the map, only valid if map_name is not NULL. */
char* proc_name; /* The function name associated with this pc, NULL if not found. */
uintptr_t proc_offset; /* pc relative to the start of the procedure, only valid if proc_name is not NULL. */
char* func_name; /* The function name associated with this pc, NULL if not found. */
uintptr_t func_offset; /* pc relative to the start of the function, only valid if func_name is not NULL. */
} backtrace_frame_data_t;
typedef struct {
backtrace_frame_data_t frames[MAX_BACKTRACE_FRAMES];
size_t num_frames;
pid_t pid;
pid_t tid;
backtrace_map_info_t* map_info_list;
void* private_data;
} backtrace_t;
/* Gather the backtrace data for tid and fill in the backtrace structure.
* If tid < 0, then gather the backtrace for the current thread.
typedef struct {
void* data;
const backtrace_t* backtrace;
} backtrace_context_t;
/* Create a context for the backtrace data and gather the backtrace.
* If pid < 0, then gather the backtrace for the current process.
*/
bool backtrace_get_data(backtrace_t* backtrace, pid_t tid);
bool backtrace_create_context(
backtrace_context_t* context, pid_t pid, pid_t tid, size_t num_ignore_frames);
/* Free any memory associated with the backtrace structure. */
void backtrace_free_data(backtrace_t* backtrace);
/* Gather the backtrace data for a pthread instead of a process. */
bool backtrace_create_thread_context(
backtrace_context_t* context, pid_t tid, size_t num_ignore_frames);
/* Free any memory allocated during the context create. */
void backtrace_destroy_context(backtrace_context_t* context);
/* Read data at a specific address for a process. */
bool backtrace_read_word(
const backtrace_t* backtrace, uintptr_t ptr, uint32_t* value);
const backtrace_context_t* context, uintptr_t ptr, uint32_t* value);
/* Get information about the map associated with a pc. If NULL is
/* Get information about the map name associated with a pc. If NULL is
* returned, then map_start is not set.
*/
const char* backtrace_get_map_info(
const backtrace_t* backtrace, uintptr_t pc, uintptr_t* map_start);
const char* backtrace_get_map_name(
const backtrace_context_t* context, uintptr_t pc, uintptr_t* map_start);
/* Get the procedure name and offest given the pc. If NULL is returned,
* then proc_offset is not set. The returned string is allocated using
/* Get the function name and offset given the pc. If NULL is returned,
* then func_offset is not set. The returned string is allocated using
* malloc and must be freed by the caller.
*/
char* backtrace_get_proc_name(
const backtrace_t* backtrace, uintptr_t pc, uintptr_t* proc_offset);
char* backtrace_get_func_name(
const backtrace_context_t* context, uintptr_t pc, uintptr_t* func_offset);
/* Loads memory map from /proc/<tid>/maps. If tid < 0, then load the memory
/* Loads memory map from /proc/<pid>/maps. If pid < 0, then load the memory
* map for the current process.
*/
backtrace_map_info_t* backtrace_create_map_info_list(pid_t tid);
backtrace_map_info_t* backtrace_create_map_info_list(pid_t pid);
/* Frees memory associated with the map list. */
void backtrace_destroy_map_info_list(backtrace_map_info_t* map_info_list);
......@@ -95,10 +103,12 @@ const backtrace_map_info_t* backtrace_find_map_info(
/* Create a formatted line of backtrace information for a single frame. */
void backtrace_format_frame_data(
const backtrace_frame_data_t* frame, size_t frame_num, char *buf, size_t buf_size);
const backtrace_context_t* context, size_t frame_num, char* buf,
size_t buf_size);
/* Get the backtrace data structure associated with the context. */
const backtrace_t* backtrace_get_data(backtrace_context_t* context);
#ifdef __cplusplus
}
#endif
__END_DECLS
#endif /* _BACKTRACE_H */
LOCAL_PATH:= $(call my-dir)
common_src := \
Backtrace.cpp \
BacktraceThread.cpp \
map_info.c \
thread_utils.c \
common_cflags := \
-Wall \
-Wno-unused-parameter \
-Werror \
common_conlyflags := \
-std=gnu99 \
common_cppflags := \
-std=gnu++11 \
common_shared_libs := \
libcutils \
libgccdemangle \
liblog \
# To enable using libunwind on each arch, add it to the list below.
ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),))
#----------------------------------------------------------------------------
# The libbacktrace library using libunwind
# The native libbacktrace library with libunwind.
#----------------------------------------------------------------------------
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
unwind.c \
unwind_remote.c \
unwind_local.c \
common.c \
demangle.c \
map_info.c \
$(common_src) \
UnwindCurrent.cpp \
UnwindPtrace.cpp \
LOCAL_CFLAGS := \
-Wall \
-Wno-unused-parameter \
-Werror \
-std=gnu99 \
$(common_cflags) \
LOCAL_CONLYFLAGS += \
$(common_conlyflags) \
LOCAL_CPPFLAGS += \
$(common_cppflags) \
LOCAL_MODULE := libbacktrace
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := \
$(common_c_includes) \
external/libunwind/include \
LOCAL_SHARED_LIBRARIES := \
liblog \
$(common_shared_libs) \
libunwind \
libunwind-ptrace \
libgccdemangle \
LOCAL_C_INCLUDES := \
external/libunwind/include \
LOCAL_ADDITIONAL_DEPENDENCIES := \
$(LOCAL_PATH)/Android.mk
# The libunwind code is not in the tree yet, so don't build this library yet.
#include $(BUILD_SHARED_LIBRARY)
include external/stlport/libstlport.mk
include $(BUILD_SHARED_LIBRARY)
else
#----------------------------------------------------------------------------
# The libbacktrace library using libcorkscrew
# The native libbacktrace library with libcorkscrew.
#----------------------------------------------------------------------------
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
corkscrew.c \
common.c \
demangle.c \
map_info.c \
$(common_src) \
Corkscrew.cpp \
LOCAL_CFLAGS := \
-Wall \
-Wno-unused-parameter \
-Werror \
-std=gnu99 \
$(common_cflags) \
LOCAL_CONLYFLAGS += \
$(common_conlyflags) \
LOCAL_CPPFLAGS += \
$(common_cppflags) \
LOCAL_MODULE := libbacktrace
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := \
$(common_c_includes) \
system/core/libcorkscrew \
LOCAL_SHARED_LIBRARIES := \
$(common_shared_libs) \
libcorkscrew \
libdl \
libgccdemangle \
liblog \
LOCAL_ADDITIONAL_DEPENDENCIES := \
$(LOCAL_PATH)/Android.mk
include external/stlport/libstlport.mk
include $(BUILD_SHARED_LIBRARY)
endif
#----------------------------------------------------------------------------
# libbacktrace test library, all optimizations turned off
#----------------------------------------------------------------------------
......@@ -77,6 +119,9 @@ LOCAL_CFLAGS += \
-std=gnu99 \
-O0 \
LOCAL_ADDITIONAL_DEPENDENCIES := \
$(LOCAL_PATH)/Android.mk
include $(BUILD_SHARED_LIBRARY)
#----------------------------------------------------------------------------
......@@ -88,16 +133,36 @@ LOCAL_MODULE := backtrace_test
LOCAL_MODULE_FLAGS := debug
LOCAL_SRC_FILES := \
backtrace_test.c \
backtrace_test.cpp \
thread_utils.c \
LOCAL_CFLAGS += \
-std=gnu99 \
-fno-builtin \
-fstack-protector-all \
-O0 \
-g \
-DGTEST_OS_LINUX_ANDROID \
-DGTEST_HAS_STD_STRING \
LOCAL_SHARED_LIBRARIES := \
LOCAL_CONLYFLAGS += \
$(common_conlyflags) \
LOCAL_CPPFLAGS += \
$(common_cppflags) \
-fpermissive \
LOCAL_SHARED_LIBRARIES += \
libcutils \
libbacktrace_test \
libbacktrace \
include $(BUILD_EXECUTABLE)
LOCAL_LDLIBS := \
-lpthread \
LOCAL_ADDITIONAL_DEPENDENCIES := \
$(LOCAL_PATH)/Android.mk
include $(BUILD_NATIVE_TEST)
#----------------------------------------------------------------------------
# Only linux-x86 host versions of libbacktrace supported.
......@@ -110,22 +175,26 @@ ifeq ($(HOST_OS)-$(HOST_ARCH),linux-x86)
include $(CLEAR_VARS)
LOCAL_SRC_FILES += \
corkscrew.c \
common.c \
demangle.c \
map_info.c \
$(common_src) \
Corkscrew.cpp \
LOCAL_CFLAGS += \
-Wall \
-Wno-unused-parameter \
-Werror \
-std=gnu99 \
$(common_cflags) \
LOCAL_CONLYFLAGS += \
$(common_conlyflags) \
LOCAL_CPPFLAGS += \
$(common_cppflags) \
LOCAL_C_INCLUDES := \
$(common_c_includes) \
system/core/libcorkscrew \
LOCAL_SHARED_LIBRARIES := \
liblog \
libcorkscrew \
libgccdemangle \
liblog \
libcorkscrew \
LOCAL_LDLIBS += \
-ldl \
......@@ -134,6 +203,9 @@ LOCAL_LDLIBS += \
LOCAL_MODULE := libbacktrace
LOCAL_MODULE_TAGS := optional
LOCAL_ADDITIONAL_DEPENDENCIES := \
$(LOCAL_PATH)/Android.mk
include $(BUILD_HOST_SHARED_LIBRARY)
#----------------------------------------------------------------------------
......@@ -151,6 +223,9 @@ LOCAL_CFLAGS += \
-std=gnu99 \
-O0 \
LOCAL_ADDITIONAL_DEPENDENCIES := \
$(LOCAL_PATH)/Android.mk
include $(BUILD_HOST_SHARED_LIBRARY)
#----------------------------------------------------------------------------
......@@ -162,15 +237,29 @@ LOCAL_MODULE := backtrace_test
LOCAL_MODULE_FLAGS := debug
LOCAL_SRC_FILES := \
backtrace_test.c \
backtrace_test.cpp \
thread_utils.c \
LOCAL_CFLAGS += \
-std=gnu99 \
-fno-builtin \
-fstack-protector-all \
-O0 \
-g \
-DGTEST_HAS_STD_STRING \
LOCAL_SHARED_LIBRARIES := \
libbacktrace_test \
libbacktrace \
include $(BUILD_HOST_EXECUTABLE)
LOCAL_CPPFLAGS += \
-fpermissive \
LOCAL_LDLIBS := \
-lpthread \
LOCAL_ADDITIONAL_DEPENDENCIES := \
$(LOCAL_PATH)/Android.mk
include $(BUILD_HOST_NATIVE_TEST)
endif # HOST_OS-HOST_ARCH == linux-x86
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <unistd.h>
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#include <string>
#include <backtrace/Backtrace.h>
#include <cutils/log.h>
#include "Backtrace.h"
#include "thread_utils.h"
//-------------------------------------------------------------------------
// BacktraceImpl functions.
//-------------------------------------------------------------------------
backtrace_t* BacktraceImpl::GetBacktraceData() {
return &backtrace_obj_->backtrace_;
}
//-------------------------------------------------------------------------
// Backtrace functions.
//-------------------------------------------------------------------------
Backtrace::Backtrace(BacktraceImpl* impl) : impl_(impl), map_info_(NULL) {
impl_->SetParent(this);
backtrace_.num_frames = 0;
backtrace_.pid = -1;
backtrace_.tid = -1;
}
Backtrace::~Backtrace() {
for (size_t i = 0; i < NumFrames(); i++) {
if (backtrace_.frames[i].func_name) {
free(backtrace_.frames[i].func_name);
backtrace_.frames[i<