提交 8458636d 编写于 作者: M minqi

8003348: SA can not read core file on OS

Summary: Macosx uses Mach-O file format for binary files, not ELF format. Currently SA works on core files on other platforms, t his change enables SA work on core file generated on Darwin.
Reviewed-by: sla, sspitsyn
Contributed-by: yumin.qi@oracle.com
上级 cdc18c13
#
# Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2002, 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
......@@ -22,34 +22,60 @@
#
#
ARCH := $(shell if ([ `uname -m` = "ia64" ]) ; then echo ia64 ; elif ([ `uname -m` = "amd64" ]) ; then echo amd64; elif ([ `uname -m` = "sparc64" ]) ; then echo sparc; else echo i386 ; fi )
ARCH := $(shell if ([ `uname -m` = "ia64" ]) ; then echo ia64 ; elif ([ `uname -m` = "amd64" ]) ; then echo amd64; elif ([ `uname -m` = "x86_64" ]) ; then echo amd64; elif ([ `uname -m` = "sparc64" ]) ; then echo sparc; else echo i386 ; fi )
OS := $(shell uname -s)
GCC = gcc
JAVAH = ${JAVA_HOME}/bin/javah
ifneq ($(OS), Darwin)
SOURCES = salibelf.c \
symtab.c \
libproc_impl.c \
ps_proc.c \
ps_core.c \
BsdDebuggerLocal.c
OBJS = $(SOURCES:.c=.o)
OBJSPLUS = $(OBJS) sadis.o
LIBSA = $(ARCH)/libsaproc.so
INCLUDES = -I${JAVA_HOME}/include -I${JAVA_HOME}/include/$(shell uname -s | tr "[:upper:]" "[:lower:]")
LIBS = -lutil -lthread_db
OBJS = $(SOURCES:.c=.o)
else
LIBS = -lutil -lthread_db
SOURCES = symtab.c \
libproc_impl.c \
ps_core.c
OBJS = $(SOURCES:.c=.o)
OBJSPLUS = MacosxDebuggerLocal.o sadis.o $(OBJS)
EXTINCLUDE = -I/System/Library/Frameworks/JavaVM.framework/Headers -I.
EXTCFLAGS = -m64 -D__APPLE__ -framework JavaNativeFoundation
FOUNDATIONFLAGS = -framework Foundation -F/System/Library/Frameworks/JavaVM.framework/Frameworks -framework JavaNativeFoundation -framework Security -framework CoreFoundation
LIBSA = $(ARCH)/libsaproc.dylib
endif # Darwin
INCLUDES = -I${JAVA_HOME}/include -I${JAVA_HOME}/include/$(shell uname -s | tr "[:upper:]" "[:lower:]") $(EXTINCLUDE)
CFLAGS = -c -fPIC -g -Wall -D_ALLBSD_SOURCE -D_GNU_SOURCE -D$(ARCH) $(INCLUDES) $(EXTCFLAGS)
CFLAGS = -c -fPIC -g -Wall -D_ALLBSD_SOURCE -D_GNU_SOURCE -D$(ARCH) $(INCLUDES)
LIBSA = $(ARCH)/libsaproc.so
all: $(LIBSA)
BsdDebuggerLocal.o: BsdDebuggerLocal.c
$(JAVAH) -jni -classpath ../../../../../build/bsd-i586/hotspot/outputdir/bsd_i486_compiler2/generated/saclasses \
MacosxDebuggerLocal.o: MacosxDebuggerLocal.m
echo "OS="$(OS)
$(JAVAH) -jni -classpath ../../../build/classes \
sun.jvm.hotspot.debugger.x86.X86ThreadContext \
sun.jvm.hotspot.debugger.amd64.AMD64ThreadContext
$(GCC) $(CFLAGS) $(FOUNDATIONFLAGS) $<
sadis.o: ../../share/native/sadis.c
$(JAVAH) -jni -classpath ../../../build/classes \
sun.jvm.hotspot.asm.Disassembler
$(GCC) $(CFLAGS) $<
.c.obj:
......@@ -59,9 +85,9 @@ ifndef LDNOMAP
LFLAGS_LIBSA = -Xlinker --version-script=mapfile
endif
$(LIBSA): $(OBJS) mapfile
$(LIBSA): $(OBJSPLUS) mapfile
if [ ! -d $(ARCH) ] ; then mkdir $(ARCH) ; fi
$(GCC) -shared $(LFLAGS_LIBSA) -o $(LIBSA) $(OBJS) $(LIBS)
$(GCC) -shared $(LFLAGS_LIBSA) -o $(LIBSA) $(FOUNDATIONFLAGS) $(OBJSPLUS) $(LIBS) $(SALIBS)
test.o: $(LIBSA) test.c
$(GCC) -c -o test.o -g -D_GNU_SOURCE -D$(ARCH) $(INCLUDES) test.c
......@@ -71,7 +97,6 @@ test: test.o
clean:
rm -f $(LIBSA)
rm -f $(OBJS)
rm -f *.o
rm -f test.o
-rmdir $(ARCH)
/*
* Copyright (c) 2003, 2007, 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
......@@ -27,9 +27,38 @@
#include <unistd.h>
#include <stdint.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#ifdef __APPLE__
typedef enum ps_err_e {
PS_OK, PS_ERR, PS_BADPID, PS_BADLID,
PS_BADADDR, PS_NOSYM, PS_NOFREGS
} ps_err_e;
#ifndef psaddr_t
#define psaddr_t uintptr_t
#endif
#ifndef bool
typedef int bool;
#define true 1
#define false 0
#endif // bool
#ifndef lwpid_t
#define lwpid_t uintptr_t
#endif
#include <mach/thread_status.h>
#else // __APPLE__
#include <elf.h>
#include <link.h>
#include <machine/reg.h>
#include <proc_service.h>
#if defined(sparc) || defined(sparcv9)
/*
If _LP64 is defined ptrace.h should be taken from /usr/include/asm-sparc64
......@@ -44,6 +73,14 @@
#endif //sparc or sparcv9
// This C bool type must be int for compatibility with BSD calls and
// it would be a mistake to equivalence it to C++ bool on many platforms
typedef int bool;
#define true 1
#define false 0
#endif // __APPLE__
/************************************************************************************
0. This is very minimal subset of Solaris libproc just enough for current application.
......@@ -72,13 +109,7 @@ combination of ptrace and /proc calls.
*************************************************************************************/
// This C bool type must be int for compatibility with BSD calls and
// it would be a mistake to equivalence it to C++ bool on many platforms
typedef int bool;
#define true 1
#define false 0
struct reg;
struct ps_prochandle;
// attach to a process
......
......@@ -21,12 +21,6 @@
* questions.
*
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <thread_db.h>
#include "libproc_impl.h"
static const char* alt_root = NULL;
......@@ -34,61 +28,65 @@ static int alt_root_len = -1;
#define SA_ALTROOT "SA_ALTROOT"
off_t ltell(int fd) {
return lseek(fd, 0, SEEK_CUR);
}
static void init_alt_root() {
if (alt_root_len == -1) {
alt_root = getenv(SA_ALTROOT);
if (alt_root) {
alt_root_len = strlen(alt_root);
} else {
alt_root_len = 0;
}
}
if (alt_root_len == -1) {
alt_root = getenv(SA_ALTROOT);
if (alt_root) {
alt_root_len = strlen(alt_root);
} else {
alt_root_len = 0;
}
}
}
int pathmap_open(const char* name) {
int fd;
char alt_path[PATH_MAX + 1];
int fd;
char alt_path[PATH_MAX + 1];
init_alt_root();
init_alt_root();
fd = open(name, O_RDONLY);
if (fd >= 0) {
if (alt_root_len > 0) {
strcpy(alt_path, alt_root);
strcat(alt_path, name);
fd = open(alt_path, O_RDONLY);
if (fd >= 0) {
print_debug("path %s substituted for %s\n", alt_path, name);
return fd;
}
}
if (alt_root_len > 0) {
if (strrchr(name, '/')) {
strcpy(alt_path, alt_root);
strcat(alt_path, name);
strcat(alt_path, strrchr(name, '/'));
fd = open(alt_path, O_RDONLY);
if (fd >= 0) {
print_debug("path %s substituted for %s\n", alt_path, name);
return fd;
}
if (strrchr(name, '/')) {
strcpy(alt_path, alt_root);
strcat(alt_path, strrchr(name, '/'));
fd = open(alt_path, O_RDONLY);
if (fd >= 0) {
print_debug("path %s substituted for %s\n", alt_path, name);
return fd;
}
print_debug("path %s substituted for %s\n", alt_path, name);
return fd;
}
}
return -1;
}
} else {
fd = open(name, O_RDONLY);
if (fd >= 0) {
return fd;
}
}
return -1;
}
static bool _libsaproc_debug;
void print_debug(const char* format,...) {
if (_libsaproc_debug) {
va_list alist;
if (_libsaproc_debug) {
va_list alist;
va_start(alist, format);
fputs("libsaproc DEBUG: ", stderr);
vfprintf(stderr, format, alist);
va_end(alist);
}
va_start(alist, format);
fputs("libsaproc DEBUG: ", stderr);
vfprintf(stderr, format, alist);
va_end(alist);
}
}
void print_error(const char* format,...) {
......@@ -100,172 +98,235 @@ void print_error(const char* format,...) {
}
bool is_debug() {
return _libsaproc_debug;
return _libsaproc_debug;
}
#ifdef __APPLE__
// get arch offset in file
bool get_arch_off(int fd, cpu_type_t cputype, off_t *offset) {
struct fat_header fatheader;
struct fat_arch fatarch;
off_t img_start = 0;
off_t pos = ltell(fd);
if (read(fd, (void *)&fatheader, sizeof(struct fat_header)) != sizeof(struct fat_header)) {
return false;
}
if (fatheader.magic == FAT_CIGAM) {
int i;
for (i = 0; i < ntohl(fatheader.nfat_arch); i++) {
if (read(fd, (void *)&fatarch, sizeof(struct fat_arch)) != sizeof(struct fat_arch)) {
return false;
}
if (ntohl(fatarch.cputype) == cputype) {
print_debug("fat offset=%x\n", ntohl(fatarch.offset));
img_start = ntohl(fatarch.offset);
break;
}
}
if (img_start == 0) {
return false;
}
}
lseek(fd, pos, SEEK_SET);
*offset = img_start;
return true;
}
bool is_macho_file(int fd) {
mach_header_64 fhdr;
off_t x86_64_off;
if (fd < 0) {
print_debug("Invalid file handle passed to is_macho_file\n");
return false;
}
off_t pos = ltell(fd);
// check fat header
if (!get_arch_off(fd, CPU_TYPE_X86_64, &x86_64_off)) {
print_debug("failed to get fat header\n");
return false;
}
lseek(fd, x86_64_off, SEEK_SET);
if (read(fd, (void *)&fhdr, sizeof(mach_header_64)) != sizeof(mach_header_64)) {
return false;
}
lseek(fd, pos, SEEK_SET); // restore
print_debug("fhdr.magic %x\n", fhdr.magic);
return (fhdr.magic == MH_MAGIC_64 || fhdr.magic == MH_CIGAM_64);
}
#endif //__APPLE__
// initialize libproc
bool init_libproc(bool debug) {
// init debug mode
_libsaproc_debug = debug;
#ifndef __APPLE__
// initialize the thread_db library
if (td_init() != TD_OK) {
print_debug("libthread_db's td_init failed\n");
return false;
}
#endif // __APPLE__
return true;
}
static void destroy_lib_info(struct ps_prochandle* ph) {
lib_info* lib = ph->libs;
while (lib) {
lib_info *next = lib->next;
if (lib->symtab) {
destroy_symtab(lib->symtab);
}
free(lib);
lib = next;
}
void destroy_lib_info(struct ps_prochandle* ph) {
lib_info* lib = ph->libs;
while (lib) {
lib_info* next = lib->next;
if (lib->symtab) {
destroy_symtab(lib->symtab);
}
free(lib);
lib = next;
}
}
static void destroy_thread_info(struct ps_prochandle* ph) {
thread_info* thr = ph->threads;
while (thr) {
thread_info *next = thr->next;
free(thr);
thr = next;
}
void destroy_thread_info(struct ps_prochandle* ph) {
sa_thread_info* thr = ph->threads;
while (thr) {
sa_thread_info* n = thr->next;
free(thr);
thr = n;
}
}
// ps_prochandle cleanup
// ps_prochandle cleanup
void Prelease(struct ps_prochandle* ph) {
// do the "derived class" clean-up first
ph->ops->release(ph);
destroy_lib_info(ph);
destroy_thread_info(ph);
free(ph);
// do the "derived class" clean-up first
ph->ops->release(ph);
destroy_lib_info(ph);
destroy_thread_info(ph);
free(ph);
}
lib_info* add_lib_info(struct ps_prochandle* ph, const char* libname, uintptr_t base) {
return add_lib_info_fd(ph, libname, -1, base);
return add_lib_info_fd(ph, libname, -1, base);
}
lib_info* add_lib_info_fd(struct ps_prochandle* ph, const char* libname, int fd, uintptr_t base) {
lib_info* newlib;
print_debug("add_lib_info_fd %s\n", libname);
if ( (newlib = (lib_info*) calloc(1, sizeof(struct lib_info))) == NULL) {
print_debug("can't allocate memory for lib_info\n");
return NULL;
}
if ( (newlib = (lib_info*) calloc(1, sizeof(struct lib_info))) == NULL) {
print_debug("can't allocate memory for lib_info\n");
return NULL;
}
strncpy(newlib->name, libname, sizeof(newlib->name));
newlib->base = base;
strncpy(newlib->name, libname, sizeof(newlib->name));
newlib->base = base;
if (fd == -1) {
if ( (newlib->fd = pathmap_open(newlib->name)) < 0) {
print_debug("can't open shared object %s\n", newlib->name);
free(newlib);
return NULL;
}
} else {
newlib->fd = fd;
}
// check whether we have got an ELF file. /proc/<pid>/map
// gives out all file mappings and not just shared objects
if (is_elf_file(newlib->fd) == false) {
close(newlib->fd);
if (fd == -1) {
if ( (newlib->fd = pathmap_open(newlib->name)) < 0) {
print_debug("can't open shared object %s\n", newlib->name);
free(newlib);
return NULL;
}
}
} else {
newlib->fd = fd;
}
newlib->symtab = build_symtab(newlib->fd);
if (newlib->symtab == NULL) {
print_debug("symbol table build failed for %s\n", newlib->name);
}
else {
print_debug("built symbol table for %s\n", newlib->name);
}
#ifdef __APPLE__
// check whether we have got an Macho file.
if (is_macho_file(newlib->fd) == false) {
close(newlib->fd);
free(newlib);
print_debug("not a mach-o file\n");
return NULL;
}
#else
// check whether we have got an ELF file. /proc/<pid>/map
// gives out all file mappings and not just shared objects
if (is_elf_file(newlib->fd) == false) {
close(newlib->fd);
free(newlib);
return NULL;
}
#endif // __APPLE__
// even if symbol table building fails, we add the lib_info.
// This is because we may need to read from the ELF file for core file
// address read functionality. lookup_symbol checks for NULL symtab.
if (ph->libs) {
ph->lib_tail->next = newlib;
ph->lib_tail = newlib;
} else {
ph->libs = ph->lib_tail = newlib;
}
ph->num_libs++;
newlib->symtab = build_symtab(newlib->fd);
if (newlib->symtab == NULL) {
print_debug("symbol table build failed for %s\n", newlib->name);
} else {
print_debug("built symbol table for %s\n", newlib->name);
}
return newlib;
// even if symbol table building fails, we add the lib_info.
// This is because we may need to read from the ELF file or MachO file for core file
// address read functionality. lookup_symbol checks for NULL symtab.
if (ph->libs) {
ph->lib_tail->next = newlib;
ph->lib_tail = newlib;
} else {
ph->libs = ph->lib_tail = newlib;
}
ph->num_libs++;
return newlib;
}
// lookup for a specific symbol
uintptr_t lookup_symbol(struct ps_prochandle* ph, const char* object_name,
const char* sym_name) {
// ignore object_name. search in all libraries
// FIXME: what should we do with object_name?? The library names are obtained
// by parsing /proc/<pid>/maps, which may not be the same as object_name.
// What we need is a utility to map object_name to real file name, something
// dlopen() does by looking at LD_LIBRARY_PATH and /etc/ld.so.cache. For
// now, we just ignore object_name and do a global search for the symbol.
lib_info* lib = ph->libs;
while (lib) {
if (lib->symtab) {
uintptr_t res = search_symbol(lib->symtab, lib->base, sym_name, NULL);
if (res) return res;
}
lib = lib->next;
}
// ignore object_name. search in all libraries
// FIXME: what should we do with object_name?? The library names are obtained
// by parsing /proc/<pid>/maps, which may not be the same as object_name.
// What we need is a utility to map object_name to real file name, something
// dlopen() does by looking at LD_LIBRARY_PATH and /etc/ld.so.cache. For
// now, we just ignore object_name and do a global search for the symbol.
lib_info* lib = ph->libs;
while (lib) {
if (lib->symtab) {
uintptr_t res = search_symbol(lib->symtab, lib->base, sym_name, NULL);
if (res) return res;
}
lib = lib->next;
}
print_debug("lookup failed for symbol '%s' in obj '%s'\n",
print_debug("lookup failed for symbol '%s' in obj '%s'\n",
sym_name, object_name);
return (uintptr_t) NULL;
return (uintptr_t) NULL;
}
const char* symbol_for_pc(struct ps_prochandle* ph, uintptr_t addr, uintptr_t* poffset) {
const char* res = NULL;
lib_info* lib = ph->libs;
while (lib) {
if (lib->symtab && addr >= lib->base) {
res = nearest_symbol(lib->symtab, addr - lib->base, poffset);
if (res) return res;
}
lib = lib->next;
}
return NULL;
const char* res = NULL;
lib_info* lib = ph->libs;
while (lib) {
if (lib->symtab && addr >= lib->base) {
res = nearest_symbol(lib->symtab, addr - lib->base, poffset);
if (res) return res;
}
lib = lib->next;
}
return NULL;
}
// add a thread to ps_prochandle
thread_info* add_thread_info(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id) {
thread_info* newthr;
if ( (newthr = (thread_info*) calloc(1, sizeof(thread_info))) == NULL) {
print_debug("can't allocate memory for thread_info\n");
return NULL;
}
sa_thread_info* add_thread_info(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id) {
sa_thread_info* newthr;
if ( (newthr = (sa_thread_info*) calloc(1, sizeof(sa_thread_info))) == NULL) {
print_debug("can't allocate memory for thread_info\n");
return NULL;
}
// initialize thread info
newthr->pthread_id = pthread_id;
newthr->lwp_id = lwp_id;
// initialize thread info
newthr->pthread_id = pthread_id;
newthr->lwp_id = lwp_id;
// add new thread to the list
newthr->next = ph->threads;
ph->threads = newthr;
ph->num_threads++;
return newthr;
// add new thread to the list
newthr->next = ph->threads;
ph->threads = newthr;
ph->num_threads++;
return newthr;
}
#ifndef __APPLE__
// struct used for client data from thread_db callback
struct thread_db_client_data {
struct ps_prochandle* ph;
thread_info_callback callback;
struct ps_prochandle* ph;
thread_info_callback callback;
};
// callback function for libthread_db
......@@ -314,6 +375,7 @@ bool read_thread_info(struct ps_prochandle* ph, thread_info_callback cb) {
return true;
}
#endif // __APPLE__
// get number of threads
int get_num_threads(struct ps_prochandle* ph) {
......@@ -322,18 +384,54 @@ int get_num_threads(struct ps_prochandle* ph) {
// get lwp_id of n'th thread
lwpid_t get_lwp_id(struct ps_prochandle* ph, int index) {
int count = 0;
thread_info* thr = ph->threads;
while (thr) {
if (count == index) {
return thr->lwp_id;
}
count++;
thr = thr->next;
}
return -1;
int count = 0;
sa_thread_info* thr = ph->threads;
while (thr) {
if (count == index) {
return thr->lwp_id;
}
count++;
thr = thr->next;
}
return 0;
}
#ifdef __APPLE__
// set lwp_id of n'th thread
bool set_lwp_id(struct ps_prochandle* ph, int index, lwpid_t lwpid) {
int count = 0;
sa_thread_info* thr = ph->threads;
while (thr) {
if (count == index) {
thr->lwp_id = lwpid;
return true;
}
count++;
thr = thr->next;
}
return false;
}
// get regs of n-th thread, only used in fillThreads the first time called
bool get_nth_lwp_regs(struct ps_prochandle* ph, int index, struct reg* regs) {
int count = 0;
sa_thread_info* thr = ph->threads;
while (thr) {
if (count == index) {
break;
}
count++;
thr = thr->next;
}
if (thr != NULL) {
memcpy(regs, &thr->regs, sizeof(struct reg));
return true;
}
return false;
}
#endif // __APPLE__
// get regs for a given lwp
bool get_lwp_regs(struct ps_prochandle* ph, lwpid_t lwp_id, struct reg* regs) {
return ph->ops->get_lwp_regs(ph, lwp_id, regs);
......@@ -341,35 +439,35 @@ bool get_lwp_regs(struct ps_prochandle* ph, lwpid_t lwp_id, struct reg* regs) {
// get number of shared objects
int get_num_libs(struct ps_prochandle* ph) {
return ph->num_libs;
return ph->num_libs;
}
// get name of n'th solib
const char* get_lib_name(struct ps_prochandle* ph, int index) {
int count = 0;
lib_info* lib = ph->libs;
while (lib) {
if (count == index) {
return lib->name;
}
count++;
lib = lib->next;
}
return NULL;
int count = 0;
lib_info* lib = ph->libs;
while (lib) {
if (count == index) {
return lib->name;
}
count++;
lib = lib->next;
}
return NULL;
}
// get base address of a lib
uintptr_t get_lib_base(struct ps_prochandle* ph, int index) {
int count = 0;
lib_info* lib = ph->libs;
while (lib) {
if (count == index) {
return lib->base;
}
count++;
lib = lib->next;
}
return (uintptr_t)NULL;
int count = 0;
lib_info* lib = ph->libs;
while (lib) {
if (count == index) {
return lib->base;
}
count++;
lib = lib->next;
}
return (uintptr_t)NULL;
}
bool find_lib(struct ps_prochandle* ph, const char *lib_name) {
......@@ -425,6 +523,7 @@ ps_plog (const char *format, ...)
va_end(alist);
}
#ifndef __APPLE__
// ------------------------------------------------------------------------
// Functions below this point are not yet implemented. They are here only
// to make the linker happy.
......@@ -458,3 +557,4 @@ ps_err_e ps_pcontinue(struct ps_prochandle *ph) {
print_debug("ps_pcontinue not implemented\n");
return PS_OK;
}
#endif // __APPLE__
......@@ -30,6 +30,60 @@
#include "libproc.h"
#include "symtab.h"
#ifdef __APPLE__
#include <inttypes.h> // for PRIx64, 32, ...
#include <pthread.h>
#include <mach-o/loader.h>
#include <mach-o/nlist.h>
#include <mach-o/fat.h>
#ifndef register_t
#define register_t uint64_t
#endif
/*** registers copied from bsd/amd64 */
typedef struct reg {
register_t r_r15;
register_t r_r14;
register_t r_r13;
register_t r_r12;
register_t r_r11;
register_t r_r10;
register_t r_r9;
register_t r_r8;
register_t r_rdi;
register_t r_rsi;
register_t r_rbp;
register_t r_rbx;
register_t r_rdx;
register_t r_rcx;
register_t r_rax;
uint32_t r_trapno; // not used
uint16_t r_fs;
uint16_t r_gs;
uint32_t r_err; // not used
uint16_t r_es; // not used
uint16_t r_ds; // not used
register_t r_rip;
register_t r_cs;
register_t r_rflags;
register_t r_rsp;
register_t r_ss; // not used
} reg;
// convenient defs
typedef struct mach_header_64 mach_header_64;
typedef struct load_command load_command;
typedef struct segment_command_64 segment_command_64;
typedef struct thread_command thread_command;
typedef struct dylib_command dylib_command;
typedef struct symtab_command symtab_command;
typedef struct nlist_64 nlist_64;
#else
#include <thread_db.h>
#include "salibelf.h"
#endif // __APPLE__
// data structures in this file mimic those of Solaris 8.0 - libproc's Pcontrol.h
#define BUF_SIZE (PATH_MAX + NAME_MAX + 1)
......@@ -44,12 +98,12 @@ typedef struct lib_info {
} lib_info;
// list of threads
typedef struct thread_info {
lwpid_t lwp_id;
pthread_t pthread_id; // not used cores, always -1
typedef struct sa_thread_info {
lwpid_t lwp_id; // same as pthread_t
pthread_t pthread_id; //
struct reg regs; // not for process, core uses for caching regset
struct thread_info* next;
} thread_info;
struct sa_thread_info* next;
} sa_thread_info;
// list of virtual memory maps
typedef struct map_info {
......@@ -91,6 +145,7 @@ struct core_data {
// part of the class sharing workaround
map_info* class_share_maps;// class share maps in a linked list
map_info** map_array; // sorted (by vaddr) array of map_info pointers
char exec_path[4096]; // file name java
};
struct ps_prochandle {
......@@ -100,12 +155,11 @@ struct ps_prochandle {
lib_info* libs; // head of lib list
lib_info* lib_tail; // tail of lib list - to append at the end
int num_threads;
thread_info* threads; // head of thread list
sa_thread_info* threads; // head of thread list
struct core_data* core; // data only used for core dumps, NULL for process
};
int pathmap_open(const char* name);
void print_debug(const char* format,...);
void print_error(const char* format,...);
bool is_debug();
......@@ -122,10 +176,45 @@ lib_info* add_lib_info(struct ps_prochandle* ph, const char* libname, uintptr_t
lib_info* add_lib_info_fd(struct ps_prochandle* ph, const char* libname, int fd,
uintptr_t base);
// adds a new thread to threads list, returns NULL on failure
thread_info* add_thread_info(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id);
sa_thread_info* add_thread_info(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id);
// a test for ELF signature without using libelf
#ifdef __APPLE__
// a test for Mach-O signature
bool is_macho_file(int fd);
// skip fat head to get image start offset of cpu_type_t
// return false if any error happens, else value in offset.
bool get_arch_off(int fd, cpu_type_t cputype, off_t *offset);
#else
bool is_elf_file(int fd);
#endif // __APPLE__
lwpid_t get_lwp_id(struct ps_prochandle* ph, int index);
bool set_lwp_id(struct ps_prochandle* ph, int index, lwpid_t lwpid);
bool get_nth_lwp_regs(struct ps_prochandle* ph, int index, struct reg* regs);
// ps_pglobal_lookup() looks up the symbol sym_name in the symbol table
// of the load object object_name in the target process identified by ph.
// It returns the symbol's value as an address in the target process in
// *sym_addr.
ps_err_e ps_pglobal_lookup(struct ps_prochandle *ph, const char *object_name,
const char *sym_name, psaddr_t *sym_addr);
// read "size" bytes info "buf" from address "addr"
ps_err_e ps_pread(struct ps_prochandle *ph, psaddr_t addr,
void *buf, size_t size);
// write "size" bytes of data to debuggee at address "addr"
ps_err_e ps_pwrite(struct ps_prochandle *ph, psaddr_t addr,
const void *buf, size_t size);
// fill in ptrace_lwpinfo for lid
ps_err_e ps_linfo(struct ps_prochandle *ph, lwpid_t lwp_id, void *linfo);
// needed for when libthread_db is compiled with TD_DEBUG defined
void ps_plog (const char *format, ...);
// untility, tells the position in file
off_t ltell(int fd);
#endif //_LIBPROC_IMPL_H_
此差异已折叠。
/*
* Copyright (c) 2003, 2010, 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
......@@ -28,32 +28,182 @@
#include <string.h>
#include <db.h>
#include <fcntl.h>
#include "libproc_impl.h"
#include "symtab.h"
#ifndef __APPLE__
#include "salibelf.h"
#endif // __APPLE__
// ----------------------------------------------------
// functions for symbol lookups
// ----------------------------------------------------
struct elf_section {
ELF_SHDR *c_shdr;
void *c_data;
};
struct elf_symbol {
char *name;
uintptr_t offset;
uintptr_t size;
};
typedef struct symtab_symbol {
char *name; // name like __ZThread_...
uintptr_t offset; // to loaded address
uintptr_t size; // size strlen
} symtab_symbol;
typedef struct symtab {
char *strs;
char *strs; // all symbols "__symbol1__'\0'__symbol2__...."
size_t num_symbols;
struct elf_symbol *symbols;
DB* hash_table;
symtab_symbol* symbols;
} symtab_t;
#ifdef __APPLE__
void build_search_table(symtab_t *symtab) {
int i;
for (i = 0; i < symtab->num_symbols; i++) {
DBT key, value;
key.data = symtab->symbols[i].name;
key.size = strlen(key.data) + 1;
value.data = &(symtab->symbols[i]);
value.size = sizeof(symtab_symbol);
(*symtab->hash_table->put)(symtab->hash_table, &key, &value, 0);
// check result
if (is_debug()) {
DBT rkey, rvalue;
char* tmp = (char *)malloc(strlen(symtab->symbols[i].name) + 1);
strcpy(tmp, symtab->symbols[i].name);
rkey.data = tmp;
rkey.size = strlen(tmp) + 1;
(*symtab->hash_table->get)(symtab->hash_table, &rkey, &rvalue, 0);
// we may get a copy back so compare contents
symtab_symbol *res = (symtab_symbol *)rvalue.data;
if (strcmp(res->name, symtab->symbols[i].name) ||
res->offset != symtab->symbols[i].offset ||
res->size != symtab->symbols[i].size) {
print_debug("error to get hash_table value!\n");
}
free(tmp);
}
}
}
// read symbol table from given fd.
struct symtab* build_symtab(int fd) {
symtab_t* symtab = NULL;
int i;
mach_header_64 header;
off_t image_start;
if (!get_arch_off(fd, CPU_TYPE_X86_64, &image_start)) {
print_debug("failed in get fat header\n");
return NULL;
}
lseek(fd, image_start, SEEK_SET);
if (read(fd, (void *)&header, sizeof(mach_header_64)) != sizeof(mach_header_64)) {
print_debug("reading header failed!\n");
return NULL;
}
// header
if (header.magic != MH_MAGIC_64) {
print_debug("not a valid .dylib file\n");
return NULL;
}
load_command lcmd;
symtab_command symtabcmd;
nlist_64 lentry;
bool lcsymtab_exist = false;
long filepos = ltell(fd);
for (i = 0; i < header.ncmds; i++) {
lseek(fd, filepos, SEEK_SET);
if (read(fd, (void *)&lcmd, sizeof(load_command)) != sizeof(load_command)) {
print_debug("read load_command failed for file\n");
return NULL;
}
filepos += lcmd.cmdsize; // next command position
if (lcmd.cmd == LC_SYMTAB) {
lseek(fd, -sizeof(load_command), SEEK_CUR);
lcsymtab_exist = true;
break;
}
}
if (!lcsymtab_exist) {
print_debug("No symtab command found!\n");
return NULL;
}
if (read(fd, (void *)&symtabcmd, sizeof(symtab_command)) != sizeof(symtab_command)) {
print_debug("read symtab_command failed for file");
return NULL;
}
symtab = (symtab_t *)malloc(sizeof(symtab_t));
if (symtab == NULL) {
print_debug("out of memory: allocating symtab\n");
return NULL;
}
// create hash table, we use berkeley db to
// manipulate the hash table.
symtab->hash_table = dbopen(NULL, O_CREAT | O_RDWR, 0600, DB_HASH, NULL);
if (symtab->hash_table == NULL)
goto quit;
symtab->num_symbols = symtabcmd.nsyms;
symtab->symbols = (symtab_symbol *)malloc(sizeof(symtab_symbol) * symtab->num_symbols);
symtab->strs = (char *)malloc(sizeof(char) * symtabcmd.strsize);
if (symtab->symbols == NULL || symtab->strs == NULL) {
print_debug("out of memory: allocating symtab.symbol or symtab.strs\n");
goto quit;
}
lseek(fd, image_start + symtabcmd.symoff, SEEK_SET);
for (i = 0; i < symtab->num_symbols; i++) {
if (read(fd, (void *)&lentry, sizeof(nlist_64)) != sizeof(nlist_64)) {
print_debug("read nlist_64 failed at %i\n", i);
goto quit;
}
symtab->symbols[i].offset = lentry.n_value;
symtab->symbols[i].size = lentry.n_un.n_strx; // index
}
// string table
lseek(fd, image_start + symtabcmd.stroff, SEEK_SET);
int size = read(fd, (void *)(symtab->strs), symtabcmd.strsize * sizeof(char));
if (size != symtabcmd.strsize * sizeof(char)) {
print_debug("reading string table failed\n");
goto quit;
}
for (i = 0; i < symtab->num_symbols; i++) {
symtab->symbols[i].name = symtab->strs + symtab->symbols[i].size;
if (i > 0) {
// fix size
symtab->symbols[i - 1].size = symtab->symbols[i].size - symtab->symbols[i - 1].size;
print_debug("%s size = %d\n", symtab->symbols[i - 1].name, symtab->symbols[i - 1].size);
}
if (i == symtab->num_symbols - 1) {
// last index
symtab->symbols[i].size =
symtabcmd.strsize - symtab->symbols[i].size;
print_debug("%s size = %d\n", symtab->symbols[i].name, symtab->symbols[i].size);
}
}
// build a hashtable for fast query
build_search_table(symtab);
return symtab;
quit:
if (symtab) destroy_symtab(symtab);
return NULL;
}
#else // __APPLE__
struct elf_section {
ELF_SHDR *c_shdr;
void *c_data;
};
// read symbol table from given fd.
struct symtab* build_symtab(int fd) {
ELF_EHDR ehdr;
......@@ -176,7 +326,7 @@ struct symtab* build_symtab(int fd) {
key.data = sym_name;
key.size = strlen(sym_name) + 1;
value.data = &(symtab->symbols[j]);
value.size = sizeof(void *);
value.size = sizeof(symtab_symbol);
(*symtab->hash_table->put)(symtab->hash_table, &key, &value, 0);
}
}
......@@ -201,30 +351,29 @@ quit:
return symtab;
}
void destroy_symtab(struct symtab* symtab) {
#endif // __APPLE__
void destroy_symtab(symtab_t* symtab) {
if (!symtab) return;
if (symtab->strs) free(symtab->strs);
if (symtab->symbols) free(symtab->symbols);
if (symtab->hash_table) {
(*symtab->hash_table->close)(symtab->hash_table);
}
free(symtab->strs);
free(symtab->symbols);
free(symtab);
}
uintptr_t search_symbol(struct symtab* symtab, uintptr_t base,
const char *sym_name, int *sym_size) {
uintptr_t search_symbol(struct symtab* symtab, uintptr_t base, const char *sym_name, int *sym_size) {
DBT key, value;
int ret;
// library does not have symbol table
if (!symtab || !symtab->hash_table)
if (!symtab || !symtab->hash_table) {
return 0;
}
key.data = (char*)(uintptr_t)sym_name;
key.size = strlen(sym_name) + 1;
ret = (*symtab->hash_table->get)(symtab->hash_table, &key, &value, 0);
if (ret == 0) {
struct elf_symbol *sym = value.data;
symtab_symbol *sym = value.data;
uintptr_t rslt = (uintptr_t) ((char*)base + sym->offset);
if (sym_size) *sym_size = sym->size;
return rslt;
......@@ -238,7 +387,7 @@ const char* nearest_symbol(struct symtab* symtab, uintptr_t offset,
int n = 0;
if (!symtab) return NULL;
for (; n < symtab->num_symbols; n++) {
struct elf_symbol* sym = &(symtab->symbols[n]);
symtab_symbol* sym = &(symtab->symbols[n]);
if (sym->name != NULL &&
offset >= sym->offset && offset < sym->offset + sym->size) {
if (poffset) *poffset = (offset - sym->offset);
......
/*
* Copyright (c) 2003, 2010, 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
......@@ -27,11 +27,11 @@
#include <stdint.h>
// interface to manage ELF symbol tables
// interface to manage ELF or MachO symbol tables
struct symtab;
// build symbol table for a given ELF file descriptor
// build symbol table for a given ELF or MachO file escriptor
struct symtab* build_symtab(int fd);
// destroy the symbol table
......
/*
* Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 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
......@@ -34,11 +34,18 @@ public class BsdVtblAccess extends BasicVtblAccess {
public BsdVtblAccess(SymbolLookup symbolLookup,
String[] dllNames) {
super(symbolLookup, dllNames);
if (symbolLookup.lookup("libjvm.so", "__vt_10JavaThread") != null ||
symbolLookup.lookup("libjvm_g.so", "__vt_10JavaThread") != null) {
boolean oldVT = false;
boolean isDarwin = dllNames[0].lastIndexOf(".dylib") != -1;
String vtJavaThread = isDarwin ? "_vt_10JavaThread" : "__vt_10JavaThread";
for (String dllName : dllNames) {
if (symbolLookup.lookup(dllName, vtJavaThread) != null) {
oldVT = true;
break;
}
}
if (oldVT) {
// old C++ ABI
vt = "__vt_";
vt = isDarwin ? "_vt_" : "__vt_";
} else {
// new C++ ABI
vt = "_ZTV";
......
......@@ -1517,7 +1517,7 @@ public class CommandProcessor {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
thread.printThreadIDOn(new PrintStream(bos));
if (all || bos.toString().equals(name)) {
out.println(bos.toString() + " = " + thread.getAddress());
out.println("Thread " + bos.toString() + " Address: " + thread.getAddress());
HTMLGenerator gen = new HTMLGenerator(false);
try {
out.println(gen.genHTMLForJavaStackTrace(thread));
......@@ -1546,7 +1546,7 @@ public class CommandProcessor {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
thread.printThreadIDOn(new PrintStream(bos));
if (all || bos.toString().equals(name)) {
out.println(bos.toString() + " = " + thread.getAddress());
out.println("Thread " + bos.toString() + " Address " + thread.getAddress());
if (!all) return;
}
}
......
/*
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 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
......@@ -311,6 +311,8 @@ public class HotSpotAgent {
setupDebuggerLinux();
} else if (os.equals("bsd")) {
setupDebuggerBsd();
} else if (os.equals("darwin")) {
setupDebuggerDarwin();
} else {
// Add support for more operating systems here
throw new DebuggerException("Operating system " + os + " not yet supported");
......@@ -370,6 +372,10 @@ public class HotSpotAgent {
db = new HotSpotTypeDataBase(machDesc,
new BsdVtblAccess(debugger, jvmLibNames),
debugger, jvmLibNames);
} else if (os.equals("darwin")) {
db = new HotSpotTypeDataBase(machDesc,
new BsdVtblAccess(debugger, jvmLibNames),
debugger, jvmLibNames);
} else {
throw new DebuggerException("OS \"" + os + "\" not yet supported (no VtblAccess yet)");
}
......@@ -459,6 +465,8 @@ public class HotSpotAgent {
setupJVMLibNamesLinux();
} else if (os.equals("bsd")) {
setupJVMLibNamesBsd();
} else if (os.equals("darwin")) {
setupJVMLibNamesDarwin();
} else {
throw new RuntimeException("Unknown OS type");
}
......@@ -567,6 +575,29 @@ public class HotSpotAgent {
jvmLibNames = new String[] { "libjvm.so", "libjvm_g.so" };
}
//
// Darwin
//
private void setupDebuggerDarwin() {
setupJVMLibNamesDarwin();
if (cpu.equals("amd64") || cpu.equals("x86_64")) {
machDesc = new MachineDescriptionAMD64();
} else {
throw new DebuggerException("Darwin only supported on x86_64. Current arch: " + cpu);
}
BsdDebuggerLocal dbg = new BsdDebuggerLocal(machDesc, !isServer);
debugger = dbg;
attachDebugger();
}
private void setupJVMLibNamesDarwin() {
jvmLibNames = new String[] { "libjvm.dylib", "libjvm_g.dylib" };
}
/** Convenience routine which should be called by per-platform
debugger setup. Should not be called when startupMode is
REMOTE_MODE. */
......
/*
* Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 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
......@@ -31,6 +31,9 @@ import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.x86.*;
import sun.jvm.hotspot.debugger.cdbg.*;
import sun.jvm.hotspot.utilities.*;
import sun.jvm.hotspot.runtime.VM;
import sun.jvm.hotspot.runtime.Threads;
import sun.jvm.hotspot.runtime.JavaThread;
import java.lang.reflect.*;
/** <P> An implementation of the JVMDebugger interface. The basic debug
......@@ -51,10 +54,11 @@ import java.lang.reflect.*;
public class BsdDebuggerLocal extends DebuggerBase implements BsdDebugger {
private boolean useGCC32ABI;
private boolean attached;
private long p_ps_prochandle; // native debugger handle
private long symbolicator; // macosx symbolicator handle
private long task; // macosx task handle
private long p_ps_prochandle; // native debugger handle
private long symbolicator; // macosx symbolicator handle
private long task; // macosx task handle
private boolean isCore;
private boolean isDarwin; // variant for bsd
// CDebugger support
private BsdCDebugger cdbg;
......@@ -208,6 +212,7 @@ public class BsdDebuggerLocal extends DebuggerBase implements BsdDebugger {
}
}
isDarwin = getOS().equals("darwin");
workerThread = new BsdDebuggerLocalWorkerThread(this);
workerThread.start();
}
......@@ -240,8 +245,11 @@ public class BsdDebuggerLocal extends DebuggerBase implements BsdDebugger {
/* called from attach methods */
private void findABIVersion() throws DebuggerException {
if (lookupByName0("libjvm.so", "__vt_10JavaThread") != 0 ||
lookupByName0("libjvm_g.so", "__vt_10JavaThread") != 0) {
String libjvmName = isDarwin ? "libjvm.dylib" : "libjvm.so";
String libjvm_gName = isDarwin? "libjvm_g.dylib" : "libjvm_g.so";
String javaThreadVt = isDarwin ? "_vt_10JavaThread" : "__vt_10JavaThread";
if (lookupByName0(libjvmName, javaThreadVt) != 0 ||
lookupByName0(libjvm_gName, javaThreadVt) != 0) {
// old C++ ABI
useGCC32ABI = false;
} else {
......@@ -360,7 +368,8 @@ public class BsdDebuggerLocal extends DebuggerBase implements BsdDebugger {
}
if (isCore) {
long addr = lookupByName0(objectName, symbol);
// MacOSX symbol with "_" as leading
long addr = lookupByName0(objectName, isDarwin ? "_" + symbol : symbol);
return (addr == 0)? null : new BsdAddress(this, handleGCC32ABI(addr, symbol));
} else {
class LookupByNameTask implements WorkerThreadTask {
......@@ -403,12 +412,12 @@ public class BsdDebuggerLocal extends DebuggerBase implements BsdDebugger {
public ThreadProxy getThreadForIdentifierAddress(Address threadIdAddr, Address uniqueThreadIdAddr) {
return new BsdThread(this, threadIdAddr, uniqueThreadIdAddr);
}
@Override
public ThreadProxy getThreadForIdentifierAddress(Address addr) {
throw new RuntimeException("unimplemented");
}
/** From the ThreadAccess interface via Debugger and JVMDebugger */
public ThreadProxy getThreadForThreadId(long id) {
return new BsdThread(this, id);
......@@ -601,6 +610,33 @@ public class BsdDebuggerLocal extends DebuggerBase implements BsdDebugger {
throw new DebuggerException("Unimplemented");
}
/** this functions used for core file reading and called from native attach0,
it returns an array of long integers as
[thread_id, stack_start, stack_end, thread_id, stack_start, stack_end, ....] for
all java threads recorded in Threads. Also adds the ThreadProxy to threadList */
public long[] getJavaThreadsInfo() {
requireAttach();
Threads threads = VM.getVM().getThreads();
int len = threads.getNumberOfThreads();
long[] result = new long[len * 3]; // triple
JavaThread t = threads.first();
long beg, end;
int i = 0;
while (t != null) {
end = t.getStackBaseValue();
beg = end - t.getStackSize();
BsdThread bsdt = (BsdThread)t.getThreadProxy();
long uid = bsdt.getUniqueThreadId();
if (threadList != null) threadList.add(bsdt);
result[i] = uid;
result[i + 1] = beg;
result[i + 2] = end;
t = t.next();
i += 3;
}
return result;
}
static {
System.loadLibrary("saproc");
init0();
......
/*
* Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 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
......@@ -44,7 +44,8 @@ class BsdThread implements ThreadProxy {
BsdThread(BsdDebugger debugger, long id) {
this.debugger = debugger;
this.thread_id = (int) id;
// use unique_thread_id to identify thread
this.unique_thread_id = id;
}
public boolean equals(Object obj) {
......@@ -52,7 +53,7 @@ class BsdThread implements ThreadProxy {
return false;
}
return (((BsdThread) obj).thread_id == thread_id);
return (((BsdThread) obj).unique_thread_id == unique_thread_id);
}
public int hashCode() {
......@@ -80,4 +81,9 @@ class BsdThread implements ThreadProxy {
throws IllegalThreadStateException, DebuggerException {
throw new DebuggerException("Unimplemented");
}
/** this is not interface function, used in core file to get unique thread id on Macosx*/
public long getUniqueThreadId() {
return unique_thread_id;
}
}
/*
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 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
......@@ -320,6 +320,10 @@ public class JavaThread extends Thread {
return stackBaseField.getValue(addr);
}
public long getStackBaseValue() {
return VM.getVM().getAddressValue(getStackBase());
}
public long getStackSize() {
return stackSizeField.getValue(addr);
}
......
/*
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 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
......@@ -42,6 +42,7 @@ import sun.jvm.hotspot.utilities.*;
public class Threads {
private static JavaThreadFactory threadFactory;
private static AddressField threadListField;
private static CIntegerField numOfThreadsField;
private static VirtualConstructor virtualConstructor;
private static JavaThreadPDAccess access;
......@@ -57,6 +58,7 @@ public class Threads {
Type type = db.lookupType("Threads");
threadListField = type.getAddressField("_thread_list");
numOfThreadsField = type.getCIntegerField("_number_of_threads");
// Instantiate appropriate platform-specific JavaThreadFactory
String os = VM.getVM().getOS();
......@@ -102,6 +104,10 @@ public class Threads {
} else if (cpu.equals("amd64") || cpu.equals("x86_64")) {
access = new BsdAMD64JavaThreadPDAccess();
}
} else if (os.equals("darwin")) {
if (cpu.equals("amd64") || cpu.equals("x86_64")) {
access = new BsdAMD64JavaThreadPDAccess();
}
}
if (access == null) {
......@@ -144,6 +150,10 @@ public class Threads {
return createJavaThreadWrapper(threadAddr);
}
public int getNumberOfThreads() {
return (int) numOfThreadsField.getValue();
}
/** Routine for instantiating appropriately-typed wrapper for a
JavaThread. Currently needs to be public for OopUtilities to
access it. */
......
/*
* 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
......@@ -32,6 +32,7 @@ import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.cdbg.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.utilities.PlatformInfo;
public class PStack extends Tool {
// in non-verbose mode, Method*s are not printed in java frames
......@@ -54,6 +55,11 @@ public class PStack extends Tool {
}
public void run(PrintStream out, Debugger dbg) {
if (PlatformInfo.getOS().equals("darwin")) {
out.println("Not available on Darwin");
return;
}
CDebugger cdbg = dbg.getCDebugger();
if (cdbg != null) {
ConcurrentLocksPrinter concLocksPrinter = null;
......
/*
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 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
......@@ -43,8 +43,8 @@ public class PlatformInfo {
return "bsd";
} else if (os.equals("OpenBSD")) {
return "bsd";
} else if (os.equals("Darwin") || os.contains("OS X")) {
return "bsd";
} else if (os.contains("Darwin") || os.contains("OS X")) {
return "darwin";
} else if (os.startsWith("Windows")) {
return "win32";
} else {
......
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 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
......@@ -48,7 +48,10 @@
#include <string.h>
#include <dlfcn.h>
#ifndef __APPLE__
#include <link.h>
#endif
#endif
......@@ -109,9 +112,7 @@ JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_asm_Disassembler_load_1library(JNIE
jstring libname_s) {
uintptr_t func = 0;
const char* error_message = NULL;
const char* java_home;
jboolean isCopy;
uintptr_t *handle = NULL;
const char * jrepath = (*env)->GetStringUTFChars(env, jrepath_s, &isCopy); // like $JAVA_HOME/jre/lib/sparc/
const char * libname = (*env)->GetStringUTFChars(env, libname_s, &isCopy);
......@@ -167,7 +168,8 @@ typedef void* (*decode_func)(uintptr_t start_va, uintptr_t end_va,
void* event_stream,
int (*printf_callback)(void*, const char*, ...),
void* printf_stream,
const char* options);
const char* options,
int newline);
/* container for call back state when decoding instructions */
typedef struct {
......@@ -281,7 +283,7 @@ JNIEXPORT void JNICALL Java_sun_jvm_hotspot_asm_Disassembler_decode(JNIEnv * env
end - start,
&event_to_env, (void*) &denv,
&printf_to_env, (void*) &denv,
options);
options, 0 /* newline */);
/* cleanup */
(*env)->ReleaseByteArrayElements(env, code, start, JNI_ABORT);
......
#
# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2005, 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
......@@ -24,7 +24,7 @@
# Rules to build serviceability agent library, used by vm.make
# libsaproc.so: serviceability agent
# libsaproc.so(dylib): serviceability agent
SAPROC = saproc
ifeq ($(OS_VENDOR), Darwin)
......@@ -37,7 +37,7 @@ AGENT_DIR = $(GAMMADIR)/agent
SASRCDIR = $(AGENT_DIR)/src/os/$(Platform_os_family)
NON_STUB_SASRCFILES = $(SASRCDIR)/salibelf.c \
BSD_NON_STUB_SASRCFILES = $(SASRCDIR)/salibelf.c \
$(SASRCDIR)/symtab.c \
$(SASRCDIR)/libproc_impl.c \
$(SASRCDIR)/ps_proc.c \
......@@ -45,13 +45,19 @@ NON_STUB_SASRCFILES = $(SASRCDIR)/salibelf.c \
$(SASRCDIR)/BsdDebuggerLocal.c \
$(AGENT_DIR)/src/share/native/sadis.c
DARWIN_NON_STUB_SASRCFILES = $(SASRCDIR)/symtab.c \
$(SASRCDIR)/libproc_impl.c \
$(SASRCDIR)/ps_core.c \
$(SASRCDIR)/MacosxDebuggerLocal.m \
$(AGENT_DIR)/src/share/native/sadis.c
ifeq ($(OS_VENDOR), FreeBSD)
SASRCFILES = $(NON_STUB_SASRCFILES)
SASRCFILES = $(BSD_NON_STUB_SASRCFILES)
SALIBS = -lutil -lthread_db
SAARCH = $(ARCHFLAG)
else
ifeq ($(OS_VENDOR), Darwin)
SASRCFILES = $(SASRCDIR)/MacosxDebuggerLocal.m
SASRCFILES = $(DARWIN_NON_STUB_SASRCFILES)
SALIBS = -g -framework Foundation -F/System/Library/Frameworks/JavaVM.framework/Frameworks -framework JavaNativeFoundation -framework Security -framework CoreFoundation
#objc compiler blows up on -march=i586, perhaps it should not be included in the macosx intel 32-bit C++ compiles?
SAARCH = $(subst -march=i586,,$(ARCHFLAG))
......@@ -102,7 +108,7 @@ $(LIBSAPROC): $(SASRCFILES) $(SAMAPFILE)
fi
@echo Making SA debugger back-end...
$(QUIETLY) $(CC) -D$(BUILDARCH) -D_GNU_SOURCE \
$(SYMFLAG) $(SAARCH) $(SHARED_FLAG) $(PICFLAG) \
$(SYMFLAG) $(SAARCH) $(SHARED_FLAG) $(PICFLAG) \
-I$(SASRCDIR) \
-I$(GENERATED) \
$(BOOT_JAVA_INCLUDES) \
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册