Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
this type name is usable as is, so add _t postfix (s_name is only for stuff that...
[simgrid.git] / src / mc / memory_map.c
1 /* Copyright (c) 2008-2012 Da SimGrid Team. All rights reserved.            */
2
3 /* This program is free software; you can redistribute it and/or modify it
4  * under the terms of the license (GNU LGPL) which comes with this package. */
5
6 #define _GNU_SOURCE
7 #include "mc_private.h"
8 #include <stdlib.h>
9
10 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_memory_map, mc,
11                                 "Logging specific to algorithms for memory_map");
12
13 memory_map_t get_memory_map(void)
14 {
15   FILE *fp;                     /* File pointer to process's proc maps file */
16   char *line = NULL;            /* Temporal storage for each line that is readed */
17   ssize_t read;                 /* Number of bytes readed */
18   size_t n = 0;                 /* Amount of bytes to read by getline */
19   memory_map_t ret = NULL;      /* The memory map to return */
20
21 /* The following variables are used during the parsing of the file "maps" */
22   s_map_region_t memreg;          /* temporal map region used for creating the map */
23   char *lfields[6], *tok, *endptr;
24   int i;
25
26 /* Open the actual process's proc maps file and create the memory_map_t */
27 /* to be returned. */
28   fp = fopen("/proc/self/maps", "r");
29
30   if(fp == NULL)
31     perror("fopen failed");
32
33   xbt_assert(fp,
34               "Cannot open /proc/self/maps to investigate the memory map of the process. Please report this bug.");
35
36   //XBT_DEBUG("/proc/self/maps");
37
38   ret = xbt_new0(s_memory_map_t, 1);
39
40   /* Read one line at the time, parse it and add it to the memory map to be returned */
41   while ((read = getline(&line, &n, fp)) != -1) {
42
43     XBT_DEBUG("%s", line);
44
45     /* Wipeout the new line character */
46     line[read - 1] = '\0';
47
48     /* Tokenize the line using spaces as delimiters and store each token */
49     /* in lfields array. We expect 5 tokens/fields */
50     lfields[0] = strtok(line, " ");
51
52     for (i = 1; i < 6 && lfields[i - 1] != NULL; i++) {
53       lfields[i] = strtok(NULL, " ");
54     }
55
56     /* Check to see if we got the expected amount of columns */
57     if (i < 6)
58       xbt_abort();
59
60     /* Ok we are good enough to try to get the info we need */
61     /* First get the start and the end address of the map   */
62     tok = strtok(lfields[0], "-");
63     if (tok == NULL)
64       xbt_abort();
65
66     memreg.start_addr = (void *) strtoul(tok, &endptr, 16);
67     /* Make sure that the entire string was an hex number */
68     if (*endptr != '\0')
69       xbt_abort();
70
71     tok = strtok(NULL, "-");
72     if (tok == NULL)
73       xbt_abort();
74
75     memreg.end_addr = (void *) strtoul(tok, &endptr, 16);
76     /* Make sure that the entire string was an hex number */
77     if (*endptr != '\0')
78       xbt_abort();
79
80     /* Get the permissions flags */
81     if (strlen(lfields[1]) < 4)
82       xbt_abort();
83
84     memreg.prot = 0;
85
86     for (i = 0; i < 3; i++){
87       switch(lfields[1][i]){
88         case 'r':
89           memreg.prot |= PROT_READ;
90           break;
91         case 'w':
92           memreg.prot |= PROT_WRITE;
93           break;
94         case 'x':
95           memreg.prot |= PROT_EXEC;
96           break;
97         default:
98           break;
99       }
100     }
101     if (memreg.prot == 0)
102       memreg.prot |= PROT_NONE;
103
104     if (lfields[1][4] == 'p')
105       memreg.flags |= MAP_PRIVATE;
106
107     else if (lfields[1][4] == 's')
108       memreg.flags |= MAP_SHARED;
109
110     /* Get the offset value */
111     memreg.offset = (void *) strtoul(lfields[2], &endptr, 16);
112     /* Make sure that the entire string was an hex number */
113     if (*endptr != '\0')
114       xbt_abort();
115
116     /* Get the device major:minor bytes */
117     tok = strtok(lfields[3], ":");
118     if (tok == NULL)
119       xbt_abort();
120
121     memreg.dev_major = (char) strtoul(tok, &endptr, 16);
122     /* Make sure that the entire string was an hex number */
123     if (*endptr != '\0')
124       xbt_abort();
125
126     tok = strtok(NULL, ":");
127     if (tok == NULL)
128       xbt_abort();
129
130     memreg.dev_minor = (char) strtoul(tok, &endptr, 16);
131     /* Make sure that the entire string was an hex number */
132     if (*endptr != '\0')
133       xbt_abort();
134
135     /* Get the inode number and make sure that the entire string was a long int */
136     memreg.inode = strtoul(lfields[4], &endptr, 10);
137     if (*endptr != '\0')
138       xbt_abort();
139
140     /* And finally get the pathname */
141     memreg.pathname = xbt_strdup(lfields[5]);
142
143     /* Create space for a new map region in the region's array and copy the */
144     /* parsed stuff from the temporal memreg variable */
145     ret->regions =
146         xbt_realloc(ret->regions, sizeof(memreg) * (ret->mapsize + 1));
147     memcpy(ret->regions + ret->mapsize, &memreg, sizeof(memreg));
148     ret->mapsize++;
149
150   }
151
152   free(line);
153
154   fclose(fp);
155
156   return ret;
157 }