Fix PE linker wibbles
authorTamar Christina <tamar@zhox.com>
Thu, 4 Oct 2018 17:50:04 +0000 (13:50 -0400)
committerBen Gamari <ben@smart-cactus.org>
Fri, 5 Oct 2018 02:27:54 +0000 (22:27 -0400)
Fix some various issues that popped up because the linker now doesn't
load import libraries for longer than it needs to.

These are all use after free issues.

Test Plan: ./validate

Reviewers: bgamari, erikd, simonmar

Reviewed By: bgamari

Subscribers: simonpj, rwbarton, carter

Differential Revision: https://phabricator.haskell.org/D5175

rts/Linker.c
rts/linker/PEi386.c

index a1de6a7..8262697 100644 (file)
@@ -1235,6 +1235,12 @@ void freeObjectCode (ObjectCode *oc)
 * Sets the initial status of a fresh ObjectCode
 */
 static void setOcInitialStatus(ObjectCode* oc) {
+    /* If a target has requested the ObjectCode not to be resolved then
+       honor this requests.  Usually this means the ObjectCode has not been
+       initialized and can't be.  */
+    if (oc->status == OBJECT_DONT_RESOLVE)
+      return;
+
     if (oc->archiveMemberName == NULL) {
         oc->status = OBJECT_NEEDED;
     } else {
index 4dbb629..ab4583d 100644 (file)
@@ -414,12 +414,11 @@ void freePreloadObjectFile_PEi386(ObjectCode *oc)
         oc->image = NULL;
     }
 
-    if (oc->info->image) {
-        HeapFree(code_heap, 0, oc->info->image);
-        oc->info->image = NULL;
-    }
-
     if (oc->info) {
+        if (oc->info->image) {
+            HeapFree(code_heap, 0, oc->info->image);
+            oc->info->image = NULL;
+        }
         if (oc->info->ch_info)
            stgFree (oc->info->ch_info);
         stgFree (oc->info);
@@ -447,15 +446,15 @@ static void releaseOcInfo(ObjectCode* oc) {
         oc->info = NULL;
     }
     for (int i = 0; i < oc->n_sections; i++){
-        Section section = oc->sections[i];
-        if (section.info) {
-            stgFree (section.info->name);
-            if (section.info->relocs) {
-                stgFree (section.info->relocs);
-                section.info->relocs = NULL;
+        Section *section = &oc->sections[i];
+        if (section->info) {
+            stgFree (section->info->name);
+            if (section->info->relocs) {
+                stgFree (section->info->relocs);
+                section->info->relocs = NULL;
             }
-            stgFree (section.info);
-            section.info = NULL;
+            stgFree (section->info);
+            section->info = NULL;
         }
     }
 }
@@ -1161,6 +1160,11 @@ ocVerifyImage_PEi386 ( ObjectCode* oc )
 {
    COFF_HEADER_INFO *info = getHeaderInfo (oc);
 
+   /* If the header could not be read, then don't process the ObjectCode.
+      This the case when the ObjectCode has been partially freed.  */
+   if (!info)
+     return false;
+
    uint32_t i, noRelocs;
    COFF_section* sectab;
    COFF_symbol*  symtab;
@@ -1530,6 +1534,7 @@ ocGetNames_PEi386 ( ObjectCode* oc )
           stgFree (oc->image);
           oc->image = NULL;
           releaseOcInfo (oc);
+          oc->status = OBJECT_DONT_RESOLVE;
           return true;
       }
 
@@ -1831,6 +1836,10 @@ ocResolve_PEi386 ( ObjectCode* oc )
    uint8_t symbol[1000];
    /* debugBelch("resolving for %s\n", oc->fileName); */
 
+   /* Such libraries have been partially freed and can't be resolved.  */
+   if (oc->status == OBJECT_DONT_RESOLVE)
+     return 1;
+
    COFF_HEADER_INFO *info = oc->info->ch_info;
    uint32_t numberOfSections = info->numberOfSections;