diff options
Diffstat (limited to 'libbacktrace/BacktraceImpl.cpp')
-rw-r--r-- | libbacktrace/BacktraceImpl.cpp | 283 |
1 files changed, 0 insertions, 283 deletions
diff --git a/libbacktrace/BacktraceImpl.cpp b/libbacktrace/BacktraceImpl.cpp deleted file mode 100644 index 4650b6a..0000000 --- a/libbacktrace/BacktraceImpl.cpp +++ /dev/null @@ -1,283 +0,0 @@ -/* - * 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/param.h> -#include <sys/ptrace.h> -#include <sys/types.h> -#include <ucontext.h> -#include <unistd.h> - -#include <string> - -#include <backtrace/Backtrace.h> -#include <backtrace/BacktraceMap.h> - -#include "BacktraceImpl.h" -#include "BacktraceLog.h" -#include "thread_utils.h" - -//------------------------------------------------------------------------- -// Backtrace functions. -//------------------------------------------------------------------------- -Backtrace::Backtrace(BacktraceImpl* impl, pid_t pid, BacktraceMap* map) - : pid_(pid), tid_(-1), map_(map), map_shared_(true), impl_(impl) { - impl_->SetParent(this); - - if (map_ == NULL) { - map_ = BacktraceMap::Create(pid); - map_shared_ = false; - } -} - -Backtrace::~Backtrace() { - if (impl_) { - delete impl_; - impl_ = NULL; - } - - if (map_ && !map_shared_) { - delete map_; - map_ = NULL; - } -} - -bool Backtrace::Unwind(size_t num_ignore_frames, ucontext_t* ucontext) { - return impl_->Unwind(num_ignore_frames, ucontext); -} - -extern "C" char* __cxa_demangle(const char* mangled, char* buf, size_t* len, - int* status); - -std::string Backtrace::GetFunctionName(uintptr_t pc, uintptr_t* offset) { - std::string func_name = impl_->GetFunctionNameRaw(pc, offset); - if (!func_name.empty()) { -#if defined(__APPLE__) - // Mac OS' __cxa_demangle demangles "f" as "float"; last tested on 10.7. - if (func_name[0] != '_') { - return func_name; - } -#endif - char* name = __cxa_demangle(func_name.c_str(), 0, 0, 0); - if (name) { - func_name = name; - free(name); - } - } - return func_name; -} - -bool Backtrace::VerifyReadWordArgs(uintptr_t ptr, word_t* out_value) { - if (ptr & (sizeof(word_t)-1)) { - BACK_LOGW("invalid pointer %p", (void*)ptr); - *out_value = (word_t)-1; - return false; - } - return true; -} - -std::string Backtrace::FormatFrameData(size_t frame_num) { - if (frame_num >= frames_.size()) { - return ""; - } - return FormatFrameData(&frames_[frame_num]); -} - -std::string Backtrace::FormatFrameData(const backtrace_frame_data_t* frame) { - const char* map_name; - if (BacktraceMap::IsValid(frame->map) && !frame->map.name.empty()) { - map_name = frame->map.name.c_str(); - } else { - map_name = "<unknown>"; - } - - uintptr_t relative_pc; - if (BacktraceMap::IsValid(frame->map)) { - relative_pc = frame->pc - frame->map.start; - } else { - relative_pc = frame->pc; - } - - char buf[512]; - if (!frame->func_name.empty() && frame->func_offset) { - snprintf(buf, sizeof(buf), "#%02zu pc %0*" PRIxPTR " %s (%s+%" PRIuPTR ")", - frame->num, (int)sizeof(uintptr_t)*2, relative_pc, map_name, - frame->func_name.c_str(), frame->func_offset); - } else if (!frame->func_name.empty()) { - snprintf(buf, sizeof(buf), "#%02zu pc %0*" PRIxPTR " %s (%s)", frame->num, - (int)sizeof(uintptr_t)*2, relative_pc, map_name, frame->func_name.c_str()); - } else { - snprintf(buf, sizeof(buf), "#%02zu pc %0*" PRIxPTR " %s", frame->num, - (int)sizeof(uintptr_t)*2, relative_pc, map_name); - } - - return buf; -} - -void Backtrace::FillInMap(uintptr_t pc, backtrace_map_t* map) { - map_->FillIn(pc, map); -} - -//------------------------------------------------------------------------- -// BacktraceCurrent functions. -//------------------------------------------------------------------------- -BacktraceCurrent::BacktraceCurrent( - BacktraceImpl* impl, BacktraceMap* map) : Backtrace(impl, getpid(), map) { -} - -BacktraceCurrent::~BacktraceCurrent() { -} - -bool BacktraceCurrent::ReadWord(uintptr_t ptr, word_t* out_value) { - if (!VerifyReadWordArgs(ptr, out_value)) { - return false; - } - - backtrace_map_t map; - FillInMap(ptr, &map); - if (BacktraceMap::IsValid(map) && map.flags & PROT_READ) { - *out_value = *reinterpret_cast<word_t*>(ptr); - return true; - } else { - BACK_LOGW("pointer %p not in a readable map", reinterpret_cast<void*>(ptr)); - *out_value = static_cast<word_t>(-1); - return false; - } -} - -size_t BacktraceCurrent::Read(uintptr_t addr, uint8_t* buffer, size_t bytes) { - backtrace_map_t map; - FillInMap(addr, &map); - if (!BacktraceMap::IsValid(map) || !(map.flags & PROT_READ)) { - return 0; - } - bytes = MIN(map.end - addr, bytes); - memcpy(buffer, reinterpret_cast<uint8_t*>(addr), bytes); - return bytes; -} - -//------------------------------------------------------------------------- -// BacktracePtrace functions. -//------------------------------------------------------------------------- -BacktracePtrace::BacktracePtrace( - BacktraceImpl* impl, pid_t pid, pid_t tid, BacktraceMap* map) - : Backtrace(impl, pid, map) { - tid_ = tid; -} - -BacktracePtrace::~BacktracePtrace() { -} - -#if !defined(__APPLE__) -static bool PtraceRead(pid_t tid, uintptr_t addr, word_t* out_value) { - // ptrace() returns -1 and sets errno when the operation fails. - // To disambiguate -1 from a valid result, we clear errno beforehand. - errno = 0; - *out_value = ptrace(PTRACE_PEEKTEXT, tid, reinterpret_cast<void*>(addr), NULL); - if (*out_value == static_cast<word_t>(-1) && errno) { - BACK_LOGW("invalid pointer %p reading from tid %d, ptrace() strerror(errno)=%s", - reinterpret_cast<void*>(addr), tid, strerror(errno)); - return false; - } - return true; -} -#endif - -bool BacktracePtrace::ReadWord(uintptr_t ptr, word_t* out_value) { -#if defined(__APPLE__) - BACK_LOGW("MacOS does not support reading from another pid."); - return false; -#else - if (!VerifyReadWordArgs(ptr, out_value)) { - return false; - } - - backtrace_map_t map; - FillInMap(ptr, &map); - if (!BacktraceMap::IsValid(map) || !(map.flags & PROT_READ)) { - return false; - } - - return PtraceRead(Tid(), ptr, out_value); -#endif -} - -size_t BacktracePtrace::Read(uintptr_t addr, uint8_t* buffer, size_t bytes) { -#if defined(__APPLE__) - BACK_LOGW("MacOS does not support reading from another pid."); - return 0; -#else - backtrace_map_t map; - FillInMap(addr, &map); - if (!BacktraceMap::IsValid(map) || !(map.flags & PROT_READ)) { - return 0; - } - - bytes = MIN(map.end - addr, bytes); - size_t bytes_read = 0; - word_t data_word; - size_t align_bytes = addr & (sizeof(word_t) - 1); - if (align_bytes != 0) { - if (!PtraceRead(Tid(), addr & ~(sizeof(word_t) - 1), &data_word)) { - return 0; - } - align_bytes = sizeof(word_t) - align_bytes; - memcpy(buffer, reinterpret_cast<uint8_t*>(&data_word) + sizeof(word_t) - align_bytes, - align_bytes); - addr += align_bytes; - buffer += align_bytes; - bytes -= align_bytes; - bytes_read += align_bytes; - } - - size_t num_words = bytes / sizeof(word_t); - for (size_t i = 0; i < num_words; i++) { - if (!PtraceRead(Tid(), addr, &data_word)) { - return bytes_read; - } - memcpy(buffer, &data_word, sizeof(word_t)); - buffer += sizeof(word_t); - addr += sizeof(word_t); - bytes_read += sizeof(word_t); - } - - size_t left_over = bytes & (sizeof(word_t) - 1); - if (left_over) { - if (!PtraceRead(Tid(), addr, &data_word)) { - return bytes_read; - } - memcpy(buffer, &data_word, left_over); - bytes_read += left_over; - } - return bytes_read; -#endif -} - -Backtrace* Backtrace::Create(pid_t pid, pid_t tid, BacktraceMap* map) { - if (pid == BACKTRACE_CURRENT_PROCESS || pid == getpid()) { - if (tid == BACKTRACE_CURRENT_THREAD || tid == gettid()) { - return CreateCurrentObj(map); - } else { - return CreateThreadObj(tid, map); - } - } else if (tid == BACKTRACE_CURRENT_THREAD) { - return CreatePtraceObj(pid, pid, map); - } else { - return CreatePtraceObj(pid, tid, map); - } -} |