Home | History | Annotate | Line # | Download | only in darwin
      1 #ifndef JEMALLOC_INTERNAL_OS_DARWIN_PROC_MAPS_H
      2 #define JEMALLOC_INTERNAL_OS_DARWIN_PROC_MAPS_H
      3 
      4 #include "jemalloc/internal/jemalloc_preamble.h"
      5 #include "jemalloc/internal/malloc_io.h"
      6 
      7 #include <mach-o/dyld.h>
      8 
      9 #define JEMALLOC_OS_PROF_NO_OPEN_MAPS
     10 
     11 #ifdef __LP64__
     12 typedef struct mach_header_64     os_mach_header_t;
     13 typedef struct segment_command_64 os_segment_command_t;
     14 #	define OS_MH_MAGIC_VALUE MH_MAGIC_64
     15 #	define OS_MH_CIGAM_VALUE MH_CIGAM_64
     16 #	define OS_LC_SEGMENT_VALUE LC_SEGMENT_64
     17 #else
     18 typedef struct mach_header     os_mach_header_t;
     19 typedef struct segment_command os_segment_command_t;
     20 #	define OS_MH_MAGIC_VALUE MH_MAGIC
     21 #	define OS_MH_CIGAM_VALUE MH_CIGAM
     22 #	define OS_LC_SEGMENT_VALUE LC_SEGMENT
     23 #endif
     24 
     25 JEMALLOC_ALWAYS_INLINE uint64_t
     26 os_prof_pid_namespace(void) {
     27 	/* Not supported on Darwin. */
     28 	return 0;
     29 }
     30 
     31 JEMALLOC_ALWAYS_INLINE int
     32 os_prof_open_maps(void) {
     33 	/* Darwin dumps dyld images instead of reading an fd-based maps file. */
     34 	return -1;
     35 }
     36 
     37 JEMALLOC_ALWAYS_INLINE void
     38 os_prof_dump_dyld_image_vmaddr(buf_writer_t *buf_writer, uint32_t image_index) {
     39 	const os_mach_header_t *header = (const os_mach_header_t *)
     40 	    _dyld_get_image_header(image_index);
     41 	if (header == NULL
     42 	    || (header->magic != OS_MH_MAGIC_VALUE
     43 	        && header->magic != OS_MH_CIGAM_VALUE)) {
     44 		/* Invalid header. */
     45 		return;
     46 	}
     47 
     48 	intptr_t             slide = _dyld_get_image_vmaddr_slide(image_index);
     49 	const char          *name = _dyld_get_image_name(image_index);
     50 	struct load_command *load_cmd = (struct load_command *)((char *)header
     51 	    + sizeof(os_mach_header_t));
     52 	for (uint32_t i = 0; load_cmd && (i < header->ncmds); i++) {
     53 		if (load_cmd->cmd == OS_LC_SEGMENT_VALUE) {
     54 			const os_segment_command_t *segment_cmd =
     55 			    (const os_segment_command_t *)load_cmd;
     56 			if (!strcmp(segment_cmd->segname, "__TEXT")) {
     57 				char buffer[PATH_MAX + 1];
     58 				malloc_snprintf(buffer, sizeof(buffer),
     59 				    "%016llx-%016llx: %s\n",
     60 				    segment_cmd->vmaddr + slide,
     61 				    segment_cmd->vmaddr + slide
     62 				        + segment_cmd->vmsize,
     63 				    name);
     64 				buf_writer_cb(buf_writer, buffer);
     65 				return;
     66 			}
     67 		}
     68 		load_cmd = (struct load_command *)((char *)load_cmd
     69 		    + load_cmd->cmdsize);
     70 	}
     71 }
     72 
     73 /*
     74  * No proc map file to read on Darwin, so os_prof_dump_maps() walks
     75  * dyld-loaded images for backtrace instead.  open_maps is never called here.
     76  */
     77 JEMALLOC_ALWAYS_INLINE void
     78 os_prof_dump_maps(buf_writer_t *buf_writer, int (*open_maps)(void)) {
     79 	(void)open_maps;
     80 	buf_writer_cb(buf_writer, "\nMAPPED_LIBRARIES:\n");
     81 	uint32_t image_count = _dyld_image_count();
     82 	for (uint32_t i = 0; i < image_count; i++) {
     83 		os_prof_dump_dyld_image_vmaddr(buf_writer, i);
     84 	}
     85 }
     86 
     87 #endif /* JEMALLOC_INTERNAL_OS_DARWIN_PROC_MAPS_H */
     88