int ocAllocateExtras()

in rts/linker/SymbolExtras.c [53:120]


int ocAllocateExtras(ObjectCode* oc, int count, int first, int bssSize)
{
  void* oldImage = oc->image;

  if (count > 0 || bssSize > 0) {
    if (!RTS_LINKER_USE_MMAP) {

      // round up to the nearest 4
      int aligned = (oc->fileSize + 3) & ~3;
      int misalignment = oc->misalignment;

      oc->image -= misalignment;
      oc->image = stgReallocBytes( oc->image,
                               misalignment +
                               aligned + sizeof (SymbolExtra) * count,
                               "ocAllocateExtras" );
      oc->image += misalignment;

      oc->symbol_extras = (SymbolExtra *) (oc->image + aligned);
    } else if (USE_CONTIGUOUS_MMAP || RtsFlags.MiscFlags.linkerAlwaysPic) {
      /* Keep image, bssExtras and symbol_extras contiguous */
      size_t n = roundUpToPage(oc->fileSize);
      bssSize = roundUpToAlign(bssSize, 8);
      size_t allocated_size = n + bssSize + (sizeof(SymbolExtra) * count);
      void *new = mmapForLinker(allocated_size, MAP_ANONYMOUS, -1, 0);
      if (new) {
          memcpy(new, oc->image, oc->fileSize);
          if (oc->imageMapped) {
              munmap(oc->image, n);
          }
          oc->image = new;
          oc->imageMapped = true;
          oc->fileSize = allocated_size;
          oc->symbol_extras = (SymbolExtra *) (oc->image + n + bssSize);
          oc->bssBegin = oc->image + n;
          oc->bssEnd = oc->image + n + bssSize;
      }
      else {
          oc->symbol_extras = NULL;
          return 0;
      }
    } else {
        oc->symbol_extras = m32_alloc(sizeof(SymbolExtra) * count, 8);
        if (oc->symbol_extras == NULL) return 0;
    }
  }

  if (oc->symbol_extras != NULL) {
      memset( oc->symbol_extras, 0, sizeof (SymbolExtra) * count );
  }

  // ObjectCodeFormatInfo contains computed addresses based on offset to
  // image, if the address of image changes, we need to invalidate
  // the ObjectCodeFormatInfo and recompute it.
  if (oc->image != oldImage) {
#if defined(OBJFORMAT_MACHO)
    ocInit_MachO( oc );
#endif
#if defined(OBJFORMAT_ELF)
    ocInit_ELF( oc );
#endif
  }

  oc->first_symbol_extra = first;
  oc->n_symbol_extras = count;

  return 1;
}