HPCToolkit
rtmap.c
Go to the documentation of this file.
1 // -*-Mode: C++;-*- // technically C99
2 
3 // * BeginRiceCopyright *****************************************************
4 //
5 // $HeadURL$
6 // $Id$
7 //
8 // --------------------------------------------------------------------------
9 // Part of HPCToolkit (hpctoolkit.org)
10 //
11 // Information about sources of support for research and development of
12 // HPCToolkit is at 'hpctoolkit.org' and in 'README.Acknowledgments'.
13 // --------------------------------------------------------------------------
14 //
15 // Copyright ((c)) 2002-2019, Rice University
16 // All rights reserved.
17 //
18 // Redistribution and use in source and binary forms, with or without
19 // modification, are permitted provided that the following conditions are
20 // met:
21 //
22 // * Redistributions of source code must retain the above copyright
23 // notice, this list of conditions and the following disclaimer.
24 //
25 // * Redistributions in binary form must reproduce the above copyright
26 // notice, this list of conditions and the following disclaimer in the
27 // documentation and/or other materials provided with the distribution.
28 //
29 // * Neither the name of Rice University (RICE) nor the names of its
30 // contributors may be used to endorse or promote products derived from
31 // this software without specific prior written permission.
32 //
33 // This software is provided by RICE and contributors "as is" and any
34 // express or implied warranties, including, but not limited to, the
35 // implied warranties of merchantability and fitness for a particular
36 // purpose are disclaimed. In no event shall RICE or contributors be
37 // liable for any direct, indirect, incidental, special, exemplary, or
38 // consequential damages (including, but not limited to, procurement of
39 // substitute goods or services; loss of use, data, or profits; or
40 // business interruption) however caused and on any theory of liability,
41 // whether in contract, strict liability, or tort (including negligence
42 // or otherwise) arising in any way out of the use of this software, even
43 // if advised of the possibility of such damage.
44 //
45 // ******************************************************* EndRiceCopyright *
46 
47 /****************************************************************************
48 //
49 // File:
50 // $HeadURL$
51 //
52 // Purpose:
53 // Finds a list of loaded modules (e.g. DSOs) for the current process.
54 //
55 // Description:
56 // [The set of functions, macros, etc. defined in the file]
57 //
58 // Author:
59 // Written by John Mellor-Crummey and Nathan Tallent, Rice University.
60 //
61 *****************************************************************************/
62 
63 /************************** System Include Files ****************************/
64 
65 #include <stdlib.h>
66 #include <stdio.h>
67 #include <unistd.h>
68 #include <string.h>
69 #include <limits.h> /* for 'PATH_MAX' */
70 #include <libgen.h> /* for dirname/basename */
71 #include <sys/types.h>
72 
73 /**************************** User Include Files ****************************/
74 
75 #include "rtmap.h"
76 
77 /**************************** Forward Declarations **************************/
78 
79 #define TESTING 0
80 
82 
83 static void finalizelines(void);
84 static int iscodeline(char *line);
85 static char* get_line_slot(void);
86 
87 static char* get_name(char *line);
88 static char* get_beg_addr(char *line);
89 static char* get_end_addr(char *line);
90 
91 static unsigned long hex2ul(char *s);
92 static uint64_t hex2u64(char *s);
93 
94 static void dumprtloadmap(void);
95 static void dumplines(void);
96 
97 static void reset_slots();
98 
99 /****************************************************************************/
100 
101 /* number of bytes to print out for a long in hex with a 0x prefix */
102 #define bhl ((int)(sizeof(long)*2+2))
103 
104 #define MAXLINELEN (PATH_MAX + 80)
105 
106 /****************************************************************************/
107 
108 /*
109  * Read lines from the load maps in /proc to find runtime libraries
110  * and load addresses. Cf. "man proc". E.g.:
111  *
112  * address perms offset dev inode pathname
113  * 08048000-08056000 r-xp 00000000 03:0c 64593 /usr/sbin/gpm
114  * 08056000-08058000 rw-p 0000d000 03:0c 64593 /usr/sbin/gpm
115  *
116  */
117 rtloadmap_t*
119 {
120  char filename[PATH_MAX];
121  FILE *fs;
122  char *line;
123  pid_t pid = getpid();
124 
125  reset_slots();
126  line = get_line_slot();
127 
128  sprintf(filename, "/proc/%d/maps", pid);
129  fs = fopen(filename, "r");
130 
131  /* read lines from the maps file in /proc for this
132  * process. discard the line if it does not correspond
133  * to an executable segment
134  */
135  do {
136  if (iscodeline(line)) {
137  line = get_line_slot();
138  }
139  } while (fgets(line, MAXLINELEN, fs) != NULL);
140  fclose(fs);
141 
142  finalizelines();
143 
144  if (dbglvl >= 3) {
145  dumprtloadmap();
146  }
147  if (dbglvl >= 4) {
148  dumplines();
149  }
150 
151  return &rtloadmap;
152 }
153 
154 
155 /*
156  * Return the name of the command invoked to create this process.
157  *
158  */
159 const char*
160 hpcrun_get_cmd(int dbglvl)
161 {
162  static char* cmd = NULL; /* */
163 
164  char filenm[PATH_MAX];
165  char cmdline[PATH_MAX];
166  FILE *fs;
167  pid_t pid = getpid();
168  char* space, *basenm;
169 
170  free(cmd);
171 
172  sprintf(filenm, "/proc/%d/cmdline", pid);
173  fs = fopen(filenm, "r");
174  fgets(cmdline, PATH_MAX, fs);
175  fclose(fs);
176 
177  /* Separate the command's path from its arguments. Assume for now
178  that there are no spaces in path name. */
179  space = strchr(cmdline, ' '); /* assume there is no */
180  if (space) {
181  *space = '\0';
182  }
183 
184  /* Find the basename of the path*/
185  basenm = basename(cmdline);
186  cmd = malloc(sizeof(const char*) * (strlen(basenm) + 1));
187  strcpy(cmd, basenm);
188 
189  return cmd;
190 }
191 
192 /****************************************************************************/
193 
194 static char **mappings = 0;
195 static int slots_avail = 0;
196 static int slots_in_use = 0;
197 
198 static void reset_slots()
199 {
200  slots_avail = 0;
201  slots_in_use = 0;
202  if (mappings) free(mappings);
203  mappings = 0;
204 }
205 
206 /* allocate a slot for a new line in an
207  * extensible array of load map lines.
208  */
209 static char*
211 {
212  if (slots_in_use == slots_avail) {
213  if (mappings == 0) {
214  slots_avail = 512;
215  mappings = malloc(slots_avail * sizeof(char*));
216  }
217  else {
218  slots_avail += 256;
219  mappings = realloc(mappings, slots_avail * sizeof(char*));
220  }
221  }
222  mappings[slots_in_use] = (char *) malloc(MAXLINELEN);
223  *mappings[slots_in_use] = '\0';
224  return mappings[slots_in_use++];
225 }
226 
227 /* check if a line in a loadmap entry represents
228  * code by testing to see if execute permission
229  * is set and file name has a path.
230  */
231 static int
232 iscodeline(char *line)
233 {
234  char *blank = strchr(line, (int) ' ');
235  char *slash = strchr(line, (int) '/');
236  return (blank && *(blank + 3) == 'x' && slash);
237 }
238 
239 /* discard the last line in the array of
240  * load map lines if it does not represent
241  * executable code.
242  */
243 static void
245 {
246  int i;
247  if (slots_in_use > 0) {
248  int last = slots_in_use - 1;
249  if (!iscodeline(mappings[last])) {
250  free(mappings[last]);
251  slots_in_use = last;
252  }
253  }
254 
255  rtloadmap.module =
257 
258  for(i = 0; i < slots_in_use; i++) {
259  char* line = mappings[i];
260  rtloadmap.module[i].name = strdup(get_name(line));
261  rtloadmap.module[i].offset = hex2u64(get_beg_addr(line));
262  rtloadmap.module[i].length = hex2ul(get_end_addr(line)) -
263  rtloadmap.module[i].offset;
264  }
265  rtloadmap.count = slots_in_use;
266 #if TESTING
267  dumprtloadmap();
268 #endif
269 
270  mappings = realloc(mappings, (slots_in_use +1) * sizeof(char*));
271  slots_avail = slots_in_use + 1;
272 }
273 
274 static char*
275 get_name(char *line)
276 {
277  char *name = strchr(line, (int) '/');
278  char *newline = strchr(line, (int) '\n');
279  if (newline) *newline = 0;
280  return name;
281 }
282 
283 static char*
284 get_beg_addr(char *line)
285 {
286  return line;
287 }
288 
289 static char*
290 get_end_addr(char *line)
291 {
292  char *minus = strchr(line, (int) '-');
293  return minus + 1;
294 }
295 
296 static unsigned long
297 hex2ul(char *s)
298 {
299  unsigned long res = 0;
300  sscanf(s, "%lx", &res);
301  return res;
302 }
303 
304 static uint64_t
305 hex2u64(char *s)
306 {
307  uint64_t res = 0;
308  sscanf(s, "%"SCNx64"", &res);
309  return res;
310 }
311 
312 
313 /* Dump a processed form of the load map
314  */
315 static void
317 {
318  int i;
319  fprintf(stderr, "Dumping currently mapped load modules (%d):\n",
320  rtloadmap.count);
321  for (i = 0; i < rtloadmap.count; i++) {
322  fprintf(stderr, " [%d] offset=%#0*"PRIx64" ",
323  i, bhl, rtloadmap.module[i].offset);
324  fprintf(stderr, "length=%#0*lx ", bhl, rtloadmap.module[i].length);
325  fprintf(stderr, "name=%s\n", rtloadmap.module[i].name);
326  }
327 }
328 
329 /* Simply regurgitate the code lines of the load map
330  */
331 static void
333 {
334  int i = 0;
335  for (; i < slots_in_use; i++) {
336  printf("%s\n",mappings[i]);
337  }
338 }
339 
340 #if TESTING
341 
342 int
343 main(void)
344 {
346 #if 0
347  dumplines();
348 #endif
349  return 0;
350 }
351 
352 #endif
353 
static char ** mappings
Definition: rtmap.c:194
void MONITOR_EXT_WRAP_NAME() free(void *ptr)
static char * get_beg_addr(char *line)
Definition: rtmap.c:284
static char * get_name(char *line)
Definition: rtmap.c:275
static const char * newline
Definition: display.c:72
const char * hpcrun_get_cmd(int dbglvl)
Definition: rtmap.c:160
rtloadmap_t * hpcrun_get_rtloadmap(int dbglvl)
Definition: rtmap.c:118
static uint64_t hex2u64(char *s)
Definition: rtmap.c:305
static __thread u32 pid
static int iscodeline(char *line)
Definition: rtmap.c:232
unsigned int count
Definition: rtmap.h:81
static char * get_line_slot(void)
Definition: rtmap.c:210
static void finalizelines(void)
Definition: rtmap.c:244
static int slots_avail
Definition: rtmap.c:195
static rtloadmap_t rtloadmap
Definition: rtmap.c:81
static unsigned long hex2ul(char *s)
Definition: rtmap.c:297
static void dumplines(void)
Definition: rtmap.c:332
unsigned long length
Definition: rtmap.h:76
int main(int argc, char *argv[])
Definition: main.cpp:125
static char * get_end_addr(char *line)
Definition: rtmap.c:290
rtloadmod_desc_t * module
Definition: rtmap.h:82
void *MONITOR_EXT_WRAP_NAME() realloc(void *ptr, size_t bytes)
void *MONITOR_EXT_WRAP_NAME() malloc(size_t bytes)
static void dumprtloadmap(void)
Definition: rtmap.c:316
#define NULL
Definition: ElfHelper.cpp:85
static int slots_in_use
Definition: rtmap.c:196
string basename(const char *fName)
Definition: FileUtil.cpp:90
uint64_t offset
Definition: rtmap.h:75
static void reset_slots()
Definition: rtmap.c:198
#define bhl
Definition: rtmap.c:102
static char * last
Definition: tokenize.c:65
#define MAXLINELEN
Definition: rtmap.c:104
char * name
Definition: rtmap.h:74