summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArtem Pyanykh <artempyanykh@gmail.com>2019-09-11 20:30:24 +0100
committerMarge Bot <ben+marge-bot@smart-cactus.org>2019-10-04 21:46:28 -0400
commit0d31ccdd5754b10fb27fcdc95ddd6c937ecec1bd (patch)
tree17d0b5fec3ab496739bff8bea3f0be153c842b87
parent0dded5ecd2f02e13292818ae3729d32832c014f3 (diff)
downloadhaskell-0d31ccdd5754b10fb27fcdc95ddd6c937ecec1bd.tar.gz
[linker, macho] Don't map/allocate zero size sections and segments
Zero size sections are common even during regular build on MacOS. For instance: ``` $ ar -xv libHSghc-prim-0.6.1.a longlong.o $ otool -l longlong.o longlong.o: Mach header magic cputype cpusubtype caps filetype ncmds sizeofcmds flags 0xfeedfacf 16777223 3 0x00 1 2 176 0x00002000 Load command 0 cmd LC_SEGMENT_64 cmdsize 152 segname vmaddr 0x0000000000000000 vmsize 0x0000000000000000 <-- segment size = 0 fileoff 208 filesize 0 maxprot 0x00000007 initprot 0x00000007 nsects 1 flags 0x0 Section sectname __text segname __TEXT addr 0x0000000000000000 size 0x0000000000000000 <-- section size = 0 offset 208 align 2^0 (1) reloff 0 nreloc 0 flags 0x80000000 reserved1 0 reserved2 0 cmd LC_BUILD_VERSION cmdsize 24 platform macos sdk 10.14 minos 10.14 ntools 0 ``` The issue of `mmap`ing 0 bytes was resolved in !1050, but the problem remained. These 0 size segments and sections were still allocated in object code, which lead to failed `ASSERT(size > 0)` in `addProddableBlock` further down the road. With this change zero size segments **and** sections are not mapped/allocated at all. Test plan: 1. Build statically linked GHC. 2. Run `ghc --interactive`. Observe that REPL loads successfully (which was not the case before). 3. Load several more compiled hs files into repl. No failures.
-rw-r--r--rts/linker/MachO.c25
1 files changed, 20 insertions, 5 deletions
diff --git a/rts/linker/MachO.c b/rts/linker/MachO.c
index 61c6d9d503..3da4f690f2 100644
--- a/rts/linker/MachO.c
+++ b/rts/linker/MachO.c
@@ -1091,6 +1091,11 @@ ocBuildSegments_MachO(ObjectCode *oc)
for (int i = 0; i < oc->n_sections; i++) {
MachOSection *macho = &oc->info->macho_sections[i];
+ if (0 == macho->size) {
+ IF_DEBUG(linker, debugBelch("ocBuildSegments_MachO: found a zero length section, skipping\n"));
+ continue;
+ }
+
size_t alignment = 1 << macho->align;
if (S_GB_ZEROFILL == (macho->flags & SECTION_TYPE)) {
@@ -1118,17 +1123,22 @@ ocBuildSegments_MachO(ObjectCode *oc)
if (n_rwSections > 0) {
n_activeSegments++;
}
- if (n_gbZerofills >0) {
+ if (n_gbZerofills > 0) {
n_activeSegments++;
}
// N.B. it's possible that there is nothing mappable in an object. In this
- // case we avoid the mmap call since it would fail. See #16701.
- if (size_compound > 0) {
- mem = mmapForLinker(size_compound, MAP_ANON, -1, 0);
- if (NULL == mem) return 0;
+ // case we avoid the mmap call and segment allocation/building since it will
+ // fail either here or further down the road, e.g. on size > 0 assert in
+ // addProddableBlock. See #16701.
+ if (0 == size_compound) {
+ IF_DEBUG(linker, debugBelch("ocBuildSegments_MachO: all segments are empty, skipping\n"));
+ return 1;
}
+ mem = mmapForLinker(size_compound, MAP_ANON, -1, 0);
+ if (NULL == mem) return 0;
+
IF_DEBUG(linker, debugBelch("ocBuildSegments: allocating %d segments\n", n_activeSegments));
segments = (Segment*)stgCallocBytes(n_activeSegments, sizeof(Segment),
"ocBuildSegments_MachO(segments)");
@@ -1182,6 +1192,11 @@ ocBuildSegments_MachO(ObjectCode *oc)
i++)
{
MachOSection *macho = &oc->info->macho_sections[i];
+ // Skip zero size sections here as well since there was no place
+ // allocated for them in Segment's sections_idx array
+ if (0 == macho->size) {
+ continue;
+ }
if (S_GB_ZEROFILL == (macho->flags & SECTION_TYPE)) {
gbZerofillSegment->sections_idx[gb++] = i;