Bug 916923 - work around crash reporter issues with adjacent memory mappings on x86 android; r=glandium,f=gbrown

This commit is contained in:
Nathan Froyd 2013-09-23 15:02:28 -04:00
parent ae0f2861dd
commit f528845993

View File

@ -183,20 +183,34 @@ public:
return NULL;
/* The Gecko crash reporter is confused by adjacent memory mappings of
* the same file. On Android, subsequent mappings are growing in memory
* address, and chances are we're going to map from the same file
* the same file and chances are we're going to map from the same file
* descriptor right away. To avoid problems with the crash reporter,
* create an empty anonymous page after the ashmem mapping. To do so,
* allocate one page more than requested, then replace the last page with
* an anonymous mapping. */
void *buf = ::mmap(NULL, length + PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
* create an empty anonymous page before and after the ashmem mapping.
* We create two anonymous pages because on some platforms, subsequent
* mappings are placed at adjacent, increasing memory addresses (ARM)
* and on others, such mappings are placed at adjacent, decreasing
* memory addresses (x86). It is more convenient to just do two pages
* everywhere than to twiddle with platform-specific #defines.
*/
size_t anon_mapping_length = length + 2 * PAGE_SIZE;
void *buf = ::mmap(NULL, anon_mapping_length, PROT_NONE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (buf != MAP_FAILED) {
::mmap(reinterpret_cast<char *>(buf) + ((length + PAGE_SIZE - 1) & PAGE_MASK),
PAGE_SIZE, PROT_NONE, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS,
-1, 0);
DEBUG_LOG("Decompression buffer of size %d in ashmem \"%s\", mapped @%p",
length, str, buf);
return new _MappableBuffer(fd.forget(), buf, length);
char *first_page = reinterpret_cast<char *>(buf);
char *map_page = first_page + PAGE_SIZE;
char *last_page = map_page + ((length + PAGE_SIZE - 1) & PAGE_MASK);
void *actual_buf = ::mmap(map_page, last_page - map_page, PROT_READ | PROT_WRITE,
MAP_FIXED | MAP_SHARED, fd, 0);
if (actual_buf == MAP_FAILED) {
::munmap(buf, anon_mapping_length);
DEBUG_LOG("Fixed allocation of decompression buffer at %p failed", map_page);
return NULL;
}
DEBUG_LOG("Decompression buffer of size 0x%x in ashmem \"%s\", mapped @%p",
length, str, actual_buf);
return new _MappableBuffer(fd.forget(), actual_buf, length);
}
#else
/* On Linux, use /dev/shm as base directory for temporary files, assuming
@ -236,8 +250,8 @@ public:
#ifdef ANDROID
~_MappableBuffer() {
/* Free the additional page we allocated. See _MappableBuffer::Create */
::munmap(*this + ((GetLength() + PAGE_SIZE - 1) & PAGE_MASK), PAGE_SIZE);
/* Free the additional pages we allocated. See _MappableBuffer::Create */
::munmap(*this - PAGE_SIZE, GetLength() + 2 * PAGE_SIZE);
}
#endif