[DynInst_API:] [PATCH dyninstAPI] Reallocate memory map buffer exponentially until there is enough space for the whole map.


Date: Mon, 14 Jul 2014 17:52:28 -0400
From: francis.deslauriers@xxxxxxxxxxxx
Subject: [DynInst_API:] [PATCH dyninstAPI] Reallocate memory map buffer exponentially until there is enough space for the whole map.
From: Francis Deslauriers <francis.deslauriers@xxxxxxxxxxxx>

Starting from the default size buffer, we try to read the memory map
without allocating new space. If we reach the end of the buffer before
the end of the file, we allocate a buffer twice as big and try again.
When we reach the MAX_MAP_SIZE we return an error to the calling
function.

Signed-off-by: Francis Deslauriers <francis.deslauriers@xxxxxxxxxxxx>
---
 dyninstAPI_RT/src/RTheap-linux.c | 80 +++++++++++++++++++++++++++-------------
 1 file changed, 55 insertions(+), 25 deletions(-)

diff --git a/dyninstAPI_RT/src/RTheap-linux.c b/dyninstAPI_RT/src/RTheap-linux.c
index 97ebd55..629e97e 100644
--- a/dyninstAPI_RT/src/RTheap-linux.c
+++ b/dyninstAPI_RT/src/RTheap-linux.c
@@ -43,6 +43,7 @@
 #include <sys/mman.h>                 /* mmap() */
 #include "RTheap.h"
 
+#define MAX_MAP_SIZE (1<<20)
 #if defined(MUTATEE64)
 
 int     DYNINSTheap_align = 4; /* heaps are word-aligned */
@@ -90,17 +91,21 @@ read it all in one call into this buffer.
 linux-2.4: reading /proc/PID/maps now returns after each line in the maps,
 so we must loop to get everything.
 */
-static char procAsciiMap[1<<15];
+
+// Static so we dont have to do the exponential backoff each time.
+static size_t mapSize = 1 << 15;
 
 int
 DYNINSTgetMemoryMap(unsigned *nump, dyninstmm_t **mapp)
 {
-   int fd;
+   int fd, done;
    ssize_t ret;
    size_t length;
    char *p;
    dyninstmm_t *ms;
    unsigned i, num;
+   char *procAsciiMap;
+
 
    /* 
       Here are two lines from 'cat /proc/self/maps' on Linux 2.2.  Each
@@ -112,40 +117,64 @@ DYNINSTgetMemoryMap(unsigned *nump, dyninstmm_t **mapp)
       0804a000-0804c000 rw-p 00001000 08:09 12089      /bin/cat
       0804c000-0804f000 rwxp 00000000 00:00 0
    */
-
-   fd = open("/proc/self/maps", O_RDONLY);
-   if (0 > fd) {
-      perror("open /proc");
-      return -1;
-   }
-   length = 0;
+   procAsciiMap = NULL;
+   done = 0;
    while (1)
    {
-      ret = read(fd, procAsciiMap + length, sizeof(procAsciiMap) - length);
-      if (0 == ret) break;
-      if (0 > ret) {
-	      close(fd);
-	      perror("read /proc");
-	      return -1;
-      }
-      length += ret;
-      if (length >= sizeof(procAsciiMap)) {
-	      close(fd);
-	      fprintf(stderr, "DYNINSTgetMemoryMap: memory map buffer overflow\n");
-	      return -1;
-      }
+       if(procAsciiMap == NULL) {
+           procAsciiMap = malloc(mapSize);
+       }
+       else
+       {
+           procAsciiMap = realloc(procAsciiMap, mapSize);
+       }
+       fd = open("/proc/self/maps", O_RDONLY);
+       if (0 > fd) {
+           perror("open /proc");
+           return -1;
+       }
+       length = 0;
+       while (1)
+       {
+           ret = read(fd, procAsciiMap + length, mapSize - length);
+           length += ret;
+           if (0 == ret) {
+               done = 1;
+               break;
+           }
+           if (0 > ret) {
+               close(fd);
+               perror("read /proc");
+               return -1;
+           }
+           /* Check if the buffer was to small and exponentially
+              increase its size */
+           if (length >= mapSize) {
+               close(fd);
+               mapSize = mapSize << 1;
+
+                  /* Return error if we reached the max size for
+                     the buffer*/
+                  if(mapSize > MAX_MAP_SIZE) {
+                      fprintf(stderr, "DYNINSTgetMemoryMap: memory map buffer is larger than the max size. max size=%d\n", MAX_MAP_SIZE);
+                      return -1;
+                  }
+               break;
+           }
+       }
+       if(done) {
+           break;
+       }
    }
    procAsciiMap[length] = '\0'; /* Now string processing works */
 
-   close(fd);
-
    /* Count lines, which is the same as the number of segments.
       Newline characters separating lines are converted to nulls. */
    for (num = 0, p = strtok(procAsciiMap, "\n");
         p != NULL;
         num++, p = strtok(NULL, "\n"))
       ;
-     
+
    ms = (dyninstmm_t *) malloc(num * sizeof(dyninstmm_t));
    if (! ms) {
       fprintf(stderr, "DYNINSTgetMemoryMap: Out of memory\n");
@@ -176,6 +205,7 @@ DYNINSTgetMemoryMap(unsigned *nump, dyninstmm_t **mapp)
 
    *nump = num;
    *mapp = ms;
+   free(procAsciiMap);
    return 0;
  parseerr:
    free(ms);
-- 
1.8.3.2

[← Prev in Thread] Current Thread [Next in Thread→]