Commit ac34ddc3 authored by Robert Sesek's avatar Robert Sesek Committed by Commit Bot

Reland "Add a utility to format a base::debug::StackTrace for CrashKeyString."

This is a reland of f12be75c
Original change's description:
> Add a utility to format a base::debug::StackTrace for CrashKeyString.
>
> Bug: 598854
> Change-Id: Ie92935f4919e57cae338c33750458c0509a93627
> Reviewed-on: https://chromium-review.googlesource.com/782040
> Commit-Queue: Robert Sesek <rsesek@chromium.org>
> Reviewed-by: Mark Mentovai <mark@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#518381}

Bug: 598854, 787669
Change-Id: I81fef0cba08240ee288d4e3db3c3bcf4ff130219
Reviewed-on: https://chromium-review.googlesource.com/793930Reviewed-by: default avatarMark Mentovai <mark@chromium.org>
Commit-Queue: Robert Sesek <rsesek@chromium.org>
Cr-Commit-Position: refs/heads/master@{#519727}
parent 9787d1d8
...@@ -15,6 +15,7 @@ group("common") { ...@@ -15,6 +15,7 @@ group("common") {
static_library("crash_key") { static_library("crash_key") {
sources = [ sources = [
"crash_key.cc",
"crash_key.h", "crash_key.h",
] ]
......
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/crash/core/common/crash_key.h"
#include "base/format_macros.h"
#include "base/strings/stringprintf.h"
namespace crash_reporter {
namespace internal {
std::string FormatStackTrace(const base::debug::StackTrace& trace,
size_t max_length) {
size_t count = 0;
const void* const* addresses = trace.Addresses(&count);
std::string value;
for (size_t i = 0; i < count; ++i) {
std::string address = base::StringPrintf(
"0x%" PRIx64, reinterpret_cast<uint64_t>(addresses[i]));
if (value.size() + address.size() > max_length)
break;
value += address + " ";
}
if (!value.empty() && value.back() == ' ') {
value.resize(value.size() - 1);
}
return value;
}
} // namespace internal
} // namespace crash_reporter
...@@ -7,6 +7,9 @@ ...@@ -7,6 +7,9 @@
#include <stdint.h> #include <stdint.h>
#include <string>
#include "base/debug/stack_trace.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/strings/string_piece.h" #include "base/strings/string_piece.h"
#include "build/build_config.h" #include "build/build_config.h"
...@@ -171,6 +174,25 @@ class ScopedCrashKeyString { ...@@ -171,6 +174,25 @@ class ScopedCrashKeyString {
DISALLOW_COPY_AND_ASSIGN(ScopedCrashKeyString); DISALLOW_COPY_AND_ASSIGN(ScopedCrashKeyString);
}; };
namespace internal {
// Formats a stack trace into a string whose length will not exceed
// |max_length|. This function ensures no addresses are truncated when
// being formatted.
std::string FormatStackTrace(const base::debug::StackTrace& trace,
size_t max_length);
} // namespace internal
// Formats a base::debug::StackTrace as a string of space-separated hexadecimal
// numbers and stores it in a CrashKeyString.
// TODO(rsesek): When all clients use Crashpad, traces should become a first-
// class Annotation type rather than being forced through string conversion.
template <uint32_t Size>
void SetCrashKeyStringToStackTrace(CrashKeyString<Size>* key,
const base::debug::StackTrace& trace) {
std::string trace_string = internal::FormatStackTrace(trace, Size);
key->Set(trace_string);
}
// Initializes the crash key subsystem if it is required. // Initializes the crash key subsystem if it is required.
void InitializeCrashKeys(); void InitializeCrashKeys();
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include "components/crash/core/common/crash_key.h" #include "components/crash/core/common/crash_key.h"
#include "base/debug/stack_trace.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
namespace crash_reporter { namespace crash_reporter {
...@@ -27,5 +29,54 @@ TEST_F(CrashKeyStringTest, ScopedCrashKeyString) { ...@@ -27,5 +29,54 @@ TEST_F(CrashKeyStringTest, ScopedCrashKeyString) {
EXPECT_FALSE(key.is_set()); EXPECT_FALSE(key.is_set());
} }
TEST_F(CrashKeyStringTest, FormatStackTrace) {
const uintptr_t addresses[] = {
0x0badbeef, 0x77778888, 0xabc, 0x000ddeeff, 0x12345678,
};
base::debug::StackTrace trace(reinterpret_cast<const void* const*>(addresses),
arraysize(addresses));
std::string too_small = internal::FormatStackTrace(trace, 3);
EXPECT_EQ(0u, too_small.size());
std::string one_value = internal::FormatStackTrace(trace, 16);
EXPECT_EQ("0xbadbeef", one_value);
std::string three_values = internal::FormatStackTrace(trace, 30);
EXPECT_EQ("0xbadbeef 0x77778888 0xabc", three_values);
std::string all_values = internal::FormatStackTrace(trace, 128);
EXPECT_EQ("0xbadbeef 0x77778888 0xabc 0xddeeff 0x12345678", all_values);
}
#if defined(ARCH_CPU_64_BITS)
TEST_F(CrashKeyStringTest, FormatStackTrace64) {
const uintptr_t addresses[] = {
0xbaaaabaaaaba, 0x1000000000000000,
};
base::debug::StackTrace trace(reinterpret_cast<const void* const*>(addresses),
arraysize(addresses));
std::string too_small = internal::FormatStackTrace(trace, 8);
EXPECT_EQ(0u, too_small.size());
std::string one_value = internal::FormatStackTrace(trace, 20);
EXPECT_EQ("0xbaaaabaaaaba", one_value);
std::string all_values = internal::FormatStackTrace(trace, 35);
EXPECT_EQ("0xbaaaabaaaaba 0x1000000000000000", all_values);
}
#endif
TEST_F(CrashKeyStringTest, SetStackTrace) {
static CrashKeyString<1024> key("test-trace");
EXPECT_FALSE(key.is_set());
SetCrashKeyStringToStackTrace(&key, base::debug::StackTrace());
EXPECT_TRUE(key.is_set());
}
} // namespace } // namespace
} // namespace crash_reporter } // namespace crash_reporter
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment