Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c4b1f0a9 authored by Christopher Ferris's avatar Christopher Ferris
Browse files

Change the 64 bit map address format.

Previously, the map printing in tombstones for 64 bit devices uses
a variable length value. This means that the maps are not lined up.
The new format is to print the map as 00000000'00000000 in all ways.

Also fix a bug where the backtrace_map_t did not initialize all
parameters.

Add unit tests for all of the dump_all_maps function.

Bug: 20950813
(cherry picked from commit 862fe029)

Change-Id: I4269d2b96ebadcc405f478265a07a830aaf9713c
parent 49ed105f
Loading
Loading
Loading
Loading
+31 −22
Original line number Diff line number Diff line
@@ -75,46 +75,55 @@ LOCAL_MULTILIB := both

include $(BUILD_EXECUTABLE)

include $(CLEAR_VARS)

LOCAL_SRC_FILES := \
debuggerd_test_src_files := \
    utility.cpp \
    test/dump_maps_test.cpp \
    test/dump_memory_test.cpp \
    test/elf_fake.cpp \
    test/log_fake.cpp \
    test/property_fake.cpp \
    test/ptrace_fake.cpp \
    test/selinux_fake.cpp \

LOCAL_MODULE := debuggerd_test

LOCAL_SHARED_LIBRARIES := \
debuggerd_shared_libraries := \
    libbacktrace \
    libbase \
    libcutils \

LOCAL_C_INCLUDES += $(LOCAL_PATH)/test
LOCAL_CPPFLAGS := $(common_cppflags)
debuggerd_c_includes := \
    $(LOCAL_PATH)/test \

debuggerd_cpp_flags := \
    $(common_cppflags) \
    -Wno-missing-field-initializers \

# Only build the host tests on linux.
ifeq ($(HOST_OS),linux)

include $(CLEAR_VARS)

LOCAL_MODULE := debuggerd_test
LOCAL_SRC_FILES := $(debuggerd_test_src_files)
LOCAL_SHARED_LIBRARIES := $(debuggerd_shared_libraries)
LOCAL_C_INCLUDES := $(debuggerd_c_includes)
LOCAL_CPPFLAGS := $(debuggerd_cpp_flags)

LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
LOCAL_MULTILIB := both

include $(BUILD_HOST_NATIVE_TEST)

include $(CLEAR_VARS)
endif

LOCAL_SRC_FILES := \
    utility.cpp \
    test/dump_memory_test.cpp \
    test/log_fake.cpp \
include $(CLEAR_VARS)

LOCAL_MODULE := debuggerd_test

LOCAL_SHARED_LIBRARIES := \
    libbacktrace \
    libbase \

LOCAL_C_INCLUDES += $(LOCAL_PATH)/test
LOCAL_CPPFLAGS := $(common_cppflags)
LOCAL_SRC_FILES := $(debuggerd_test_src_files)
LOCAL_SHARED_LIBRARIES := $(debuggerd_shared_libraries)
LOCAL_C_INCLUDES := $(debuggerd_c_includes)
LOCAL_CPPFLAGS := $(debuggerd_cpp_flags)

LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
LOCAL_MULTILIB := both

include $(BUILD_NATIVE_TEST)
+4 −0
Original line number Diff line number Diff line
@@ -32,6 +32,10 @@ class BacktraceMapMock : public BacktraceMap {
 public:
  BacktraceMapMock() : BacktraceMap(0) {}
  virtual ~BacktraceMapMock() {}

  void AddMap(backtrace_map_t& map) {
    maps_.push_back(map);
  }
};


+571 −0
Original line number Diff line number Diff line
/*
 * 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 <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 DumpMapsTest : 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;
    log_.amfd = -1;
    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 = SIGPIPE;
    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_;
};

TEST_F(DumpMapsTest, 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());

  // Verify that the log buf is empty, and no error messages.
  ASSERT_STREQ("", getFakeLogBuf().c_str());
  ASSERT_STREQ("", getFakeLogPrint().c_str());
}

TEST_F(DumpMapsTest, 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());

  // 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(DumpMapsTest, 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());

  // Verify that the log buf is empty, and no error messages.
  ASSERT_STREQ("", getFakeLogBuf().c_str());
  ASSERT_STREQ("", getFakeLogPrint().c_str());
}

TEST_F(DumpMapsTest, 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());

  // Verify that the log buf is empty, and no error messages.
  ASSERT_STREQ("", getFakeLogBuf().c_str());
  ASSERT_STREQ("", getFakeLogPrint().c_str());
}

TEST_F(DumpMapsTest, 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());

  // Verify that the log buf is empty, and no error messages.
  ASSERT_STREQ("", getFakeLogBuf().c_str());
  ASSERT_STREQ("", getFakeLogPrint().c_str());
}

TEST_F(DumpMapsTest, 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());

  // Verify that the log buf is empty, and no error messages.
  ASSERT_STREQ("", getFakeLogBuf().c_str());
  ASSERT_STREQ("", getFakeLogPrint().c_str());
}

TEST_F(DumpMapsTest, 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());

  // Verify that the log buf is empty, and no error messages.
  ASSERT_STREQ("", getFakeLogBuf().c_str());
  ASSERT_STREQ("", getFakeLogPrint().c_str());
}

TEST_F(DumpMapsTest, 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());

  // Verify that the log buf is empty, and no error messages.
  ASSERT_STREQ("", getFakeLogBuf().c_str());
  ASSERT_STREQ("", getFakeLogPrint().c_str());
}

TEST_F(DumpMapsTest, 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 = \
"Cannot get siginfo for 100: Bad address\n"
"\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());

  // Verify that the log buf is empty, and no error messages.
  ASSERT_STREQ("DEBUG Cannot get siginfo for 100: Bad address\n",
               getFakeLogBuf().c_str());
  ASSERT_STREQ("", getFakeLogPrint().c_str());
}

TEST_F(DumpMapsTest, 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.";
    }

    // Verify that the log buf is empty, and no error messages.
    ASSERT_STREQ("", getFakeLogBuf().c_str());
    ASSERT_STREQ("", getFakeLogPrint().c_str());
  }
}
+35 −0
Original line number Diff line number Diff line
/*
 * 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 <stdint.h>

#include <string>

class Backtrace;

std::string g_build_id;

void elf_set_fake_build_id(const std::string& build_id) {
  g_build_id = build_id;
}

bool elf_get_build_id(Backtrace*, uintptr_t, std::string* build_id) {
  if (g_build_id != "") {
    *build_id = g_build_id;
    return true;
  }
  return false;
}
+24 −0
Original line number Diff line number Diff line
/*
 * 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.
 */

#ifndef _DEBUGGERD_TEST_ELF_FAKE_H
#define _DEBUGGERD_TEST_ELF_FAKE_H

#include <string>

void elf_set_fake_build_id(const std::string&);

#endif // _DEBUGGERD_TEST_ELF_FAKE_H
Loading