From cdaf5f2027ea9678e9f92e9140c79da2daa78360 Mon Sep 17 00:00:00 2001
From: Bartosz Nitka <niteria@gmail.com>
Date: Mon, 18 Sep 2017 07:53:56 -0700
Subject: [PATCH] [RTS] Add getObjectLoadStatus

This adds a function to the RTS linker API which lets the
user check the status of dynamically linked objects.

It was initially proposed by @afarmer in D2068.
It's useful for testing the linker and also for detecting retention
problems in production.

It takes a path, because it's easier to use path as key instead of producing
some stable handle.

It returns an enum instead of bool, because I see no reason for destroying
information. All the complexity is already out in the open, so there's
nothing to save the users from.

Test Plan: ./validate

Reviewers: simonmar, Phyx, bgamari, austin, erikd

Reviewed By: Phyx, bgamari

Subscribers: rwbarton, afarmer, thomie

Differential Revision: https://phabricator.haskell.org/D3963
---
 includes/rts/Linker.h | 14 ++++++++++++++
 rts/Linker.c          | 24 ++++++++++++++++++++++++
 rts/LinkerInternals.h |  9 ---------
 3 files changed, 38 insertions(+), 9 deletions(-)

diff --git a/includes/rts/Linker.h b/includes/rts/Linker.h
index 793195b3ab46..298dc6a3664a 100644
--- a/includes/rts/Linker.h
+++ b/includes/rts/Linker.h
@@ -47,6 +47,20 @@ HsInt insertSymbol(pathchar* obj_name, char* key, void* data);
 /* lookup a symbol in the hash table */
 void *lookupSymbol( char *lbl );
 
+/* See Linker.c Note [runtime-linker-phases] */
+typedef enum {
+    OBJECT_LOADED,
+    OBJECT_NEEDED,
+    OBJECT_RESOLVED,
+    OBJECT_UNLOADED,
+    OBJECT_DONT_RESOLVE,
+    OBJECT_NOT_LOADED     /* The object was either never loaded or has been
+                             fully unloaded */
+} OStatus;
+
+/* check object load status */
+OStatus getObjectLoadStatus( pathchar *path );
+
 /* delete an object from the pool */
 HsInt unloadObj( pathchar *path );
 
diff --git a/rts/Linker.c b/rts/Linker.c
index 18f2c6b958c7..30d7e87f92e6 100644
--- a/rts/Linker.c
+++ b/rts/Linker.c
@@ -1708,6 +1708,30 @@ HsInt purgeObj (pathchar *path)
     return r;
 }
 
+static OStatus getObjectLoadStatus_ (pathchar *path)
+{
+    ObjectCode *o;
+    for (o = objects; o; o = o->next) {
+       if (0 == pathcmp(o->fileName, path)) {
+           return o->status;
+       }
+    }
+    for (o = unloaded_objects; o; o = o->next) {
+       if (0 == pathcmp(o->fileName, path)) {
+           return o->status;
+       }
+    }
+    return OBJECT_NOT_LOADED;
+}
+
+OStatus getObjectLoadStatus (pathchar *path)
+{
+    ACQUIRE_LOCK(&linker_mutex);
+    OStatus r = getObjectLoadStatus_(path);
+    RELEASE_LOCK(&linker_mutex);
+    return r;
+}
+
 /* -----------------------------------------------------------------------------
  * Sanity checking.  For each ObjectCode, maintain a list of address ranges
  * which may be prodded during relocation, and abort if we try and write
diff --git a/rts/LinkerInternals.h b/rts/LinkerInternals.h
index 2e8491789d62..dd17be099204 100644
--- a/rts/LinkerInternals.h
+++ b/rts/LinkerInternals.h
@@ -20,15 +20,6 @@
 typedef void SymbolAddr;
 typedef char SymbolName;
 
-/* See Linker.c Note [runtime-linker-phases] */
-typedef enum {
-    OBJECT_LOADED,
-    OBJECT_NEEDED,
-    OBJECT_RESOLVED,
-    OBJECT_UNLOADED,
-    OBJECT_DONT_RESOLVE
-} OStatus;
-
 /* Indication of section kinds for loaded objects.  Needed by
    the GC for deciding whether or not a pointer on the stack
    is a code pointer.
-- 
GitLab