634 lines
20 KiB
C++
634 lines
20 KiB
C++
/*
|
|
* Copyright (C) 2015 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 <stdlib.h>
|
|
|
|
#include <memory>
|
|
#include <string>
|
|
|
|
#include <gtest/gtest.h>
|
|
#include <android-base/file.h>
|
|
|
|
#include "utility.h"
|
|
|
|
#include "BacktraceMock.h"
|
|
#include "elf_fake.h"
|
|
#include "host_signal_fixup.h"
|
|
#include "log_fake.h"
|
|
#include "ptrace_fake.h"
|
|
|
|
// In order to test this code, we need to include the tombstone.cpp code.
|
|
// Including it, also allows us to override the ptrace function.
|
|
#define ptrace ptrace_fake
|
|
|
|
#include "tombstone.cpp"
|
|
|
|
void dump_registers(log_t*, pid_t) {
|
|
}
|
|
|
|
void dump_memory_and_code(log_t*, Backtrace*) {
|
|
}
|
|
|
|
void dump_backtrace_to_log(Backtrace*, log_t*, char const*) {
|
|
}
|
|
|
|
class TombstoneTest : public ::testing::Test {
|
|
protected:
|
|
virtual void SetUp() {
|
|
map_mock_.reset(new BacktraceMapMock());
|
|
backtrace_mock_.reset(new BacktraceMock(map_mock_.get()));
|
|
|
|
char tmp_file[256];
|
|
const char data_template[] = "/data/local/tmp/debuggerd_memory_testXXXXXX";
|
|
memcpy(tmp_file, data_template, sizeof(data_template));
|
|
int tombstone_fd = mkstemp(tmp_file);
|
|
if (tombstone_fd == -1) {
|
|
const char tmp_template[] = "/tmp/debuggerd_memory_testXXXXXX";
|
|
memcpy(tmp_file, tmp_template, sizeof(tmp_template));
|
|
tombstone_fd = mkstemp(tmp_file);
|
|
if (tombstone_fd == -1) {
|
|
abort();
|
|
}
|
|
}
|
|
if (unlink(tmp_file) == -1) {
|
|
abort();
|
|
}
|
|
|
|
log_.tfd = tombstone_fd;
|
|
amfd_data_.clear();
|
|
log_.amfd_data = &amfd_data_;
|
|
log_.crashed_tid = 12;
|
|
log_.current_tid = 12;
|
|
log_.should_retrieve_logcat = false;
|
|
|
|
resetLogs();
|
|
elf_set_fake_build_id("");
|
|
siginfo_t si;
|
|
si.si_signo = SIGABRT;
|
|
ptrace_set_fake_getsiginfo(si);
|
|
}
|
|
|
|
virtual void TearDown() {
|
|
if (log_.tfd >= 0) {
|
|
close(log_.tfd);
|
|
}
|
|
}
|
|
|
|
std::unique_ptr<BacktraceMapMock> map_mock_;
|
|
std::unique_ptr<BacktraceMock> backtrace_mock_;
|
|
|
|
log_t log_;
|
|
std::string amfd_data_;
|
|
};
|
|
|
|
TEST_F(TombstoneTest, single_map) {
|
|
backtrace_map_t map;
|
|
#if defined(__LP64__)
|
|
map.start = 0x123456789abcd000UL;
|
|
map.end = 0x123456789abdf000UL;
|
|
#else
|
|
map.start = 0x1234000;
|
|
map.end = 0x1235000;
|
|
#endif
|
|
map_mock_->AddMap(map);
|
|
|
|
dump_all_maps(backtrace_mock_.get(), map_mock_.get(), &log_, 100);
|
|
|
|
std::string tombstone_contents;
|
|
ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
|
|
ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
|
|
const char* expected_dump = \
|
|
"\nmemory map:\n"
|
|
#if defined(__LP64__)
|
|
" 12345678'9abcd000-12345678'9abdefff --- 0 12000\n";
|
|
#else
|
|
" 01234000-01234fff --- 0 1000\n";
|
|
#endif
|
|
ASSERT_STREQ(expected_dump, tombstone_contents.c_str());
|
|
|
|
ASSERT_STREQ("", amfd_data_.c_str());
|
|
|
|
// Verify that the log buf is empty, and no error messages.
|
|
ASSERT_STREQ("", getFakeLogBuf().c_str());
|
|
ASSERT_STREQ("", getFakeLogPrint().c_str());
|
|
}
|
|
|
|
TEST_F(TombstoneTest, single_map_elf_build_id) {
|
|
backtrace_map_t map;
|
|
#if defined(__LP64__)
|
|
map.start = 0x123456789abcd000UL;
|
|
map.end = 0x123456789abdf000UL;
|
|
#else
|
|
map.start = 0x1234000;
|
|
map.end = 0x1235000;
|
|
#endif
|
|
map.flags = PROT_READ;
|
|
map.name = "/system/lib/libfake.so";
|
|
map_mock_->AddMap(map);
|
|
|
|
elf_set_fake_build_id("abcdef1234567890abcdef1234567890");
|
|
dump_all_maps(backtrace_mock_.get(), map_mock_.get(), &log_, 100);
|
|
|
|
std::string tombstone_contents;
|
|
ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
|
|
ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
|
|
const char* expected_dump = \
|
|
"\nmemory map:\n"
|
|
#if defined(__LP64__)
|
|
" 12345678'9abcd000-12345678'9abdefff r-- 0 12000 /system/lib/libfake.so (BuildId: abcdef1234567890abcdef1234567890)\n";
|
|
#else
|
|
" 01234000-01234fff r-- 0 1000 /system/lib/libfake.so (BuildId: abcdef1234567890abcdef1234567890)\n";
|
|
#endif
|
|
ASSERT_STREQ(expected_dump, tombstone_contents.c_str());
|
|
|
|
ASSERT_STREQ("", amfd_data_.c_str());
|
|
|
|
// Verify that the log buf is empty, and no error messages.
|
|
ASSERT_STREQ("", getFakeLogBuf().c_str());
|
|
ASSERT_STREQ("", getFakeLogPrint().c_str());
|
|
}
|
|
|
|
// Even though build id is present, it should not be printed in either of
|
|
// these cases.
|
|
TEST_F(TombstoneTest, single_map_no_build_id) {
|
|
backtrace_map_t map;
|
|
#if defined(__LP64__)
|
|
map.start = 0x123456789abcd000UL;
|
|
map.end = 0x123456789abdf000UL;
|
|
#else
|
|
map.start = 0x1234000;
|
|
map.end = 0x1235000;
|
|
#endif
|
|
map.flags = PROT_WRITE;
|
|
map_mock_->AddMap(map);
|
|
|
|
map.name = "/system/lib/libfake.so";
|
|
map_mock_->AddMap(map);
|
|
|
|
elf_set_fake_build_id("abcdef1234567890abcdef1234567890");
|
|
dump_all_maps(backtrace_mock_.get(), map_mock_.get(), &log_, 100);
|
|
|
|
std::string tombstone_contents;
|
|
ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
|
|
ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
|
|
const char* expected_dump = \
|
|
"\nmemory map:\n"
|
|
#if defined(__LP64__)
|
|
" 12345678'9abcd000-12345678'9abdefff -w- 0 12000\n"
|
|
" 12345678'9abcd000-12345678'9abdefff -w- 0 12000 /system/lib/libfake.so\n";
|
|
#else
|
|
" 01234000-01234fff -w- 0 1000\n"
|
|
" 01234000-01234fff -w- 0 1000 /system/lib/libfake.so\n";
|
|
#endif
|
|
ASSERT_STREQ(expected_dump, tombstone_contents.c_str());
|
|
|
|
ASSERT_STREQ("", amfd_data_.c_str());
|
|
|
|
// Verify that the log buf is empty, and no error messages.
|
|
ASSERT_STREQ("", getFakeLogBuf().c_str());
|
|
ASSERT_STREQ("", getFakeLogPrint().c_str());
|
|
}
|
|
|
|
TEST_F(TombstoneTest, multiple_maps) {
|
|
backtrace_map_t map;
|
|
|
|
map.start = 0xa234000;
|
|
map.end = 0xa235000;
|
|
map_mock_->AddMap(map);
|
|
|
|
map.start = 0xa334000;
|
|
map.end = 0xa335000;
|
|
map.offset = 0xf000;
|
|
map.flags = PROT_READ;
|
|
map_mock_->AddMap(map);
|
|
|
|
map.start = 0xa434000;
|
|
map.end = 0xa435000;
|
|
map.offset = 0x1000;
|
|
map.load_base = 0xd000;
|
|
map.flags = PROT_WRITE;
|
|
map_mock_->AddMap(map);
|
|
|
|
map.start = 0xa534000;
|
|
map.end = 0xa535000;
|
|
map.offset = 0x3000;
|
|
map.load_base = 0x2000;
|
|
map.flags = PROT_EXEC;
|
|
map_mock_->AddMap(map);
|
|
|
|
map.start = 0xa634000;
|
|
map.end = 0xa635000;
|
|
map.offset = 0;
|
|
map.load_base = 0;
|
|
map.flags = PROT_READ | PROT_WRITE | PROT_EXEC;
|
|
map.name = "/system/lib/fake.so";
|
|
map_mock_->AddMap(map);
|
|
|
|
dump_all_maps(backtrace_mock_.get(), map_mock_.get(), &log_, 100);
|
|
|
|
std::string tombstone_contents;
|
|
ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
|
|
ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
|
|
const char* expected_dump = \
|
|
"\nmemory map:\n"
|
|
#if defined(__LP64__)
|
|
" 00000000'0a234000-00000000'0a234fff --- 0 1000\n"
|
|
" 00000000'0a334000-00000000'0a334fff r-- f000 1000\n"
|
|
" 00000000'0a434000-00000000'0a434fff -w- 1000 1000 (load base 0xd000)\n"
|
|
" 00000000'0a534000-00000000'0a534fff --x 3000 1000 (load base 0x2000)\n"
|
|
" 00000000'0a634000-00000000'0a634fff rwx 0 1000 /system/lib/fake.so\n";
|
|
#else
|
|
" 0a234000-0a234fff --- 0 1000\n"
|
|
" 0a334000-0a334fff r-- f000 1000\n"
|
|
" 0a434000-0a434fff -w- 1000 1000 (load base 0xd000)\n"
|
|
" 0a534000-0a534fff --x 3000 1000 (load base 0x2000)\n"
|
|
" 0a634000-0a634fff rwx 0 1000 /system/lib/fake.so\n";
|
|
#endif
|
|
ASSERT_STREQ(expected_dump, tombstone_contents.c_str());
|
|
|
|
ASSERT_STREQ("", amfd_data_.c_str());
|
|
|
|
// Verify that the log buf is empty, and no error messages.
|
|
ASSERT_STREQ("", getFakeLogBuf().c_str());
|
|
ASSERT_STREQ("", getFakeLogPrint().c_str());
|
|
}
|
|
|
|
TEST_F(TombstoneTest, multiple_maps_fault_address_before) {
|
|
backtrace_map_t map;
|
|
|
|
map.start = 0xa434000;
|
|
map.end = 0xa435000;
|
|
map.offset = 0x1000;
|
|
map.load_base = 0xd000;
|
|
map.flags = PROT_WRITE;
|
|
map_mock_->AddMap(map);
|
|
|
|
map.start = 0xa534000;
|
|
map.end = 0xa535000;
|
|
map.offset = 0x3000;
|
|
map.load_base = 0x2000;
|
|
map.flags = PROT_EXEC;
|
|
map_mock_->AddMap(map);
|
|
|
|
map.start = 0xa634000;
|
|
map.end = 0xa635000;
|
|
map.offset = 0;
|
|
map.load_base = 0;
|
|
map.flags = PROT_READ | PROT_WRITE | PROT_EXEC;
|
|
map.name = "/system/lib/fake.so";
|
|
map_mock_->AddMap(map);
|
|
|
|
siginfo_t si;
|
|
si.si_signo = SIGBUS;
|
|
si.si_addr = reinterpret_cast<void*>(0x1000);
|
|
ptrace_set_fake_getsiginfo(si);
|
|
dump_all_maps(backtrace_mock_.get(), map_mock_.get(), &log_, 100);
|
|
|
|
std::string tombstone_contents;
|
|
ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
|
|
ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
|
|
const char* expected_dump = \
|
|
"\nmemory map: (fault address prefixed with --->)\n"
|
|
#if defined(__LP64__)
|
|
"--->Fault address falls at 00000000'00001000 before any mapped regions\n"
|
|
" 00000000'0a434000-00000000'0a434fff -w- 1000 1000 (load base 0xd000)\n"
|
|
" 00000000'0a534000-00000000'0a534fff --x 3000 1000 (load base 0x2000)\n"
|
|
" 00000000'0a634000-00000000'0a634fff rwx 0 1000 /system/lib/fake.so\n";
|
|
#else
|
|
"--->Fault address falls at 00001000 before any mapped regions\n"
|
|
" 0a434000-0a434fff -w- 1000 1000 (load base 0xd000)\n"
|
|
" 0a534000-0a534fff --x 3000 1000 (load base 0x2000)\n"
|
|
" 0a634000-0a634fff rwx 0 1000 /system/lib/fake.so\n";
|
|
#endif
|
|
ASSERT_STREQ(expected_dump, tombstone_contents.c_str());
|
|
|
|
ASSERT_STREQ("", amfd_data_.c_str());
|
|
|
|
// Verify that the log buf is empty, and no error messages.
|
|
ASSERT_STREQ("", getFakeLogBuf().c_str());
|
|
ASSERT_STREQ("", getFakeLogPrint().c_str());
|
|
}
|
|
|
|
TEST_F(TombstoneTest, multiple_maps_fault_address_between) {
|
|
backtrace_map_t map;
|
|
|
|
map.start = 0xa434000;
|
|
map.end = 0xa435000;
|
|
map.offset = 0x1000;
|
|
map.load_base = 0xd000;
|
|
map.flags = PROT_WRITE;
|
|
map_mock_->AddMap(map);
|
|
|
|
map.start = 0xa534000;
|
|
map.end = 0xa535000;
|
|
map.offset = 0x3000;
|
|
map.load_base = 0x2000;
|
|
map.flags = PROT_EXEC;
|
|
map_mock_->AddMap(map);
|
|
|
|
map.start = 0xa634000;
|
|
map.end = 0xa635000;
|
|
map.offset = 0;
|
|
map.load_base = 0;
|
|
map.flags = PROT_READ | PROT_WRITE | PROT_EXEC;
|
|
map.name = "/system/lib/fake.so";
|
|
map_mock_->AddMap(map);
|
|
|
|
siginfo_t si;
|
|
si.si_signo = SIGBUS;
|
|
si.si_addr = reinterpret_cast<void*>(0xa533000);
|
|
ptrace_set_fake_getsiginfo(si);
|
|
dump_all_maps(backtrace_mock_.get(), map_mock_.get(), &log_, 100);
|
|
|
|
std::string tombstone_contents;
|
|
ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
|
|
ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
|
|
const char* expected_dump = \
|
|
"\nmemory map: (fault address prefixed with --->)\n"
|
|
#if defined(__LP64__)
|
|
" 00000000'0a434000-00000000'0a434fff -w- 1000 1000 (load base 0xd000)\n"
|
|
"--->Fault address falls at 00000000'0a533000 between mapped regions\n"
|
|
" 00000000'0a534000-00000000'0a534fff --x 3000 1000 (load base 0x2000)\n"
|
|
" 00000000'0a634000-00000000'0a634fff rwx 0 1000 /system/lib/fake.so\n";
|
|
#else
|
|
" 0a434000-0a434fff -w- 1000 1000 (load base 0xd000)\n"
|
|
"--->Fault address falls at 0a533000 between mapped regions\n"
|
|
" 0a534000-0a534fff --x 3000 1000 (load base 0x2000)\n"
|
|
" 0a634000-0a634fff rwx 0 1000 /system/lib/fake.so\n";
|
|
#endif
|
|
ASSERT_STREQ(expected_dump, tombstone_contents.c_str());
|
|
|
|
ASSERT_STREQ("", amfd_data_.c_str());
|
|
|
|
// Verify that the log buf is empty, and no error messages.
|
|
ASSERT_STREQ("", getFakeLogBuf().c_str());
|
|
ASSERT_STREQ("", getFakeLogPrint().c_str());
|
|
}
|
|
|
|
TEST_F(TombstoneTest, multiple_maps_fault_address_in_map) {
|
|
backtrace_map_t map;
|
|
|
|
map.start = 0xa434000;
|
|
map.end = 0xa435000;
|
|
map.offset = 0x1000;
|
|
map.load_base = 0xd000;
|
|
map.flags = PROT_WRITE;
|
|
map_mock_->AddMap(map);
|
|
|
|
map.start = 0xa534000;
|
|
map.end = 0xa535000;
|
|
map.offset = 0x3000;
|
|
map.load_base = 0x2000;
|
|
map.flags = PROT_EXEC;
|
|
map_mock_->AddMap(map);
|
|
|
|
map.start = 0xa634000;
|
|
map.end = 0xa635000;
|
|
map.offset = 0;
|
|
map.load_base = 0;
|
|
map.flags = PROT_READ | PROT_WRITE | PROT_EXEC;
|
|
map.name = "/system/lib/fake.so";
|
|
map_mock_->AddMap(map);
|
|
|
|
siginfo_t si;
|
|
si.si_signo = SIGBUS;
|
|
si.si_addr = reinterpret_cast<void*>(0xa534040);
|
|
ptrace_set_fake_getsiginfo(si);
|
|
dump_all_maps(backtrace_mock_.get(), map_mock_.get(), &log_, 100);
|
|
|
|
std::string tombstone_contents;
|
|
ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
|
|
ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
|
|
const char* expected_dump = \
|
|
"\nmemory map: (fault address prefixed with --->)\n"
|
|
#if defined(__LP64__)
|
|
" 00000000'0a434000-00000000'0a434fff -w- 1000 1000 (load base 0xd000)\n"
|
|
"--->00000000'0a534000-00000000'0a534fff --x 3000 1000 (load base 0x2000)\n"
|
|
" 00000000'0a634000-00000000'0a634fff rwx 0 1000 /system/lib/fake.so\n";
|
|
#else
|
|
" 0a434000-0a434fff -w- 1000 1000 (load base 0xd000)\n"
|
|
"--->0a534000-0a534fff --x 3000 1000 (load base 0x2000)\n"
|
|
" 0a634000-0a634fff rwx 0 1000 /system/lib/fake.so\n";
|
|
#endif
|
|
ASSERT_STREQ(expected_dump, tombstone_contents.c_str());
|
|
|
|
ASSERT_STREQ("", amfd_data_.c_str());
|
|
|
|
// Verify that the log buf is empty, and no error messages.
|
|
ASSERT_STREQ("", getFakeLogBuf().c_str());
|
|
ASSERT_STREQ("", getFakeLogPrint().c_str());
|
|
}
|
|
|
|
TEST_F(TombstoneTest, multiple_maps_fault_address_after) {
|
|
backtrace_map_t map;
|
|
|
|
map.start = 0xa434000;
|
|
map.end = 0xa435000;
|
|
map.offset = 0x1000;
|
|
map.load_base = 0xd000;
|
|
map.flags = PROT_WRITE;
|
|
map_mock_->AddMap(map);
|
|
|
|
map.start = 0xa534000;
|
|
map.end = 0xa535000;
|
|
map.offset = 0x3000;
|
|
map.load_base = 0x2000;
|
|
map.flags = PROT_EXEC;
|
|
map_mock_->AddMap(map);
|
|
|
|
map.start = 0xa634000;
|
|
map.end = 0xa635000;
|
|
map.offset = 0;
|
|
map.load_base = 0;
|
|
map.flags = PROT_READ | PROT_WRITE | PROT_EXEC;
|
|
map.name = "/system/lib/fake.so";
|
|
map_mock_->AddMap(map);
|
|
|
|
siginfo_t si;
|
|
si.si_signo = SIGBUS;
|
|
#if defined(__LP64__)
|
|
si.si_addr = reinterpret_cast<void*>(0x12345a534040UL);
|
|
#else
|
|
si.si_addr = reinterpret_cast<void*>(0xf534040UL);
|
|
#endif
|
|
ptrace_set_fake_getsiginfo(si);
|
|
dump_all_maps(backtrace_mock_.get(), map_mock_.get(), &log_, 100);
|
|
|
|
std::string tombstone_contents;
|
|
ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
|
|
ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
|
|
const char* expected_dump = \
|
|
"\nmemory map: (fault address prefixed with --->)\n"
|
|
#if defined(__LP64__)
|
|
" 00000000'0a434000-00000000'0a434fff -w- 1000 1000 (load base 0xd000)\n"
|
|
" 00000000'0a534000-00000000'0a534fff --x 3000 1000 (load base 0x2000)\n"
|
|
" 00000000'0a634000-00000000'0a634fff rwx 0 1000 /system/lib/fake.so\n"
|
|
"--->Fault address falls at 00001234'5a534040 after any mapped regions\n";
|
|
#else
|
|
" 0a434000-0a434fff -w- 1000 1000 (load base 0xd000)\n"
|
|
" 0a534000-0a534fff --x 3000 1000 (load base 0x2000)\n"
|
|
" 0a634000-0a634fff rwx 0 1000 /system/lib/fake.so\n"
|
|
"--->Fault address falls at 0f534040 after any mapped regions\n";
|
|
#endif
|
|
ASSERT_STREQ(expected_dump, tombstone_contents.c_str());
|
|
|
|
ASSERT_STREQ("", amfd_data_.c_str());
|
|
|
|
// Verify that the log buf is empty, and no error messages.
|
|
ASSERT_STREQ("", getFakeLogBuf().c_str());
|
|
ASSERT_STREQ("", getFakeLogPrint().c_str());
|
|
}
|
|
|
|
TEST_F(TombstoneTest, multiple_maps_getsiginfo_fail) {
|
|
backtrace_map_t map;
|
|
|
|
map.start = 0xa434000;
|
|
map.end = 0xa435000;
|
|
map.offset = 0x1000;
|
|
map.load_base = 0xd000;
|
|
map.flags = PROT_WRITE;
|
|
map_mock_->AddMap(map);
|
|
|
|
siginfo_t si;
|
|
si.si_signo = 0;
|
|
ptrace_set_fake_getsiginfo(si);
|
|
dump_all_maps(backtrace_mock_.get(), map_mock_.get(), &log_, 100);
|
|
|
|
std::string tombstone_contents;
|
|
ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
|
|
ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
|
|
const char* expected_dump = \
|
|
"\nmemory map:\n"
|
|
#if defined(__LP64__)
|
|
" 00000000'0a434000-00000000'0a434fff -w- 1000 1000 (load base 0xd000)\n";
|
|
#else
|
|
" 0a434000-0a434fff -w- 1000 1000 (load base 0xd000)\n";
|
|
#endif
|
|
ASSERT_STREQ(expected_dump, tombstone_contents.c_str());
|
|
|
|
ASSERT_STREQ("", amfd_data_.c_str());
|
|
|
|
// Verify that the log buf is empty, and no error messages.
|
|
ASSERT_STREQ("", getFakeLogBuf().c_str());
|
|
ASSERT_STREQ("6 DEBUG Cannot get siginfo for 100: Bad address\n\n", getFakeLogPrint().c_str());
|
|
}
|
|
|
|
TEST_F(TombstoneTest, multiple_maps_check_signal_has_si_addr) {
|
|
backtrace_map_t map;
|
|
|
|
map.start = 0xa434000;
|
|
map.end = 0xa435000;
|
|
map.flags = PROT_WRITE;
|
|
map_mock_->AddMap(map);
|
|
|
|
for (int i = 1; i < 255; i++) {
|
|
ASSERT_TRUE(ftruncate(log_.tfd, 0) == 0);
|
|
ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
|
|
|
|
siginfo_t si;
|
|
si.si_signo = i;
|
|
si.si_addr = reinterpret_cast<void*>(0x1000);
|
|
ptrace_set_fake_getsiginfo(si);
|
|
dump_all_maps(backtrace_mock_.get(), map_mock_.get(), &log_, 100);
|
|
|
|
std::string tombstone_contents;
|
|
ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
|
|
ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
|
|
bool has_addr = false;
|
|
switch (si.si_signo) {
|
|
case SIGBUS:
|
|
case SIGFPE:
|
|
case SIGILL:
|
|
case SIGSEGV:
|
|
case SIGTRAP:
|
|
has_addr = true;
|
|
break;
|
|
}
|
|
|
|
const char* expected_addr_dump = \
|
|
"\nmemory map: (fault address prefixed with --->)\n"
|
|
#if defined(__LP64__)
|
|
"--->Fault address falls at 00000000'00001000 before any mapped regions\n"
|
|
" 00000000'0a434000-00000000'0a434fff -w- 0 1000\n";
|
|
#else
|
|
"--->Fault address falls at 00001000 before any mapped regions\n"
|
|
" 0a434000-0a434fff -w- 0 1000\n";
|
|
#endif
|
|
const char* expected_dump = \
|
|
"\nmemory map:\n"
|
|
#if defined(__LP64__)
|
|
" 00000000'0a434000-00000000'0a434fff -w- 0 1000\n";
|
|
#else
|
|
" 0a434000-0a434fff -w- 0 1000\n";
|
|
#endif
|
|
if (has_addr) {
|
|
ASSERT_STREQ(expected_addr_dump, tombstone_contents.c_str())
|
|
<< "Signal " << si.si_signo << " expected to include an address.";
|
|
} else {
|
|
ASSERT_STREQ(expected_dump, tombstone_contents.c_str())
|
|
<< "Signal " << si.si_signo << " is not expected to include an address.";
|
|
}
|
|
|
|
ASSERT_STREQ("", amfd_data_.c_str());
|
|
|
|
// Verify that the log buf is empty, and no error messages.
|
|
ASSERT_STREQ("", getFakeLogBuf().c_str());
|
|
ASSERT_STREQ("", getFakeLogPrint().c_str());
|
|
}
|
|
}
|
|
|
|
TEST_F(TombstoneTest, dump_signal_info_error) {
|
|
siginfo_t si;
|
|
si.si_signo = 0;
|
|
ptrace_set_fake_getsiginfo(si);
|
|
|
|
dump_signal_info(&log_, 123, SIGSEGV, 10);
|
|
|
|
std::string tombstone_contents;
|
|
ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
|
|
ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
|
|
ASSERT_STREQ("", tombstone_contents.c_str());
|
|
|
|
ASSERT_STREQ("", getFakeLogBuf().c_str());
|
|
ASSERT_STREQ("6 DEBUG cannot get siginfo: Bad address\n\n", getFakeLogPrint().c_str());
|
|
|
|
ASSERT_STREQ("", amfd_data_.c_str());
|
|
}
|
|
|
|
TEST_F(TombstoneTest, dump_log_file_error) {
|
|
log_.should_retrieve_logcat = true;
|
|
dump_log_file(&log_, 123, "/fake/filename", 10);
|
|
|
|
std::string tombstone_contents;
|
|
ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
|
|
ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
|
|
ASSERT_STREQ("", tombstone_contents.c_str());
|
|
|
|
ASSERT_STREQ("", getFakeLogBuf().c_str());
|
|
ASSERT_STREQ("6 DEBUG Unable to open /fake/filename: Permission denied\n\n",
|
|
getFakeLogPrint().c_str());
|
|
|
|
ASSERT_STREQ("", amfd_data_.c_str());
|
|
}
|
|
|
|
TEST_F(TombstoneTest, dump_header_info) {
|
|
dump_header_info(&log_);
|
|
|
|
std::string expected = "Build fingerprint: 'unknown'\nRevision: 'unknown'\n";
|
|
expected += android::base::StringPrintf("ABI: '%s'\n", ABI_STRING);
|
|
ASSERT_STREQ(expected.c_str(), amfd_data_.c_str());
|
|
}
|