agent/src/os/bsd/ps_core.c
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File
*** old/agent/src/os/bsd/ps_core.c	Wed Mar 13 23:31:46 2013
--- new/agent/src/os/bsd/ps_core.c	Wed Mar 13 23:31:45 2013

*** 1,7 **** --- 1,7 ---- /* ! * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. ! * 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 **** --- 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" + #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_elf_files(struct ps_prochandle* ph) { ! 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 **** --- 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); + if (fd >= 0 && fd != ph->core->exec_fd) { + close(fd); + } lib = lib->next; } } // clean all map_info stuff
*** 92,102 **** --- 94,104 ---- } // ps_prochandle operations static void core_release(struct ps_prochandle* ph) { if (ph->core) { ! close_elf_files(ph); ! close_files(ph); destroy_map_info(ph); free(ph->core); } }
*** 152,174 **** --- 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) + if (addr >= ph->core->map_array[mid]->vaddr) { lo = mid; else + } else { hi = mid; } + } if (addr < ph->core->map_array[hi]->vaddr) + if (addr < ph->core->map_array[hi]->vaddr) { mp = ph->core->map_array[lo]; else + } else { mp = ph->core->map_array[hi]; + } if (addr >= mp->vaddr && addr < mp->vaddr + mp->memsz) + 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 **** --- 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); + 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); + print_debug("located map_info at 0x%lx from class share maps\n", addr); return (mp); } mp = mp->next; }
*** 248,258 **** --- 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, &uip, sizeof(uip)) == PS_OK) { ! if (ps_pread(ph, (psaddr_t) addr, (char *)&uip, sizeof(uip)) == PS_OK) { *pvalue = uip; return true; } else { return false; }
*** 262,300 **** --- 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) + if (ps_pread(ph, (psaddr_t) addr, &c, sizeof(char)) != PS_OK) { return false; if (i < size - 1) + } + if (i < size - 1) { buf[i] = c; else // smaller buffer + } else { + // smaller buffer return false; + } i++; addr++; } buf[i] = '\0'; return true; } #define USE_SHARED_SPACES_SYM "UseSharedSpaces" + #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; ! size_t n = 0; int fd = -1, m = 0; ! 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 **** --- 405,414 ---- 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.
*** 398,409 **** --- 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) + 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 **** --- 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); + 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 **** --- 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 **** --- 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 from NOTE section ! thread_info* thr = ph->threads; ! // 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 **** --- 539,549 ---- 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 = {
*** 530,545 **** --- 552,1007 ---- .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 + // 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 **** --- 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 **** --- 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; ! 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 **** --- 1263,1272 ---- 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)
*** 847,864 **** --- 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 **** --- 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("can't 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