Skip to content
Snippets Groups Projects
Commit 0d31ccdd authored by Artem Pyanykh's avatar Artem Pyanykh Committed by Marge Bot
Browse files

[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
No related branches found
No related tags found
No related merge requests found
......@@ -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;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment