| From 22a67f6b18d2854bcdf740833cf4e1a0555c7295 Mon Sep 17 00:00:00 2001 |
| From: Martin Richter <xricht17@stud.fit.vutbr.cz> |
| Date: Wed, 5 Aug 2015 23:36:25 +0100 |
| Subject: [PATCH 10/15] Fix using large PCH |
| |
| The following patch fixes segfault when gt_pch_use_address |
| fails (returns -1). fatal_error now correctly shows an error |
| message and terminates the program. |
| I have basicly only reordered reads, and placed them after |
| the file mapping itself. Global pointers are changed only |
| after gt_pch_use_address succeeds, so in case of failure |
| they still contain valid addresses. |
| |
| This patch is meant for the master branch. However, it |
| should not be hard to modify it for others. |
| |
| https://gcc.gnu.org/bugzilla/show_bug.cgi?id=14940 |
| https://sourceforge.net/p/mingw-w64/bugs/382/ |
| --- |
| gcc/config/i386/host-mingw32.c | 10 ++------- |
| gcc/ggc-common.c | 51 +++++++++++++++++++++++++++++++++--------- |
| 2 files changed, 42 insertions(+), 19 deletions(-) |
| |
| diff --git a/gcc/config/i386/host-mingw32.c b/gcc/config/i386/host-mingw32.c |
| index aa17378..631d9c4 100644 |
| --- a/gcc/config/i386/host-mingw32.c |
| +++ b/gcc/config/i386/host-mingw32.c |
| @@ -44,9 +44,6 @@ static size_t mingw32_gt_pch_alloc_granularity (void); |
| |
| static inline void w32_error(const char*, const char*, int, const char*); |
| |
| -/* FIXME: Is this big enough? */ |
| -static const size_t pch_VA_max_size = 128 * 1024 * 1024; |
| - |
| /* Granularity for reserving address space. */ |
| static size_t va_granularity = 0x10000; |
| |
| @@ -85,9 +82,6 @@ static void * |
| mingw32_gt_pch_get_address (size_t size, int) |
| { |
| void* res; |
| - size = (size + va_granularity - 1) & ~(va_granularity - 1); |
| - if (size > pch_VA_max_size) |
| - return NULL; |
| |
| /* FIXME: We let system determine base by setting first arg to NULL. |
| Allocating at top of available address space avoids unnecessary |
| @@ -94,7 +88,7 @@ mingw32_gt_pch_get_address (size_t size, int) |
| If we allocate at bottom we need to reserve the address as early |
| as possible and at the same point in each invocation. */ |
| |
| - res = VirtualAlloc (NULL, pch_VA_max_size, |
| + res = VirtualAlloc (NULL, size, |
| MEM_RESERVE | MEM_TOP_DOWN, |
| PAGE_NOACCESS); |
| if (!res) |
| @@ -144,7 +138,7 @@ mingw32_gt_pch_use_address (void *addr, size_t size, int fd, |
| |
| /* Offset must be also be a multiple of allocation granularity for |
| this to work. We can't change the offset. */ |
| - if ((offset & (va_granularity - 1)) != 0 || size > pch_VA_max_size) |
| + if ((offset & (va_granularity - 1)) != 0) |
| return -1; |
| |
| |
| diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c |
| index 03fbe7d..3a5df8a 100644 |
| --- a/gcc/ggc-common.c |
| +++ b/gcc/ggc-common.c |
| @@ -591,7 +591,9 @@ gt_pch_restore (FILE *f) |
| size_t i; |
| struct mmap_info mmi; |
| int result; |
| - |
| + long pch_tabs_off; |
| + long pch_data_off; |
| + |
| /* Delete any deletable objects. This makes ggc_pch_read much |
| faster, as it can be sure that no GCable objects remain other |
| than the ones just read in. */ |
| @@ -601,20 +601,24 @@ gt_pch_restore (FILE *f) |
| for (rti = *rt; rti->base != NULL; rti++) |
| memset (rti->base, 0, rti->stride); |
| |
| - /* Read in all the scalar variables. */ |
| + /* We need to read tables after mapping, or fatal_error will |
| + segfault when gt_pch_use_address returns -1. Skip them for now. */ |
| + pch_tabs_off = ftell(f); |
| + |
| + /* Skip all the scalar variables. */ |
| for (rt = gt_pch_scalar_rtab; *rt; rt++) |
| for (rti = *rt; rti->base != NULL; rti++) |
| - if (fread (rti->base, rti->stride, 1, f) != 1) |
| - fatal_error (input_location, "cannot read PCH file: %m"); |
| + if (fseek (f, rti->stride, SEEK_CUR) != 0) |
| + fatal_error (input_location, "cannot read PCH file: %m"); |
| |
| - /* Read in all the global pointers, in 6 easy loops. */ |
| + /* Skip all the global pointers. */ |
| for (rt = gt_ggc_rtab; *rt; rt++) |
| for (rti = *rt; rti->base != NULL; rti++) |
| for (i = 0; i < rti->nelt; i++) |
| - if (fread ((char *)rti->base + rti->stride * i, |
| - sizeof (void *), 1, f) != 1) |
| - fatal_error (input_location, "cannot read PCH file: %m"); |
| - |
| + if (fseek (f, sizeof (void *), SEEK_CUR) != 0) |
| + fatal_error (input_location, "cannot read PCH file: %m"); |
| + |
| + /* mmi still has to be read now. */ |
| if (fread (&mmi, sizeof (mmi), 1, f) != 1) |
| fatal_error (input_location, "cannot read PCH file: %m"); |
| |
| @@ -617,12 +629,35 @@ gt_pch_restore (FILE *f) |
| if (result == 0) |
| { |
| if (fseek (f, mmi.offset, SEEK_SET) != 0 |
| - || fread (mmi.preferred_base, mmi.size, 1, f) != 1) |
| - fatal_error (input_location, "cannot read PCH file: %m"); |
| + || fread (mmi.preferred_base, mmi.size, 1, f) != 1) |
| + fatal_error (input_location, "cannot read PCH file: %m"); |
| } |
| else if (fseek (f, mmi.offset + mmi.size, SEEK_SET) != 0) |
| fatal_error (input_location, "cannot read PCH file: %m"); |
| + |
| + /* File mapping done, read tables now. */ |
| + pch_data_off = ftell(f); |
| + |
| + if (fseek (f, pch_tabs_off, SEEK_SET) != 0) |
| + fatal_error (input_location, "cannot read PCH file: %m"); |
| |
| + /* Read in all the scalar variables. */ |
| + for (rt = gt_pch_scalar_rtab; *rt; rt++) |
| + for (rti = *rt; rti->base != NULL; rti++) |
| + if (fread (rti->base, rti->stride, 1, f) != 1) |
| + fatal_error (input_location, "cannot read PCH file: %m"); |
| + |
| + /* Read in all the global pointers, in 6 easy loops. */ |
| + for (rt = gt_ggc_rtab; *rt; rt++) |
| + for (rti = *rt; rti->base != NULL; rti++) |
| + for (i = 0; i < rti->nelt; i++) |
| + if (fread ((char *)rti->base + rti->stride * i, |
| + sizeof (void *), 1, f) != 1) |
| + fatal_error (input_location, "cannot read PCH file: %m"); |
| + |
| + if (fseek (f, pch_data_off, SEEK_SET) != 0) |
| + fatal_error (input_location, "cannot read PCH file: %m"); |
| + |
| ggc_pch_read (f, mmi.preferred_base); |
| |
| gt_pch_restore_stringpool (); |
| -- |
| 2.8.1 |
| |