diff options
Diffstat (limited to 'src/common/linux')
-rw-r--r-- | src/common/linux/elf_core_dump_unittest.cc | 21 | ||||
-rw-r--r-- | src/common/linux/file_id.cc | 2 | ||||
-rw-r--r-- | src/common/linux/memory_mapped_file.cc | 28 | ||||
-rw-r--r-- | src/common/linux/memory_mapped_file.h | 5 | ||||
-rw-r--r-- | src/common/linux/memory_mapped_file_unittest.cc | 54 |
5 files changed, 77 insertions, 33 deletions
diff --git a/src/common/linux/elf_core_dump_unittest.cc b/src/common/linux/elf_core_dump_unittest.cc index 63ecb2f3..9b41dcee 100644 --- a/src/common/linux/elf_core_dump_unittest.cc +++ b/src/common/linux/elf_core_dump_unittest.cc @@ -70,7 +70,7 @@ TEST(ElfCoreDumpTest, TestElfHeader) { ElfCoreDump core; ASSERT_TRUE(WriteFile(core_file, &header, sizeof(header) - 1)); - ASSERT_TRUE(mapped_core_file.Map(core_file)); + ASSERT_TRUE(mapped_core_file.Map(core_file, 0)); core.SetContent(mapped_core_file.content()); EXPECT_FALSE(core.IsValid()); EXPECT_EQ(NULL, core.GetHeader()); @@ -80,49 +80,49 @@ TEST(ElfCoreDumpTest, TestElfHeader) { EXPECT_FALSE(core.GetFirstNote().IsValid()); ASSERT_TRUE(WriteFile(core_file, &header, sizeof(header))); - ASSERT_TRUE(mapped_core_file.Map(core_file)); + ASSERT_TRUE(mapped_core_file.Map(core_file, 0)); core.SetContent(mapped_core_file.content()); EXPECT_FALSE(core.IsValid()); header.e_ident[0] = ELFMAG0; ASSERT_TRUE(WriteFile(core_file, &header, sizeof(header))); - ASSERT_TRUE(mapped_core_file.Map(core_file)); + ASSERT_TRUE(mapped_core_file.Map(core_file, 0)); core.SetContent(mapped_core_file.content()); EXPECT_FALSE(core.IsValid()); header.e_ident[1] = ELFMAG1; ASSERT_TRUE(WriteFile(core_file, &header, sizeof(header))); - ASSERT_TRUE(mapped_core_file.Map(core_file)); + ASSERT_TRUE(mapped_core_file.Map(core_file, 0)); core.SetContent(mapped_core_file.content()); EXPECT_FALSE(core.IsValid()); header.e_ident[2] = ELFMAG2; ASSERT_TRUE(WriteFile(core_file, &header, sizeof(header))); - ASSERT_TRUE(mapped_core_file.Map(core_file)); + ASSERT_TRUE(mapped_core_file.Map(core_file, 0)); core.SetContent(mapped_core_file.content()); EXPECT_FALSE(core.IsValid()); header.e_ident[3] = ELFMAG3; ASSERT_TRUE(WriteFile(core_file, &header, sizeof(header))); - ASSERT_TRUE(mapped_core_file.Map(core_file)); + ASSERT_TRUE(mapped_core_file.Map(core_file, 0)); core.SetContent(mapped_core_file.content()); EXPECT_FALSE(core.IsValid()); header.e_ident[4] = ElfCoreDump::kClass; ASSERT_TRUE(WriteFile(core_file, &header, sizeof(header))); - ASSERT_TRUE(mapped_core_file.Map(core_file)); + ASSERT_TRUE(mapped_core_file.Map(core_file, 0)); core.SetContent(mapped_core_file.content()); EXPECT_FALSE(core.IsValid()); header.e_version = EV_CURRENT; ASSERT_TRUE(WriteFile(core_file, &header, sizeof(header))); - ASSERT_TRUE(mapped_core_file.Map(core_file)); + ASSERT_TRUE(mapped_core_file.Map(core_file, 0)); core.SetContent(mapped_core_file.content()); EXPECT_FALSE(core.IsValid()); header.e_type = ET_CORE; ASSERT_TRUE(WriteFile(core_file, &header, sizeof(header))); - ASSERT_TRUE(mapped_core_file.Map(core_file)); + ASSERT_TRUE(mapped_core_file.Map(core_file, 0)); core.SetContent(mapped_core_file.content()); EXPECT_TRUE(core.IsValid()); } @@ -156,7 +156,8 @@ TEST(ElfCoreDumpTest, ValidCoreFile) { #endif MemoryMappedFile mapped_core_file; - ASSERT_TRUE(mapped_core_file.Map(crash_generator.GetCoreFilePath().c_str())); + ASSERT_TRUE( + mapped_core_file.Map(crash_generator.GetCoreFilePath().c_str(), 0)); ElfCoreDump core; core.SetContent(mapped_core_file.content()); diff --git a/src/common/linux/file_id.cc b/src/common/linux/file_id.cc index dc74e9e0..00b37313 100644 --- a/src/common/linux/file_id.cc +++ b/src/common/linux/file_id.cc @@ -149,7 +149,7 @@ bool FileID::ElfFileIdentifierFromMappedFile(const void* base, } bool FileID::ElfFileIdentifier(uint8_t identifier[kMDGUIDSize]) { - MemoryMappedFile mapped_file(path_.c_str()); + MemoryMappedFile mapped_file(path_.c_str(), 0); if (!mapped_file.data()) // Should probably check if size >= ElfW(Ehdr)? return false; diff --git a/src/common/linux/memory_mapped_file.cc b/src/common/linux/memory_mapped_file.cc index 0f0fcb2b..064326bb 100644 --- a/src/common/linux/memory_mapped_file.cc +++ b/src/common/linux/memory_mapped_file.cc @@ -46,15 +46,15 @@ namespace google_breakpad { MemoryMappedFile::MemoryMappedFile() {} -MemoryMappedFile::MemoryMappedFile(const char* path) { - Map(path); +MemoryMappedFile::MemoryMappedFile(const char* path, size_t offset) { + Map(path, offset); } MemoryMappedFile::~MemoryMappedFile() { Unmap(); } -bool MemoryMappedFile::Map(const char* path) { +bool MemoryMappedFile::Map(const char* path, size_t offset) { Unmap(); int fd = sys_open(path, O_RDONLY, 0); @@ -73,25 +73,33 @@ bool MemoryMappedFile::Map(const char* path) { return false; } - // If the file size is zero, simply use an empty MemoryRange and return - // true. Don't bother to call mmap() even though mmap() can handle an - // empty file on some platforms. - if (st.st_size == 0) { + // Strangely file size can be negative, but we check above that it is not. + size_t file_len = static_cast<size_t>(st.st_size); + // If the file does not extend beyond the offset, simply use an empty + // MemoryRange and return true. Don't bother to call mmap() + // even though mmap() can handle an empty file on some platforms. + if (offset >= file_len) { sys_close(fd); return true; } #if defined(__x86_64__) || defined(__aarch64__) - void* data = sys_mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + void* data = sys_mmap(NULL, file_len, PROT_READ, MAP_PRIVATE, fd, offset); #else - void* data = sys_mmap2(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if ((offset & 4095) != 0) { + // Not page aligned. + sys_close(fd); + return false; + } + void* data = sys_mmap2( + NULL, file_len, PROT_READ, MAP_PRIVATE, fd, offset >> 12); #endif sys_close(fd); if (data == MAP_FAILED) { return false; } - content_.Set(data, st.st_size); + content_.Set(data, file_len - offset); return true; } diff --git a/src/common/linux/memory_mapped_file.h b/src/common/linux/memory_mapped_file.h index 6abd5b0c..fa660cc9 100644 --- a/src/common/linux/memory_mapped_file.h +++ b/src/common/linux/memory_mapped_file.h @@ -33,6 +33,7 @@ #ifndef COMMON_LINUX_MEMORY_MAPPED_FILE_H_ #define COMMON_LINUX_MEMORY_MAPPED_FILE_H_ +#include <stddef.h> #include "common/basictypes.h" #include "common/memory_range.h" @@ -47,7 +48,7 @@ class MemoryMappedFile { // Constructor that calls Map() to map a file at |path| into memory. // If Map() fails, the object behaves as if it is default constructed. - explicit MemoryMappedFile(const char* path); + MemoryMappedFile(const char* path, size_t offset); ~MemoryMappedFile(); @@ -56,7 +57,7 @@ class MemoryMappedFile { // success. Mapping an empty file will succeed but with data() and size() // returning NULL and 0, respectively. An existing mapping is unmapped // before a new mapping is created. - bool Map(const char* path); + bool Map(const char* path, size_t offset); // Unmaps the memory for the mapped file. It's a no-op if no file is // mapped. diff --git a/src/common/linux/memory_mapped_file_unittest.cc b/src/common/linux/memory_mapped_file_unittest.cc index 4fa50cf9..fad59f40 100644 --- a/src/common/linux/memory_mapped_file_unittest.cc +++ b/src/common/linux/memory_mapped_file_unittest.cc @@ -71,12 +71,12 @@ TEST_F(MemoryMappedFileTest, UnmapWithoutMap) { TEST_F(MemoryMappedFileTest, MapNonexistentFile) { { - MemoryMappedFile mapped_file("nonexistent-file"); + MemoryMappedFile mapped_file("nonexistent-file", 0); ExpectNoMappedData(mapped_file); } { MemoryMappedFile mapped_file; - EXPECT_FALSE(mapped_file.Map("nonexistent-file")); + EXPECT_FALSE(mapped_file.Map("nonexistent-file", 0)); ExpectNoMappedData(mapped_file); } } @@ -87,12 +87,12 @@ TEST_F(MemoryMappedFileTest, MapEmptyFile) { ASSERT_TRUE(WriteFile(test_file.c_str(), NULL, 0)); { - MemoryMappedFile mapped_file(test_file.c_str()); + MemoryMappedFile mapped_file(test_file.c_str(), 0); ExpectNoMappedData(mapped_file); } { MemoryMappedFile mapped_file; - EXPECT_TRUE(mapped_file.Map(test_file.c_str())); + EXPECT_TRUE(mapped_file.Map(test_file.c_str(), 0)); ExpectNoMappedData(mapped_file); } } @@ -109,7 +109,7 @@ TEST_F(MemoryMappedFileTest, MapNonEmptyFile) { ASSERT_TRUE(WriteFile(test_file.c_str(), data, data_size)); { - MemoryMappedFile mapped_file(test_file.c_str()); + MemoryMappedFile mapped_file(test_file.c_str(), 0); EXPECT_FALSE(mapped_file.content().IsEmpty()); EXPECT_TRUE(mapped_file.data() != NULL); EXPECT_EQ(data_size, mapped_file.size()); @@ -117,7 +117,7 @@ TEST_F(MemoryMappedFileTest, MapNonEmptyFile) { } { MemoryMappedFile mapped_file; - EXPECT_TRUE(mapped_file.Map(test_file.c_str())); + EXPECT_TRUE(mapped_file.Map(test_file.c_str(), 0)); EXPECT_FALSE(mapped_file.content().IsEmpty()); EXPECT_TRUE(mapped_file.data() != NULL); EXPECT_EQ(data_size, mapped_file.size()); @@ -145,13 +145,13 @@ TEST_F(MemoryMappedFileTest, RemapAfterMap) { ASSERT_TRUE(WriteFile(test_file2.c_str(), data2, data2_size)); { - MemoryMappedFile mapped_file(test_file1.c_str()); + MemoryMappedFile mapped_file(test_file1.c_str(), 0); EXPECT_FALSE(mapped_file.content().IsEmpty()); EXPECT_TRUE(mapped_file.data() != NULL); EXPECT_EQ(data1_size, mapped_file.size()); EXPECT_EQ(0, memcmp(data1, mapped_file.data(), data1_size)); - mapped_file.Map(test_file2.c_str()); + mapped_file.Map(test_file2.c_str(), 0); EXPECT_FALSE(mapped_file.content().IsEmpty()); EXPECT_TRUE(mapped_file.data() != NULL); EXPECT_EQ(data2_size, mapped_file.size()); @@ -159,16 +159,50 @@ TEST_F(MemoryMappedFileTest, RemapAfterMap) { } { MemoryMappedFile mapped_file; - EXPECT_TRUE(mapped_file.Map(test_file1.c_str())); + EXPECT_TRUE(mapped_file.Map(test_file1.c_str(), 0)); EXPECT_FALSE(mapped_file.content().IsEmpty()); EXPECT_TRUE(mapped_file.data() != NULL); EXPECT_EQ(data1_size, mapped_file.size()); EXPECT_EQ(0, memcmp(data1, mapped_file.data(), data1_size)); - mapped_file.Map(test_file2.c_str()); + mapped_file.Map(test_file2.c_str(), 0); EXPECT_FALSE(mapped_file.content().IsEmpty()); EXPECT_TRUE(mapped_file.data() != NULL); EXPECT_EQ(data2_size, mapped_file.size()); EXPECT_EQ(0, memcmp(data2, mapped_file.data(), data2_size)); } } + +TEST_F(MemoryMappedFileTest, MapWithOffset) { + // Put more data in the test file this time. Offsets can only be + // done on page boundaries, so we need a two page file to test this. + const int page_size = 4096; + char data1[2 * page_size]; + size_t data1_size = sizeof(data1); + for (size_t i = 0; i < data1_size; ++i) { + data1[i] = i & 0x7f; + } + + AutoTempDir temp_dir; + string test_file1 = temp_dir.path() + "/test_file1"; + ASSERT_TRUE(WriteFile(test_file1.c_str(), data1, data1_size)); + { + MemoryMappedFile mapped_file(test_file1.c_str(), page_size); + EXPECT_FALSE(mapped_file.content().IsEmpty()); + EXPECT_TRUE(mapped_file.data() != NULL); + EXPECT_EQ(data1_size - page_size, mapped_file.size()); + EXPECT_EQ( + 0, + memcmp(data1 + page_size, mapped_file.data(), data1_size - page_size)); + } + { + MemoryMappedFile mapped_file; + mapped_file.Map(test_file1.c_str(), page_size); + EXPECT_FALSE(mapped_file.content().IsEmpty()); + EXPECT_TRUE(mapped_file.data() != NULL); + EXPECT_EQ(data1_size - page_size, mapped_file.size()); + EXPECT_EQ( + 0, + memcmp(data1 + page_size, mapped_file.data(), data1_size - page_size)); + } +} |