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