blob: 65e6e433ce5bfd3eda759c796ab61335c18d48d5 [file] [log] [blame]
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "partition_alloc/partition_alloc_base/debug/stack_trace.h"
#include "partition_alloc/partition_alloc_base/logging.h"
#include "partition_alloc/partition_alloc_base/strings/safe_sprintf.h"
#include <string.h>
#include <unistd.h>
#include <unwind.h>
namespace partition_alloc::internal::base::debug {
namespace {
struct StackCrawlState {
StackCrawlState(uintptr_t* frames, size_t max_depth)
: frames(frames),
frame_count(0),
max_depth(max_depth),
have_skipped_self(false) {}
uintptr_t* frames;
size_t frame_count;
size_t max_depth;
bool have_skipped_self;
};
_Unwind_Reason_Code TraceStackFrame(_Unwind_Context* context, void* arg) {
StackCrawlState* state = static_cast<StackCrawlState*>(arg);
uintptr_t ip = _Unwind_GetIP(context);
// The first stack frame is this function itself. Skip it.
if (ip != 0 && !state->have_skipped_self) {
state->have_skipped_self = true;
return _URC_NO_REASON;
}
state->frames[state->frame_count++] = ip;
if (state->frame_count >= state->max_depth) {
return _URC_END_OF_STACK;
}
return _URC_NO_REASON;
}
} // namespace
size_t CollectStackTrace(const void** trace, size_t count) {
StackCrawlState state(reinterpret_cast<uintptr_t*>(trace), count);
_Unwind_Backtrace(&TraceStackFrame, &state);
return state.frame_count;
}
void OutputStackTrace(unsigned index,
uintptr_t address,
uintptr_t base_address,
const char* module_name,
uintptr_t offset) {
size_t module_name_len = strlen(module_name);
char buffer[256];
if (module_name_len > 4 &&
!strcmp(module_name + module_name_len - 4, ".apk")) {
strings::SafeSPrintf(buffer, "#%02d pc 0x%0x %s (offset 0x%0x)\n", index,
address - base_address, module_name, offset);
} else {
strings::SafeSPrintf(buffer, "#%02d pc 0x%0x %s\n", index,
address - base_address, module_name);
}
PA_RAW_LOG(INFO, buffer);
}
} // namespace partition_alloc::internal::base::debug