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