summaryrefslogtreecommitdiff
path: root/rts/Linker.c
diff options
context:
space:
mode:
Diffstat (limited to 'rts/Linker.c')
-rw-r--r--rts/Linker.c50
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;
+ }
+}
+