Powerpc fix for gdb.base/ending-run.exp
[binutils-gdb.git] / gprofng / libcollector / mmaptrace.c
1 /* Copyright (C) 2021 Free Software Foundation, Inc.
2 Contributed by Oracle.
3
4 This file is part of GNU Binutils.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
20
21 /*
22 * memory map tracking
23 * incorporating former "loadobjects" into more general "map"
24 * (including code and data segments and dynamic functions)
25 */
26
27 #include "config.h"
28 #include <alloca.h>
29 #include <dlfcn.h>
30 #include <errno.h>
31 #include <fcntl.h>
32 #include <elf.h>
33 #include <sys/mman.h>
34 #include <sys/param.h>
35 #include <stdint.h>
36
37 #include "gp-defs.h"
38 #include "collector.h"
39 #include "gp-experiment.h"
40 #include "memmgr.h"
41
42 /*
43 * These are obsolete and unreliable.
44 * They are included here only for historical compatibility.
45 */
46 #define MA_SHARED 0x08 /* changes are shared by mapped object */
47 #define MA_ANON 0x40 /* anonymous memory (e.g. /dev/zero) */
48 #define MA_ISM 0x80 /* intimate shared mem (shared MMU resources) */
49 #define MA_BREAK 0x10 /* grown by brk(2) */
50 #define MA_STACK 0x20 /* grown automatically on stack faults */
51
52 typedef struct prmap_t
53 {
54 unsigned long pr_vaddr; /* virtual address of mapping */
55 unsigned long pr_size; /* size of mapping in bytes */
56 char *pr_mapname; /* name in /proc/<pid>/object */
57 int pr_mflags; /* protection and attribute flags (see below) */
58 unsigned long pr_offset; /* offset into mapped object, if any */
59 unsigned long pr_dev;
60 unsigned long pr_ino;
61 int pr_pagesize; /* pagesize (bytes) for this mapping */
62 } prmap_t;
63
64 /* TprintfT(<level>,...) definitions. Adjust per module as needed */
65 #define DBG_LT0 0 // for high-level configuration, unexpected errors/warnings
66 #define DBG_LT1 1 // for configuration details, warnings
67 #define DBG_LT2 2
68 #define DBG_LT3 3
69 #define DBG_LT4 4
70
71 #define SYS_MMAP_NAME "mmap"
72 #define SYS_MMAP64_NAME "mmap64"
73 #define SYS_MUNMAP_NAME "munmap"
74 #define SYS_DLOPEN_NAME "dlopen"
75 #define SYS_DLCLOSE_NAME "dlclose"
76
77 typedef struct MapInfo
78 {
79 struct MapInfo *next;
80 unsigned long vaddr;
81 unsigned long size;
82 char *mapname; /* name in /proc/<pid>/object */
83 char *filename;
84 unsigned long offset;
85 int mflags;
86 int pagesize;
87 } MapInfo;
88
89 typedef struct NameInfo
90 {
91 struct NameInfo *next;
92 char *mapname;
93 char filename[1]; /* dynamic length file name */
94 } NameInfo;
95
96 static NameInfo *namemaps = NULL;
97 static MapInfo mmaps; /* current memory maps */
98 static struct DataHandle *map_hndl = NULL;
99 static char dyntext_fname[MAXPATHLEN];
100 static void *mapcache = NULL;
101 static char *maptext = NULL;
102 static size_t maptext_sz = 4096; /* initial buffer size */
103 static int mmap_mode = 0;
104 static int mmap_initted = 0;
105 static collector_mutex_t map_lock = COLLECTOR_MUTEX_INITIALIZER;
106 static collector_mutex_t dyntext_lock = COLLECTOR_MUTEX_INITIALIZER;
107
108 /* a reentrance guard for the interposition functions ensures that updates to
109 the map cache/file are sequential, with the first doing the final update */
110 static int reentrance = 0;
111 #define CHCK_REENTRANCE (reentrance || mmap_mode <= 0)
112 #define CURR_REENTRANCE reentrance
113 #define PUSH_REENTRANCE reentrance++
114 #define POP_REENTRANCE reentrance--
115
116 #define CALL_REAL(x) (__real_##x)
117 #define NULL_PTR(x) (__real_##x == NULL)
118
119 /* interposition function handles */
120 static void *(*__real_mmap)(void* start, size_t length, int prot, int flags,
121 int fd, off_t offset) = NULL;
122 static void *(*__real_mmap64)(void* start, size_t length, int prot, int flags,
123 int fd, off64_t offset) = NULL;
124 static int (*__real_munmap)(void* start, size_t length) = NULL;
125 static void *(*__real_dlopen)(const char* pathname, int mode) = NULL;
126 #if (ARCH(Intel) && WSIZE(32)) || ARCH(SPARC)
127 static void *(*__real_dlopen_2_1)(const char* pathname, int mode) = NULL;
128 static void *(*__real_dlopen_2_0)(const char* pathname, int mode) = NULL;
129 #endif
130 static int (*__real_dlclose)(void* handle) = NULL;
131 static void (*collector_heap_record)(int, size_t, void*) = NULL;
132
133 /* internal function prototypes */
134 static int init_mmap_intf ();
135 static int init_mmap_files ();
136 static void append_segment_record (char *format, ...);
137 static void update_map_segments (hrtime_t hrt, int resolve);
138 static void resolve_mapname (MapInfo *map, char *name);
139 static void record_segment_map (hrtime_t timestamp, uint64_t loadaddr,
140 unsigned long msize, int pagesize, int modeflags,
141 long long offset, unsigned check, char *name);
142 static void record_segment_unmap (hrtime_t timestamp, uint64_t loadaddr);
143
144 /* Linux needs handling of the vsyscall page to get its data into the map.xml file */
145 static void process_vsyscall_page ();
146
147 #define MAXVSYSFUNCS 10
148 static int nvsysfuncs = 0;
149 static char *sysfuncname[MAXVSYSFUNCS];
150 static uint64_t sysfuncvaddr[MAXVSYSFUNCS];
151 static unsigned long sysfuncsize[MAXVSYSFUNCS];
152
153 #define MAXDYN 20
154 static int ndyn = 0;
155 static char *dynname [MAXDYN];
156 static void *dynvaddr [MAXDYN];
157 static unsigned dynsize [MAXDYN];
158 static char *dynfuncname[MAXDYN];
159
160 /*===================================================================*/
161
162 /*
163 * void __collector_mmap_init_mutex_locks()
164 * Iinitialize mmap mutex locks.
165 */
166 void
167 __collector_mmap_init_mutex_locks ()
168 {
169 __collector_mutex_init (&map_lock);
170 __collector_mutex_init (&dyntext_lock);
171 }
172
173 /* __collector_ext_update_map_segments called by the audit agent
174 * Is is also called by dbx/collector when a (possible) map update
175 * is intimated, such as after dlopen/dlclose.
176 * Required when libcollector.so is not preloaded and interpositions inactive.
177 */
178 int
179 __collector_ext_update_map_segments (void)
180 {
181 if (!mmap_initted)
182 return 0;
183 TprintfT (0, "__collector_ext_update_map_segments(%d)\n", CURR_REENTRANCE);
184 if (CHCK_REENTRANCE)
185 return 0;
186 PUSH_REENTRANCE;
187 update_map_segments (GETRELTIME (), 1);
188 POP_REENTRANCE;
189 return 0;
190 }
191 /*
192 * int __collector_ext_mmap_install()
193 * Install and initialise mmap tracing.
194 */
195 int
196 __collector_ext_mmap_install (int record)
197 {
198 TprintfT (0, "__collector_ext_mmap_install(mmap_mode=%d)\n", mmap_mode);
199 if (NULL_PTR (mmap))
200 {
201 if (init_mmap_intf ())
202 {
203 TprintfT (0, "ERROR: collector mmap tracing initialization failed.\n");
204 return COL_ERROR_EXPOPEN;
205 }
206 }
207 else
208 TprintfT (DBG_LT2, "collector mmap tracing: mmap pointer not null\n");
209
210 /* Initialize side door interface with the heap tracing module */
211 collector_heap_record = (void(*)(int, size_t, void*))dlsym (RTLD_DEFAULT, "__collector_heap_record");
212 if (record)
213 {
214 map_hndl = __collector_create_handle (SP_MAP_FILE);
215 if (map_hndl == NULL)
216 return COL_ERROR_MAPOPEN;
217 if (init_mmap_files ())
218 {
219 TprintfT (0, "ERROR: collector init_mmap_files() failed.\n");
220 return COL_ERROR_EXPOPEN;
221 }
222 }
223 mmaps.next = NULL;
224 mapcache = NULL;
225 PUSH_REENTRANCE;
226 update_map_segments (GETRELTIME (), 1); // initial map
227 POP_REENTRANCE;
228 mmap_mode = 1;
229 mmap_initted = 1;
230 process_vsyscall_page ();
231 return COL_ERROR_NONE;
232 }
233
234 /*
235 * int __collector_ext_mmap_deinstall()
236 * Optionally update final map and stop tracing mmap events.
237 */
238 int
239 __collector_ext_mmap_deinstall (int update)
240 {
241 if (!mmap_initted)
242 return COL_ERROR_NONE;
243 mmap_mode = 0;
244 if (update)
245 {
246 /* Final map */
247 PUSH_REENTRANCE;
248 update_map_segments (GETRELTIME (), 1);
249 POP_REENTRANCE;
250 }
251 TprintfT (0, "__collector_ext_mmap_deinstall(%d)\n", update);
252 if (map_hndl != NULL)
253 {
254 __collector_delete_handle (map_hndl);
255 map_hndl = NULL;
256 }
257 __collector_mutex_lock (&map_lock); // get lock before resetting
258
259 /* Free all memory maps */
260 MapInfo *mp;
261 for (mp = mmaps.next; mp;)
262 {
263 MapInfo *next = mp->next;
264 __collector_freeCSize (__collector_heap, mp, sizeof (*mp));
265 mp = next;
266 }
267 mmaps.next = NULL;
268
269 /* Free all name maps */
270 NameInfo *np;
271 for (np = namemaps; np;)
272 {
273 NameInfo *next = np->next;
274 __collector_freeCSize (__collector_heap, np, sizeof (*np) + __collector_strlen (np->filename));
275 np = next;
276 }
277 namemaps = NULL;
278 mapcache = __collector_reallocVSize (__collector_heap, mapcache, 0);
279 mmaps.next = NULL;
280 mapcache = NULL;
281 __collector_mutex_unlock (&map_lock);
282 TprintfT (0, "__collector_ext_mmap_deinstall done\n");
283 return 0;
284 }
285
286 /*
287 * void __collector_mmap_fork_child_cleanup()
288 * Perform all necessary cleanup steps in child process after fork().
289 */
290 void
291 __collector_mmap_fork_child_cleanup ()
292 {
293 /* Initialize all mmap "mutex" locks */
294 __collector_mmap_init_mutex_locks ();
295 if (!mmap_initted)
296 return;
297 mmap_mode = 0;
298 __collector_delete_handle (map_hndl);
299 __collector_mutex_lock (&map_lock); // get lock before resetting
300
301 /* Free all memory maps */
302 MapInfo *mp;
303 for (mp = mmaps.next; mp;)
304 {
305 MapInfo *next = mp->next;
306 __collector_freeCSize (__collector_heap, mp, sizeof (*mp));
307 mp = next;
308 }
309 mmaps.next = NULL;
310
311 /* Free all name maps */
312 NameInfo *np;
313 for (np = namemaps; np;)
314 {
315 NameInfo *next = np->next;
316 __collector_freeCSize (__collector_heap, np, sizeof (*np) + __collector_strlen (np->filename));
317 np = next;
318 }
319 namemaps = NULL;
320 mapcache = __collector_reallocVSize (__collector_heap, mapcache, 0);
321 mmap_initted = 0;
322 reentrance = 0;
323 __collector_mutex_unlock (&map_lock);
324 }
325
326 static int
327 init_mmap_files ()
328 {
329 TprintfT (DBG_LT2, "init_mmap_files\n");
330 /* also create the headerless dyntext file (if required) */
331 CALL_UTIL (snprintf)(dyntext_fname, sizeof (dyntext_fname), "%s/%s",
332 __collector_exp_dir_name, SP_DYNTEXT_FILE);
333 if (CALL_UTIL (access)(dyntext_fname, F_OK) != 0)
334 {
335 int fd = CALL_UTIL (open)(dyntext_fname, O_RDWR | O_CREAT | O_TRUNC,
336 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
337 if (fd == -1)
338 {
339 char errmsg[256];
340 TprintfT (0, "ERROR: init_mmap_files: open(%s) failed\n",
341 dyntext_fname);
342 __collector_log_write ("<event kind=\"%s\" id=\"%d\" ec=\"%d\">%s: %s</event>\n",
343 SP_JCMD_CERROR, COL_ERROR_DYNOPEN, errno,
344 dyntext_fname, errmsg);
345 return COL_ERROR_DYNOPEN;
346 }
347 else
348 CALL_UTIL (close)(fd);
349 }
350 return COL_ERROR_NONE;
351 }
352
353 static void
354 append_segment_record (char *format, ...)
355 {
356 char buf[1024];
357 char *bufptr = buf;
358 va_list va;
359 va_start (va, format);
360 int sz = __collector_xml_vsnprintf (bufptr, sizeof (buf), format, va);
361 va_end (va);
362
363 if (__collector_expstate != EXP_OPEN && __collector_expstate != EXP_PAUSED)
364 {
365 TprintfT (0, "append_segment_record: expt neither open nor paused (%d); "
366 "not writing to map.xml\n\t%s", __collector_expstate, buf);
367 return;
368 }
369 if (sz >= sizeof (buf))
370 {
371 /* Allocate a new buffer */
372 sz += 1; /* add the terminating null byte */
373 bufptr = (char*) alloca (sz);
374 va_start (va, format);
375 sz = __collector_xml_vsnprintf (bufptr, sz, format, va);
376 va_end (va);
377 }
378 int rc = __collector_write_string (map_hndl, bufptr, sz);
379 if (rc != 0)
380 (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\"></event>\n",
381 SP_JCMD_CERROR, COL_ERROR_MAPWRITE);
382 }
383
384 static void
385 record_segment_map (hrtime_t timestamp, uint64_t loadaddr, unsigned long msize,
386 int pagesize, int modeflags, long long offset,
387 unsigned check, char *name)
388 {
389
390 TprintfT (DBG_LT2, "record_segment_map(%s @ 0x%llx)\n", name, (long long) loadaddr);
391 append_segment_record ("<event kind=\"map\" object=\"segment\" tstamp=\"%u.%09u\" "
392 "vaddr=\"0x%016llX\" size=\"%lu\" pagesz=\"%d\" foffset=\"%c0x%08llX\" "
393 "modes=\"0x%03X\" chksum=\"0x%0X\" name=\"%s\"/>\n",
394 (unsigned) (timestamp / NANOSEC),
395 (unsigned) (timestamp % NANOSEC),
396 loadaddr, msize, pagesize,
397 offset < 0 ? '-' : '+', offset < 0 ? -offset : offset,
398 modeflags, check, name);
399 }
400
401 static void
402 record_segment_unmap (hrtime_t timestamp, uint64_t loadaddr)
403 {
404 TprintfT (DBG_LT2, "record_segment_unmap(@ 0x%llx)\n", (long long) loadaddr);
405 append_segment_record ("<event kind=\"unmap\" tstamp=\"%u.%09u\" vaddr=\"0x%016llX\"/>\n",
406 (unsigned) (timestamp / NANOSEC),
407 (unsigned) (timestamp % NANOSEC), loadaddr);
408 }
409
410 #if WSIZE(64)
411 #define ELF_EHDR Elf64_Ehdr
412 #define ELF_PHDR Elf64_Phdr
413 #define ELF_SHDR Elf64_Shdr
414 #define ELF_DYN Elf64_Dyn
415 #define ELF_AUX Elf64_auxv_t
416 #define ELF_SYM Elf64_Sym
417 #define ELF_ST_BIND ELF64_ST_BIND
418 #define ELF_ST_TYPE ELF64_ST_TYPE
419 #elif WSIZE(32)
420 #define ELF_EHDR Elf32_Ehdr
421 #define ELF_PHDR Elf32_Phdr
422 #define ELF_SHDR Elf32_Shdr
423 #define ELF_DYN Elf32_Dyn
424 #define ELF_AUX Elf32_auxv_t
425 #define ELF_SYM Elf32_Sym
426 #define ELF_ST_BIND ELF32_ST_BIND
427 #define ELF_ST_TYPE ELF32_ST_TYPE
428 #endif
429
430 static unsigned
431 checksum_mapname (MapInfo* map)
432 {
433 unsigned checksum = 0;
434 /* only checksum code segments */
435 if ((map->mflags & (PROT_EXEC | PROT_READ)) == 0 ||
436 (map->mflags & PROT_WRITE) != 0)
437 return 0;
438 checksum = (unsigned) - 1;
439 TprintfT (DBG_LT2, "checksum_mapname checksum = 0x%0X\n", checksum);
440 return checksum;
441 }
442
443
444 #if (ARCH(Intel) && WSIZE(32)) || ARCH(SPARC)
445 static void*
446 dlopen_searchpath_symver (void*(real_dlopen) (), void* caller_addr, const char* basename, int mode)
447 #else
448 static void*
449 dlopen_searchpath (void* caller_addr, const char* basename, int mode)
450 #endif
451 {
452 TprintfT (DBG_LT2, "dlopen_searchpath(%p, %s, %d)\n", caller_addr, basename, mode);
453 Dl_info dl_info;
454 if (dladdr (caller_addr, &dl_info) == 0)
455 {
456 TprintfT (0, "ERROR: dladdr(%p): %s\n", caller_addr, dlerror ());
457 return 0;
458 }
459 TprintfT (DBG_LT2, "dladdr(%p): %p fname=%s\n",
460 caller_addr, dl_info.dli_fbase, dl_info.dli_fname);
461 int noload = RTLD_BINDING_MASK | RTLD_NOLOAD; //XXXX why RTLD_BINDING_MASK?
462 #define WORKAROUND_RTLD_BUG 1
463 #ifdef WORKAROUND_RTLD_BUG
464 // A dynamic linker dlopen bug can result in corruption/closure of open streams
465 // XXXX workaround should be removed once linker patches are all available
466 #if WSIZE(64)
467 #define MAINBASE 0x400000
468 #elif WSIZE(32)
469 #define MAINBASE 0x08048000
470 #endif
471 const char* tmp_path =
472 (dl_info.dli_fbase == (void*) MAINBASE) ? NULL : dl_info.dli_fname;
473 void* caller_hndl = NULL;
474 #if ((ARCH(Intel) && WSIZE(32)) || ARCH(SPARC))
475 caller_hndl = (real_dlopen) (tmp_path, noload);
476 #else
477 caller_hndl = CALL_REAL (dlopen)(tmp_path, noload);
478 #endif
479
480 #else //XXXX workaround should be removed once linker patches are all available
481
482 void* caller_hndl = NULL;
483 #if (ARCH(Intel) && WSIZE(32) || ARCH(SPARC)
484 caller_hndl = (real_dlopen) (dl_info.dli_fname, noload);
485 #else
486 caller_hndl = CALL_REAL (dlopen)(dl_info.dli_fname, noload);
487 #endif
488
489 #endif //XXXX workaround should be removed once linker patches are all available
490
491 if (!caller_hndl)
492 {
493 TprintfT (0, "ERROR: dlopen(%s,NOLOAD): %s\n", dl_info.dli_fname, dlerror ());
494 return 0;
495 }
496 Dl_serinfo _info, *info = &_info;
497 Dl_serpath *path;
498
499 /* determine search path count and required buffer size */
500 dlinfo (caller_hndl, RTLD_DI_SERINFOSIZE, (void *) info);
501
502 /* allocate new buffer and initialize */
503 /*
504 CR# 7191331
505 There is a bug in Linux that causes the first call
506 to dlinfo() to return a small value for the dls_size.
507
508 The first call to dlinfo() determines the search path
509 count and the required buffer size. The second call to
510 dlinfo() tries to obtain the search path information.
511
512 However, the size of the buffer that is returned by
513 the first call to the dlinfo() is incorrect (too small).
514 The second call to dlinfo() uses the incorrect size to
515 allocate memory on the stack and internally uses the memcpy()
516 function to copy the search paths to the allocated memory space.
517 The length of the search path is much larger than the buffer
518 that is allocated on the stack. The memcpy() overwrites some
519 of the information that are saved on the stack, specifically,
520 it overwrites the "basename" parameter.
521
522 collect crashes right after the second call to dlinfo().
523
524 The search paths are used to locate the shared libraries.
525 dlinfo() creates the search paths based on the paths
526 that are assigned to LD_LIBRARY_PATH environment variable
527 and the standard library paths. The standard library paths
528 consists of the /lib and the /usr/lib paths. The
529 standard library paths are always included to the search
530 paths by dlinfo() even if the LD_LIBRARY_PATH environment
531 variable is not defined. Therefore, at the very least the
532 dls_cnt is assigned to 2 (/lib and /usr/lib) and dlinfo()
533 will never assign dls_cnt to zero. The dls_cnt is the count
534 of the potential paths for searching the shared libraries.
535
536 So we need to increase the buffer size before the second
537 call to dlinfo(). There are number of ways to increase
538 the buffer size. However, none of them can calculate the
539 buffer size precisely. Some users on the web have suggested
540 to multiply the MAXPATHLEN by dls_cnt for the buffer size.
541 The MAXPATHLEN is assigned to 1024 bytes. In my opinion
542 this is too much. So I have decided to multiply dls_size
543 by dls_cnt for the buffer size since the dls_size is much
544 smaller than 1024 bytes.
545
546 I have already confirmed with our user that the workaround
547 is working with his real application. Additionally,
548 the dlopen_searchpath() function is called only by the
549 libcorrector init() function when the experiment is started.
550 Therefore, allocating some extra bytes on the stack which
551 is local to this routine is harmless.
552 */
553
554 info = alloca (_info.dls_size * _info.dls_cnt);
555 info->dls_size = _info.dls_size;
556 info->dls_cnt = _info.dls_cnt;
557
558 /* obtain search path information */
559 dlinfo (caller_hndl, RTLD_DI_SERINFO, (void *) info);
560 path = &info->dls_serpath[0];
561
562 char pathname[MAXPATHLEN];
563 for (unsigned int cnt = 1; cnt <= info->dls_cnt; cnt++, path++)
564 {
565 __collector_strlcpy (pathname, path->dls_name, sizeof (pathname));
566 __collector_strlcat (pathname, "/", sizeof (pathname));
567 __collector_strlcat (pathname, basename, sizeof (pathname));
568 void* ret = NULL;
569 #if (ARCH(Intel) && WSIZE(32)) || ARCH(SPARC)
570 ret = (real_dlopen) (pathname, mode);
571 #else
572 ret = CALL_REAL (dlopen)(pathname, mode);
573 #endif
574 TprintfT (DBG_LT2, "try %d/%d: %s = %p\n", cnt, info->dls_cnt, pathname, ret);
575 if (ret)
576 return ret; // success!
577 }
578 return 0;
579 }
580
581 static void
582 resolve_mapname (MapInfo *map, char *name)
583 {
584 map->filename = "";
585 map->mapname = "";
586 if (name == NULL || *name == '\0')
587 {
588 if (map->mflags & MA_STACK)
589 map->filename = "<" SP_MAP_STACK ">";
590 else if (map->mflags & MA_BREAK)
591 map->filename = "<" SP_MAP_HEAP ">";
592 else if (map->mflags & MA_ISM)
593 map->filename = "<" SP_MAP_SHMEM ">";
594 return;
595 }
596 NameInfo *np;
597 for (np = namemaps; np; np = np->next)
598 if (__collector_strcmp (np->mapname, name) == 0)
599 break;
600
601 if (np == NULL)
602 {
603 const char *fname;
604 fname = name;
605 /* Create and link a new name map */
606 size_t fnamelen = __collector_strlen (fname) + 1;
607 np = (NameInfo*) __collector_allocCSize (__collector_heap, sizeof (NameInfo) + fnamelen, 1);
608 if (np == NULL) // We could not get memory
609 return;
610 np->mapname = np->filename;
611 __collector_strlcpy (np->filename, fname, fnamelen);
612 np->next = namemaps;
613 namemaps = np;
614 }
615 map->mapname = np->mapname;
616 map->filename = np->filename;
617 if (map->filename[0] == (char) 0)
618 map->filename = map->mapname;
619 TprintfT (DBG_LT2, "resolve_mapname: %s resolved to %s\n", map->mapname, map->filename);
620 }
621
622 static unsigned long
623 str2ulong (char **ss)
624 {
625 char *s = *ss;
626 unsigned long val = 0UL;
627 const int base = 16;
628 for (;;)
629 {
630 char c = *s++;
631 if (c >= '0' && c <= '9')
632 val = val * base + (c - '0');
633 else if (c >= 'a' && c <= 'f')
634 val = val * base + (c - 'a') + 10;
635 else if (c >= 'A' && c <= 'F')
636 val = val * base + (c - 'A') + 10;
637 else
638 break;
639 }
640 *ss = s - 1;
641 return val;
642 }
643
644 static void
645 update_map_segments (hrtime_t hrt, int resolve)
646 {
647 size_t filesz;
648 if (__collector_mutex_trylock (&map_lock))
649 {
650 TprintfT (0, "WARNING: update_map_segments(resolve=%d) BUSY\n", resolve);
651 return;
652 }
653 TprintfT (DBG_LT2, "\n");
654 TprintfT (DBG_LT2, "begin update_map_segments(hrt, %d)\n", resolve);
655
656 // Note: there is similar code to read /proc/$PID/map[s] in
657 // perfan/er_kernel/src/KSubExp.cc KSubExp::write_subexpt_map()
658 const char* proc_map = "/proc/self/maps";
659 size_t bufsz = maptext_sz;
660 int done = 0;
661 filesz = 0;
662 int map_fd = CALL_UTIL (open)(proc_map, O_RDONLY);
663 while (!done)
664 {
665 bufsz *= 2;
666 maptext = __collector_reallocVSize (__collector_heap, maptext, bufsz);
667 TprintfT (DBG_LT2, " update_map_segments: Loop for bufsize=%ld\n",
668 (long) bufsz);
669 for (;;)
670 {
671 int n = CALL_UTIL (read)(map_fd, maptext + filesz, bufsz - filesz);
672 TprintfT (DBG_LT2, " update_map_segments: __collector_read(bufp=%p nbyte=%ld)=%d\n",
673 maptext + filesz, (long) ( bufsz - filesz), n);
674 if (n < 0)
675 {
676 TprintfT (0, "ERROR: update_map_segments: read(maps): errno=%d\n", errno);
677 (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\" ec=\"%d\">%s</event>\n",
678 SP_JCMD_CERROR, COL_ERROR_MAPREAD, errno, proc_map);
679 CALL_UTIL (close)(map_fd);
680 __collector_mutex_unlock (&map_lock);
681 return;
682 }
683 else if (n == 0)
684 {
685 done = 1;
686 break;
687 }
688 filesz += n;
689 if (filesz >= bufsz) /* Buffer too small */
690 break;
691 }
692 }
693 CALL_UTIL (close)(map_fd);
694 maptext_sz = filesz;
695
696 int mapcache_entries = 0;
697 char *str, *str1;
698 for (str = maptext;; str = str1)
699 {
700 for (str1 = str; str1 - maptext < filesz; str1++)
701 {
702 if (*str1 == '\n')
703 {
704 *str1 = (char) 0;
705 break;
706 }
707 }
708 if (str1 - maptext >= filesz)
709 break;
710 str1++;
711 mapcache_entries++;
712 mapcache = __collector_reallocVSize (__collector_heap, mapcache,
713 sizeof (prmap_t) * mapcache_entries);
714 prmap_t *map = ((prmap_t *) mapcache) + (mapcache_entries - 1);
715 map->pr_vaddr = str2ulong (&str);
716 str++;
717 unsigned long eaddr = str2ulong (&str);
718 str++;
719 map->pr_size = eaddr - map->pr_vaddr;
720 map->pr_mflags = 0;
721 map->pr_mflags += (*str++ == 'r' ? PROT_READ : 0);
722 map->pr_mflags += (*str++ == 'w' ? PROT_WRITE : 0);
723 map->pr_mflags += (*str++ == 'x' ? PROT_EXEC : 0);
724 map->pr_mflags += (*str++ == 's' ? MA_SHARED : 0);
725 str++;
726 map->pr_offset = str2ulong (&str);
727 str++;
728 map->pr_dev = str2ulong (&str) * 0x100;
729 str++;
730 map->pr_dev += str2ulong (&str);
731 str++;
732 map->pr_ino = str2ulong (&str);
733 if (map->pr_dev == 0)
734 map->pr_mflags |= MA_ANON;
735 while (*str == ' ')
736 str++;
737 map->pr_mapname = str;
738 map->pr_pagesize = 4096;
739 }
740
741 /* Compare two maps and record all differences */
742 unsigned nidx = 0;
743 MapInfo *prev = &mmaps;
744 MapInfo *oldp = mmaps.next;
745 for (;;)
746 {
747 prmap_t *newp = nidx < mapcache_entries ?
748 (prmap_t*) mapcache + nidx : NULL;
749 if (oldp == NULL && newp == NULL)
750 break;
751
752 /* If two maps are equal proceed to the next pair */
753 if (oldp && newp &&
754 oldp->vaddr == newp->pr_vaddr &&
755 oldp->size == newp->pr_size &&
756 __collector_strcmp (oldp->mapname, newp->pr_mapname) == 0)
757 {
758 prev = oldp;
759 oldp = oldp->next;
760 nidx++;
761 continue;
762 }
763 /* Check if we need to unload the old map first */
764 if (newp == NULL || (oldp && oldp->vaddr <= newp->pr_vaddr))
765 {
766 if (oldp != NULL)
767 {
768 /* Don't record MA_ANON maps except MA_STACK and MA_BREAK */
769 if ((!(oldp->mflags & MA_ANON) || (oldp->mflags & (MA_STACK | MA_BREAK))))
770 record_segment_unmap (hrt, oldp->vaddr);
771 /* Remove and free map */
772 prev->next = oldp->next;
773 MapInfo *tmp = oldp;
774 oldp = oldp->next;
775 __collector_freeCSize (__collector_heap, tmp, sizeof (*tmp));
776 }
777 }
778 else
779 {
780 MapInfo *map = (MapInfo*) __collector_allocCSize (__collector_heap, sizeof (MapInfo), 1);
781 if (map == NULL)
782 {
783 __collector_mutex_unlock (&map_lock);
784 return;
785 }
786 map->vaddr = newp->pr_vaddr;
787 map->size = newp->pr_size;
788 map->offset = newp->pr_offset;
789 map->mflags = newp->pr_mflags;
790 map->pagesize = newp->pr_pagesize;
791 resolve_mapname (map, newp->pr_mapname);
792
793 /* Insert new map */
794 map->next = prev->next;
795 prev->next = map;
796 prev = map;
797
798 /* Don't record MA_ANON maps except MA_STACK and MA_BREAK */
799 if (!(newp->pr_mflags & MA_ANON) || (newp->pr_mflags & (MA_STACK | MA_BREAK)))
800 {
801 unsigned checksum = checksum_mapname (map);
802 record_segment_map (hrt, map->vaddr, map->size,
803 map->pagesize, map->mflags,
804 map->offset, checksum, map->filename);
805 }
806 nidx++;
807 }
808 }
809 TprintfT (DBG_LT2, "update_map_segments: done\n\n");
810 __collector_mutex_unlock (&map_lock);
811 } /* update_map_segments */
812
813 /*
814 * Map addr to a segment. Cope with split segments.
815 */
816 int
817 __collector_check_segment_internal (unsigned long addr, unsigned long *base,
818 unsigned long *end, int maxnretries, int MA_FLAGS)
819 {
820 int number_of_tries = 0;
821 retry:
822 ;
823
824 unsigned long curbase = 0;
825 unsigned long curfoff = 0;
826 unsigned long cursize = 0;
827
828 MapInfo *mp;
829 for (mp = mmaps.next; mp; mp = mp->next)
830 {
831
832 if (curbase + cursize == mp->vaddr &&
833 curfoff + cursize == mp->offset &&
834 ((mp->mflags & MA_FLAGS) == MA_FLAGS
835 || __collector_strncmp (mp->mapname, "[vdso]", 6) == 0
836 || __collector_strncmp (mp->mapname, "[vsyscall]", 10) == 0
837 ))
838 cursize = mp->vaddr + mp->size - curbase;
839 else if (addr < mp->vaddr)
840 break;
841 else if ((mp->mflags & MA_FLAGS) != MA_FLAGS
842 && __collector_strncmp (mp->mapname, "[vdso]", 6)
843 && __collector_strncmp (mp->mapname, "[vsyscall]", 10))
844 {
845 curbase = 0;
846 curfoff = 0;
847 cursize = 0;
848 }
849 else
850 {
851 curbase = mp->vaddr;
852 curfoff = mp->offset;
853 cursize = mp->size;
854 }
855 }
856
857 if (addr >= curbase && addr < curbase + cursize)
858 {
859 *base = curbase;
860 *end = curbase + cursize;
861 return 1;
862 }
863
864 /*
865 * 21275311 Unwind failure in native stack for java application running on jdk8 on x86
866 *
867 * On JDK8, we've observed cases where Java-compiled methods end up
868 * in virtual address segments that were "dead zones" (mflags&PROT_READ==0) at
869 * the time of the last update_map_segments() but are now "live". So if we
870 * fail to find a segment, let's call update_map_segments and then retry
871 * before giving up.
872 */
873 if (number_of_tries < maxnretries)
874 {
875 number_of_tries++;
876 __collector_ext_update_map_segments ();
877 goto retry;
878 }
879 *base = 0;
880 *end = 0;
881 return 0;
882 }
883
884 /**
885 * Check if address belongs to a readable and executable segment
886 * @param addr
887 * @param base
888 * @param end
889 * @param maxnretries
890 * @return 1 - yes, 0 - no
891 */
892 int
893 __collector_check_segment (unsigned long addr, unsigned long *base,
894 unsigned long *end, int maxnretries)
895 {
896 int MA_FLAGS = PROT_READ | PROT_EXEC;
897 int res = __collector_check_segment_internal (addr, base, end, maxnretries, MA_FLAGS);
898 return res;
899 }
900
901 /**
902 * Check if address belongs to a readable segment
903 * @param addr
904 * @param base
905 * @param end
906 * @param maxnretries
907 * @return 1 - yes, 0 - no
908 */
909 int
910 __collector_check_readable_segment( unsigned long addr, unsigned long *base, unsigned long *end, int maxnretries )
911 {
912 int MA_FLAGS = PROT_READ;
913 int res = __collector_check_segment_internal(addr, base, end, maxnretries, MA_FLAGS);
914 return res;
915 }
916
917 static ELF_AUX *auxv = NULL;
918
919 static void
920 process_vsyscall_page ()
921 {
922 TprintfT (DBG_LT2, "process_vsyscall_page()\n");
923 if (ndyn != 0)
924 {
925 /* We've done this one in this process, and cached the results */
926 /* use the cached results */
927 for (int i = 0; i < ndyn; i++)
928 {
929 append_segment_record ("<event kind=\"map\" object=\"dynfunc\" name=\"%s\" "
930 "vaddr=\"0x%016lX\" size=\"%u\" funcname=\"%s\" />\n",
931 dynname[i], dynvaddr[i], dynsize[i], dynfuncname[i]);
932 TprintfT (DBG_LT2, "process_vsyscall_page: append_segment_record map dynfunc='%s' vaddr=0x%016lX size=%ld funcname='%s' -- from cache\n",
933 dynname[i], (unsigned long) dynvaddr[i],
934 (long) dynsize[i], dynfuncname[i]);
935 }
936 }
937 if (nvsysfuncs != 0)
938 {
939 /* We've done this one in this process, and cached the results */
940 /* use the cached results */
941 hrtime_t hrt = GETRELTIME ();
942 for (int i = 0; i < nvsysfuncs; i++)
943 {
944 append_segment_record ("<event kind=\"map\" object=\"function\" tstamp=\"%u.%09u\" "
945 "vaddr=\"0x%016lX\" size=\"%u\" name=\"%s\" />\n",
946 (unsigned) (hrt / NANOSEC), (unsigned) (hrt % NANOSEC),
947 (unsigned long) sysfuncvaddr[i], (unsigned) sysfuncsize[i], sysfuncname[i]);
948 TprintfT (DBG_LT2, "process_vsyscall_page: append_segment_record map function='%s' vaddr=0x%016lX size=%ld -- from cache\n",
949 sysfuncname[i], (unsigned long) sysfuncvaddr[i], (long) sysfuncsize[i]);
950 }
951 }
952 if (ndyn + nvsysfuncs != 0)
953 return;
954
955 /* After fork we can't rely on environ as it might have
956 * been moved by putenv(). Use the pointer saved by the parent.
957 */
958 if (auxv == NULL)
959 {
960 char **envp = (char**) environ;
961 if (envp == NULL)
962 return;
963 while (*envp++ != NULL);
964 auxv = (ELF_AUX*) envp;
965 }
966 TprintfT (DBG_LT2, "process_vsyscall_page, auxv = ox%p\n", auxv);
967
968 ELF_AUX *ap;
969 #ifdef DEBUG
970 for (ap = auxv; ap->a_type != AT_NULL; ap++)
971 TprintfT (DBG_LT2, "process_vsyscall_page: ELF_AUX: "
972 " a_type = 0x%016llx %10lld "
973 " a_un.a_val = 0x%016llx %10lld\n",
974 (long long) ap->a_type, (long long) ap->a_type,
975 (long long) ap->a_un.a_val, (long long) ap->a_un.a_val);
976 #endif
977
978 // find the first ELF_AUX of type AT_SYSINFO_EHDR
979 ELF_EHDR *ehdr = NULL;
980 for (ap = auxv; ap->a_type != AT_NULL; ap++)
981 {
982 if (ap->a_type == AT_SYSINFO_EHDR)
983 {
984 // newer Linuxes do not have a_ptr field, they just have a_val
985 ehdr = (ELF_EHDR*) ap->a_un.a_val;
986 if (ehdr != NULL)
987 break;
988 }
989 }
990
991 // If one is found
992 if (ehdr != NULL)
993 {
994 char *mapName = "SYSINFO_EHDR";
995 MapInfo *mp;
996 for (mp = mmaps.next; mp; mp = mp->next)
997 {
998 if ((unsigned long) ehdr == mp->vaddr)
999 {
1000 mp->mflags |= PROT_EXEC;
1001 if (mp->mapname && mp->mapname[0])
1002 mapName = mp->mapname;
1003 break;
1004 }
1005 }
1006
1007 // Find the dynsym section and record all symbols
1008 char *base = (char*) ehdr;
1009 ELF_SHDR *shdr = (ELF_SHDR*) (base + ehdr->e_shoff);
1010 int i;
1011
1012 #if 0
1013 TprintfT (DBG_LT2, "process_vsyscall_page: ehdr: EI_CLASS=%lld EI_DATA=%lld EI_OSABI=%lld e_type=%lld e_machine=%lld e_version=%lld\n"
1014 " e_entry =0x%016llx %10lld e_phoff =0x%016llx %10lld\n"
1015 " e_shoff =0x%016llx %10lld e_flags =0x%016llx %10lld\n"
1016 " e_ehsize =0x%016llx %10lld e_phentsize =0x%016llx %10lld\n"
1017 " e_phnum =0x%016llx %10lld e_shentsize =0x%016llx %10lld\n"
1018 " e_shnum =0x%016llx %10lld e_shstrndx =0x%016llx %10lld\n",
1019 (long long) ehdr->e_ident[EI_CLASS], (long long) ehdr->e_ident[EI_DATA], (long long) ehdr->e_ident[EI_OSABI],
1020 (long long) ehdr->e_type, (long long) ehdr->e_machine, (long long) ehdr->e_version,
1021 (long long) ehdr->e_entry, (long long) ehdr->e_entry,
1022 (long long) ehdr->e_phoff, (long long) ehdr->e_phoff,
1023 (long long) ehdr->e_shoff, (long long) ehdr->e_shoff,
1024 (long long) ehdr->e_flags, (long long) ehdr->e_flags,
1025 (long long) ehdr->e_ehsize, (long long) ehdr->e_ehsize,
1026 (long long) ehdr->e_phentsize, (long long) ehdr->e_phentsize,
1027 (long long) ehdr->e_phnum, (long long) ehdr->e_phnum,
1028 (long long) ehdr->e_shentsize, (long long) ehdr->e_shentsize,
1029 (long long) ehdr->e_shnum, (long long) ehdr->e_shnum,
1030 (long long) ehdr->e_shstrndx, (long long) ehdr->e_shstrndx);
1031 for (i = 1; i < ehdr->e_shnum; i++)
1032 {
1033 TprintfT (DBG_LT2, "process_vsyscall_page: SECTION=%d sh_name=%lld '%s'\n"
1034 " sh_type =0x%016llx %10lld\n"
1035 " sh_flags =0x%016llx %10lld\n"
1036 " sh_addr =0x%016llx %10lld\n"
1037 " sh_offset =0x%016llx %10lld\n"
1038 " sh_size =0x%016llx %10lld\n"
1039 " sh_link =0x%016llx %10lld\n"
1040 " sh_info =0x%016llx %10lld\n"
1041 " sh_addralign =0x%016llx %10lld\n"
1042 " sh_entsize =0x%016llx %10lld\n",
1043 i, (long long) shdr[i].sh_name, base + shdr[ehdr->e_shstrndx].sh_offset + shdr[i].sh_name,
1044 (long long) shdr[i].sh_type, (long long) shdr[i].sh_type,
1045 (long long) shdr[i].sh_flags, (long long) shdr[i].sh_flags,
1046 (long long) shdr[i].sh_addr, (long long) shdr[i].sh_addr,
1047 (long long) shdr[i].sh_offset, (long long) shdr[i].sh_offset,
1048 (long long) shdr[i].sh_size, (long long) shdr[i].sh_size,
1049 (long long) shdr[i].sh_link, (long long) shdr[i].sh_link,
1050 (long long) shdr[i].sh_info, (long long) shdr[i].sh_info,
1051 (long long) shdr[i].sh_addralign, (long long) shdr[i].sh_addralign,
1052 (long long) shdr[i].sh_entsize, (long long) shdr[i].sh_entsize);
1053 }
1054 #endif
1055
1056 int dynSec = -1;
1057 for (i = 1; i < ehdr->e_shnum; i++)
1058 if (shdr[i].sh_type == SHT_DYNSYM)
1059 {
1060 dynSec = i;
1061 break;
1062 }
1063 if (dynSec != -1)
1064 {
1065 char *symbase = base + shdr[shdr[dynSec].sh_link].sh_offset;
1066 ELF_SYM *symbols = (ELF_SYM*) (base + shdr[dynSec].sh_offset);
1067 int nextSec = 0;
1068 int n = shdr[dynSec].sh_size / shdr[dynSec].sh_entsize;
1069 for (i = 0; i < n; i++)
1070 {
1071 ELF_SYM *sym = symbols + i;
1072 TprintfT (DBG_LT2, "process_vsyscall_page: symbol=%d st_name=%lld '%s'\n"
1073 " st_size = 0x%016llx %10lld\n"
1074 " st_value = 0x%016llx %10lld\n"
1075 " st_shndx = 0x%016llx %10lld\n"
1076 " st_info = 0x%016llx %10lld\n",
1077 i, (long long) sym->st_name, symbase + sym->st_name,
1078 (long long) sym->st_size, (long long) sym->st_size,
1079 (long long) sym->st_value, (long long) sym->st_value,
1080 (long long) sym->st_shndx, (long long) sym->st_shndx,
1081 (long long) sym->st_info, (long long) sym->st_info);
1082 if (sym->st_shndx <= 0 || sym->st_size <= 0 ||
1083 ELF_ST_BIND (sym->st_info) != STB_GLOBAL || ELF_ST_TYPE (sym->st_info) != STT_FUNC)
1084 continue;
1085 if (nextSec == 0)
1086 nextSec = sym->st_shndx;
1087 else if (nextSec > sym->st_shndx)
1088 nextSec = sym->st_shndx;
1089 }
1090 if (nextSec == 0)
1091 ehdr = NULL;
1092
1093 while (nextSec != 0)
1094 {
1095 int curSec = nextSec;
1096 char *bgn = base + shdr[curSec].sh_offset;
1097 char *end = bgn + shdr[curSec].sh_size;
1098 for (i = 0; i < n; i++)
1099 {
1100 ELF_SYM *sym = symbols + i;
1101 if (sym->st_shndx <= 0 || sym->st_size <= 0 ||
1102 ELF_ST_BIND (sym->st_info) != STB_GLOBAL || ELF_ST_TYPE (sym->st_info) != STT_FUNC)
1103 continue;
1104 if (sym->st_shndx > curSec)
1105 {
1106 if (nextSec == curSec)
1107 nextSec = sym->st_shndx;
1108 else if (nextSec > sym->st_shndx)
1109 nextSec = sym->st_shndx;
1110 nextSec = sym->st_shndx;
1111 continue;
1112 }
1113 if (sym->st_shndx != curSec)
1114 continue;
1115 long long st_delta = (sym->st_value >= shdr[sym->st_shndx].sh_addr) ?
1116 (sym->st_value - shdr[sym->st_shndx].sh_addr) : -1;
1117 char *st_value = bgn + st_delta;
1118 if (st_delta >= 0 && st_value + sym->st_size <= end)
1119 {
1120 append_segment_record ("<event kind=\"map\" object=\"dynfunc\" name=\"%s\" "
1121 "vaddr=\"0x%016lX\" size=\"%u\" funcname=\"%s\" />\n",
1122 mapName, (void*) st_value, sym->st_size, symbase + sym->st_name);
1123
1124 TprintfT (DBG_LT2, "process_vsyscall_page: append_segment_record map dynfunc='%s' vaddr=%016lX size=%ld funcname='%s'\n",
1125 mapName, (unsigned long) st_value,
1126 (long) sym->st_size, symbase + sym->st_name);
1127
1128 /* now cache this for a subsequent experiment */
1129 if (ndyn >= MAXDYN)
1130 __collector_log_write ("<event kind=\"%s\" id=\"%d\">MAXDYN=%d</event>\n",
1131 SP_JCMD_CERROR, COL_ERROR_MAPCACHE, MAXDYN);
1132 else
1133 {
1134 dynname [ndyn] = CALL_UTIL (libc_strdup)(mapName);
1135 dynvaddr [ndyn] = (void *) st_value;
1136 dynsize [ndyn] = (unsigned) sym->st_size;
1137 dynfuncname[ndyn] = CALL_UTIL (libc_strdup)(symbase + sym->st_name);
1138 TprintfT (DBG_LT2, "process_vsyscall_page: cached entry %d map function='%s' vaddr=0x%016lX size=%ld '%s'\n",
1139 ndyn, dynname[ndyn], (unsigned long) dynvaddr[ndyn],
1140 (long) dynsize[ndyn], dynfuncname[ndyn]);
1141 ndyn++;
1142 }
1143 }
1144 }
1145 __collector_int_func_load (DFUNC_KERNEL, mapName, NULL,
1146 (void*) (base + shdr[curSec].sh_offset), shdr[curSec].sh_size, 0, NULL);
1147
1148 /* now cache this function for a subsequent experiment */
1149 if (nvsysfuncs >= MAXVSYSFUNCS)
1150 __collector_log_write ("<event kind=\"%s\" id=\"%d\">MAXVSYSFUNCS=%d</event>\n",
1151 SP_JCMD_CERROR, COL_ERROR_MAPCACHE, MAXVSYSFUNCS);
1152 else
1153 {
1154 sysfuncname[nvsysfuncs] = CALL_UTIL (libc_strdup)(mapName);
1155 sysfuncvaddr[nvsysfuncs] = (unsigned long) (base + shdr[curSec].sh_offset);
1156 sysfuncsize[nvsysfuncs] = (unsigned long) (shdr[curSec].sh_size);
1157 TprintfT (DBG_LT2, "process_vsyscall_page: cached entry %d map function='%s' vaddr=0x%016lX size=%ld\n",
1158 nvsysfuncs, sysfuncname[nvsysfuncs],
1159 (unsigned long) sysfuncvaddr[nvsysfuncs],
1160 (long) sysfuncsize[nvsysfuncs]);
1161 nvsysfuncs++;
1162 }
1163 TprintfT (DBG_LT2, "process_vsyscall_page: collector_int_func_load='%s' vaddr=0x%016lX size=%ld\n",
1164 mapName, (unsigned long) (base + shdr[curSec].sh_offset),
1165 (long) shdr[curSec].sh_size);
1166 if (curSec == nextSec)
1167 break;
1168 }
1169 }
1170 }
1171
1172 #if WSIZE(32)
1173 unsigned long vsysaddr = (unsigned long) 0xffffe000;
1174 #elif WSIZE(64)
1175 unsigned long vsysaddr = (unsigned long) 0xffffffffff600000;
1176 #endif
1177 // Make sure the vsyscall map has PROT_EXEC
1178 MapInfo *mp;
1179 for (mp = mmaps.next; mp; mp = mp->next)
1180 {
1181 TprintfT (DBG_LT2, "MapInfo: vaddr=0x%016llx [size=%lld] mflags=0x%llx offset=%lld pagesize=%lld\n"
1182 " mapname='%s' filename='%s'\n",
1183 (unsigned long long) mp->vaddr, (long long) mp->size,
1184 (long long) mp->mflags, (long long) mp->offset, (long long) mp->pagesize,
1185 mp->mapname ? mp->mapname : "NULL",
1186 mp->filename ? mp->filename : "NULL");
1187 if (vsysaddr == mp->vaddr)
1188 mp->mflags |= PROT_EXEC;
1189 if ((unsigned long) ehdr == (unsigned long) mp->vaddr)
1190 continue;
1191 if (__collector_strncmp (mp->mapname, "[vdso]", 6) == 0
1192 || __collector_strncmp (mp->mapname, "[vsyscall]", 10) == 0)
1193 {
1194 /*
1195 * On rubbia ( 2.6.9-5.ELsmp #1 SMP 32-bit ) access to ehdr causes SEGV.
1196 * There doesn't seem to be a way to reliably determine the actual presence
1197 * of the page: even when /proc reports it's there it can't be accessed.
1198 * We will have to put up with <Unknown> on some Linuxes until this is resolved.
1199 __collector_int_func_load(DFUNC_KERNEL, mp->mapname, NULL, (void*) mp->vaddr, mp->size, 0, NULL);
1200 */
1201 hrtime_t hrt = GETRELTIME ();
1202 append_segment_record (
1203 "<event kind=\"map\" object=\"function\" tstamp=\"%u.%09u\" "
1204 "vaddr=\"0x%016lX\" size=\"%u\" name=\"%s\" />\n",
1205 (unsigned) (hrt / NANOSEC), (unsigned) (hrt % NANOSEC),
1206 (unsigned long) mp->vaddr, (unsigned) mp->size, mp->mapname);
1207 TprintfT (DBG_LT2, "process_vsyscall_page: append_segment_record map function = %s, vaddr = 0x%016lX, size = %u\n",
1208 mp->mapname, (unsigned long) mp->vaddr, (unsigned) mp->size);
1209
1210 /* now cache this function for a subsequent experiment */
1211 if (nvsysfuncs >= MAXVSYSFUNCS)
1212 __collector_log_write ("<event kind=\"%s\" id=\"%d\">MAXVSYSFUNCS=%d</event>\n",
1213 SP_JCMD_CERROR, COL_ERROR_MAPCACHE, MAXVSYSFUNCS);
1214 else
1215 {
1216 sysfuncname[nvsysfuncs] = CALL_UTIL (libc_strdup)(mp->mapname);
1217 sysfuncvaddr[nvsysfuncs] = mp->vaddr;
1218 sysfuncsize[nvsysfuncs] = (unsigned long) mp->size;
1219 TprintfT (DBG_LT2, "process_vsyscall_page: cached entry %d map function='%s' vaddr=0x%016lX size=%ld\n",
1220 nvsysfuncs, sysfuncname[nvsysfuncs],
1221 (unsigned long) sysfuncvaddr[nvsysfuncs],
1222 (long) sysfuncsize[nvsysfuncs]);
1223 nvsysfuncs++;
1224
1225 }
1226 }
1227 }
1228 }
1229
1230 /*
1231 * collector API for dynamic functions
1232 */
1233 void collector_func_load () __attribute__ ((weak, alias ("__collector_func_load")));
1234 void
1235 __collector_func_load (char *name, char *alias, char *sourcename,
1236 void *vaddr, int size, int lntsize, DT_lineno *lntable)
1237 {
1238 __collector_int_func_load (DFUNC_API, name, sourcename,
1239 vaddr, size, lntsize, lntable);
1240 }
1241
1242 void collector_func_unload () __attribute__ ((weak, alias ("__collector_func_unload")));
1243 void
1244 __collector_func_unload (void *vaddr)
1245 {
1246 __collector_int_func_unload (DFUNC_API, vaddr);
1247 }
1248
1249 /* routines for handling dynamic functions */
1250 static void
1251 rwrite (int fd, void *buf, size_t nbyte)
1252 {
1253 size_t left = nbyte;
1254 size_t res;
1255 char *ptr = (char*) buf;
1256 while (left > 0)
1257 {
1258 res = CALL_UTIL (write)(fd, ptr, left);
1259 if (res == -1)
1260 {
1261 TprintfT (0, "ERROR: rwrite(%s) failed: errno=%d\n", dyntext_fname, errno);
1262 (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\" ec=\"%d\">%s</event>\n",
1263 SP_JCMD_CERROR, COL_ERROR_DYNWRITE, errno, dyntext_fname);
1264 return;
1265 }
1266 left -= res;
1267 ptr += res;
1268 }
1269 }
1270
1271 void
1272 __collector_int_func_load (dfunc_mode_t mode, char *name, char *sourcename,
1273 void *vaddr, int size, int lntsize, DT_lineno *lntable)
1274 {
1275 char name_buf[32];
1276 int slen;
1277 static char pad[16];
1278 int padn;
1279 if (!mmap_initted)
1280 return;
1281 hrtime_t hrt = GETRELTIME ();
1282
1283 if (name == NULL)
1284 {
1285 /* generate a name based on vaddr */
1286 CALL_UTIL (snprintf)(name_buf, sizeof (name_buf), "0x%lx", (unsigned long) vaddr);
1287 name = name_buf;
1288 }
1289
1290 switch (mode)
1291 {
1292 case DFUNC_API:
1293 case DFUNC_KERNEL:
1294 append_segment_record ("<event kind=\"map\" object=\"function\" tstamp=\"%u.%09u\" "
1295 "vaddr=\"0x%016lX\" size=\"%u\" name=\"%s\" />\n",
1296 (unsigned) (hrt / NANOSEC), (unsigned) (hrt % NANOSEC),
1297 (unsigned long) vaddr, (unsigned) size, name);
1298 break;
1299 case DFUNC_JAVA:
1300 append_segment_record ("<event kind=\"map\" object=\"jcm\" tstamp=\"%u.%09u\" "
1301 "vaddr=\"0x%016lX\" size=\"%u\" methodId=\"%s\" />\n",
1302 (unsigned) (hrt / NANOSEC), (unsigned) (hrt % NANOSEC),
1303 (unsigned long) vaddr, (unsigned) size, name);
1304 break;
1305 default:
1306 return;
1307 }
1308
1309 /* 21275311 Unwind failure in native stack for java application running on jdk8 on x86
1310 * Check:
1311 * - function starts in a known segment (base1 != 0)
1312 * - function ends in the same segment (base1==base2 && end1==end2)
1313 * If not, then call update_map_segments().
1314 */
1315 unsigned long base1, end1, base2, end2;
1316 __collector_check_segment ((unsigned long) vaddr, &base1, &end1, 0);
1317 if (base1)
1318 __collector_check_segment (((unsigned long) vaddr)+((unsigned long) size), &base2, &end2, 0);
1319 if (base1 == 0 || base1 != base2 || end1 != end2)
1320 __collector_ext_update_map_segments ();
1321
1322 /* Write a copy of actual code to the "dyntext" file */
1323 DT_header dt_hdr;
1324 dt_hdr.type = DT_HEADER;
1325 dt_hdr.size = sizeof (dt_hdr);
1326 dt_hdr.time = hrt;
1327 unsigned long t = (unsigned long) vaddr; /* to suppress a warning from gcc */
1328 dt_hdr.vaddr = (uint64_t) t;
1329
1330 DT_code dt_code;
1331 dt_code.type = DT_CODE;
1332 void *code = vaddr;
1333 if (vaddr != NULL && size > 0)
1334 {
1335 dt_code.size = sizeof (dt_code) + ((size + 0xf) & ~0xf);
1336 if (mode == DFUNC_KERNEL)
1337 {
1338 /* Some Linuxes don't accept vaddrs from the vsyscall
1339 * page in write(). Make a copy.
1340 */
1341 code = alloca (size);
1342 __collector_memcpy (code, vaddr, size);
1343 }
1344 }
1345 else
1346 dt_code.size = 0;
1347
1348 DT_srcfile dt_src;
1349 dt_src.type = DT_SRCFILE;
1350 if (sourcename)
1351 {
1352 slen = CALL_UTIL (strlen)(sourcename) + 1;
1353 dt_src.size = slen ? sizeof (dt_src) + ((slen + 0xf) & ~0xf) : 0;
1354 }
1355 else
1356 {
1357 slen = 0;
1358 dt_src.size = 0;
1359 }
1360
1361 DT_ltable dt_ltbl;
1362 dt_ltbl.type = DT_LTABLE;
1363 if (lntable != NULL && lntsize > 0)
1364 dt_ltbl.size = sizeof (dt_ltbl) + lntsize * sizeof (DT_lineno);
1365 else
1366 dt_ltbl.size = 0;
1367
1368 int fd = CALL_UTIL (open)(dyntext_fname, O_RDWR | O_APPEND);
1369 if (fd == -1)
1370 {
1371 TprintfT (0, "ERROR: __collector_int_func_load: open(%s) failed: errno=%d\n",
1372 dyntext_fname, errno);
1373 (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\" ec=\"%d\">%s</event>\n",
1374 SP_JCMD_CERROR, COL_ERROR_DYNOPEN, errno, dyntext_fname);
1375 return;
1376 }
1377
1378 /* Lock the whole file */
1379 __collector_mutex_lock (&dyntext_lock);
1380 rwrite (fd, &dt_hdr, sizeof (dt_hdr));
1381 if (dt_code.size)
1382 {
1383 padn = dt_code.size - sizeof (dt_code) - size;
1384 rwrite (fd, &dt_code, sizeof (dt_code));
1385 rwrite (fd, code, size);
1386 rwrite (fd, &pad, padn);
1387 }
1388 if (dt_src.size)
1389 {
1390 padn = dt_src.size - sizeof (dt_src) - slen;
1391 rwrite (fd, &dt_src, sizeof (dt_src));
1392 rwrite (fd, sourcename, slen);
1393 rwrite (fd, &pad, padn);
1394 }
1395 if (dt_ltbl.size)
1396 {
1397 rwrite (fd, &dt_ltbl, sizeof (dt_ltbl));
1398 rwrite (fd, lntable, dt_ltbl.size - sizeof (dt_ltbl));
1399 }
1400
1401 /* Unlock the file */
1402 __collector_mutex_unlock( &dyntext_lock );
1403 CALL_UTIL(close( fd ) );
1404 }
1405
1406 void
1407 __collector_int_func_unload (dfunc_mode_t mode, void *vaddr)
1408 {
1409 if (!mmap_initted)
1410 return;
1411 hrtime_t hrt = GETRELTIME ();
1412 if (mode == DFUNC_API)
1413 append_segment_record ("<event kind=\"unmap\" tstamp=\"%u.%09u\" vaddr=\"0x%016lX\"/>\n",
1414 (unsigned) (hrt / NANOSEC), (unsigned) (hrt % NANOSEC), (unsigned long) vaddr);
1415 else if (mode == DFUNC_JAVA)
1416 /* note that the "vaddr" is really a method id, not an address */
1417 append_segment_record ("<event kind=\"unmap\" tstamp=\"%u.%09u\" methodId=\"0x%016lX\"/>\n",
1418 (unsigned) (hrt / NANOSEC), (unsigned) (hrt % NANOSEC), (unsigned long) vaddr);
1419 else
1420 return;
1421 }
1422
1423 /*
1424 * int init_mmap_intf()
1425 * Set up interposition (if not already done).
1426 */
1427 static int
1428 init_mmap_intf ()
1429 {
1430 if (__collector_dlsym_guard)
1431 return 1;
1432 void *dlflag;
1433 __real_mmap = (void*(*)(void* addr, size_t len, int prot, int flags,
1434 int fildes, off_t off))dlsym (RTLD_NEXT, SYS_MMAP_NAME);
1435 if (__real_mmap == NULL)
1436 {
1437
1438 /* We are probably dlopened after libthread/libc,
1439 * try to search in the previously loaded objects
1440 */
1441 __real_mmap = (void*(*)(void* addr, size_t len, int prot, int flags,
1442 int fildes, off_t off))dlsym (RTLD_DEFAULT, SYS_MMAP_NAME);
1443 if (__real_mmap == NULL)
1444 {
1445 TprintfT (0, "ERROR: collector real mmap not found\n");
1446 return 1;
1447 }
1448 TprintfT (DBG_LT2, "collector real mmap found with RTLD_DEFAULT\n");
1449 dlflag = RTLD_DEFAULT;
1450 }
1451 else
1452 {
1453 TprintfT (DBG_LT2, "collector real mmap found with RTLD_NEXT\n");
1454 dlflag = RTLD_NEXT;
1455 }
1456
1457 TprintfT (DBG_LT2, "init_mmap_intf() @%p __real_mmap\n", __real_mmap);
1458 __real_mmap64 = (void*(*)(void *, size_t, int, int, int, off64_t))
1459 dlsym (dlflag, SYS_MMAP64_NAME);
1460 TprintfT (DBG_LT2, "init_mmap_intf() @%p __real_mmap64\n", __real_mmap64);
1461 __real_munmap = (int(*)(void *, size_t)) dlsym (dlflag, SYS_MUNMAP_NAME);
1462 TprintfT (DBG_LT2, "init_mmap_intf() @%p __real_munmap\n", __real_munmap);
1463
1464 // dlopen/dlmopen/dlclose are in libdl.so
1465 __real_dlopen = (void*(*)(const char *, int))
1466 dlvsym (dlflag, SYS_DLOPEN_NAME, SYS_DLOPEN_VERSION);
1467 TprintfT (DBG_LT2, "init_mmap_intf() [%s] @%p __real_dlopen\n",
1468 SYS_DLOPEN_VERSION, __real_dlopen);
1469 #if (ARCH(Intel) && WSIZE(32)) || ARCH(SPARC)
1470 __real_dlopen_2_1 = __real_dlopen;
1471 __real_dlopen_2_0 = (void*(*)(const char *, int))
1472 dlvsym (dlflag, SYS_DLOPEN_NAME, "GLIBC_2.0");
1473 #endif
1474
1475 __real_dlclose = (int(*)(void* handle))dlsym (dlflag, SYS_DLCLOSE_NAME);
1476 TprintfT (DBG_LT2, "init_mmap_intf() @%p __real_dlclose\n", __real_dlclose);
1477 TprintfT (DBG_LT2, "init_mmap_intf() done\n");
1478
1479 return 0;
1480 }
1481
1482 /*------------------------------------------------------------- mmap */
1483 void *
1484 mmap (void *start, size_t length, int prot, int flags, int fd, off_t offset)
1485 {
1486 int err = 0;
1487 if (NULL_PTR (mmap))
1488 err = init_mmap_intf ();
1489 if (err)
1490 return MAP_FAILED;
1491
1492 /* hrtime_t hrt = GETRELTIME(); */
1493 void *ret = CALL_REAL (mmap)(start, length, prot, flags, fd, offset);
1494
1495 if (!CHCK_REENTRANCE && (ret != MAP_FAILED) && collector_heap_record != NULL)
1496 {
1497 PUSH_REENTRANCE;
1498 /* write a separate record for mmap tracing */
1499 collector_heap_record (MMAP_TRACE, length, ret);
1500 POP_REENTRANCE;
1501 }
1502 TprintfT (DBG_LT2, "libcollector.mmap(%p, %ld, %d, %d, %d, 0x%lld) = %p\n",
1503 start, (long) length, prot, flags, fd, (long long) offset, ret);
1504 return ret;
1505 }
1506
1507 /*------------------------------------------------------------- mmap64 */
1508 #if WSIZE(32) /* mmap64 only defined for non-64-bit */
1509
1510 void *
1511 mmap64 (void *start, size_t length, int prot, int flags, int fd, off64_t offset)
1512 {
1513 if (NULL_PTR (mmap64))
1514 init_mmap_intf ();
1515
1516 /* hrtime_t hrt = GETRELTIME(); */
1517 void *ret = CALL_REAL (mmap64)(start, length, prot, flags, fd, offset);
1518 if (!CHCK_REENTRANCE && (ret != MAP_FAILED) && collector_heap_record != NULL)
1519 {
1520 PUSH_REENTRANCE;
1521 /* write a separate record for mmap tracing */
1522 collector_heap_record (MMAP_TRACE, length, ret);
1523 POP_REENTRANCE;
1524 }
1525 TprintfT (DBG_LT2, "libcollector.mmap64(%p, %ld, %d, %d, %d, 0x%lld) = %p\n",
1526 start, (long) length, prot, flags, fd, (long long) offset, ret);
1527 return ret;
1528 }
1529 #endif /* WSIZE(32) */
1530
1531 /*------------------------------------------------------------- munmap */
1532 int
1533 munmap (void *start, size_t length)
1534 {
1535 if (NULL_PTR (munmap))
1536 init_mmap_intf ();
1537
1538 /* hrtime_t hrt = GETRELTIME(); */
1539 int rc = CALL_REAL (munmap)(start, length);
1540 if (!CHCK_REENTRANCE && (rc == 0) && collector_heap_record != NULL)
1541 {
1542 PUSH_REENTRANCE;
1543 /* write a separate record for mmap tracing */
1544 collector_heap_record (MUNMAP_TRACE, length, start);
1545 POP_REENTRANCE;
1546 }
1547 TprintfT (DBG_LT2, "libcollector.munmap(%p, %ld) = %d\n", start, (long) length, rc);
1548 return rc;
1549 }
1550
1551
1552 /*------------------------------------------------------------- dlopen */
1553 // map interposed symbol versions
1554 #if (ARCH(Intel) && WSIZE(32)) || ARCH(SPARC)
1555
1556 static void *
1557 __collector_dlopen_symver (void*(real_dlopen) (), void *caller, const char *pathname, int mode);
1558
1559 SYMVER_ATTRIBUTE (__collector_dlopen_2_1, dlopen@@GLIBC_2.1)
1560 void *
1561 __collector_dlopen_2_1 (const char *pathname, int mode)
1562 {
1563 if (NULL_PTR (dlopen))
1564 init_mmap_intf ();
1565 void *caller = __builtin_return_address (0); // must be called inside dlopen first layer interpostion
1566 return __collector_dlopen_symver (CALL_REAL (dlopen_2_1), caller, pathname, mode);
1567 }
1568
1569 SYMVER_ATTRIBUTE (__collector_dlopen_2_0, dlopen@GLIBC_2.0)
1570 void *
1571 __collector_dlopen_2_0 (const char *pathname, int mode)
1572 {
1573 if (NULL_PTR (dlopen))
1574 init_mmap_intf ();
1575 void* caller = __builtin_return_address (0); // must be called inside dlopen first layer interpostion
1576 return __collector_dlopen_symver (CALL_REAL (dlopen_2_0), caller, pathname, mode);
1577 }
1578 #endif
1579
1580 #if (ARCH(Intel) && WSIZE(32)) || ARCH(SPARC)
1581 static void *
1582 __collector_dlopen_symver (void*(real_dlopen) (), void *caller, const char *pathname, int mode)
1583 #else
1584 void *
1585 dlopen (const char *pathname, int mode)
1586 #endif
1587 {
1588 const char * real_pathname = pathname;
1589 char new_pathname[MAXPATHLEN];
1590 int origin_offset = 0;
1591 TprintfT (DBG_LT2, "dlopen: pathname=%s, mode=%d\n", pathname ? pathname : "NULL", mode);
1592 if (pathname && __collector_strStartWith (pathname, "$ORIGIN/") == 0)
1593 origin_offset = 8;
1594 else if (pathname && __collector_strStartWith (pathname, "${ORIGIN}/") == 0)
1595 origin_offset = 10;
1596 if (origin_offset)
1597 {
1598 #if ! ((ARCH(Intel) && WSIZE(32)) || ARCH(SPARC))
1599 // 'caller' is not passed as an argument
1600 void * caller = __builtin_return_address (0); // must be called inside dlopen first layer interpostion
1601 #endif
1602 Dl_info dl_info;
1603 if (caller && dladdr (caller, &dl_info) != 0)
1604 {
1605 TprintfT (DBG_LT2, "dladdr(%p): %p fname=%s\n",
1606 caller, dl_info.dli_fbase, dl_info.dli_fname);
1607 new_pathname[0] = '\0';
1608 const char *p = __collector_strrchr (dl_info.dli_fname, '/');
1609 if (p)
1610 __collector_strlcpy (new_pathname, dl_info.dli_fname,
1611 (p - dl_info.dli_fname + 2) < MAXPATHLEN ? (p - dl_info.dli_fname + 2) : MAXPATHLEN);
1612 __collector_strlcat (new_pathname, pathname + origin_offset, MAXPATHLEN - CALL_UTIL (strlen)(new_pathname));
1613 real_pathname = new_pathname;
1614 }
1615 else
1616 TprintfT (0, "ERROR: dladdr(%p): %s\n", caller, dlerror ());
1617 }
1618 if (NULL_PTR (dlopen))
1619 init_mmap_intf ();
1620 TprintfT (DBG_LT2, "libcollector.dlopen(%s,%d) interposing\n",
1621 pathname ? pathname : "", mode);
1622 void* ret = NULL;
1623
1624 // set guard for duration of handling dlopen, since want to ensure
1625 // new mappings are resolved after the actual dlopen has occurred
1626 PUSH_REENTRANCE;
1627 hrtime_t hrt = GETRELTIME ();
1628
1629 if (real_pathname && !__collector_strchr (real_pathname, '/'))
1630 { // got an unqualified name
1631 // get caller and use its searchpath
1632 #if ! ((ARCH(Intel) && WSIZE(32)) || ARCH(SPARC))
1633 void* caller = __builtin_return_address (0); // must be called inside dlopen
1634 #endif
1635 if (caller)
1636 {
1637 #if (ARCH(Intel) && WSIZE(32)) || ARCH(SPARC)
1638 ret = dlopen_searchpath_symver (real_dlopen, caller, real_pathname, mode);
1639 #else
1640 ret = dlopen_searchpath (caller, real_pathname, mode);
1641 #endif
1642 }
1643 }
1644
1645 if (!ret)
1646 {
1647 #if (ARCH(Intel) && WSIZE(32)) || ARCH(SPARC)
1648 ret = (real_dlopen) (real_pathname, mode);
1649 #else
1650 ret = CALL_REAL (dlopen)(real_pathname, mode);
1651 #endif
1652 }
1653 TprintfT (DBG_LT2, "libcollector -- dlopen(%s) returning %p\n", pathname, ret);
1654
1655 /* Don't call update if dlopen failed: preserve dlerror() */
1656 if (ret && (mmap_mode > 0) && !(mode & RTLD_NOLOAD))
1657 update_map_segments (hrt, 1);
1658 TprintfT (DBG_LT2, "libcollector -- dlopen(%s) returning %p\n", pathname, ret);
1659 POP_REENTRANCE;
1660 return ret;
1661 }
1662
1663 /*------------------------------------------------------------- dlclose */
1664 int
1665 dlclose (void *handle)
1666 {
1667 if (NULL_PTR (dlclose))
1668 init_mmap_intf ();
1669 TprintfT (DBG_LT2, "__collector_dlclose(%p) entered\n", handle);
1670 hrtime_t hrt = GETRELTIME ();
1671 if (!CHCK_REENTRANCE)
1672 {
1673 PUSH_REENTRANCE;
1674 update_map_segments (hrt, 1);
1675 POP_REENTRANCE;
1676 hrt = GETRELTIME ();
1677 }
1678 int ret = CALL_REAL (dlclose)(handle);
1679
1680 /* Don't call update if dlclose failed: preserve dlerror() */
1681 if (!ret && !CHCK_REENTRANCE)
1682 {
1683 PUSH_REENTRANCE;
1684 update_map_segments (hrt, 1);
1685 POP_REENTRANCE;
1686 }
1687 TprintfT (DBG_LT2, "__collector_dlclose(%p) returning %d\n", handle, ret);
1688 return ret;
1689 }