GTTF: dump registers on crash on 64-bit Linux

BUG=none

Review URL: https://codereview.chromium.org/11745003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@176110 0039d316-1c4b-4281-b951-d872f2087c98
parent f8eee19d
......@@ -86,7 +86,11 @@ namespace internal {
// conversion was successful or NULL otherwise. It never writes more than "sz"
// bytes. Output will be truncated as needed, and a NUL character is always
// appended.
BASE_EXPORT char *itoa_r(intptr_t i, char *buf, size_t sz, int base);
BASE_EXPORT char *itoa_r(intptr_t i,
char *buf,
size_t sz,
int base,
size_t padding);
#endif // defined(OS_POSIX) && !defined(OS_ANDROID)
} // namespace internal
......
......@@ -114,7 +114,8 @@ class BacktraceOutputHandler {
void OutputPointer(void* pointer, BacktraceOutputHandler* handler) {
char buf[1024] = { '\0' };
handler->HandleOutput(" [0x");
internal::itoa_r(reinterpret_cast<intptr_t>(pointer), buf, sizeof(buf), 16);
internal::itoa_r(reinterpret_cast<intptr_t>(pointer),
buf, sizeof(buf), 16, 12);
handler->HandleOutput(buf);
handler->HandleOutput("]");
}
......@@ -127,7 +128,8 @@ void ProcessBacktrace(void *const *trace,
#if defined(USE_SYMBOLIZE)
for (int i = 0; i < size; ++i) {
handler->HandleOutput("\t");
OutputPointer(trace[i], handler);
handler->HandleOutput(" ");
char buf[1024] = { '\0' };
......@@ -139,7 +141,6 @@ void ProcessBacktrace(void *const *trace,
else
handler->HandleOutput("<unknown>");
OutputPointer(trace[i], handler);
handler->HandleOutput("\n");
}
#else
......@@ -183,13 +184,57 @@ void StackDumpSignalHandler(int signal, siginfo_t* info, ucontext_t* context) {
char buf[1024] = "Received signal ";
size_t buf_len = strlen(buf);
internal::itoa_r(signal, buf + buf_len, sizeof(buf) - buf_len, 10);
internal::itoa_r(signal, buf + buf_len, sizeof(buf) - buf_len, 10, 0);
RAW_LOG(ERROR, buf);
debug::StackTrace().PrintBacktrace();
// TODO(shess): Port to Linux.
#if defined(OS_MACOSX)
#if defined(OS_LINUX)
// TODO(phajdan.jr): Port to 32-bit.
#if ARCH_CPU_X86_FAMILY && ARCH_CPU_64_BITS
const struct {
const char* label;
greg_t value;
} registers[] = {
{ " r8: ", context->uc_mcontext.gregs[REG_R8] },
{ " r9: ", context->uc_mcontext.gregs[REG_R9] },
{ " r10: ", context->uc_mcontext.gregs[REG_R10] },
{ " r11: ", context->uc_mcontext.gregs[REG_R11] },
{ " r12: ", context->uc_mcontext.gregs[REG_R12] },
{ " r13: ", context->uc_mcontext.gregs[REG_R13] },
{ " r14: ", context->uc_mcontext.gregs[REG_R14] },
{ " r15: ", context->uc_mcontext.gregs[REG_R15] },
{ " di: ", context->uc_mcontext.gregs[REG_RDI] },
{ " si: ", context->uc_mcontext.gregs[REG_RSI] },
{ " bp: ", context->uc_mcontext.gregs[REG_RBP] },
{ " bx: ", context->uc_mcontext.gregs[REG_RBX] },
{ " dx: ", context->uc_mcontext.gregs[REG_RDX] },
{ " ax: ", context->uc_mcontext.gregs[REG_RAX] },
{ " cx: ", context->uc_mcontext.gregs[REG_RCX] },
{ " sp: ", context->uc_mcontext.gregs[REG_RSP] },
{ " ip: ", context->uc_mcontext.gregs[REG_RIP] },
{ " efl: ", context->uc_mcontext.gregs[REG_EFL] },
{ " cgf: ", context->uc_mcontext.gregs[REG_CSGSFS] },
{ " erf: ", context->uc_mcontext.gregs[REG_ERR] },
{ " trp: ", context->uc_mcontext.gregs[REG_TRAPNO] },
{ " msk: ", context->uc_mcontext.gregs[REG_OLDMASK] },
{ " cr2: ", context->uc_mcontext.gregs[REG_CR2] },
};
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(registers); i++) {
HANDLE_EINTR(write(STDERR_FILENO,
registers[i].label,
strlen(registers[i].label)));
internal::itoa_r(registers[i].value, buf, sizeof(buf), 16, 16);
HANDLE_EINTR(write(STDERR_FILENO, buf, strlen(buf)));
if ((i + 1) % 4 == 0) {
HANDLE_EINTR(write(STDERR_FILENO, "\n", 1));
}
}
HANDLE_EINTR(write(STDERR_FILENO, "\n", 1));
#endif
#elif defined(OS_MACOSX)
// TODO(shess): Port to 64-bit.
#if ARCH_CPU_X86_FAMILY && ARCH_CPU_32_BITS
size_t len;
......@@ -347,7 +392,7 @@ void StackTrace::OutputToStream(std::ostream* os) const {
namespace internal {
// NOTE: code from sandbox/linux/seccomp-bpf/demo.cc.
char *itoa_r(intptr_t i, char *buf, size_t sz, int base) {
char *itoa_r(intptr_t i, char *buf, size_t sz, int base, size_t padding) {
// Make sure we can write at least one NUL byte.
size_t n = 1;
if (n > sz)
......@@ -387,7 +432,10 @@ char *itoa_r(intptr_t i, char *buf, size_t sz, int base) {
// Output the next digit.
*ptr++ = "0123456789abcdef"[j % base];
j /= base;
} while (j);
if (padding > 0)
padding--;
} while (j > 0 || padding > 0);
// Terminate the output with a NUL character.
*ptr = '\000';
......
......@@ -151,11 +151,11 @@ TEST_F(StackTraceTest, AsyncSignalUnsafeSignalHandlerHang) {
namespace {
std::string itoa_r_wrapper(intptr_t i, size_t sz, int base) {
std::string itoa_r_wrapper(intptr_t i, size_t sz, int base, size_t padding) {
char buffer[1024];
CHECK_LE(sz, sizeof(buffer));
char* result = internal::itoa_r(i, buffer, sz, base);
char* result = internal::itoa_r(i, buffer, sz, base, padding);
EXPECT_TRUE(result);
return std::string(buffer);
}
......@@ -163,47 +163,64 @@ std::string itoa_r_wrapper(intptr_t i, size_t sz, int base) {
} // namespace
TEST_F(StackTraceTest, itoa_r) {
EXPECT_EQ("0", itoa_r_wrapper(0, 128, 10));
EXPECT_EQ("-1", itoa_r_wrapper(-1, 128, 10));
EXPECT_EQ("0", itoa_r_wrapper(0, 128, 10, 0));
EXPECT_EQ("-1", itoa_r_wrapper(-1, 128, 10, 0));
// Test edge cases.
if (sizeof(intptr_t) == 4) {
EXPECT_EQ("ffffffff", itoa_r_wrapper(-1, 128, 16));
EXPECT_EQ("ffffffff", itoa_r_wrapper(-1, 128, 16, 0));
EXPECT_EQ("-2147483648",
itoa_r_wrapper(std::numeric_limits<intptr_t>::min(), 128, 10));
itoa_r_wrapper(std::numeric_limits<intptr_t>::min(), 128, 10, 0));
EXPECT_EQ("2147483647",
itoa_r_wrapper(std::numeric_limits<intptr_t>::max(), 128, 10));
itoa_r_wrapper(std::numeric_limits<intptr_t>::max(), 128, 10, 0));
EXPECT_EQ("80000000",
itoa_r_wrapper(std::numeric_limits<intptr_t>::min(), 128, 16));
itoa_r_wrapper(std::numeric_limits<intptr_t>::min(), 128, 16, 0));
EXPECT_EQ("7fffffff",
itoa_r_wrapper(std::numeric_limits<intptr_t>::max(), 128, 16));
itoa_r_wrapper(std::numeric_limits<intptr_t>::max(), 128, 16, 0));
} else if (sizeof(intptr_t) == 8) {
EXPECT_EQ("ffffffffffffffff", itoa_r_wrapper(-1, 128, 16));
EXPECT_EQ("ffffffffffffffff", itoa_r_wrapper(-1, 128, 16, 0));
EXPECT_EQ("-9223372036854775808",
itoa_r_wrapper(std::numeric_limits<intptr_t>::min(), 128, 10));
itoa_r_wrapper(std::numeric_limits<intptr_t>::min(), 128, 10, 0));
EXPECT_EQ("9223372036854775807",
itoa_r_wrapper(std::numeric_limits<intptr_t>::max(), 128, 10));
itoa_r_wrapper(std::numeric_limits<intptr_t>::max(), 128, 10, 0));
EXPECT_EQ("8000000000000000",
itoa_r_wrapper(std::numeric_limits<intptr_t>::min(), 128, 16));
itoa_r_wrapper(std::numeric_limits<intptr_t>::min(), 128, 16, 0));
EXPECT_EQ("7fffffffffffffff",
itoa_r_wrapper(std::numeric_limits<intptr_t>::max(), 128, 16));
itoa_r_wrapper(std::numeric_limits<intptr_t>::max(), 128, 16, 0));
} else {
ADD_FAILURE() << "Missing test case for your size of intptr_t ("
<< sizeof(intptr_t) << ")";
}
// Test hex output.
EXPECT_EQ("688", itoa_r_wrapper(0x688, 128, 16));
EXPECT_EQ("deadbeef", itoa_r_wrapper(0xdeadbeef, 128, 16));
EXPECT_EQ("688", itoa_r_wrapper(0x688, 128, 16, 0));
EXPECT_EQ("deadbeef", itoa_r_wrapper(0xdeadbeef, 128, 16, 0));
// Check that itoa_r respects passed buffer size limit.
char buffer[1024];
EXPECT_TRUE(internal::itoa_r(0xdeadbeef, buffer, 10, 16));
EXPECT_TRUE(internal::itoa_r(0xdeadbeef, buffer, 9, 16));
EXPECT_FALSE(internal::itoa_r(0xdeadbeef, buffer, 8, 16));
EXPECT_FALSE(internal::itoa_r(0xdeadbeef, buffer, 7, 16));
EXPECT_TRUE(internal::itoa_r(0xdeadbeef, buffer, 10, 16, 0));
EXPECT_TRUE(internal::itoa_r(0xdeadbeef, buffer, 9, 16, 0));
EXPECT_FALSE(internal::itoa_r(0xdeadbeef, buffer, 8, 16, 0));
EXPECT_FALSE(internal::itoa_r(0xdeadbeef, buffer, 7, 16, 0));
EXPECT_TRUE(internal::itoa_r(0xbeef, buffer, 5, 16, 4));
EXPECT_FALSE(internal::itoa_r(0xbeef, buffer, 5, 16, 5));
EXPECT_FALSE(internal::itoa_r(0xbeef, buffer, 5, 16, 6));
// Test padding.
EXPECT_EQ("1", itoa_r_wrapper(1, 128, 10, 0));
EXPECT_EQ("1", itoa_r_wrapper(1, 128, 10, 1));
EXPECT_EQ("01", itoa_r_wrapper(1, 128, 10, 2));
EXPECT_EQ("001", itoa_r_wrapper(1, 128, 10, 3));
EXPECT_EQ("0001", itoa_r_wrapper(1, 128, 10, 4));
EXPECT_EQ("00001", itoa_r_wrapper(1, 128, 10, 5));
EXPECT_EQ("688", itoa_r_wrapper(0x688, 128, 16, 0));
EXPECT_EQ("688", itoa_r_wrapper(0x688, 128, 16, 1));
EXPECT_EQ("688", itoa_r_wrapper(0x688, 128, 16, 2));
EXPECT_EQ("688", itoa_r_wrapper(0x688, 128, 16, 3));
EXPECT_EQ("0688", itoa_r_wrapper(0x688, 128, 16, 4));
EXPECT_EQ("00688", itoa_r_wrapper(0x688, 128, 16, 5));
}
#endif // defined(OS_POSIX) && !defined(OS_ANDROID)
......
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