Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[mc] Basic support for more other libraries than libsimgrid.so
[simgrid.git] / src / mc / mc_process.c
1 #include <stddef.h>
2 #include <stdbool.h>
3 #include <stdint.h>
4
5 #include <sys/types.h>
6 #include <unistd.h>
7 #include <regex.h>
8 #include <sys/mman.h> // PROT_*
9
10 #include <libgen.h>
11
12 #include "mc_process.h"
13 #include "mc_object_info.h"
14
15 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_process, mc,
16                                 "MC process information");
17
18 static void MC_init_memory_map_info(mc_process_t process);
19
20 void MC_process_init(mc_process_t process, pid_t pid)
21 {
22   process->process_flags = MC_PROCESS_NO_FLAG;
23   process->pid = pid;
24   if (pid==getpid())
25     process->process_flags |= MC_PROCESS_SELF_FLAG;
26   process->memory_map = MC_get_memory_map(pid);
27   MC_init_memory_map_info(process);
28 }
29
30 void MC_process_clear(mc_process_t process)
31 {
32   process->process_flags = MC_PROCESS_NO_FLAG;
33   process->pid = 0;
34
35   MC_free_memory_map(process->memory_map);
36   process->memory_map = NULL;
37
38   process->maestro_stack_start = NULL;
39   process->maestro_stack_end = NULL;
40
41   size_t i;
42   for (i=0; i!=process->object_infos_size; ++i) {
43     MC_free_object_info(&process->object_infos[i]);
44   }
45   free(process->object_infos);
46   process->object_infos = NULL;
47   process->object_infos_size = 0;
48 }
49
50 #define SO_RE "\\.so[\\.0-9]*$"
51 #define VERSION_RE "-[\\.0-9]*$"
52
53 const char* FILTERED_LIBS[] = {
54   "libstdc++",
55   "libc++",
56   "libm",
57   "libgcc_s",
58   "libpthread",
59   "libunwind",
60   "libunwind-x86_64",
61   "libunwind-x86",
62   "libdw",
63   "libdl",
64   "librt",
65   "liblzma",
66   "libelf",
67   "libbz2",
68   "libz",
69   "libelf",
70   "libc",
71   "ld"
72 };
73
74 static bool MC_is_simgrid_lib(const char* libname)
75 {
76   return !strcmp(libname, "libsimgrid");
77 }
78
79 static bool MC_is_filtered_lib(const char* libname)
80 {
81   const size_t n = sizeof(FILTERED_LIBS) / sizeof(const char*);
82   size_t i;
83   for (i=0; i!=n; ++i)
84     if (strcmp(libname, FILTERED_LIBS[i])==0)
85       return true;
86   return false;
87 }
88
89 struct s_mc_memory_map_re {
90   regex_t so_re;
91   regex_t version_re;
92 };
93
94 static char* MC_get_lib_name(const char* pathname, struct s_mc_memory_map_re* res) {
95   const char* map_basename = basename((char*) pathname);
96
97   regmatch_t match;
98   if(regexec(&res->so_re, map_basename, 1, &match, 0))
99     return NULL;
100
101   char* libname = strndup(map_basename, match.rm_so);
102
103   // Strip the version suffix:
104   if(libname && !regexec(&res->version_re, libname, 1, &match, 0)) {
105     char* temp = libname;
106     libname = strndup(temp, match.rm_so);
107     free(temp);
108   }
109
110   return libname;
111 }
112
113 /** @brief Finds the range of the different memory segments and binary paths */
114 static void MC_init_memory_map_info(mc_process_t process)
115 {
116   XBT_INFO("Get debug information ...");
117   process->maestro_stack_start = NULL;
118   process->maestro_stack_end = NULL;
119   process->object_infos = NULL;
120   process->object_infos_size = 0;
121   process->binary_info = NULL;
122   process->libsimgrid_info = NULL;
123
124   struct s_mc_memory_map_re res;
125
126   if(regcomp(&res.so_re, SO_RE, 0) || regcomp(&res.version_re, VERSION_RE, 0))
127     xbt_die(".so regexp did not compile");
128
129   memory_map_t maps = process->memory_map;
130
131   const char* current_name = NULL;
132
133   size_t i = 0;
134   for (i=0; i < maps->mapsize; i++) {
135     map_region_t reg = &(maps->regions[i]);
136     const char* pathname = maps->regions[i].pathname;
137
138     // Nothing to do
139     if (maps->regions[i].pathname == NULL) {
140       current_name = NULL;
141       continue;
142     }
143
144     // [stack], [vvar], [vsyscall], [vdso] ...
145     if (pathname[0] == '[') {
146       if ((reg->prot & PROT_WRITE) && !memcmp(pathname, "[stack]", 7)) {
147         process->maestro_stack_start = reg->start_addr;
148         process->maestro_stack_end = reg->end_addr;
149       }
150       current_name = NULL;
151       continue;
152     }
153
154     if (current_name && strcmp(current_name, pathname)==0)
155       continue;
156
157     current_name = pathname;
158     if (!(reg->prot & PROT_READ) && (reg->prot & PROT_EXEC))
159       continue;
160
161     const bool is_executable = !i;
162     char* libname = NULL;
163     if (!is_executable) {
164       libname = MC_get_lib_name(pathname, &res);
165       if(!libname)
166         continue;
167       if (MC_is_filtered_lib(libname)) {
168         free(libname);
169         continue;
170       }
171     }
172
173     mc_object_info_t info =
174       MC_find_object_info(process->memory_map, pathname, is_executable);
175     process->object_infos = (mc_object_info_t*) realloc(process->object_infos,
176       (process->object_infos_size+1) * sizeof(mc_object_info_t*));
177     process->object_infos[process->object_infos_size] = info;
178     process->object_infos_size++;
179     if (is_executable)
180       process->binary_info = info;
181     else if (libname && MC_is_simgrid_lib(libname))
182       process->libsimgrid_info = info;
183     free(libname);
184   }
185
186   regfree(&res.so_re);
187   regfree(&res.version_re);
188
189   // Resolve time (including accress differents objects):
190   for (i=0; i!=process->object_infos_size; ++i)
191     MC_post_process_object_info(process, process->object_infos[i]);
192
193   xbt_assert(process->maestro_stack_start, "maestro_stack_start");
194   xbt_assert(process->maestro_stack_end, "maestro_stack_end");
195
196   XBT_INFO("Get debug information done !");
197 }
198
199 mc_object_info_t MC_process_find_object_info(mc_process_t process, void *ip)
200 {
201   size_t i;
202   for (i = 0; i != process->object_infos_size; ++i) {
203     if (ip >= (void *) process->object_infos[i]->start_exec
204         && ip <= (void *) process->object_infos[i]->end_exec) {
205       return process->object_infos[i];
206     }
207   }
208   return NULL;
209 }
210
211 dw_frame_t MC_process_find_function(mc_process_t process, void *ip)
212 {
213   mc_object_info_t info = MC_process_find_object_info(process, ip);
214   if (info == NULL)
215     return NULL;
216   else
217     return MC_file_object_info_find_function(info, ip);
218 }