From 1807e385d74aba56b2fb61ea570a5f848da224d5 Mon Sep 17 00:00:00 2001 From: "ted.mielczarek" Date: Fri, 6 May 2011 23:23:31 +0000 Subject: Fix linux-gate handling in LinuxDumper so it gets a valid debug ID A=ted R=nealsid at http://breakpad.appspot.com/284001 git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@788 4c0a9323-5329-0410-9bdc-e9ce6186880e --- src/client/linux/minidump_writer/linux_dumper.cc | 15 ++++ .../linux/minidump_writer/linux_dumper_unittest.cc | 79 +++++++++++++++++++++- 2 files changed, 92 insertions(+), 2 deletions(-) (limited to 'src/client/linux') diff --git a/src/client/linux/minidump_writer/linux_dumper.cc b/src/client/linux/minidump_writer/linux_dumper.cc index 76dc4db4..ab3a5ea5 100644 --- a/src/client/linux/minidump_writer/linux_dumper.cc +++ b/src/client/linux/minidump_writer/linux_dumper.cc @@ -213,6 +213,21 @@ LinuxDumper::ElfFileIdentifierForMapping(const MappingInfo& mapping, if (IsMappedFileOpenUnsafe(mapping)) return false; + // Special-case linux-gate because it's not a real file. + if (my_strcmp(mapping.name, kLinuxGateLibraryName) == 0) { + const uintptr_t kPageSize = getpagesize(); + void* linux_gate = NULL; + if (pid_ == sys_getpid()) { + linux_gate = reinterpret_cast(mapping.start_addr); + } else { + linux_gate = allocator_.Alloc(kPageSize); + CopyFromProcess(linux_gate, pid_, + reinterpret_cast(mapping.start_addr), + kPageSize); + } + return FileID::ElfFileIdentifierFromMappedFile(linux_gate, identifier); + } + char filename[NAME_MAX]; size_t filename_len = my_strlen(mapping.name); assert(filename_len < NAME_MAX); diff --git a/src/client/linux/minidump_writer/linux_dumper_unittest.cc b/src/client/linux/minidump_writer/linux_dumper_unittest.cc index c537ce93..1eee9a18 100644 --- a/src/client/linux/minidump_writer/linux_dumper_unittest.cc +++ b/src/client/linux/minidump_writer/linux_dumper_unittest.cc @@ -276,6 +276,7 @@ TEST(LinuxDumperTest, BuildProcPath) { } #if !defined(__ARM_EABI__) +// Ensure that the linux-gate VDSO is included in the mapping list. TEST(LinuxDumperTest, MappingsIncludeLinuxGate) { LinuxDumper dumper(getpid()); ASSERT_TRUE(dumper.Init()); @@ -297,6 +298,80 @@ TEST(LinuxDumperTest, MappingsIncludeLinuxGate) { EXPECT_EQ(linux_gate_loc, reinterpret_cast(mapping->start_addr)); EXPECT_EQ(0, memcmp(linux_gate_loc, ELFMAG, SELFMAG)); } + +// Ensure that the linux-gate VDSO can generate a non-zeroed File ID. +TEST(LinuxDumperTest, LinuxGateMappingID) { + LinuxDumper dumper(getpid()); + ASSERT_TRUE(dumper.Init()); + + bool found_linux_gate = false; + const wasteful_vector mappings = dumper.mappings(); + unsigned index = 0; + for (unsigned i = 0; i < mappings.size(); ++i) { + if (!strcmp(mappings[i]->name, kLinuxGateLibraryName)) { + found_linux_gate = true; + index = i; + break; + } + } + ASSERT_TRUE(found_linux_gate); + + uint8_t identifier[sizeof(MDGUID)]; + ASSERT_TRUE(dumper.ElfFileIdentifierForMapping(*mappings[index], + true, + index, + identifier)); + uint8_t empty_identifier[sizeof(MDGUID)]; + memset(empty_identifier, 0, sizeof(empty_identifier)); + EXPECT_NE(0, memcmp(empty_identifier, identifier, sizeof(identifier))); +} + +// Ensure that the linux-gate VDSO can generate a non-zeroed File ID +// from a child process. +TEST(LinuxDumperTest, LinuxGateMappingIDChild) { + int fds[2]; + ASSERT_NE(-1, pipe(fds)); + + // Fork a child so ptrace works. + const pid_t child = fork(); + if (child == 0) { + close(fds[1]); + // Now wait forever for the parent. + char b; + HANDLE_EINTR(read(fds[0], &b, sizeof(b))); + close(fds[0]); + syscall(__NR_exit); + } + close(fds[0]); + + LinuxDumper dumper(child); + ASSERT_TRUE(dumper.Init()); + + bool found_linux_gate = false; + const wasteful_vector mappings = dumper.mappings(); + unsigned index = 0; + for (unsigned i = 0; i < mappings.size(); ++i) { + if (!strcmp(mappings[i]->name, kLinuxGateLibraryName)) { + found_linux_gate = true; + index = i; + break; + } + } + ASSERT_TRUE(found_linux_gate); + + // Need to suspend the child so ptrace actually works. + ASSERT_TRUE(dumper.ThreadsSuspend()); + uint8_t identifier[sizeof(MDGUID)]; + ASSERT_TRUE(dumper.ElfFileIdentifierForMapping(*mappings[index], + true, + index, + identifier)); + uint8_t empty_identifier[sizeof(MDGUID)]; + memset(empty_identifier, 0, sizeof(empty_identifier)); + EXPECT_NE(0, memcmp(empty_identifier, identifier, sizeof(identifier))); + EXPECT_TRUE(dumper.ThreadsResume()); + close(fds[1]); +} #endif TEST(LinuxDumperTest, FileIDsMatch) { @@ -311,11 +386,11 @@ TEST(LinuxDumperTest, FileIDsMatch) { int fds[2]; ASSERT_NE(-1, pipe(fds)); - // fork a child so we can ptrace it + // Fork a child so ptrace works. const pid_t child = fork(); if (child == 0) { close(fds[1]); - // now wait forever for the parent + // Now wait forever for the parent. char b; HANDLE_EINTR(read(fds[0], &b, sizeof(b))); close(fds[0]); -- cgit v1.2.1