Commit 0d31ccdd authored by Artem Pyanykh's avatar Artem Pyanykh Committed by Marge Bot

[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.
parent 0dded5ec
Pipeline #10912 passed with stages
in 480 minutes and 48 seconds
......@@ -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;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment