agent/src/os/bsd/ps_core.c
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File hotspot-8003348 Cdiff agent/src/os/bsd/ps_core.c

agent/src/os/bsd/ps_core.c

Print this page
8003348: SA can not read core file on OS X

*** 1,7 **** /* ! * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. --- 1,7 ---- /* ! * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.
*** 26,51 **** #include <unistd.h> #include <fcntl.h> #include <string.h> #include <stdlib.h> #include <stddef.h> - #include <elf.h> - #include <link.h> #include "libproc_impl.h" - #include "salibelf.h" // This file has the libproc implementation to read core files. // For live processes, refer to ps_proc.c. Portions of this is adapted // /modelled after Solaris libproc.so (in particular Pcore.c) //---------------------------------------------------------------------- // ps_prochandle cleanup helper functions // close all file descriptors ! static void close_elf_files(struct ps_prochandle* ph) { lib_info* lib = NULL; - // close core file descriptor if (ph->core->core_fd >= 0) close(ph->core->core_fd); // close exec file descriptor --- 26,51 ---- #include <unistd.h> #include <fcntl.h> #include <string.h> #include <stdlib.h> #include <stddef.h> #include "libproc_impl.h" + #ifdef __APPLE__ + #include "sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext.h" + #endif + // This file has the libproc implementation to read core files. // For live processes, refer to ps_proc.c. Portions of this is adapted // /modelled after Solaris libproc.so (in particular Pcore.c) //---------------------------------------------------------------------- // ps_prochandle cleanup helper functions // close all file descriptors ! static void close_files(struct ps_prochandle* ph) { lib_info* lib = NULL; // close core file descriptor if (ph->core->core_fd >= 0) close(ph->core->core_fd); // close exec file descriptor
*** 62,72 **** // close all library file descriptors lib = ph->libs; while (lib) { int fd = lib->fd; ! if (fd >= 0 && fd != ph->core->exec_fd) close(fd); lib = lib->next; } } // clean all map_info stuff --- 62,74 ---- // close all library file descriptors lib = ph->libs; while (lib) { int fd = lib->fd; ! if (fd >= 0 && fd != ph->core->exec_fd) { ! close(fd); ! } lib = lib->next; } } // clean all map_info stuff
*** 92,102 **** } // ps_prochandle operations static void core_release(struct ps_prochandle* ph) { if (ph->core) { ! close_elf_files(ph); destroy_map_info(ph); free(ph->core); } } --- 94,104 ---- } // ps_prochandle operations static void core_release(struct ps_prochandle* ph) { if (ph->core) { ! close_files(ph); destroy_map_info(ph); free(ph->core); } }
*** 152,174 **** int mid, lo = 0, hi = ph->core->num_maps - 1; map_info *mp; while (hi - lo > 1) { mid = (lo + hi) / 2; ! if (addr >= ph->core->map_array[mid]->vaddr) lo = mid; ! else hi = mid; } ! if (addr < ph->core->map_array[hi]->vaddr) mp = ph->core->map_array[lo]; ! else mp = ph->core->map_array[hi]; ! if (addr >= mp->vaddr && addr < mp->vaddr + mp->memsz) return (mp); // Part of the class sharing workaround // Unfortunately, we have no way of detecting -Xshare state. // Check out the share maps atlast, if we don't find anywhere. --- 154,179 ---- int mid, lo = 0, hi = ph->core->num_maps - 1; map_info *mp; while (hi - lo > 1) { mid = (lo + hi) / 2; ! if (addr >= ph->core->map_array[mid]->vaddr) { lo = mid; ! } else { hi = mid; } + } ! if (addr < ph->core->map_array[hi]->vaddr) { mp = ph->core->map_array[lo]; ! } else { mp = ph->core->map_array[hi]; + } ! if (addr >= mp->vaddr && addr < mp->vaddr + mp->memsz) { return (mp); + } // Part of the class sharing workaround // Unfortunately, we have no way of detecting -Xshare state. // Check out the share maps atlast, if we don't find anywhere.
*** 175,191 **** // This is done this way so to avoid reading share pages // ahead of other normal maps. For eg. with -Xshare:off we don't // want to prefer class sharing data to data from core. mp = ph->core->class_share_maps; if (mp) { ! print_debug("can't locate map_info at 0x%lx, trying class share maps\n", ! addr); } while (mp) { if (addr >= mp->vaddr && addr < mp->vaddr + mp->memsz) { ! print_debug("located map_info at 0x%lx from class share maps\n", ! addr); return (mp); } mp = mp->next; } --- 180,194 ---- // This is done this way so to avoid reading share pages // ahead of other normal maps. For eg. with -Xshare:off we don't // want to prefer class sharing data to data from core. mp = ph->core->class_share_maps; if (mp) { ! print_debug("can't locate map_info at 0x%lx, trying class share maps\n", addr); } while (mp) { if (addr >= mp->vaddr && addr < mp->vaddr + mp->memsz) { ! print_debug("located map_info at 0x%lx from class share maps\n", addr); return (mp); } mp = mp->next; }
*** 248,258 **** } } static bool read_pointer(struct ps_prochandle* ph, uintptr_t addr, uintptr_t* pvalue) { uintptr_t uip; ! if (ps_pread(ph, (psaddr_t) addr, &uip, sizeof(uip)) == PS_OK) { *pvalue = uip; return true; } else { return false; } --- 251,261 ---- } } static bool read_pointer(struct ps_prochandle* ph, uintptr_t addr, uintptr_t* pvalue) { uintptr_t uip; ! if (ps_pread(ph, (psaddr_t) addr, (char *)&uip, sizeof(uip)) == PS_OK) { *pvalue = uip; return true; } else { return false; }
*** 262,300 **** static bool read_string(struct ps_prochandle* ph, uintptr_t addr, char* buf, size_t size) { size_t i = 0; char c = ' '; while (c != '\0') { ! if (ps_pread(ph, (psaddr_t) addr, &c, sizeof(char)) != PS_OK) return false; ! if (i < size - 1) buf[i] = c; ! else // smaller buffer return false; i++; addr++; } - buf[i] = '\0'; return true; } ! #define USE_SHARED_SPACES_SYM "UseSharedSpaces" // mangled name of Arguments::SharedArchivePath #define SHARED_ARCHIVE_PATH_SYM "_ZN9Arguments17SharedArchivePathE" static bool init_classsharing_workaround(struct ps_prochandle* ph) { lib_info* lib = ph->libs; while (lib != NULL) { // we are iterating over shared objects from the core dump. look for // libjvm[_g].so. const char *jvm_name = 0; if ((jvm_name = strstr(lib->name, "/libjvm.so")) != 0 || ! (jvm_name = strstr(lib->name, "/libjvm_g.so")) != 0) { char classes_jsa[PATH_MAX]; struct FileMapHeader header; ! size_t n = 0; ! int fd = -1, m = 0; uintptr_t base = 0, useSharedSpacesAddr = 0; uintptr_t sharedArchivePathAddrAddr = 0, sharedArchivePathAddr = 0; jboolean useSharedSpaces = 0; memset(classes_jsa, 0, sizeof(classes_jsa)); --- 265,318 ---- static bool read_string(struct ps_prochandle* ph, uintptr_t addr, char* buf, size_t size) { size_t i = 0; char c = ' '; while (c != '\0') { ! if (ps_pread(ph, (psaddr_t) addr, &c, sizeof(char)) != PS_OK) { return false; ! } ! if (i < size - 1) { buf[i] = c; ! } else { ! // smaller buffer return false; + } i++; addr++; } buf[i] = '\0'; return true; } ! #ifdef __APPLE__ ! #define USE_SHARED_SPACES_SYM "_UseSharedSpaces" // mangled name of Arguments::SharedArchivePath #define SHARED_ARCHIVE_PATH_SYM "_ZN9Arguments17SharedArchivePathE" + #else + #define USE_SHARED_SPACES_SYM "UseSharedSpaces" + // mangled name of Arguments::SharedArchivePath + #define SHARED_ARCHIVE_PATH_SYM "__ZN9Arguments17SharedArchivePathE" + #endif // __APPLE_ static bool init_classsharing_workaround(struct ps_prochandle* ph) { + int m; + size_t n; lib_info* lib = ph->libs; while (lib != NULL) { // we are iterating over shared objects from the core dump. look for // libjvm[_g].so. const char *jvm_name = 0; + #ifdef __APPLE__ + if ((jvm_name = strstr(lib->name, "/libjvm.dylib")) != 0 || + (jvm_name = strstr(lib->name, "/libjvm_g.dylib")) != 0) + #else if ((jvm_name = strstr(lib->name, "/libjvm.so")) != 0 || ! (jvm_name = strstr(lib->name, "/libjvm_g.so")) != 0) ! #endif // __APPLE__ ! { char classes_jsa[PATH_MAX]; struct FileMapHeader header; ! int fd = -1; uintptr_t base = 0, useSharedSpacesAddr = 0; uintptr_t sharedArchivePathAddrAddr = 0, sharedArchivePathAddr = 0; jboolean useSharedSpaces = 0; memset(classes_jsa, 0, sizeof(classes_jsa));
*** 387,397 **** lib = lib->next; } return true; } - //--------------------------------------------------------------------------- // functions to handle map_info // Order mappings based on virtual address. We use this function as the // callback for sorting the array of map_info pointers. --- 405,414 ----
*** 398,409 **** static int core_cmp_mapping(const void *lhsp, const void *rhsp) { const map_info *lhs = *((const map_info **)lhsp); const map_info *rhs = *((const map_info **)rhsp); ! if (lhs->vaddr == rhs->vaddr) return (0); return (lhs->vaddr < rhs->vaddr ? -1 : 1); } // we sort map_info by starting virtual address so that we can do --- 415,427 ---- static int core_cmp_mapping(const void *lhsp, const void *rhsp) { const map_info *lhs = *((const map_info **)lhsp); const map_info *rhs = *((const map_info **)rhsp); ! if (lhs->vaddr == rhs->vaddr) { return (0); + } return (lhs->vaddr < rhs->vaddr ? -1 : 1); } // we sort map_info by starting virtual address so that we can do
*** 426,436 **** i++; map = map->next; } // sort is called twice. If this is second time, clear map array ! if (ph->core->map_array) free(ph->core->map_array); ph->core->map_array = array; // sort the map_info array by base virtual address. qsort(ph->core->map_array, ph->core->num_maps, sizeof (map_info*), core_cmp_mapping); --- 444,456 ---- i++; map = map->next; } // sort is called twice. If this is second time, clear map array ! if (ph->core->map_array) { ! free(ph->core->map_array); ! } ph->core->map_array = array; // sort the map_info array by base virtual address. qsort(ph->core->map_array, ph->core->num_maps, sizeof (map_info*), core_cmp_mapping);
*** 459,478 **** uintptr_t mapoff; ssize_t len, rem; off_t off; int fd; ! if (mp == NULL) break; /* No mapping for this address */ fd = mp->fd; mapoff = addr - mp->vaddr; len = MIN(resid, mp->memsz - mapoff); off = mp->offset + mapoff; ! if ((len = pread(fd, buf, len, off)) <= 0) break; resid -= len; addr += len; buf = (char *)buf + len; --- 479,500 ---- uintptr_t mapoff; ssize_t len, rem; off_t off; int fd; ! if (mp == NULL) { break; /* No mapping for this address */ + } fd = mp->fd; mapoff = addr - mp->vaddr; len = MIN(resid, mp->memsz - mapoff); off = mp->offset + mapoff; ! if ((len = pread(fd, buf, len, off)) <= 0) { break; + } resid -= len; addr += len; buf = (char *)buf + len;
*** 505,516 **** return false; } static bool core_get_lwp_regs(struct ps_prochandle* ph, lwpid_t lwp_id, struct reg* regs) { ! // for core we have cached the lwp regs from NOTE section ! thread_info* thr = ph->threads; while (thr) { if (thr->lwp_id == lwp_id) { memcpy(regs, &thr->regs, sizeof(struct reg)); return true; } --- 527,538 ---- return false; } static bool core_get_lwp_regs(struct ps_prochandle* ph, lwpid_t lwp_id, struct reg* regs) { ! // for core we have cached the lwp regs after segment parsed ! sa_thread_info* thr = ph->threads; while (thr) { if (thr->lwp_id == lwp_id) { memcpy(regs, &thr->regs, sizeof(struct reg)); return true; }
*** 517,527 **** thr = thr->next; } return false; } ! static bool core_get_lwp_info(struct ps_prochandle *ph, lwpid_t lwp_id, void *linfo) { print_debug("core_get_lwp_info not implemented\n"); return false; } static ps_prochandle_ops core_ops = { --- 539,549 ---- thr = thr->next; } return false; } ! static bool core_get_lwp_info(struct ps_prochandle *ph, lwpid_t id, void *info) { print_debug("core_get_lwp_info not implemented\n"); return false; } static ps_prochandle_ops core_ops = {
*** 530,545 **** .p_pwrite= core_write_data, .get_lwp_regs= core_get_lwp_regs, .get_lwp_info= core_get_lwp_info }; ! // read regs and create thread from NT_PRSTATUS entries from core file static bool core_handle_prstatus(struct ps_prochandle* ph, const char* buf, size_t nbytes) { // we have to read prstatus_t from buf // assert(nbytes == sizeof(prstaus_t), "size mismatch on prstatus_t"); prstatus_t* prstat = (prstatus_t*) buf; ! thread_info* newthr; print_debug("got integer regset for lwp %d\n", prstat->pr_pid); // we set pthread_t to -1 for core dump if((newthr = add_thread_info(ph, (pthread_t) -1, prstat->pr_pid)) == NULL) return false; --- 552,1007 ---- .p_pwrite= core_write_data, .get_lwp_regs= core_get_lwp_regs, .get_lwp_info= core_get_lwp_info }; ! // from this point, mainly two blocks divided by def __APPLE__ ! // one for Macosx, the other for regular Bsd ! ! #ifdef __APPLE__ ! ! void print_thread(sa_thread_info *threadinfo) { ! print_debug("thread added: %d\n", threadinfo->lwp_id); ! print_debug("registers:\n"); ! print_debug(" r_r15: 0x%" PRIx64 "\n", threadinfo->regs.r_r15); ! print_debug(" r_r14: 0x%" PRIx64 "\n", threadinfo->regs.r_r14); ! print_debug(" r_r13: 0x%" PRIx64 "\n", threadinfo->regs.r_r13); ! print_debug(" r_r12: 0x%" PRIx64 "\n", threadinfo->regs.r_r12); ! print_debug(" r_r11: 0x%" PRIx64 "\n", threadinfo->regs.r_r11); ! print_debug(" r_r10: 0x%" PRIx64 "\n", threadinfo->regs.r_r10); ! print_debug(" r_r9: 0x%" PRIx64 "\n", threadinfo->regs.r_r9); ! print_debug(" r_r8: 0x%" PRIx64 "\n", threadinfo->regs.r_r8); ! print_debug(" r_rdi: 0x%" PRIx64 "\n", threadinfo->regs.r_rdi); ! print_debug(" r_rsi: 0x%" PRIx64 "\n", threadinfo->regs.r_rsi); ! print_debug(" r_rbp: 0x%" PRIx64 "\n", threadinfo->regs.r_rbp); ! print_debug(" r_rbx: 0x%" PRIx64 "\n", threadinfo->regs.r_rbx); ! print_debug(" r_rdx: 0x%" PRIx64 "\n", threadinfo->regs.r_rdx); ! print_debug(" r_rcx: 0x%" PRIx64 "\n", threadinfo->regs.r_rcx); ! print_debug(" r_rax: 0x%" PRIx64 "\n", threadinfo->regs.r_rax); ! print_debug(" r_fs: 0x%" PRIx32 "\n", threadinfo->regs.r_fs); ! print_debug(" r_gs: 0x%" PRIx32 "\n", threadinfo->regs.r_gs); ! print_debug(" r_rip 0x%" PRIx64 "\n", threadinfo->regs.r_rip); ! print_debug(" r_cs: 0x%" PRIx64 "\n", threadinfo->regs.r_cs); ! print_debug(" r_rsp: 0x%" PRIx64 "\n", threadinfo->regs.r_rsp); ! print_debug(" r_rflags: 0x%" PRIx64 "\n", threadinfo->regs.r_rflags); ! } ! ! // read all segments64 commands from core file ! // read all thread commands from core file ! static bool read_core_segments(struct ps_prochandle* ph) { ! int i = 0; ! int num_threads = 0; ! int fd = ph->core->core_fd; ! off_t offset = 0; ! mach_header_64 fhead; ! load_command lcmd; ! segment_command_64 segcmd; ! // thread_command thrcmd; ! ! lseek(fd, offset, SEEK_SET); ! if(read(fd, (void *)&fhead, sizeof(mach_header_64)) != sizeof(mach_header_64)) { ! goto err; ! } ! print_debug("total commands: %d\n", fhead.ncmds); ! offset += sizeof(mach_header_64); ! for (i = 0; i < fhead.ncmds; i++) { ! lseek(fd, offset, SEEK_SET); ! if (read(fd, (void *)&lcmd, sizeof(load_command)) != sizeof(load_command)) { ! goto err; ! } ! offset += lcmd.cmdsize; // next command position ! if (lcmd.cmd == LC_SEGMENT_64) { ! lseek(fd, -sizeof(load_command), SEEK_CUR); ! if (read(fd, (void *)&segcmd, sizeof(segment_command_64)) != sizeof(segment_command_64)) { ! print_debug("failed to read LC_SEGMENT_64 i = %d!\n", i); ! goto err; ! } ! if (add_map_info(ph, fd, segcmd.fileoff, segcmd.vmaddr, segcmd.vmsize) == NULL) { ! print_debug("Failed to add map_info at i = %d\n", i); ! goto err; ! } ! print_debug("segment added: %" PRIu64 " 0x%" PRIx64 " %d\n", ! segcmd.fileoff, segcmd.vmaddr, segcmd.vmsize); ! } else if (lcmd.cmd == LC_THREAD || lcmd.cmd == LC_UNIXTHREAD) { ! typedef struct thread_fc { ! uint32_t flavor; ! uint32_t count; ! } thread_fc; ! thread_fc fc; ! uint32_t size = sizeof(load_command); ! while (size < lcmd.cmdsize) { ! if (read(fd, (void *)&fc, sizeof(thread_fc)) != sizeof(thread_fc)) { ! printf("Reading flavor, count failed.\n"); ! goto err; ! } ! size += sizeof(thread_fc); ! if (fc.flavor == x86_THREAD_STATE) { ! x86_thread_state_t thrstate; ! if (read(fd, (void *)&thrstate, sizeof(x86_thread_state_t)) != sizeof(x86_thread_state_t)) { ! printf("Reading flavor, count failed.\n"); ! goto err; ! } ! size += sizeof(x86_thread_state_t); ! // create thread info list, update lwp_id later ! sa_thread_info* newthr = add_thread_info(ph, (pthread_t) -1, (lwpid_t) num_threads++); ! if (newthr == NULL) { ! printf("create thread_info failed\n"); ! goto err; ! } ! ! // note __DARWIN_UNIX03 depengs on other definitions ! #if __DARWIN_UNIX03 ! #define get_register_v(regst, regname) \ ! regst.uts.ts64.__##regname ! #else ! #define get_register_v(regst, regname) \ ! regst.uts.ts64.##regname ! #endif // __DARWIN_UNIX03 ! newthr->regs.r_rax = get_register_v(thrstate, rax); ! newthr->regs.r_rbx = get_register_v(thrstate, rbx); ! newthr->regs.r_rcx = get_register_v(thrstate, rcx); ! newthr->regs.r_rdx = get_register_v(thrstate, rdx); ! newthr->regs.r_rdi = get_register_v(thrstate, rdi); ! newthr->regs.r_rsi = get_register_v(thrstate, rsi); ! newthr->regs.r_rbp = get_register_v(thrstate, rbp); ! newthr->regs.r_rsp = get_register_v(thrstate, rsp); ! newthr->regs.r_r8 = get_register_v(thrstate, r8); ! newthr->regs.r_r9 = get_register_v(thrstate, r9); ! newthr->regs.r_r10 = get_register_v(thrstate, r10); ! newthr->regs.r_r11 = get_register_v(thrstate, r11); ! newthr->regs.r_r12 = get_register_v(thrstate, r12); ! newthr->regs.r_r13 = get_register_v(thrstate, r13); ! newthr->regs.r_r14 = get_register_v(thrstate, r14); ! newthr->regs.r_r15 = get_register_v(thrstate, r15); ! newthr->regs.r_rip = get_register_v(thrstate, rip); ! newthr->regs.r_rflags = get_register_v(thrstate, rflags); ! newthr->regs.r_cs = get_register_v(thrstate, cs); ! newthr->regs.r_fs = get_register_v(thrstate, fs); ! newthr->regs.r_gs = get_register_v(thrstate, gs); ! print_thread(newthr); ! } else if (fc.flavor == x86_FLOAT_STATE) { ! x86_float_state_t flstate; ! if (read(fd, (void *)&flstate, sizeof(x86_float_state_t)) != sizeof(x86_float_state_t)) { ! print_debug("Reading flavor, count failed.\n"); ! goto err; ! } ! size += sizeof(x86_float_state_t); ! } else if (fc.flavor == x86_EXCEPTION_STATE) { ! x86_exception_state_t excpstate; ! if (read(fd, (void *)&excpstate, sizeof(x86_exception_state_t)) != sizeof(x86_exception_state_t)) { ! printf("Reading flavor, count failed.\n"); ! goto err; ! } ! size += sizeof(x86_exception_state_t); ! } ! } ! } ! } ! return true; ! err: ! return false; ! } ! ! /**local function **/ ! bool exists(const char *fname) ! { ! int fd; ! if ((fd = open(fname, O_RDONLY)) > 0) { ! close(fd); ! return true; ! } ! return false; ! } ! ! // we check: 1. lib ! // 2. lib/server ! // 3. jre/lib ! // 4. jre/lib/server ! // from: 1. exe path ! // 2. JAVA_HOME ! // 3. DYLD_LIBRARY_PATH ! static bool get_real_path(struct ps_prochandle* ph, char *rpath) { ! /** check if they exist in JAVA ***/ ! char* execname = ph->core->exec_path; ! char filepath[4096]; ! char* filename = strrchr(rpath, '/'); // like /libjvm.dylib ! if (filename == NULL) { ! return false; ! } ! ! char* posbin = strstr(execname, "/bin/java"); ! if (posbin != NULL) { ! memcpy(filepath, execname, posbin - execname); // not include trailing '/' ! filepath[posbin - execname] = '\0'; ! } else { ! char* java_home = getenv("JAVA_HOME"); ! if (java_home != NULL) { ! strcpy(filepath, java_home); ! } else { ! char* dyldpath = getenv("DYLD_LIBRARY_PATH"); ! char* dypath = strtok(dyldpath, ":"); ! while (dypath != NULL) { ! strcpy(filepath, dypath); ! strcat(filepath, filename); ! if (exists(filepath)) { ! strcpy(rpath, filepath); ! return true; ! } ! dypath = strtok(dyldpath, ":"); ! } ! // not found ! return false; ! } ! } ! // for exec and java_home, jdkpath now is filepath ! size_t filepath_base_size = strlen(filepath); ! ! // first try /lib/ and /lib/server ! strcat(filepath, "/lib"); ! strcat(filepath, filename); ! if (exists(filepath)) { ! strcpy(rpath, filepath); ! return true; ! } ! char* pos = strstr(filepath, filename); // like /libjvm.dylib ! *pos = '\0'; ! strcat(filepath, "/server"); ! strcat(filepath, filename); ! if (exists(filepath)) { ! strcpy(rpath, filepath); ! return true; ! } ! ! ! // then try /jre/lib/ and /jre/lib/server ! filepath[filepath_base_size] = '\0'; ! strcat(filepath, "/jre/lib"); ! strcat(filepath, filename); ! if (exists(filepath)) { ! strcpy(rpath, filepath); ! return true; ! } ! pos = strstr(filepath, filename); ! *pos = '\0'; ! strcat(filepath, "/server"); ! strcat(filepath, filename); ! if (exists(filepath)) { ! strcpy(rpath, filepath); ! return true; ! } ! ! return false; ! } ! ! static bool read_shared_lib_info(struct ps_prochandle* ph) { ! static int pagesize = 0; ! int fd = ph->core->core_fd; ! int i = 0, j; ! uint32_t v; ! mach_header_64 header; // used to check if a file header in segment ! load_command lcmd; ! dylib_command dylibcmd; ! ! char name[BUF_SIZE]; // use to store name ! ! if (pagesize == 0) { ! pagesize = getpagesize(); ! print_debug("page size is %d\n", pagesize); ! } ! for (j = 0; j < ph->core->num_maps; j++) { ! map_info *iter = ph->core->map_array[j]; // head ! off_t fpos = iter->offset; ! if (iter->fd != fd) { ! // only search core file! ! continue; ! } ! print_debug("map_info %d: vmaddr = 0x%016" PRIx64 " fileoff = %" PRIu64 " vmsize = %" PRIu64 "\n", ! j, iter->vaddr, iter->offset, iter->memsz); ! lseek(fd, fpos, SEEK_SET); ! // we assume .dylib loaded at segment address --- which is true for JVM libraries ! // multiple files may be loaded in one segment. ! // if first word is not a magic word, means this segment does not contain lib file. ! if (read(fd, (void *)&v, sizeof(uint32_t)) == sizeof(uint32_t)) { ! if (v != MH_MAGIC_64) { ! continue; ! } ! } else { ! // may be encountered last map, which is not readable ! continue; ! } ! while (ltell(fd) - iter->offset < iter->memsz) { ! lseek(fd, fpos, SEEK_SET); ! if (read(fd, (void *)&v, sizeof(uint32_t)) != sizeof(uint32_t)) { ! break; ! } ! if (v != MH_MAGIC_64) { ! fpos = (ltell(fd) + pagesize -1)/pagesize * pagesize; ! continue; ! } ! lseek(fd, -sizeof(uint32_t), SEEK_CUR); ! // this is the file begining to core file. ! if (read(fd, (void *)&header, sizeof(mach_header_64)) != sizeof(mach_header_64)) { ! goto err; ! } ! fpos = ltell(fd); ! ! // found a mach-o file in this segment ! for (i = 0; i < header.ncmds; i++) { ! // read commands in this "file" ! // LC_ID_DYLIB is the file itself for a .dylib ! lseek(fd, fpos, SEEK_SET); ! if (read(fd, (void *)&lcmd, sizeof(load_command)) != sizeof(load_command)) { ! return false; // error ! } ! fpos += lcmd.cmdsize; // next command position ! // make sure still within seg size. ! if (fpos - lcmd.cmdsize - iter->offset > iter->memsz) { ! print_debug("Warning: out of segement limit: %ld \n", fpos - lcmd.cmdsize - iter->offset); ! break; // no need to iterate all commands ! } ! if (lcmd.cmd == LC_ID_DYLIB) { ! lseek(fd, -sizeof(load_command), SEEK_CUR); ! if (read(fd, (void *)&dylibcmd, sizeof(dylib_command)) != sizeof(dylib_command)) { ! return false; ! } ! /**** name stored at dylib_command.dylib.name.offset, is a C string */ ! lseek(fd, dylibcmd.dylib.name.offset - sizeof(dylib_command), SEEK_CUR); ! int j = 0; ! while (j < BUF_SIZE) { ! read(fd, (void *)(name + j), sizeof(char)); ! if (name[j] == '\0') break; ! j++; ! } ! print_debug("%s\n", name); ! // changed name from @rpath/xxxx.dylib to real path ! if (strrchr(name, '@')) { ! get_real_path(ph, name); ! print_debug("get_real_path returned: %s\n", name); ! } ! add_lib_info(ph, name, iter->vaddr); ! break; ! } ! } ! // done with the file, advanced to next page to search more files ! fpos = (ltell(fd) + pagesize - 1) / pagesize * pagesize; ! } ! } ! return true; ! err: ! return false; ! } ! ! bool read_macho64_header(int fd, mach_header_64* core_header) { ! bool is_macho = false; ! if (fd < 0) return false; ! off_t pos = ltell(fd); ! lseek(fd, 0, SEEK_SET); ! if (read(fd, (void *)core_header, sizeof(mach_header_64)) != sizeof(mach_header_64)) { ! is_macho = false; ! } else { ! is_macho = (core_header->magic == MH_MAGIC_64 || core_header->magic == MH_CIGAM_64); ! } ! lseek(fd, pos, SEEK_SET); ! return is_macho; ! } ! ! // the one and only one exposed stuff from this file ! struct ps_prochandle* Pgrab_core(const char* exec_file, const char* core_file) { ! mach_header_64 core_header; ! mach_header_64 exec_header; ! ! struct ps_prochandle* ph = (struct ps_prochandle*) calloc(1, sizeof(struct ps_prochandle)); ! if (ph == NULL) { ! print_debug("cant allocate ps_prochandle\n"); ! return NULL; ! } ! ! if ((ph->core = (struct core_data*) calloc(1, sizeof(struct core_data))) == NULL) { ! free(ph); ! print_debug("can't allocate ps_prochandle\n"); ! return NULL; ! } ! ! // initialize ph ! ph->ops = &core_ops; ! ph->core->core_fd = -1; ! ph->core->exec_fd = -1; ! ph->core->interp_fd = -1; ! ! print_debug("exec: %s core: %s", exec_file, core_file); ! ! strncpy(ph->core->exec_path, exec_file, sizeof(ph->core->exec_path)); ! ! // open the core file ! if ((ph->core->core_fd = open(core_file, O_RDONLY)) < 0) { ! print_error("can't open core file\n"); ! goto err; ! } ! ! // read core file header ! if (read_macho64_header(ph->core->core_fd, &core_header) != true || core_header.filetype != MH_CORE) { ! print_debug("core file is not a valid Mach-O file\n"); ! goto err; ! } ! ! if ((ph->core->exec_fd = open(exec_file, O_RDONLY)) < 0) { ! print_error("can't open executable file\n"); ! goto err; ! } ! ! if (read_macho64_header(ph->core->exec_fd, &exec_header) != true || ! exec_header.filetype != MH_EXECUTE) { ! print_error("executable file is not a valid Mach-O file\n"); ! goto err; ! } ! ! // process core file segments ! if (read_core_segments(ph) != true) { ! print_error("failed to read core segments\n"); ! goto err; ! } ! ! // allocate and sort maps into map_array, we need to do this ! // here because read_shared_lib_info needs to read from debuggee ! // address space ! if (sort_map_array(ph) != true) { ! print_error("failed to sort segment map array\n"); ! goto err; ! } ! ! if (read_shared_lib_info(ph) != true) { ! print_error("failed to read libraries\n"); ! goto err; ! } ! ! // sort again because we have added more mappings from shared objects ! if (sort_map_array(ph) != true) { ! print_error("failed to sort segment map array\n"); ! goto err; ! } ! ! if (init_classsharing_workaround(ph) != true) { ! print_error("failed to workaround classshareing\n"); ! goto err; ! } ! ! print_debug("Leave Pgrab_core\n"); ! return ph; ! ! err: ! Prelease(ph); ! return NULL; ! } ! ! #else // __APPLE__ (none macosx) ! ! // read regs and create thread from core file static bool core_handle_prstatus(struct ps_prochandle* ph, const char* buf, size_t nbytes) { // we have to read prstatus_t from buf // assert(nbytes == sizeof(prstaus_t), "size mismatch on prstatus_t"); prstatus_t* prstat = (prstatus_t*) buf; ! sa_thread_info* newthr; print_debug("got integer regset for lwp %d\n", prstat->pr_pid); // we set pthread_t to -1 for core dump if((newthr = add_thread_info(ph, (pthread_t) -1, prstat->pr_pid)) == NULL) return false;
*** 630,642 **** char* descdata = p + sizeof(ELF_NHDR) + ROUNDUP(notep->n_namesz, 4); print_debug("Note header with n_type = %d and n_descsz = %u\n", notep->n_type, notep->n_descsz); if (notep->n_type == NT_PRSTATUS) { ! if (core_handle_prstatus(ph, descdata, notep->n_descsz) != true) return false; } p = descdata + ROUNDUP(notep->n_descsz, 4); } free(buf); return true; --- 1092,1105 ---- char* descdata = p + sizeof(ELF_NHDR) + ROUNDUP(notep->n_namesz, 4); print_debug("Note header with n_type = %d and n_descsz = %u\n", notep->n_type, notep->n_descsz); if (notep->n_type == NT_PRSTATUS) { ! if (core_handle_prstatus(ph, descdata, notep->n_descsz) != true) { return false; } + } p = descdata + ROUNDUP(notep->n_descsz, 4); } free(buf); return true;
*** 679,689 **** */ for (core_php = phbuf, i = 0; i < core_ehdr->e_phnum; i++) { switch (core_php->p_type) { case PT_NOTE: ! if (core_handle_note(ph, core_php) != true) goto err; break; case PT_LOAD: { if (core_php->p_filesz != 0) { if (add_map_info(ph, ph->core->core_fd, core_php->p_offset, --- 1142,1154 ---- */ for (core_php = phbuf, i = 0; i < core_ehdr->e_phnum; i++) { switch (core_php->p_type) { case PT_NOTE: ! if (core_handle_note(ph, core_php) != true) { ! goto err; ! } break; case PT_LOAD: { if (core_php->p_filesz != 0) { if (add_map_info(ph, ph->core->core_fd, core_php->p_offset,
*** 798,808 **** err: free(phbuf); return false; } - #define FIRST_LINK_MAP_OFFSET offsetof(struct r_debug, r_map) #define LD_BASE_OFFSET offsetof(struct r_debug, r_ldbase) #define LINK_MAP_ADDR_OFFSET offsetof(struct link_map, l_addr) #define LINK_MAP_NAME_OFFSET offsetof(struct link_map, l_name) #define LINK_MAP_NEXT_OFFSET offsetof(struct link_map, l_next) --- 1263,1272 ----
*** 847,864 **** return false; } // read ld_base address from struct r_debug // XXX: There is no r_ldbase member on BSD ! /* if (ps_pread(ph, (psaddr_t) debug_base + LD_BASE_OFFSET, &ld_base_addr, sizeof(uintptr_t)) != PS_OK) { print_debug("can't read ld base address\n"); return false; } ph->core->ld_base_addr = ld_base_addr; ! */ ph->core->ld_base_addr = 0; print_debug("interpreter base address is 0x%lx\n", ld_base_addr); // now read segments from interp (i.e ld-elf.so.1) --- 1311,1328 ---- return false; } // read ld_base address from struct r_debug // XXX: There is no r_ldbase member on BSD ! /* if (ps_pread(ph, (psaddr_t) debug_base + LD_BASE_OFFSET, &ld_base_addr, sizeof(uintptr_t)) != PS_OK) { print_debug("can't read ld base address\n"); return false; } ph->core->ld_base_addr = ld_base_addr; ! */ ph->core->ld_base_addr = 0; print_debug("interpreter base address is 0x%lx\n", ld_base_addr); // now read segments from interp (i.e ld-elf.so.1)
*** 945,955 **** ELF_EHDR core_ehdr; ELF_EHDR exec_ehdr; struct ps_prochandle* ph = (struct ps_prochandle*) calloc(1, sizeof(struct ps_prochandle)); if (ph == NULL) { ! print_debug("can't allocate ps_prochandle\n"); return NULL; } if ((ph->core = (struct core_data*) calloc(1, sizeof(struct core_data))) == NULL) { free(ph); --- 1409,1419 ---- ELF_EHDR core_ehdr; ELF_EHDR exec_ehdr; struct ps_prochandle* ph = (struct ps_prochandle*) calloc(1, sizeof(struct ps_prochandle)); if (ph == NULL) { ! print_debug("cant allocate ps_prochandle\n"); return NULL; } if ((ph->core = (struct core_data*) calloc(1, sizeof(struct core_data))) == NULL) { free(ph);
*** 961,970 **** --- 1425,1436 ---- ph->ops = &core_ops; ph->core->core_fd = -1; ph->core->exec_fd = -1; ph->core->interp_fd = -1; + print_debug("exec: %s core: %s", exec_file, core_file); + // open the core file if ((ph->core->core_fd = open(core_file, O_RDONLY)) < 0) { print_debug("can't open core file\n"); goto err; }
*** 1012,1022 **** --- 1478,1491 ---- goto err; if (init_classsharing_workaround(ph) != true) goto err; + print_debug("Leave Pgrab_core\n"); return ph; err: Prelease(ph); return NULL; } + + #endif // __APPLE__
agent/src/os/bsd/ps_core.c
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File