diff options
Diffstat (limited to 'rts/Linker.c')
-rw-r--r-- | rts/Linker.c | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/rts/Linker.c b/rts/Linker.c index ba78efe7b6..3d56989677 100644 --- a/rts/Linker.c +++ b/rts/Linker.c @@ -1195,6 +1195,7 @@ void freeObjectCode (ObjectCode *oc) } freeProddableBlocks(oc); + freeSegments(oc); /* Free symbol_extras. On x86_64 Windows, symbol_extras are allocated * alongside the image, so we don't need to free. */ @@ -1279,6 +1280,8 @@ mkOc( pathchar *path, char *image, int imageSize, oc->symbols = NULL; oc->n_sections = 0; oc->sections = NULL; + oc->n_segments = 0; + oc->segments = NULL; oc->proddables = NULL; oc->stable_ptrs = NULL; #if defined(NEED_SYMBOL_EXTRAS) @@ -1840,3 +1843,50 @@ addSection (Section *s, SectionKind kind, SectionAlloc alloc, start, (void*)((StgWord)start + size), size, kind )); } + +/* ----------------------------------------------------------------------------- + * Segment management + */ +void +initSegment (Segment *s, void *start, size_t size, SegmentProt prot, int n_sections) +{ + s->start = start; + s->size = size; + s->prot = prot; + s->sections_idx = (int *)stgCallocBytes(n_sections, sizeof(int), + "initSegment(segment)"); + s->n_sections = n_sections; +} + +void freeSegments (ObjectCode *oc) +{ + if (oc->segments != NULL) { + IF_DEBUG(linker, debugBelch("freeSegments: freeing %d segments\n", oc->n_segments)); + + for (int i = 0; i < oc->n_segments; i++) { + Segment *s = &oc->segments[i]; + + IF_DEBUG(linker, debugBelch("freeSegments: freeing segment %d at %p size %zu\n", + i, s->start, s->size)); + + stgFree(s->sections_idx); + s->sections_idx = NULL; + + if (0 == s->size) { + IF_DEBUG(linker, debugBelch("freeSegment: skipping segment of 0 size\n")); + continue; + } else { +#if RTS_LINKER_USE_MMAP + CHECKM(0 == munmap(s->start, s->size), "freeSegments: failed to unmap memory"); +#else + stgFree(s->start); +#endif + } + s->start = NULL; + } + + stgFree(oc->segments); + oc->segments = NULL; + } +} + |