Index: cpukit/libdl/rtl-obj-cache.c
===================================================================
--- cpukit/libdl/rtl-obj-cache.c	(revision 25c5583f92419dd03869a55e7f71e62b363e2f0f)
+++ cpukit/libdl/rtl-obj-cache.c	(revision 35edf82463f33d30e6bbbbbbafe3aadd80acffbb)
@@ -20,4 +20,5 @@
 
 #include <errno.h>
+#include <stdio.h>
 #include <string.h>
 #include <unistd.h>
@@ -26,4 +27,5 @@
 #include "rtl-obj-cache.h"
 #include "rtl-error.h"
+#include "rtl-trace.h"
 
 bool
@@ -47,5 +49,8 @@
 rtems_rtl_obj_cache_close (rtems_rtl_obj_cache_t* cache)
 {
+  if (rtems_rtl_trace (RTEMS_RTL_TRACE_CACHE))
+    printf ("rtl: cache: %2d: close\n", cache->fd);
   rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, cache->buffer);
+  cache->buffer    = NULL;
   cache->fd        = -1;
   cache->file_size = 0;
@@ -56,6 +61,9 @@
 rtems_rtl_obj_cache_flush (rtems_rtl_obj_cache_t* cache)
 {
+  if (rtems_rtl_trace (RTEMS_RTL_TRACE_CACHE))
+    printf ("rtl: cache: %2d: flush\n", cache->fd);
   cache->fd        = -1;
   cache->file_size = 0;
+  cache->offset    = 0;
   cache->level     = 0;
 }
@@ -70,4 +78,11 @@
   struct stat sb;
 
+  if (rtems_rtl_trace (RTEMS_RTL_TRACE_CACHE))
+    printf ("rtl: cache: %2d: fd=%d offset=%d length=%d area=[%d,%d] cache=[%d,%d] size=%d\n",
+            fd, cache->fd, (int) offset, (int) *length,
+            (int) offset, (int) offset + *length,
+            (int) cache->offset, (int) cache->offset + cache->level,
+            (int) cache->file_size);
+
   if (*length > cache->size)
   {
@@ -85,6 +100,13 @@
     }
 
+    /*
+     * We sometimes are asked to read strings of a length we do not know.
+     */
     if ((offset + *length) > cache->file_size)
+    {
       *length = cache->file_size - offset;
+      if (rtems_rtl_trace (RTEMS_RTL_TRACE_CACHE))
+        printf ("rtl: cache: %2d: truncate length=%d\n", fd, (int) *length);
+    }
   }
 
@@ -99,4 +121,10 @@
     if (fd == cache->fd)
     {
+      /*
+       * Do not read past the end of the file.
+       */
+      if ((offset + buffer_read) > cache->file_size)
+        buffer_read = cache->file_size - offset;
+
       /*
        * Is any part of the data in the cache ?
@@ -105,5 +133,8 @@
           (offset < (cache->offset + cache->level)))
       {
+        size_t size;
+
         buffer_offset = offset - cache->offset;
+        size          = cache->level - buffer_offset;
 
         /*
@@ -115,21 +146,35 @@
          * Is all the data in the cache or just a part ?
          */
-        if (*length <= (cache->level - buffer_offset))
-        {
+        if (*length <= size)
           return true;
-        }
-
-        /*
-         * Copy down the data in the buffer and then fill the remaining
-         * space with as much data we are able to read.
-         */
-        memmove (cache->buffer,
-                 cache->buffer + buffer_offset,
-                 cache->size - buffer_offset);
-
-        buffer_read   = buffer_offset;
-        buffer_offset = cache->size - buffer_offset;
-      }
-    }
+
+        if (rtems_rtl_trace (RTEMS_RTL_TRACE_CACHE))
+          printf ("rtl: cache: %2d: copy-down: buffer_offset=%d size=%d level=%d\n",
+                  fd, (int) buffer_offset, (int) size, (int) cache->level);
+
+        /*
+         * Copy down the data in the buffer and then fill the remaining space
+         * with as much data we are able to read.
+         */
+        memmove (cache->buffer, cache->buffer + buffer_offset, size);
+
+        cache->offset = offset;
+        cache->level  = size;
+        buffer_read   = cache->size - cache->level;
+        buffer_offset = size;
+
+        /*
+         * Do not read past the end of the file.
+         */
+        if ((offset + buffer_offset + buffer_read) > cache->file_size)
+          buffer_read = cache->file_size - (offset + buffer_offset);
+      }
+    }
+
+    if (rtems_rtl_trace (RTEMS_RTL_TRACE_CACHE))
+      printf ("rtl: cache: %2d: seek: offset=%d buffer_offset=%d read=%d cache=[%d,%d] dist=%d\n",
+              fd, (int) offset + buffer_offset, (int) buffer_offset, (int) buffer_read,
+              (int) offset, (int) offset + buffer_read,
+              (int) (cache->file_size - offset));
 
     if (lseek (fd, offset + buffer_offset, SEEK_SET) < 0)
@@ -144,5 +189,7 @@
      * want. If not it is an error. A POSIX read can read data in fragments.
      */
-    cache->level = buffer_read;
+
+    cache->level = buffer_offset + buffer_read;
+
     while (buffer_read)
     {
@@ -155,4 +202,6 @@
       if ((r == 0) && buffer_read)
       {
+        if (rtems_rtl_trace (RTEMS_RTL_TRACE_CACHE))
+          printf ("rtl: cache: %2d: read: past end by=%d\n", fd, (int) buffer_read);
         cache->level = cache->level - buffer_read;
         buffer_read = 0;
@@ -165,14 +214,18 @@
     }
 
-    cache->fd = fd;
     cache->offset = offset;
 
-    if (fstat (cache->fd, &sb) < 0)
-    {
-      rtems_rtl_set_error (errno, "file stat failed");
-      return false;
-    }
-
-    cache->file_size = sb.st_size;
+    if (cache->fd != fd)
+    {
+      cache->fd = fd;
+
+      if (fstat (cache->fd, &sb) < 0)
+      {
+        rtems_rtl_set_error (errno, "file stat failed");
+        return false;
+      }
+
+      cache->file_size = sb.st_size;
+    }
   }
 
Index: cpukit/libdl/rtl-trace.c
===================================================================
--- cpukit/libdl/rtl-trace.c	(revision 25c5583f92419dd03869a55e7f71e62b363e2f0f)
+++ cpukit/libdl/rtl-trace.c	(revision 35edf82463f33d30e6bbbbbbafe3aadd80acffbb)
@@ -59,4 +59,6 @@
   const char* table[] =
   {
+    "detail",
+    "warning",
     "load",
     "unload",
@@ -68,5 +70,5 @@
     "allocator",
     "unresolved",
-    "detail"
+    "cache"
   };
 
Index: cpukit/libdl/rtl-trace.h
===================================================================
--- cpukit/libdl/rtl-trace.h	(revision 25c5583f92419dd03869a55e7f71e62b363e2f0f)
+++ cpukit/libdl/rtl-trace.h	(revision 35edf82463f33d30e6bbbbbbafe3aadd80acffbb)
@@ -37,16 +37,17 @@
  * List of tracing bits for the various parts of the link editor.
  */
-#define RTEMS_RTL_TRACE_ALL                    (0xffffffffUL)
-#define RTEMS_RTL_TRACE_LOAD                   (1UL << 0)
-#define RTEMS_RTL_TRACE_UNLOAD                 (1UL << 1)
-#define RTEMS_RTL_TRACE_SECTION                (1UL << 2)
-#define RTEMS_RTL_TRACE_SYMBOL                 (1UL << 3)
-#define RTEMS_RTL_TRACE_RELOC                  (1UL << 4)
-#define RTEMS_RTL_TRACE_GLOBAL_SYM             (1UL << 5)
-#define RTEMS_RTL_TRACE_LOAD_SECT              (1UL << 6)
-#define RTEMS_RTL_TRACE_ALLOCATOR              (1UL << 7)
-#define RTEMS_RTL_TRACE_UNRESOLVED             (1UL << 8)
-#define RTEMS_RTL_TRACE_DETAIL                 (1UL << 9)
-#define RTEMS_RTL_TRACE_WARNING                (1UL << 10)
+#define RTEMS_RTL_TRACE_DETAIL                 (1UL << 0)
+#define RTEMS_RTL_TRACE_WARNING                (1UL << 1)
+#define RTEMS_RTL_TRACE_LOAD                   (1UL << 2)
+#define RTEMS_RTL_TRACE_UNLOAD                 (1UL << 3)
+#define RTEMS_RTL_TRACE_SECTION                (1UL << 4)
+#define RTEMS_RTL_TRACE_SYMBOL                 (1UL << 5)
+#define RTEMS_RTL_TRACE_RELOC                  (1UL << 6)
+#define RTEMS_RTL_TRACE_GLOBAL_SYM             (1UL << 7)
+#define RTEMS_RTL_TRACE_LOAD_SECT              (1UL << 8)
+#define RTEMS_RTL_TRACE_ALLOCATOR              (1UL << 9)
+#define RTEMS_RTL_TRACE_UNRESOLVED             (1UL << 10)
+#define RTEMS_RTL_TRACE_CACHE                  (1UL << 11)
+#define RTEMS_RTL_TRACE_ALL                    (0xffffffffUL & ~(RTEMS_RTL_TRACE_CACHE))
 
 /**
