From 82d0ff76a632f1678522c988318b8d23fd49891a Mon Sep 17 00:00:00 2001 From: "rmcilroy@chromium.org" Date: Fri, 19 Sep 2014 15:00:04 +0000 Subject: Extend mapping merge to include reserved but unused mappings. When parsing /proc/pid/maps, current code merges adjacent entries that refer to the same library and where the start of the second is equal to the end of the first, for example: 40022000-40025000 r-xp 00000000 b3:11 827 /system/lib/liblog.so 40025000-40026000 r--p 00002000 b3:11 827 /system/lib/liblog.so 40026000-40027000 rw-p 00003000 b3:11 827 /system/lib/liblog.so When the system linker loads a library it first reserves all the address space required, from the smallest start to the largest end address, using an anonymous mapping, and then maps loaded segments inside that reservation. If the loaded segments do not fully occupy the reservation this leaves gaps, and these gaps prevent merges that should occur from occurring: 40417000-4044a000 r-xp 00000000 b3:11 820 /system/lib/libjpeg.so > 4044a000-4044b000 ---p 00000000 00:00 0 4044b000-4044c000 r--p 00033000 b3:11 820 /system/lib/libjpeg.so 4044c000-4044d000 rw-p 00034000 b3:11 820 /system/lib/libjpeg.so Where the segments that follow this gap do not contain executable code the failure to merge does not affect breakpad operation. However, where they do then the merge needs to occur. Packing relocations in a large library splits the executable segment into two, resulting in: 73b0c000-73b21000 r-xp 00000000 b3:19 786460 /data/.../libchrome.2160.0.so > 73b21000-73d12000 ---p 00000000 00:00 0 73d12000-75a90000 r-xp 00014000 b3:19 786460 /data/.../libchrome.2160.0.so 75a90000-75c0d000 rw-p 01d91000 b3:19 786460 /data/.../libchrome.2160.0.so Here the mapping at 73d12000-75a90000 must be merged into 73b0c000-73b21000 so that breakpad correctly calculates the base address for text. This change enables the full merge by also merging anonymous maps which result from unused reservation, identified as '---p' with offset 0, and which follow on from an executable mapping, into that executable mapping. BUG=chromium:394703 R=rmcilroy@chromium.org, thestig@chromium.org Review URL: https://breakpad.appspot.com/7714003 Patch from Simon Baldwin . git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1380 4c0a9323-5329-0410-9bdc-e9ce6186880e --- src/client/linux/minidump_writer/linux_dumper.cc | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/client/linux/minidump_writer/linux_dumper.cc b/src/client/linux/minidump_writer/linux_dumper.cc index c1e77c96..2f17c649 100644 --- a/src/client/linux/minidump_writer/linux_dumper.cc +++ b/src/client/linux/minidump_writer/linux_dumper.cc @@ -54,6 +54,7 @@ static const char kMappedFileUnsafePrefix[] = "/dev/"; static const char kDeletedSuffix[] = " (deleted)"; +static const char kReservedFlags[] = " ---p"; inline static bool IsMappedFileOpenUnsafe( const google_breakpad::MappingInfo& mapping) { @@ -296,6 +297,23 @@ bool LinuxDumper::EnumerateMappings() { continue; } } + // Also merge mappings that result from address ranges that the + // linker reserved but which a loaded library did not use. These + // appear as an anonymous private mapping with no access flags set + // and which directly follow an executable mapping. + if (!name && !mappings_.empty()) { + MappingInfo* module = mappings_.back(); + if ((start_addr == module->start_addr + module->size) && + module->exec && + module->name && module->name[0] == '/' && + offset == 0 && my_strncmp(i2, + kReservedFlags, + sizeof(kReservedFlags) - 1) == 0) { + module->size = end_addr - module->start_addr; + line_reader->PopLine(line_len); + continue; + } + } MappingInfo* const module = new(allocator_) MappingInfo; my_memset(module, 0, sizeof(MappingInfo)); module->start_addr = start_addr; -- cgit v1.2.1