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;
}