Merge adjacent mappings with the same name into one module in LinuxDumper.
A=Mike Hommey <mh+mozilla@glandium.org> R=ted at https://bugzilla.mozilla.org/show_bug.cgi?id=637316
git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@781 4c0a9323-5329-0410-9bdc-e9ce6186880e
diff --git a/src/client/linux/minidump_writer/linux_dumper_unittest.cc b/src/client/linux/minidump_writer/linux_dumper_unittest.cc
index a3e84db..33d9da7 100644
--- a/src/client/linux/minidump_writer/linux_dumper_unittest.cc
+++ b/src/client/linux/minidump_writer/linux_dumper_unittest.cc
@@ -33,6 +33,7 @@
#include <unistd.h>
#include <signal.h>
#include <stdint.h>
+#include <sys/mman.h>
#include <sys/poll.h>
#include <sys/types.h>
@@ -47,6 +48,24 @@
namespace {
typedef testing::Test LinuxDumperTest;
+
+string GetHelperBinary() {
+ // Locate helper binary next to the current binary.
+ char self_path[PATH_MAX];
+ if (readlink("/proc/self/exe", self_path, sizeof(self_path) - 1) == -1) {
+ return "";
+ }
+ string helper_path(self_path);
+ size_t pos = helper_path.rfind('/');
+ if (pos == string::npos) {
+ return "";
+ }
+ helper_path.erase(pos + 1);
+ helper_path += "linux_dumper_unittest_helper";
+
+ return helper_path;
+}
+
}
TEST(LinuxDumperTest, Setup) {
@@ -76,6 +95,79 @@
}
}
+// Helper stack class to close a file descriptor and unmap
+// a mmap'ed mapping.
+class StackHelper {
+public:
+ StackHelper(int fd, char* mapping, size_t size)
+ : fd_(fd), mapping_(mapping), size_(size) {}
+ ~StackHelper() {
+ munmap(mapping_, size_);
+ close(fd_);
+ }
+
+private:
+ int fd_;
+ char* mapping_;
+ size_t size_;
+};
+
+TEST(LinuxDumperTest, MergedMappings) {
+ string helper_path(GetHelperBinary());
+ if (helper_path.empty()) {
+ FAIL() << "Couldn't find helper binary";
+ exit(1);
+ }
+
+ // mmap two segments out of the helper binary, one
+ // enclosed in the other, but with different protections.
+ const size_t kPageSize = sysconf(_SC_PAGESIZE);
+ const size_t kMappingSize = 3 * kPageSize;
+ int fd = open(helper_path.c_str(), O_RDONLY);
+ ASSERT_NE(-1, fd);
+ char* mapping =
+ reinterpret_cast<char*>(mmap(NULL,
+ kMappingSize,
+ PROT_READ,
+ MAP_SHARED,
+ fd,
+ 0));
+ ASSERT_TRUE(mapping);
+
+ const u_int64_t kMappingAddress = reinterpret_cast<u_int64_t>(mapping);
+
+ // Ensure that things get cleaned up.
+ StackHelper helper(fd, mapping, kMappingSize);
+
+ // Carve a page out of the first mapping with different permissions.
+ char* inside_mapping = reinterpret_cast<char*>(mmap(mapping + 2 *kPageSize,
+ kPageSize,
+ PROT_NONE,
+ MAP_SHARED | MAP_FIXED,
+ fd,
+ // Map a different offset just to
+ // better test real-world conditions.
+ kPageSize));
+ ASSERT_TRUE(inside_mapping);
+
+ // Now check that LinuxDumper interpreted the mappings properly.
+ LinuxDumper dumper(getpid());
+ ASSERT_TRUE(dumper.Init());
+ int mapping_count = 0;
+ for (unsigned i = 0; i < dumper.mappings().size(); ++i) {
+ const MappingInfo& mapping = *dumper.mappings()[i];
+ if (strcmp(mapping.name, helper_path.c_str()) == 0) {
+ // This mapping should encompass the entire original mapped
+ // range.
+ EXPECT_EQ(kMappingAddress, mapping.start_addr);
+ EXPECT_EQ(kMappingSize, mapping.size);
+ EXPECT_EQ(0, mapping.offset);
+ mapping_count++;
+ }
+ }
+ EXPECT_EQ(1, mapping_count);
+}
+
TEST(LinuxDumperTest, VerifyStackReadWithMultipleThreads) {
static const int kNumberOfThreadsInHelperProgram = 5;
char kNumberOfThreadsArgument[2];
@@ -89,20 +181,11 @@
// In child process.
close(fds[0]);
- // Locate helper binary next to the current binary.
- char self_path[PATH_MAX];
- if (readlink("/proc/self/exe", self_path, sizeof(self_path) - 1) == -1) {
- FAIL() << "readlink failed: " << strerror(errno);
+ string helper_path(GetHelperBinary());
+ if (helper_path.empty()) {
+ FAIL() << "Couldn't find helper binary";
exit(1);
}
- string helper_path(self_path);
- size_t pos = helper_path.rfind('/');
- if (pos == string::npos) {
- FAIL() << "no trailing slash in path: " << helper_path;
- exit(1);
- }
- helper_path.erase(pos + 1);
- helper_path += "linux_dumper_unittest_helper";
// Pass the pipe fd and the number of threads as arguments.
char pipe_fd_string[8];