1 /* Copyright (C) 2021 Free Software Foundation, Inc.
4 This file is part of GNU Binutils.
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)
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.
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. */
23 * incorporating former "loadobjects" into more general "map"
24 * (including code and data segments and dynamic functions)
34 #include <sys/param.h>
38 #include "collector.h"
39 #include "gp-experiment.h"
43 * These are obsolete and unreliable.
44 * They are included here only for historical compatibility.
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 */
52 typedef struct prmap_t
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 */
61 int pr_pagesize
; /* pagesize (bytes) for this mapping */
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
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"
77 typedef struct MapInfo
82 char *mapname
; /* name in /proc/<pid>/object */
89 typedef struct NameInfo
91 struct NameInfo
*next
;
93 char filename
[1]; /* dynamic length file name */
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
;
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--
116 #define CALL_REAL(x) (__real_##x)
117 #define NULL_PTR(x) (__real_##x == NULL)
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
;
130 static int (*__real_dlclose
)(void* handle
) = NULL
;
131 static void (*collector_heap_record
)(int, size_t, void*) = NULL
;
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
);
144 /* Linux needs handling of the vsyscall page to get its data into the map.xml file */
145 static void process_vsyscall_page ();
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
];
155 static char *dynname
[MAXDYN
];
156 static void *dynvaddr
[MAXDYN
];
157 static unsigned dynsize
[MAXDYN
];
158 static char *dynfuncname
[MAXDYN
];
160 /*===================================================================*/
163 * void __collector_mmap_init_mutex_locks()
164 * Iinitialize mmap mutex locks.
167 __collector_mmap_init_mutex_locks ()
169 __collector_mutex_init (&map_lock
);
170 __collector_mutex_init (&dyntext_lock
);
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.
179 __collector_ext_update_map_segments (void)
183 TprintfT (0, "__collector_ext_update_map_segments(%d)\n", CURR_REENTRANCE
);
187 update_map_segments (GETRELTIME (), 1);
192 * int __collector_ext_mmap_install()
193 * Install and initialise mmap tracing.
196 __collector_ext_mmap_install (int record
)
198 TprintfT (0, "__collector_ext_mmap_install(mmap_mode=%d)\n", mmap_mode
);
201 if (init_mmap_intf ())
203 TprintfT (0, "ERROR: collector mmap tracing initialization failed.\n");
204 return COL_ERROR_EXPOPEN
;
208 TprintfT (DBG_LT2
, "collector mmap tracing: mmap pointer not null\n");
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");
214 map_hndl
= __collector_create_handle (SP_MAP_FILE
);
215 if (map_hndl
== NULL
)
216 return COL_ERROR_MAPOPEN
;
217 if (init_mmap_files ())
219 TprintfT (0, "ERROR: collector init_mmap_files() failed.\n");
220 return COL_ERROR_EXPOPEN
;
226 update_map_segments (GETRELTIME (), 1); // initial map
230 process_vsyscall_page ();
231 return COL_ERROR_NONE
;
235 * int __collector_ext_mmap_deinstall()
236 * Optionally update final map and stop tracing mmap events.
239 __collector_ext_mmap_deinstall (int update
)
242 return COL_ERROR_NONE
;
248 update_map_segments (GETRELTIME (), 1);
251 TprintfT (0, "__collector_ext_mmap_deinstall(%d)\n", update
);
252 if (map_hndl
!= NULL
)
254 __collector_delete_handle (map_hndl
);
257 __collector_mutex_lock (&map_lock
); // get lock before resetting
259 /* Free all memory maps */
261 for (mp
= mmaps
.next
; mp
;)
263 MapInfo
*next
= mp
->next
;
264 __collector_freeCSize (__collector_heap
, mp
, sizeof (*mp
));
269 /* Free all name maps */
271 for (np
= namemaps
; np
;)
273 NameInfo
*next
= np
->next
;
274 __collector_freeCSize (__collector_heap
, np
, sizeof (*np
) + __collector_strlen (np
->filename
));
278 mapcache
= __collector_reallocVSize (__collector_heap
, mapcache
, 0);
281 __collector_mutex_unlock (&map_lock
);
282 TprintfT (0, "__collector_ext_mmap_deinstall done\n");
287 * void __collector_mmap_fork_child_cleanup()
288 * Perform all necessary cleanup steps in child process after fork().
291 __collector_mmap_fork_child_cleanup ()
293 /* Initialize all mmap "mutex" locks */
294 __collector_mmap_init_mutex_locks ();
298 __collector_delete_handle (map_hndl
);
299 __collector_mutex_lock (&map_lock
); // get lock before resetting
301 /* Free all memory maps */
303 for (mp
= mmaps
.next
; mp
;)
305 MapInfo
*next
= mp
->next
;
306 __collector_freeCSize (__collector_heap
, mp
, sizeof (*mp
));
311 /* Free all name maps */
313 for (np
= namemaps
; np
;)
315 NameInfo
*next
= np
->next
;
316 __collector_freeCSize (__collector_heap
, np
, sizeof (*np
) + __collector_strlen (np
->filename
));
320 mapcache
= __collector_reallocVSize (__collector_heap
, mapcache
, 0);
323 __collector_mutex_unlock (&map_lock
);
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)
335 int fd
= CALL_UTIL (open
)(dyntext_fname
, O_RDWR
| O_CREAT
| O_TRUNC
,
336 S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
);
340 TprintfT (0, "ERROR: init_mmap_files: open(%s) failed\n",
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
;
348 CALL_UTIL (close
)(fd
);
350 return COL_ERROR_NONE
;
354 append_segment_record (char *format
, ...)
359 va_start (va
, format
);
360 int sz
= __collector_xml_vsnprintf (bufptr
, sizeof (buf
), format
, va
);
363 if (__collector_expstate
!= EXP_OPEN
&& __collector_expstate
!= EXP_PAUSED
)
365 TprintfT (0, "append_segment_record: expt neither open nor paused (%d); "
366 "not writing to map.xml\n\t%s", __collector_expstate
, buf
);
369 if (sz
>= sizeof (buf
))
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
);
378 int rc
= __collector_write_string (map_hndl
, bufptr
, sz
);
380 (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\"></event>\n",
381 SP_JCMD_CERROR
, COL_ERROR_MAPWRITE
);
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
)
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
);
402 record_segment_unmap (hrtime_t timestamp
, uint64_t loadaddr
)
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
);
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
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
431 checksum_mapname (MapInfo
* map
)
433 unsigned checksum
= 0;
434 /* only checksum code segments */
435 if ((map
->mflags
& (PROT_EXEC
| PROT_READ
)) == 0 ||
436 (map
->mflags
& PROT_WRITE
) != 0)
438 checksum
= (unsigned) - 1;
439 TprintfT (DBG_LT2
, "checksum_mapname checksum = 0x%0X\n", checksum
);
444 #if (ARCH(Intel) && WSIZE(32)) || ARCH(SPARC)
446 dlopen_searchpath_symver (void*(real_dlopen
) (), void* caller_addr
, const char* basename
, int mode
)
449 dlopen_searchpath (void* caller_addr
, const char* basename
, int mode
)
452 TprintfT (DBG_LT2
, "dlopen_searchpath(%p, %s, %d)\n", caller_addr
, basename
, mode
);
454 if (dladdr (caller_addr
, &dl_info
) == 0)
456 TprintfT (0, "ERROR: dladdr(%p): %s\n", caller_addr
, dlerror ());
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
467 #define MAINBASE 0x400000
469 #define MAINBASE 0x08048000
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
);
477 caller_hndl
= CALL_REAL (dlopen
)(tmp_path
, noload
);
480 #else //XXXX workaround should be removed once linker patches are all available
482 void* caller_hndl
= NULL
;
483 #if (ARCH(Intel) && WSIZE(32) || ARCH(SPARC)
484 caller_hndl
= (real_dlopen
) (dl_info
.dli_fname
, noload
);
486 caller_hndl
= CALL_REAL (dlopen
)(dl_info
.dli_fname
, noload
);
489 #endif //XXXX workaround should be removed once linker patches are all available
493 TprintfT (0, "ERROR: dlopen(%s,NOLOAD): %s\n", dl_info
.dli_fname
, dlerror ());
496 Dl_serinfo _info
, *info
= &_info
;
499 /* determine search path count and required buffer size */
500 dlinfo (caller_hndl
, RTLD_DI_SERINFOSIZE
, (void *) info
);
502 /* allocate new buffer and initialize */
505 There is a bug in Linux that causes the first call
506 to dlinfo() to return a small value for the dls_size.
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.
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.
522 collect crashes right after the second call to dlinfo().
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.
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.
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.
554 info
= alloca (_info
.dls_size
* _info
.dls_cnt
);
555 info
->dls_size
= _info
.dls_size
;
556 info
->dls_cnt
= _info
.dls_cnt
;
558 /* obtain search path information */
559 dlinfo (caller_hndl
, RTLD_DI_SERINFO
, (void *) info
);
560 path
= &info
->dls_serpath
[0];
562 char pathname
[MAXPATHLEN
];
563 for (unsigned int cnt
= 1; cnt
<= info
->dls_cnt
; cnt
++, path
++)
565 __collector_strlcpy (pathname
, path
->dls_name
, sizeof (pathname
));
566 __collector_strlcat (pathname
, "/", sizeof (pathname
));
567 __collector_strlcat (pathname
, basename
, sizeof (pathname
));
569 #if (ARCH(Intel) && WSIZE(32)) || ARCH(SPARC)
570 ret
= (real_dlopen
) (pathname
, mode
);
572 ret
= CALL_REAL (dlopen
)(pathname
, mode
);
574 TprintfT (DBG_LT2
, "try %d/%d: %s = %p\n", cnt
, info
->dls_cnt
, pathname
, ret
);
576 return ret
; // success!
582 resolve_mapname (MapInfo
*map
, char *name
)
586 if (name
== NULL
|| *name
== '\0')
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
">";
597 for (np
= namemaps
; np
; np
= np
->next
)
598 if (__collector_strcmp (np
->mapname
, name
) == 0)
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
610 np
->mapname
= np
->filename
;
611 __collector_strlcpy (np
->filename
, fname
, fnamelen
);
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
);
623 str2ulong (char **ss
)
626 unsigned long val
= 0UL;
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;
645 update_map_segments (hrtime_t hrt
, int resolve
)
648 if (__collector_mutex_trylock (&map_lock
))
650 TprintfT (0, "WARNING: update_map_segments(resolve=%d) BUSY\n", resolve
);
653 TprintfT (DBG_LT2
, "\n");
654 TprintfT (DBG_LT2
, "begin update_map_segments(hrt, %d)\n", resolve
);
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
;
662 int map_fd
= CALL_UTIL (open
)(proc_map
, O_RDONLY
);
666 maptext
= __collector_reallocVSize (__collector_heap
, maptext
, bufsz
);
667 TprintfT (DBG_LT2
, " update_map_segments: Loop for bufsize=%ld\n",
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
);
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
);
689 if (filesz
>= bufsz
) /* Buffer too small */
693 CALL_UTIL (close
)(map_fd
);
696 int mapcache_entries
= 0;
698 for (str
= maptext
;; str
= str1
)
700 for (str1
= str
; str1
- maptext
< filesz
; str1
++)
708 if (str1
- maptext
>= filesz
)
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
);
717 unsigned long eaddr
= str2ulong (&str
);
719 map
->pr_size
= eaddr
- map
->pr_vaddr
;
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);
726 map
->pr_offset
= str2ulong (&str
);
728 map
->pr_dev
= str2ulong (&str
) * 0x100;
730 map
->pr_dev
+= str2ulong (&str
);
732 map
->pr_ino
= str2ulong (&str
);
733 if (map
->pr_dev
== 0)
734 map
->pr_mflags
|= MA_ANON
;
737 map
->pr_mapname
= str
;
738 map
->pr_pagesize
= 4096;
741 /* Compare two maps and record all differences */
743 MapInfo
*prev
= &mmaps
;
744 MapInfo
*oldp
= mmaps
.next
;
747 prmap_t
*newp
= nidx
< mapcache_entries
?
748 (prmap_t
*) mapcache
+ nidx
: NULL
;
749 if (oldp
== NULL
&& newp
== NULL
)
752 /* If two maps are equal proceed to the next pair */
754 oldp
->vaddr
== newp
->pr_vaddr
&&
755 oldp
->size
== newp
->pr_size
&&
756 __collector_strcmp (oldp
->mapname
, newp
->pr_mapname
) == 0)
763 /* Check if we need to unload the old map first */
764 if (newp
== NULL
|| (oldp
&& oldp
->vaddr
<= newp
->pr_vaddr
))
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
;
775 __collector_freeCSize (__collector_heap
, tmp
, sizeof (*tmp
));
780 MapInfo
*map
= (MapInfo
*) __collector_allocCSize (__collector_heap
, sizeof (MapInfo
), 1);
783 __collector_mutex_unlock (&map_lock
);
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
);
794 map
->next
= prev
->next
;
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
)))
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
);
809 TprintfT (DBG_LT2
, "update_map_segments: done\n\n");
810 __collector_mutex_unlock (&map_lock
);
811 } /* update_map_segments */
814 * Map addr to a segment. Cope with split segments.
817 __collector_check_segment_internal (unsigned long addr
, unsigned long *base
,
818 unsigned long *end
, int maxnretries
, int MA_FLAGS
)
820 int number_of_tries
= 0;
824 unsigned long curbase
= 0;
825 unsigned long curfoff
= 0;
826 unsigned long cursize
= 0;
829 for (mp
= mmaps
.next
; mp
; mp
= mp
->next
)
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
838 cursize
= mp
->vaddr
+ mp
->size
- curbase
;
839 else if (addr
< mp
->vaddr
)
841 else if ((mp
->mflags
& MA_FLAGS
) != MA_FLAGS
842 && __collector_strncmp (mp
->mapname
, "[vdso]", 6)
843 && __collector_strncmp (mp
->mapname
, "[vsyscall]", 10))
852 curfoff
= mp
->offset
;
857 if (addr
>= curbase
&& addr
< curbase
+ cursize
)
860 *end
= curbase
+ cursize
;
865 * 21275311 Unwind failure in native stack for java application running on jdk8 on x86
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
873 if (number_of_tries
< maxnretries
)
876 __collector_ext_update_map_segments ();
885 * Check if address belongs to a readable and executable segment
890 * @return 1 - yes, 0 - no
893 __collector_check_segment (unsigned long addr
, unsigned long *base
,
894 unsigned long *end
, int maxnretries
)
896 int MA_FLAGS
= PROT_READ
| PROT_EXEC
;
897 int res
= __collector_check_segment_internal (addr
, base
, end
, maxnretries
, MA_FLAGS
);
902 * Check if address belongs to a readable segment
907 * @return 1 - yes, 0 - no
910 __collector_check_readable_segment( unsigned long addr
, unsigned long *base
, unsigned long *end
, int maxnretries
)
912 int MA_FLAGS
= PROT_READ
;
913 int res
= __collector_check_segment_internal(addr
, base
, end
, maxnretries
, MA_FLAGS
);
917 static ELF_AUX
*auxv
= NULL
;
920 process_vsyscall_page ()
922 TprintfT (DBG_LT2
, "process_vsyscall_page()\n");
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
++)
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
]);
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
++)
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
]);
952 if (ndyn
+ nvsysfuncs
!= 0)
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.
960 char **envp
= (char**) environ
;
963 while (*envp
++ != NULL
);
964 auxv
= (ELF_AUX
*) envp
;
966 TprintfT (DBG_LT2
, "process_vsyscall_page, auxv = ox%p\n", auxv
);
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
);
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
++)
982 if (ap
->a_type
== AT_SYSINFO_EHDR
)
984 // newer Linuxes do not have a_ptr field, they just have a_val
985 ehdr
= (ELF_EHDR
*) ap
->a_un
.a_val
;
994 char *mapName
= "SYSINFO_EHDR";
996 for (mp
= mmaps
.next
; mp
; mp
= mp
->next
)
998 if ((unsigned long) ehdr
== mp
->vaddr
)
1000 mp
->mflags
|= PROT_EXEC
;
1001 if (mp
->mapname
&& mp
->mapname
[0])
1002 mapName
= mp
->mapname
;
1007 // Find the dynsym section and record all symbols
1008 char *base
= (char*) ehdr
;
1009 ELF_SHDR
*shdr
= (ELF_SHDR
*) (base
+ ehdr
->e_shoff
);
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
++)
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
);
1057 for (i
= 1; i
< ehdr
->e_shnum
; i
++)
1058 if (shdr
[i
].sh_type
== SHT_DYNSYM
)
1065 char *symbase
= base
+ shdr
[shdr
[dynSec
].sh_link
].sh_offset
;
1066 ELF_SYM
*symbols
= (ELF_SYM
*) (base
+ shdr
[dynSec
].sh_offset
);
1068 int n
= shdr
[dynSec
].sh_size
/ shdr
[dynSec
].sh_entsize
;
1069 for (i
= 0; i
< n
; i
++)
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
)
1086 nextSec
= sym
->st_shndx
;
1087 else if (nextSec
> sym
->st_shndx
)
1088 nextSec
= sym
->st_shndx
;
1093 while (nextSec
!= 0)
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
++)
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
)
1104 if (sym
->st_shndx
> curSec
)
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
;
1113 if (sym
->st_shndx
!= curSec
)
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
)
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
);
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
);
1128 /* now cache this for a subsequent experiment */
1130 __collector_log_write ("<event kind=\"%s\" id=\"%d\">MAXDYN=%d</event>\n",
1131 SP_JCMD_CERROR
, COL_ERROR_MAPCACHE
, MAXDYN
);
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
]);
1145 __collector_int_func_load (DFUNC_KERNEL
, mapName
, NULL
,
1146 (void*) (base
+ shdr
[curSec
].sh_offset
), shdr
[curSec
].sh_size
, 0, NULL
);
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
);
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
]);
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
)
1173 unsigned long vsysaddr
= (unsigned long) 0xffffe000;
1175 unsigned long vsysaddr
= (unsigned long) 0xffffffffff600000;
1177 // Make sure the vsyscall map has PROT_EXEC
1179 for (mp
= mmaps
.next
; mp
; mp
= mp
->next
)
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
)
1191 if (__collector_strncmp (mp
->mapname
, "[vdso]", 6) == 0
1192 || __collector_strncmp (mp
->mapname
, "[vsyscall]", 10) == 0)
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);
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
);
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
);
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
]);
1231 * collector API for dynamic functions
1233 void collector_func_load () __attribute__ ((weak
, alias ("__collector_func_load")));
1235 __collector_func_load (char *name
, char *alias
, char *sourcename
,
1236 void *vaddr
, int size
, int lntsize
, DT_lineno
*lntable
)
1238 __collector_int_func_load (DFUNC_API
, name
, sourcename
,
1239 vaddr
, size
, lntsize
, lntable
);
1242 void collector_func_unload () __attribute__ ((weak
, alias ("__collector_func_unload")));
1244 __collector_func_unload (void *vaddr
)
1246 __collector_int_func_unload (DFUNC_API
, vaddr
);
1249 /* routines for handling dynamic functions */
1251 rwrite (int fd
, void *buf
, size_t nbyte
)
1253 size_t left
= nbyte
;
1255 char *ptr
= (char*) buf
;
1258 res
= CALL_UTIL (write
)(fd
, ptr
, left
);
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
);
1272 __collector_int_func_load (dfunc_mode_t mode
, char *name
, char *sourcename
,
1273 void *vaddr
, int size
, int lntsize
, DT_lineno
*lntable
)
1277 static char pad
[16];
1281 hrtime_t hrt
= GETRELTIME ();
1285 /* generate a name based on vaddr */
1286 CALL_UTIL (snprintf
)(name_buf
, sizeof (name_buf
), "0x%lx", (unsigned long) vaddr
);
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
);
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
);
1309 /* 21275311 Unwind failure in native stack for java application running on jdk8 on x86
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().
1315 unsigned long base1
, end1
, base2
, end2
;
1316 __collector_check_segment ((unsigned long) vaddr
, &base1
, &end1
, 0);
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 ();
1322 /* Write a copy of actual code to the "dyntext" file */
1324 dt_hdr
.type
= DT_HEADER
;
1325 dt_hdr
.size
= sizeof (dt_hdr
);
1327 unsigned long t
= (unsigned long) vaddr
; /* to suppress a warning from gcc */
1328 dt_hdr
.vaddr
= (uint64_t) t
;
1331 dt_code
.type
= DT_CODE
;
1333 if (vaddr
!= NULL
&& size
> 0)
1335 dt_code
.size
= sizeof (dt_code
) + ((size
+ 0xf) & ~0xf);
1336 if (mode
== DFUNC_KERNEL
)
1338 /* Some Linuxes don't accept vaddrs from the vsyscall
1339 * page in write(). Make a copy.
1341 code
= alloca (size
);
1342 __collector_memcpy (code
, vaddr
, size
);
1349 dt_src
.type
= DT_SRCFILE
;
1352 slen
= CALL_UTIL (strlen
)(sourcename
) + 1;
1353 dt_src
.size
= slen
? sizeof (dt_src
) + ((slen
+ 0xf) & ~0xf) : 0;
1362 dt_ltbl
.type
= DT_LTABLE
;
1363 if (lntable
!= NULL
&& lntsize
> 0)
1364 dt_ltbl
.size
= sizeof (dt_ltbl
) + lntsize
* sizeof (DT_lineno
);
1368 int fd
= CALL_UTIL (open
)(dyntext_fname
, O_RDWR
| O_APPEND
);
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
);
1378 /* Lock the whole file */
1379 __collector_mutex_lock (&dyntext_lock
);
1380 rwrite (fd
, &dt_hdr
, sizeof (dt_hdr
));
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
);
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
);
1397 rwrite (fd
, &dt_ltbl
, sizeof (dt_ltbl
));
1398 rwrite (fd
, lntable
, dt_ltbl
.size
- sizeof (dt_ltbl
));
1401 /* Unlock the file */
1402 __collector_mutex_unlock( &dyntext_lock
);
1403 CALL_UTIL(close( fd
) );
1407 __collector_int_func_unload (dfunc_mode_t mode
, void *vaddr
)
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
);
1424 * int init_mmap_intf()
1425 * Set up interposition (if not already done).
1430 if (__collector_dlsym_guard
)
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
)
1438 /* We are probably dlopened after libthread/libc,
1439 * try to search in the previously loaded objects
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
)
1445 TprintfT (0, "ERROR: collector real mmap not found\n");
1448 TprintfT (DBG_LT2
, "collector real mmap found with RTLD_DEFAULT\n");
1449 dlflag
= RTLD_DEFAULT
;
1453 TprintfT (DBG_LT2
, "collector real mmap found with RTLD_NEXT\n");
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
);
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");
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");
1482 /*------------------------------------------------------------- mmap */
1484 mmap (void *start
, size_t length
, int prot
, int flags
, int fd
, off_t offset
)
1487 if (NULL_PTR (mmap
))
1488 err
= init_mmap_intf ();
1492 /* hrtime_t hrt = GETRELTIME(); */
1493 void *ret
= CALL_REAL (mmap
)(start
, length
, prot
, flags
, fd
, offset
);
1495 if (!CHCK_REENTRANCE
&& (ret
!= MAP_FAILED
) && collector_heap_record
!= NULL
)
1498 /* write a separate record for mmap tracing */
1499 collector_heap_record (MMAP_TRACE
, length
, ret
);
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
);
1507 /*------------------------------------------------------------- mmap64 */
1508 #if WSIZE(32) /* mmap64 only defined for non-64-bit */
1511 mmap64 (void *start
, size_t length
, int prot
, int flags
, int fd
, off64_t offset
)
1513 if (NULL_PTR (mmap64
))
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
)
1521 /* write a separate record for mmap tracing */
1522 collector_heap_record (MMAP_TRACE
, length
, ret
);
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
);
1529 #endif /* WSIZE(32) */
1531 /*------------------------------------------------------------- munmap */
1533 munmap (void *start
, size_t length
)
1535 if (NULL_PTR (munmap
))
1538 /* hrtime_t hrt = GETRELTIME(); */
1539 int rc
= CALL_REAL (munmap
)(start
, length
);
1540 if (!CHCK_REENTRANCE
&& (rc
== 0) && collector_heap_record
!= NULL
)
1543 /* write a separate record for mmap tracing */
1544 collector_heap_record (MUNMAP_TRACE
, length
, start
);
1547 TprintfT (DBG_LT2
, "libcollector.munmap(%p, %ld) = %d\n", start
, (long) length
, rc
);
1552 /*------------------------------------------------------------- dlopen */
1553 // map interposed symbol versions
1554 #if (ARCH(Intel) && WSIZE(32)) || ARCH(SPARC)
1557 __collector_dlopen_symver (void*(real_dlopen
) (), void *caller
, const char *pathname
, int mode
);
1559 SYMVER_ATTRIBUTE (__collector_dlopen_2_1
, dlopen@@GLIBC_2
.1
)
1561 __collector_dlopen_2_1 (const char *pathname
, int mode
)
1563 if (NULL_PTR (dlopen
))
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
);
1569 SYMVER_ATTRIBUTE (__collector_dlopen_2_0
, dlopen@GLIBC_2
.0
)
1571 __collector_dlopen_2_0 (const char *pathname
, int mode
)
1573 if (NULL_PTR (dlopen
))
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
);
1580 #if (ARCH(Intel) && WSIZE(32)) || ARCH(SPARC)
1582 __collector_dlopen_symver (void*(real_dlopen
) (), void *caller
, const char *pathname
, int mode
)
1585 dlopen (const char *pathname
, int mode
)
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)
1594 else if (pathname
&& __collector_strStartWith (pathname
, "${ORIGIN}/") == 0)
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
1603 if (caller
&& dladdr (caller
, &dl_info
) != 0)
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
, '/');
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
;
1616 TprintfT (0, "ERROR: dladdr(%p): %s\n", caller
, dlerror ());
1618 if (NULL_PTR (dlopen
))
1620 TprintfT (DBG_LT2
, "libcollector.dlopen(%s,%d) interposing\n",
1621 pathname
? pathname
: "", mode
);
1624 // set guard for duration of handling dlopen, since want to ensure
1625 // new mappings are resolved after the actual dlopen has occurred
1627 hrtime_t hrt
= GETRELTIME ();
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
1637 #if (ARCH(Intel) && WSIZE(32)) || ARCH(SPARC)
1638 ret
= dlopen_searchpath_symver (real_dlopen
, caller
, real_pathname
, mode
);
1640 ret
= dlopen_searchpath (caller
, real_pathname
, mode
);
1647 #if (ARCH(Intel) && WSIZE(32)) || ARCH(SPARC)
1648 ret
= (real_dlopen
) (real_pathname
, mode
);
1650 ret
= CALL_REAL (dlopen
)(real_pathname
, mode
);
1653 TprintfT (DBG_LT2
, "libcollector -- dlopen(%s) returning %p\n", pathname
, ret
);
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
);
1663 /*------------------------------------------------------------- dlclose */
1665 dlclose (void *handle
)
1667 if (NULL_PTR (dlclose
))
1669 TprintfT (DBG_LT2
, "__collector_dlclose(%p) entered\n", handle
);
1670 hrtime_t hrt
= GETRELTIME ();
1671 if (!CHCK_REENTRANCE
)
1674 update_map_segments (hrt
, 1);
1676 hrt
= GETRELTIME ();
1678 int ret
= CALL_REAL (dlclose
)(handle
);
1680 /* Don't call update if dlclose failed: preserve dlerror() */
1681 if (!ret
&& !CHCK_REENTRANCE
)
1684 update_map_segments (hrt
, 1);
1687 TprintfT (DBG_LT2
, "__collector_dlclose(%p) returning %d\n", handle
, ret
);