8199682: Clean up building the saproc library
Reviewed-by: erikj, dholmes, sundar
This commit is contained in:
parent
c71bc3581a
commit
3522b53f7b
make/lib
src/jdk.hotspot.agent
linux/native/libsaproc
macosx/native/libsaproc
share/classes/sun/jvm/hotspot/debugger/windbg
solaris/native/libsaproc
windows/native/libsaproc
@ -29,17 +29,15 @@ $(eval $(call IncludeCustomExtension, hotspot/lib/Lib-jdk.hotspot.agent.gmk))
|
||||
|
||||
################################################################################
|
||||
|
||||
ifneq ($(findstring $(OPENJDK_TARGET_OS), macosx windows), )
|
||||
DISABLE_MAPFILES := true
|
||||
endif
|
||||
|
||||
SA_TOPDIR := $(TOPDIR)/src/jdk.hotspot.agent
|
||||
|
||||
# Defaults for most platforms
|
||||
SA_TOOLCHAIN := TOOLCHAIN_DEFAULT
|
||||
SA_NAME := saproc
|
||||
SA_SRC += $(SA_TOPDIR)/share/native/libsaproc $(SA_TOPDIR)/$(OPENJDK_TARGET_OS)/native/libsaproc
|
||||
SA_SRC += \
|
||||
$(SA_TOPDIR)/share/native/libsaproc \
|
||||
$(SA_TOPDIR)/$(OPENJDK_TARGET_OS)/native/libsaproc \
|
||||
#
|
||||
|
||||
SA_MAPFILE := $(TOPDIR)/make/mapfiles/libsaproc/mapfile-$(OPENJDK_TARGET_OS)
|
||||
|
||||
SA_INCLUDES := \
|
||||
$(addprefix -I, $(SA_SRC)) \
|
||||
-I$(SUPPORT_OUTPUTDIR)/headers/jdk.hotspot.agent \
|
||||
@ -47,59 +45,40 @@ SA_INCLUDES := \
|
||||
#
|
||||
|
||||
ifeq ($(OPENJDK_TARGET_OS), linux)
|
||||
SA_CFLAGS := $(CFLAGS_JDKLIB) -D_FILE_OFFSET_BITS=64
|
||||
ifeq ($(OPENJDK_TARGET_CPU), x86)
|
||||
SA_LDFLAGS := -march=i586
|
||||
endif
|
||||
|
||||
SA_LIBS := -lthread_db $(LIBDL)
|
||||
SA_CFLAGS := -D_FILE_OFFSET_BITS=64
|
||||
|
||||
else ifeq ($(OPENJDK_TARGET_OS), solaris)
|
||||
SA_TOOLCHAIN := TOOLCHAIN_LINK_CXX
|
||||
SA_CFLAGS := $(CFLAGS_JDKLIB)
|
||||
SA_CXXFLAGS := $(CXXFLAGS_JDKLIB)
|
||||
SA_LDFLAGS := -mt $(LDFLAGS_CXX_JDK)
|
||||
SA_LIBS := -ldl -ldemangle -lthread -lproc
|
||||
SA_LDFLAGS := -mt
|
||||
|
||||
else ifeq ($(OPENJDK_TARGET_OS), macosx)
|
||||
SA_EXCLUDE_FILES := BsdDebuggerLocal.c ps_proc.c salibelf.c StubDebuggerLocal.c
|
||||
SA_CFLAGS := $(CFLAGS_JDKLIB) \
|
||||
-Damd64 -D_GNU_SOURCE -mno-omit-leaf-frame-pointer \
|
||||
SA_CFLAGS := -Damd64 -D_GNU_SOURCE -mno-omit-leaf-frame-pointer \
|
||||
-mstack-alignment=16 -fPIC
|
||||
SA_LIBS := -framework Foundation -framework JavaNativeFoundation \
|
||||
-framework JavaRuntimeSupport -framework Security -framework CoreFoundation
|
||||
|
||||
else ifeq ($(OPENJDK_TARGET_OS), windows)
|
||||
SA_NAME := sawindbg
|
||||
COMMON_CFLAGS := -D_WINDOWS -D_DEBUG -D_CONSOLE -D_MBCS -EHsc
|
||||
SA_CFLAGS := $(subst -DWIN32_LEAN_AND_MEAN,, $(CFLAGS_JDKLIB)) \
|
||||
$(COMMON_CFLAGS)
|
||||
SA_CXXFLAGS := $(subst -DWIN32_LEAN_AND_MEAN,, $(CXXFLAGS_JDKLIB)) \
|
||||
$(COMMON_CFLAGS)
|
||||
SA_LDFLAGS := -manifest
|
||||
SA_LIBS := dbgeng.lib
|
||||
SA_CFLAGS := -D_WINDOWS -D_DEBUG -D_CONSOLE -D_MBCS -EHsc
|
||||
ifeq ($(OPENJDK_TARGET_CPU), x86_64)
|
||||
SA_CXXFLAGS += -DWIN64
|
||||
SA_CXXFLAGS := -DWIN64
|
||||
else
|
||||
SA_CXXFLAGS += -RTC1
|
||||
SA_CXXFLAGS := -RTC1
|
||||
endif
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
|
||||
$(eval $(call SetupJdkLibrary, BUILD_LIBSA, \
|
||||
NAME := $(SA_NAME), \
|
||||
TOOLCHAIN := $(SA_TOOLCHAIN), \
|
||||
NAME := saproc, \
|
||||
OPTIMIZATION := NONE, \
|
||||
DISABLED_WARNINGS_microsoft := 4267, \
|
||||
DISABLED_WARNINGS_gcc := sign-compare, \
|
||||
DISABLED_WARNINGS_CXX_solstudio := truncwarn unknownpragma, \
|
||||
SRC := $(SA_SRC), \
|
||||
EXCLUDE_FILES := test.c saproc_audit.cpp $(SA_EXCLUDE_FILES), \
|
||||
CFLAGS := $(SA_INCLUDES) $(SA_CFLAGS) $(SA_CUSTOM_CFLAGS), \
|
||||
CXXFLAGS := $(SA_INCLUDES) $(SA_CXXFLAGS) $(SA_CUSTOM_CXXFLAGS), \
|
||||
CFLAGS := $(CFLAGS_JDKLIB) $(SA_INCLUDES) $(SA_CFLAGS) $(SA_CUSTOM_CFLAGS), \
|
||||
CXXFLAGS := $(CXXFLAGS_JDKLIB) $(SA_INCLUDES) $(SA_CFLAGS) $(SA_CXXFLAGS), \
|
||||
LDFLAGS := $(LDFLAGS_JDKLIB) $(SA_LDFLAGS), \
|
||||
LIBS := $(SA_LIBS), \
|
||||
LIBS_linux := -lthread_db $(LIBDL), \
|
||||
LIBS_solaris := -ldl -ldemangle -lthread -lproc, \
|
||||
LIBS_macosx := -framework Foundation -framework JavaNativeFoundation \
|
||||
-framework JavaRuntimeSupport -framework Security -framework CoreFoundation, \
|
||||
LIBS_windows := dbgeng.lib, \
|
||||
MAPFILE := $(SA_MAPFILE), \
|
||||
))
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2018, 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
|
||||
@ -30,10 +30,6 @@
|
||||
#include <stdint.h>
|
||||
#include "proc_service.h"
|
||||
|
||||
#ifdef ALT_SASRCDIR
|
||||
#include "libproc_md.h"
|
||||
#endif
|
||||
|
||||
#include <sys/ptrace.h>
|
||||
|
||||
/************************************************************************************
|
||||
|
@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "libproc.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
struct ps_prochandle* ph;
|
||||
|
||||
init_libproc(true);
|
||||
switch (argc) {
|
||||
case 2: {
|
||||
// process
|
||||
ph = Pgrab(atoi(argv[1]));
|
||||
break;
|
||||
}
|
||||
|
||||
case 3: {
|
||||
// core
|
||||
ph = Pgrab_core(argv[1], argv[2]);
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
printf("usage %s <pid> or %s <exec file> <core file>\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ph) {
|
||||
Prelease(ph);
|
||||
return 0;
|
||||
} else {
|
||||
printf("can't connect to debuggee\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
@ -1,402 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2017, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <jni.h>
|
||||
#include "libproc.h"
|
||||
|
||||
#if defined(x86_64) && !defined(amd64)
|
||||
#define amd64 1
|
||||
#endif
|
||||
|
||||
#ifdef i386
|
||||
#include "sun_jvm_hotspot_debugger_x86_X86ThreadContext.h"
|
||||
#endif
|
||||
|
||||
#ifdef amd64
|
||||
#include "sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext.h"
|
||||
#endif
|
||||
|
||||
#if defined(sparc) || defined(sparcv9)
|
||||
#include "sun_jvm_hotspot_debugger_sparc_SPARCThreadContext.h"
|
||||
#endif
|
||||
|
||||
static jfieldID p_ps_prochandle_ID = 0;
|
||||
static jfieldID threadList_ID = 0;
|
||||
static jfieldID loadObjectList_ID = 0;
|
||||
|
||||
static jmethodID createClosestSymbol_ID = 0;
|
||||
static jmethodID createLoadObject_ID = 0;
|
||||
static jmethodID getThreadForThreadId_ID = 0;
|
||||
static jmethodID listAdd_ID = 0;
|
||||
|
||||
#define CHECK_EXCEPTION_(value) if ((*env)->ExceptionOccurred(env)) { return value; }
|
||||
#define CHECK_EXCEPTION if ((*env)->ExceptionOccurred(env)) { return;}
|
||||
#define THROW_NEW_DEBUGGER_EXCEPTION_(str, value) { throw_new_debugger_exception(env, str); return value; }
|
||||
#define THROW_NEW_DEBUGGER_EXCEPTION(str) { throw_new_debugger_exception(env, str); return;}
|
||||
|
||||
static void throw_new_debugger_exception(JNIEnv* env, const char* errMsg) {
|
||||
(*env)->ThrowNew(env, (*env)->FindClass(env, "sun/jvm/hotspot/debugger/DebuggerException"), errMsg);
|
||||
}
|
||||
|
||||
static struct ps_prochandle* get_proc_handle(JNIEnv* env, jobject this_obj) {
|
||||
jlong ptr = (*env)->GetLongField(env, this_obj, p_ps_prochandle_ID);
|
||||
return (struct ps_prochandle*)(intptr_t)ptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
|
||||
* Method: init0
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0
|
||||
(JNIEnv *env, jclass cls) {
|
||||
jclass listClass;
|
||||
|
||||
if (init_libproc(getenv("LIBSAPROC_DEBUG") != NULL) != true) {
|
||||
THROW_NEW_DEBUGGER_EXCEPTION("can't initialize libproc");
|
||||
}
|
||||
|
||||
// fields we use
|
||||
p_ps_prochandle_ID = (*env)->GetFieldID(env, cls, "p_ps_prochandle", "J");
|
||||
CHECK_EXCEPTION;
|
||||
threadList_ID = (*env)->GetFieldID(env, cls, "threadList", "Ljava/util/List;");
|
||||
CHECK_EXCEPTION;
|
||||
loadObjectList_ID = (*env)->GetFieldID(env, cls, "loadObjectList", "Ljava/util/List;");
|
||||
CHECK_EXCEPTION;
|
||||
|
||||
// methods we use
|
||||
createClosestSymbol_ID = (*env)->GetMethodID(env, cls, "createClosestSymbol",
|
||||
"(Ljava/lang/String;J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;");
|
||||
CHECK_EXCEPTION;
|
||||
createLoadObject_ID = (*env)->GetMethodID(env, cls, "createLoadObject",
|
||||
"(Ljava/lang/String;JJ)Lsun/jvm/hotspot/debugger/cdbg/LoadObject;");
|
||||
CHECK_EXCEPTION;
|
||||
getThreadForThreadId_ID = (*env)->GetMethodID(env, cls, "getThreadForThreadId",
|
||||
"(J)Lsun/jvm/hotspot/debugger/ThreadProxy;");
|
||||
CHECK_EXCEPTION;
|
||||
// java.util.List method we call
|
||||
listClass = (*env)->FindClass(env, "java/util/List");
|
||||
CHECK_EXCEPTION;
|
||||
listAdd_ID = (*env)->GetMethodID(env, listClass, "add", "(Ljava/lang/Object;)Z");
|
||||
CHECK_EXCEPTION;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getAddressSize
|
||||
(JNIEnv *env, jclass cls)
|
||||
{
|
||||
#ifdef _LP64
|
||||
return 8;
|
||||
#else
|
||||
return 4;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void fillThreadsAndLoadObjects(JNIEnv* env, jobject this_obj, struct ps_prochandle* ph) {
|
||||
int n = 0, i = 0;
|
||||
|
||||
// add threads
|
||||
n = get_num_threads(ph);
|
||||
for (i = 0; i < n; i++) {
|
||||
jobject thread;
|
||||
jobject threadList;
|
||||
lwpid_t lwpid;
|
||||
|
||||
lwpid = get_lwp_id(ph, i);
|
||||
thread = (*env)->CallObjectMethod(env, this_obj, getThreadForThreadId_ID,
|
||||
(jlong)lwpid);
|
||||
CHECK_EXCEPTION;
|
||||
threadList = (*env)->GetObjectField(env, this_obj, threadList_ID);
|
||||
CHECK_EXCEPTION;
|
||||
(*env)->CallBooleanMethod(env, threadList, listAdd_ID, thread);
|
||||
CHECK_EXCEPTION;
|
||||
}
|
||||
|
||||
// add load objects
|
||||
n = get_num_libs(ph);
|
||||
for (i = 0; i < n; i++) {
|
||||
uintptr_t base;
|
||||
const char* name;
|
||||
jobject loadObject;
|
||||
jobject loadObjectList;
|
||||
|
||||
base = get_lib_base(ph, i);
|
||||
name = get_lib_name(ph, i);
|
||||
loadObject = (*env)->CallObjectMethod(env, this_obj, createLoadObject_ID,
|
||||
(*env)->NewStringUTF(env, name), (jlong)0, (jlong)base);
|
||||
CHECK_EXCEPTION;
|
||||
loadObjectList = (*env)->GetObjectField(env, this_obj, loadObjectList_ID);
|
||||
CHECK_EXCEPTION;
|
||||
(*env)->CallBooleanMethod(env, loadObjectList, listAdd_ID, loadObject);
|
||||
CHECK_EXCEPTION;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
|
||||
* Method: attach0
|
||||
* Signature: (I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__I
|
||||
(JNIEnv *env, jobject this_obj, jint jpid) {
|
||||
|
||||
struct ps_prochandle* ph;
|
||||
if ( (ph = Pgrab(jpid)) == NULL) {
|
||||
THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the process");
|
||||
}
|
||||
(*env)->SetLongField(env, this_obj, p_ps_prochandle_ID, (jlong)(intptr_t)ph);
|
||||
fillThreadsAndLoadObjects(env, this_obj, ph);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
|
||||
* Method: attach0
|
||||
* Signature: (Ljava/lang/String;Ljava/lang/String;)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2
|
||||
(JNIEnv *env, jobject this_obj, jstring execName, jstring coreName) {
|
||||
const char *execName_cstr;
|
||||
const char *coreName_cstr;
|
||||
jboolean isCopy;
|
||||
struct ps_prochandle* ph;
|
||||
|
||||
execName_cstr = (*env)->GetStringUTFChars(env, execName, &isCopy);
|
||||
CHECK_EXCEPTION;
|
||||
coreName_cstr = (*env)->GetStringUTFChars(env, coreName, &isCopy);
|
||||
CHECK_EXCEPTION;
|
||||
|
||||
if ( (ph = Pgrab_core(execName_cstr, coreName_cstr)) == NULL) {
|
||||
(*env)->ReleaseStringUTFChars(env, execName, execName_cstr);
|
||||
(*env)->ReleaseStringUTFChars(env, coreName, coreName_cstr);
|
||||
THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the core file");
|
||||
}
|
||||
(*env)->SetLongField(env, this_obj, p_ps_prochandle_ID, (jlong)(intptr_t)ph);
|
||||
(*env)->ReleaseStringUTFChars(env, execName, execName_cstr);
|
||||
(*env)->ReleaseStringUTFChars(env, coreName, coreName_cstr);
|
||||
fillThreadsAndLoadObjects(env, this_obj, ph);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
|
||||
* Method: detach0
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0
|
||||
(JNIEnv *env, jobject this_obj) {
|
||||
struct ps_prochandle* ph = get_proc_handle(env, this_obj);
|
||||
if (ph != NULL) {
|
||||
Prelease(ph);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
|
||||
* Method: lookupByName0
|
||||
* Signature: (Ljava/lang/String;Ljava/lang/String;)J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0
|
||||
(JNIEnv *env, jobject this_obj, jstring objectName, jstring symbolName) {
|
||||
const char *objectName_cstr, *symbolName_cstr;
|
||||
jlong addr;
|
||||
jboolean isCopy;
|
||||
struct ps_prochandle* ph = get_proc_handle(env, this_obj);
|
||||
|
||||
objectName_cstr = NULL;
|
||||
if (objectName != NULL) {
|
||||
objectName_cstr = (*env)->GetStringUTFChars(env, objectName, &isCopy);
|
||||
CHECK_EXCEPTION_(0);
|
||||
}
|
||||
symbolName_cstr = (*env)->GetStringUTFChars(env, symbolName, &isCopy);
|
||||
CHECK_EXCEPTION_(0);
|
||||
|
||||
addr = (jlong) lookup_symbol(ph, objectName_cstr, symbolName_cstr);
|
||||
|
||||
if (objectName_cstr != NULL) {
|
||||
(*env)->ReleaseStringUTFChars(env, objectName, objectName_cstr);
|
||||
}
|
||||
(*env)->ReleaseStringUTFChars(env, symbolName, symbolName_cstr);
|
||||
return addr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
|
||||
* Method: lookupByAddress0
|
||||
* Signature: (J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;
|
||||
*/
|
||||
JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByAddress0
|
||||
(JNIEnv *env, jobject this_obj, jlong addr) {
|
||||
uintptr_t offset;
|
||||
const char* sym = NULL;
|
||||
|
||||
struct ps_prochandle* ph = get_proc_handle(env, this_obj);
|
||||
sym = symbol_for_pc(ph, (uintptr_t) addr, &offset);
|
||||
if (sym == NULL) return 0;
|
||||
return (*env)->CallObjectMethod(env, this_obj, createClosestSymbol_ID,
|
||||
(*env)->NewStringUTF(env, sym), (jlong)offset);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
|
||||
* Method: readBytesFromProcess0
|
||||
* Signature: (JJ)Lsun/jvm/hotspot/debugger/ReadResult;
|
||||
*/
|
||||
JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0
|
||||
(JNIEnv *env, jobject this_obj, jlong addr, jlong numBytes) {
|
||||
|
||||
jboolean isCopy;
|
||||
jbyteArray array;
|
||||
jbyte *bufPtr;
|
||||
ps_err_e err;
|
||||
|
||||
array = (*env)->NewByteArray(env, numBytes);
|
||||
CHECK_EXCEPTION_(0);
|
||||
bufPtr = (*env)->GetByteArrayElements(env, array, &isCopy);
|
||||
CHECK_EXCEPTION_(0);
|
||||
|
||||
err = ps_pread(get_proc_handle(env, this_obj), (psaddr_t) (uintptr_t)addr, bufPtr, numBytes);
|
||||
(*env)->ReleaseByteArrayElements(env, array, bufPtr, 0);
|
||||
return (err == PS_OK)? array : 0;
|
||||
}
|
||||
|
||||
JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0
|
||||
(JNIEnv *env, jobject this_obj, jint lwp_id) {
|
||||
|
||||
struct reg gregs;
|
||||
jboolean isCopy;
|
||||
jlongArray array;
|
||||
jlong *regs;
|
||||
|
||||
struct ps_prochandle* ph = get_proc_handle(env, this_obj);
|
||||
if (get_lwp_regs(ph, lwp_id, &gregs) != true) {
|
||||
THROW_NEW_DEBUGGER_EXCEPTION_("get_thread_regs failed for a lwp", 0);
|
||||
}
|
||||
|
||||
#undef NPRGREG
|
||||
#ifdef i386
|
||||
#define NPRGREG sun_jvm_hotspot_debugger_x86_X86ThreadContext_NPRGREG
|
||||
#endif
|
||||
#ifdef amd64
|
||||
#define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG
|
||||
#endif
|
||||
#if defined(sparc) || defined(sparcv9)
|
||||
#define NPRGREG sun_jvm_hotspot_debugger_sparc_SPARCThreadContext_NPRGREG
|
||||
#endif
|
||||
|
||||
array = (*env)->NewLongArray(env, NPRGREG);
|
||||
CHECK_EXCEPTION_(0);
|
||||
regs = (*env)->GetLongArrayElements(env, array, &isCopy);
|
||||
|
||||
#undef REG_INDEX
|
||||
|
||||
#ifdef i386
|
||||
#define REG_INDEX(reg) sun_jvm_hotspot_debugger_x86_X86ThreadContext_##reg
|
||||
|
||||
regs[REG_INDEX(GS)] = (uintptr_t) gregs.r_gs;
|
||||
regs[REG_INDEX(FS)] = (uintptr_t) gregs.r_fs;
|
||||
regs[REG_INDEX(ES)] = (uintptr_t) gregs.r_es;
|
||||
regs[REG_INDEX(DS)] = (uintptr_t) gregs.r_ds;
|
||||
regs[REG_INDEX(EDI)] = (uintptr_t) gregs.r_edi;
|
||||
regs[REG_INDEX(ESI)] = (uintptr_t) gregs.r_esi;
|
||||
regs[REG_INDEX(FP)] = (uintptr_t) gregs.r_ebp;
|
||||
regs[REG_INDEX(SP)] = (uintptr_t) gregs.r_isp;
|
||||
regs[REG_INDEX(EBX)] = (uintptr_t) gregs.r_ebx;
|
||||
regs[REG_INDEX(EDX)] = (uintptr_t) gregs.r_edx;
|
||||
regs[REG_INDEX(ECX)] = (uintptr_t) gregs.r_ecx;
|
||||
regs[REG_INDEX(EAX)] = (uintptr_t) gregs.r_eax;
|
||||
regs[REG_INDEX(PC)] = (uintptr_t) gregs.r_eip;
|
||||
regs[REG_INDEX(CS)] = (uintptr_t) gregs.r_cs;
|
||||
regs[REG_INDEX(SS)] = (uintptr_t) gregs.r_ss;
|
||||
|
||||
#endif /* i386 */
|
||||
|
||||
#ifdef amd64
|
||||
#define REG_INDEX(reg) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##reg
|
||||
|
||||
regs[REG_INDEX(R15)] = gregs.r_r15;
|
||||
regs[REG_INDEX(R14)] = gregs.r_r14;
|
||||
regs[REG_INDEX(R13)] = gregs.r_r13;
|
||||
regs[REG_INDEX(R12)] = gregs.r_r12;
|
||||
regs[REG_INDEX(RBP)] = gregs.r_rbp;
|
||||
regs[REG_INDEX(RBX)] = gregs.r_rbx;
|
||||
regs[REG_INDEX(R11)] = gregs.r_r11;
|
||||
regs[REG_INDEX(R10)] = gregs.r_r10;
|
||||
regs[REG_INDEX(R9)] = gregs.r_r9;
|
||||
regs[REG_INDEX(R8)] = gregs.r_r8;
|
||||
regs[REG_INDEX(RAX)] = gregs.r_rax;
|
||||
regs[REG_INDEX(RCX)] = gregs.r_rcx;
|
||||
regs[REG_INDEX(RDX)] = gregs.r_rdx;
|
||||
regs[REG_INDEX(RSI)] = gregs.r_rsi;
|
||||
regs[REG_INDEX(RDI)] = gregs.r_rdi;
|
||||
regs[REG_INDEX(RIP)] = gregs.r_rip;
|
||||
regs[REG_INDEX(CS)] = gregs.r_cs;
|
||||
regs[REG_INDEX(RSP)] = gregs.r_rsp;
|
||||
regs[REG_INDEX(SS)] = gregs.r_ss;
|
||||
// regs[REG_INDEX(FSBASE)] = gregs.fs_base;
|
||||
// regs[REG_INDEX(GSBASE)] = gregs.gs_base;
|
||||
// regs[REG_INDEX(DS)] = gregs.ds;
|
||||
// regs[REG_INDEX(ES)] = gregs.es;
|
||||
// regs[REG_INDEX(FS)] = gregs.fs;
|
||||
// regs[REG_INDEX(GS)] = gregs.gs;
|
||||
|
||||
#endif /* amd64 */
|
||||
|
||||
#if defined(sparc) || defined(sparcv9)
|
||||
|
||||
#define REG_INDEX(reg) sun_jvm_hotspot_debugger_sparc_SPARCThreadContext_##reg
|
||||
|
||||
#ifdef _LP64
|
||||
regs[REG_INDEX(R_PSR)] = gregs.tstate;
|
||||
regs[REG_INDEX(R_PC)] = gregs.tpc;
|
||||
regs[REG_INDEX(R_nPC)] = gregs.tnpc;
|
||||
regs[REG_INDEX(R_Y)] = gregs.y;
|
||||
#else
|
||||
regs[REG_INDEX(R_PSR)] = gregs.psr;
|
||||
regs[REG_INDEX(R_PC)] = gregs.pc;
|
||||
regs[REG_INDEX(R_nPC)] = gregs.npc;
|
||||
regs[REG_INDEX(R_Y)] = gregs.y;
|
||||
#endif
|
||||
regs[REG_INDEX(R_G0)] = 0 ;
|
||||
regs[REG_INDEX(R_G1)] = gregs.u_regs[0];
|
||||
regs[REG_INDEX(R_G2)] = gregs.u_regs[1];
|
||||
regs[REG_INDEX(R_G3)] = gregs.u_regs[2];
|
||||
regs[REG_INDEX(R_G4)] = gregs.u_regs[3];
|
||||
regs[REG_INDEX(R_G5)] = gregs.u_regs[4];
|
||||
regs[REG_INDEX(R_G6)] = gregs.u_regs[5];
|
||||
regs[REG_INDEX(R_G7)] = gregs.u_regs[6];
|
||||
regs[REG_INDEX(R_O0)] = gregs.u_regs[7];
|
||||
regs[REG_INDEX(R_O1)] = gregs.u_regs[8];
|
||||
regs[REG_INDEX(R_O2)] = gregs.u_regs[ 9];
|
||||
regs[REG_INDEX(R_O3)] = gregs.u_regs[10];
|
||||
regs[REG_INDEX(R_O4)] = gregs.u_regs[11];
|
||||
regs[REG_INDEX(R_O5)] = gregs.u_regs[12];
|
||||
regs[REG_INDEX(R_O6)] = gregs.u_regs[13];
|
||||
regs[REG_INDEX(R_O7)] = gregs.u_regs[14];
|
||||
#endif /* sparc */
|
||||
|
||||
|
||||
(*env)->ReleaseLongArrayElements(env, array, regs, JNI_COMMIT);
|
||||
return array;
|
||||
}
|
@ -1,120 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <jni.h>
|
||||
|
||||
#define CHECK_EXCEPTION_(value) if ((*env)->ExceptionOccurred(env)) { return value; }
|
||||
#define CHECK_EXCEPTION if ((*env)->ExceptionOccurred(env)) { return;}
|
||||
#define THROW_NEW_DEBUGGER_EXCEPTION_(str, value) { throw_new_debugger_exception(env, str); return value; }
|
||||
#define THROW_NEW_DEBUGGER_EXCEPTION(str) { throw_new_debugger_exception(env, str); return;}
|
||||
|
||||
static void throw_new_debugger_exception(JNIEnv* env, const char* errMsg) {
|
||||
(*env)->ThrowNew(env, (*env)->FindClass(env, "sun/jvm/hotspot/debugger/DebuggerException"), errMsg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
|
||||
* Method: init0
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0
|
||||
(JNIEnv *env, jclass cls) {
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getAddressSize
|
||||
(JNIEnv *env, jclass cls)
|
||||
{
|
||||
#ifdef _LP64
|
||||
return 8;
|
||||
#else
|
||||
return 4;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
|
||||
* Method: attach0
|
||||
* Signature: (I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__I
|
||||
(JNIEnv *env, jobject this_obj, jint jpid) {
|
||||
|
||||
THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the process");
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
|
||||
* Method: attach0
|
||||
* Signature: (Ljava/lang/String;Ljava/lang/String;)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2
|
||||
(JNIEnv *env, jobject this_obj, jstring execName, jstring coreName) {
|
||||
THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the core file");
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
|
||||
* Method: detach0
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0
|
||||
(JNIEnv *env, jobject this_obj) {
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
|
||||
* Method: lookupByName0
|
||||
* Signature: (Ljava/lang/String;Ljava/lang/String;)J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0
|
||||
(JNIEnv *env, jobject this_obj, jstring objectName, jstring symbolName) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
|
||||
* Method: lookupByAddress0
|
||||
* Signature: (J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;
|
||||
*/
|
||||
JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByAddress0
|
||||
(JNIEnv *env, jobject this_obj, jlong addr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
|
||||
* Method: readBytesFromProcess0
|
||||
* Signature: (JJ)Lsun/jvm/hotspot/debugger/ReadResult;
|
||||
*/
|
||||
JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0
|
||||
(JNIEnv *env, jobject this_obj, jlong addr, jlong numBytes) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0
|
||||
(JNIEnv *env, jobject this_obj, jint lwp_id) {
|
||||
return 0;
|
||||
}
|
@ -1,467 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/user.h>
|
||||
#include <elf.h>
|
||||
#include <sys/elf_common.h>
|
||||
#include <sys/link_elf.h>
|
||||
#include <libutil.h>
|
||||
#include "libproc_impl.h"
|
||||
#include "elfmacros.h"
|
||||
|
||||
// This file has the libproc implementation specific to live process
|
||||
// For core files, refer to ps_core.c
|
||||
|
||||
static inline uintptr_t align(uintptr_t ptr, size_t size) {
|
||||
return (ptr & ~(size - 1));
|
||||
}
|
||||
|
||||
// ---------------------------------------------
|
||||
// ptrace functions
|
||||
// ---------------------------------------------
|
||||
|
||||
// read "size" bytes of data from "addr" within the target process.
|
||||
// unlike the standard ptrace() function, process_read_data() can handle
|
||||
// unaligned address - alignment check, if required, should be done
|
||||
// before calling process_read_data.
|
||||
|
||||
static bool process_read_data(struct ps_prochandle* ph, uintptr_t addr, char *buf, size_t size) {
|
||||
int rslt;
|
||||
size_t i, words;
|
||||
uintptr_t end_addr = addr + size;
|
||||
uintptr_t aligned_addr = align(addr, sizeof(int));
|
||||
|
||||
if (aligned_addr != addr) {
|
||||
char *ptr = (char *)&rslt;
|
||||
errno = 0;
|
||||
rslt = ptrace(PT_READ_D, ph->pid, (caddr_t) aligned_addr, 0);
|
||||
if (errno) {
|
||||
print_debug("ptrace(PT_READ_D, ..) failed for %d bytes @ %lx\n", size, addr);
|
||||
return false;
|
||||
}
|
||||
for (; aligned_addr != addr; aligned_addr++, ptr++);
|
||||
for (; ((intptr_t)aligned_addr % sizeof(int)) && aligned_addr < end_addr;
|
||||
aligned_addr++)
|
||||
*(buf++) = *(ptr++);
|
||||
}
|
||||
|
||||
words = (end_addr - aligned_addr) / sizeof(int);
|
||||
|
||||
// assert((intptr_t)aligned_addr % sizeof(int) == 0);
|
||||
for (i = 0; i < words; i++) {
|
||||
errno = 0;
|
||||
rslt = ptrace(PT_READ_D, ph->pid, (caddr_t) aligned_addr, 0);
|
||||
if (errno) {
|
||||
print_debug("ptrace(PT_READ_D, ..) failed for %d bytes @ %lx\n", size, addr);
|
||||
return false;
|
||||
}
|
||||
*(int *)buf = rslt;
|
||||
buf += sizeof(int);
|
||||
aligned_addr += sizeof(int);
|
||||
}
|
||||
|
||||
if (aligned_addr != end_addr) {
|
||||
char *ptr = (char *)&rslt;
|
||||
errno = 0;
|
||||
rslt = ptrace(PT_READ_D, ph->pid, (caddr_t) aligned_addr, 0);
|
||||
if (errno) {
|
||||
print_debug("ptrace(PT_READ_D, ..) failed for %d bytes @ %lx\n", size, addr);
|
||||
return false;
|
||||
}
|
||||
for (; aligned_addr != end_addr; aligned_addr++)
|
||||
*(buf++) = *(ptr++);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// null implementation for write
|
||||
static bool process_write_data(struct ps_prochandle* ph,
|
||||
uintptr_t addr, const char *buf , size_t size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// "user" should be a pointer to a reg
|
||||
static bool process_get_lwp_regs(struct ps_prochandle* ph, pid_t pid, struct reg *user) {
|
||||
// we have already attached to all thread 'pid's, just use ptrace call
|
||||
// to get regset now. Note that we don't cache regset upfront for processes.
|
||||
if (ptrace(PT_GETREGS, pid, (caddr_t) user, 0) < 0) {
|
||||
print_debug("ptrace(PTRACE_GETREGS, ...) failed for lwp %d\n", pid);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// fill in ptrace_lwpinfo for lid
|
||||
static bool process_get_lwp_info(struct ps_prochandle *ph, lwpid_t lwp_id, void *linfo) {
|
||||
errno = 0;
|
||||
ptrace(PT_LWPINFO, lwp_id, linfo, sizeof(struct ptrace_lwpinfo));
|
||||
|
||||
return (errno == 0)? true: false;
|
||||
}
|
||||
|
||||
static bool ptrace_continue(pid_t pid, int signal) {
|
||||
// pass the signal to the process so we don't swallow it
|
||||
if (ptrace(PT_CONTINUE, pid, NULL, signal) < 0) {
|
||||
print_debug("ptrace(PTRACE_CONT, ..) failed for %d\n", pid);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// waits until the ATTACH has stopped the process
|
||||
// by signal SIGSTOP
|
||||
static bool ptrace_waitpid(pid_t pid) {
|
||||
int ret;
|
||||
int status;
|
||||
do {
|
||||
// Wait for debuggee to stop.
|
||||
ret = waitpid(pid, &status, 0);
|
||||
if (ret >= 0) {
|
||||
if (WIFSTOPPED(status)) {
|
||||
// Any signal will stop the thread, make sure it is SIGSTOP. Otherwise SIGSTOP
|
||||
// will still be pending and delivered when the process is DETACHED and the process
|
||||
// will go to sleep.
|
||||
if (WSTOPSIG(status) == SIGSTOP) {
|
||||
// Debuggee stopped by SIGSTOP.
|
||||
return true;
|
||||
}
|
||||
if (!ptrace_continue(pid, WSTOPSIG(status))) {
|
||||
print_error("Failed to correctly attach to VM. VM might HANG! [PTRACE_CONT failed, stopped by %d]\n", WSTOPSIG(status));
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
print_debug("waitpid(): Child process exited/terminated (status = 0x%x)\n", status);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
switch (errno) {
|
||||
case EINTR:
|
||||
continue;
|
||||
break;
|
||||
case ECHILD:
|
||||
print_debug("waitpid() failed. Child process pid (%d) does not exist \n", pid);
|
||||
break;
|
||||
case EINVAL:
|
||||
print_debug("waitpid() failed. Invalid options argument.\n");
|
||||
break;
|
||||
default:
|
||||
print_debug("waitpid() failed. Unexpected error %d\n",errno);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} while(true);
|
||||
}
|
||||
|
||||
// attach to a process/thread specified by "pid"
|
||||
static bool ptrace_attach(pid_t pid) {
|
||||
if (ptrace(PT_ATTACH, pid, NULL, 0) < 0) {
|
||||
print_debug("ptrace(PTRACE_ATTACH, ..) failed for %d\n", pid);
|
||||
return false;
|
||||
} else {
|
||||
return ptrace_waitpid(pid);
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------
|
||||
// functions for obtaining library information
|
||||
// -------------------------------------------------------
|
||||
|
||||
// callback for read_thread_info
|
||||
static bool add_new_thread(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id) {
|
||||
return add_thread_info(ph, pthread_id, lwp_id) != NULL;
|
||||
}
|
||||
|
||||
#if defined(__FreeBSD__) && __FreeBSD_version < 701000
|
||||
/*
|
||||
* TEXT_START_ADDR from binutils/ld/emulparams/<arch_spec>.sh
|
||||
* Not the most robust but good enough.
|
||||
*/
|
||||
|
||||
#if defined(amd64) || defined(x86_64)
|
||||
#define TEXT_START_ADDR 0x400000
|
||||
#elif defined(i386)
|
||||
#define TEXT_START_ADDR 0x8048000
|
||||
#else
|
||||
#error TEXT_START_ADDR not defined
|
||||
#endif
|
||||
|
||||
#define BUF_SIZE (PATH_MAX + NAME_MAX + 1)
|
||||
|
||||
uintptr_t linkmap_addr(struct ps_prochandle *ph) {
|
||||
uintptr_t ehdr_addr, phdr_addr, dyn_addr, dmap_addr, lmap_addr;
|
||||
ELF_EHDR ehdr;
|
||||
ELF_PHDR *phdrs, *phdr;
|
||||
ELF_DYN *dyns, *dyn;
|
||||
struct r_debug dmap;
|
||||
unsigned long hdrs_size;
|
||||
unsigned int i;
|
||||
|
||||
/* read ELF_EHDR at TEXT_START_ADDR and validate */
|
||||
|
||||
ehdr_addr = (uintptr_t)TEXT_START_ADDR;
|
||||
|
||||
if (process_read_data(ph, ehdr_addr, (char *)&ehdr, sizeof(ehdr)) != true) {
|
||||
print_debug("process_read_data failed for ehdr_addr %p\n", ehdr_addr);
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (!IS_ELF(ehdr) ||
|
||||
ehdr.e_ident[EI_CLASS] != ELF_TARG_CLASS ||
|
||||
ehdr.e_ident[EI_DATA] != ELF_TARG_DATA ||
|
||||
ehdr.e_ident[EI_VERSION] != EV_CURRENT ||
|
||||
ehdr.e_phentsize != sizeof(ELF_PHDR) ||
|
||||
ehdr.e_version != ELF_TARG_VER ||
|
||||
ehdr.e_machine != ELF_TARG_MACH) {
|
||||
print_debug("not an ELF_EHDR at %p\n", ehdr_addr);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* allocate space for all ELF_PHDR's and read */
|
||||
|
||||
phdr_addr = ehdr_addr + ehdr.e_phoff;
|
||||
hdrs_size = ehdr.e_phnum * sizeof(ELF_PHDR);
|
||||
|
||||
if ((phdrs = malloc(hdrs_size)) == NULL)
|
||||
return (0);
|
||||
|
||||
if (process_read_data(ph, phdr_addr, (char *)phdrs, hdrs_size) != true) {
|
||||
print_debug("process_read_data failed for phdr_addr %p\n", phdr_addr);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* find PT_DYNAMIC section */
|
||||
|
||||
for (i = 0, phdr = phdrs; i < ehdr.e_phnum; i++, phdr++) {
|
||||
if (phdr->p_type == PT_DYNAMIC)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= ehdr.e_phnum) {
|
||||
print_debug("PT_DYNAMIC section not found!\n");
|
||||
free(phdrs);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* allocate space and read in ELF_DYN headers */
|
||||
|
||||
dyn_addr = phdr->p_vaddr;
|
||||
hdrs_size = phdr->p_memsz;
|
||||
free(phdrs);
|
||||
|
||||
if ((dyns = malloc(hdrs_size)) == NULL)
|
||||
return (0);
|
||||
|
||||
if (process_read_data(ph, dyn_addr, (char *)dyns, hdrs_size) != true) {
|
||||
print_debug("process_read_data failed for dyn_addr %p\n", dyn_addr);
|
||||
free(dyns);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* find DT_DEBUG */
|
||||
|
||||
dyn = dyns;
|
||||
while (dyn->d_tag != DT_DEBUG && dyn->d_tag != DT_NULL) {
|
||||
dyn++;
|
||||
}
|
||||
|
||||
if (dyn->d_tag != DT_DEBUG) {
|
||||
print_debug("failed to find DT_DEBUG\n");
|
||||
free(dyns);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* read struct r_debug into dmap */
|
||||
|
||||
dmap_addr = (uintptr_t)dyn->d_un.d_ptr;
|
||||
free(dyns);
|
||||
|
||||
if (process_read_data(ph, dmap_addr, (char *)&dmap, sizeof(dmap)) != true) {
|
||||
print_debug("process_read_data failed for dmap_addr %p\n", dmap_addr);
|
||||
return (0);
|
||||
}
|
||||
|
||||
lmap_addr = (uintptr_t)dmap.r_map;
|
||||
|
||||
return (lmap_addr);
|
||||
}
|
||||
#endif // __FreeBSD__ && __FreeBSD_version < 701000
|
||||
|
||||
static bool read_lib_info(struct ps_prochandle* ph) {
|
||||
#if defined(__FreeBSD__) && __FreeBSD_version >= 701000
|
||||
struct kinfo_vmentry *freep, *kve;
|
||||
int i, cnt;
|
||||
|
||||
freep = kinfo_getvmmap(ph->pid, &cnt);
|
||||
if (freep == NULL) {
|
||||
print_debug("can't get vm map for pid\n", ph->pid);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
kve = &freep[i];
|
||||
if ((kve->kve_flags & KVME_FLAG_COW) &&
|
||||
kve->kve_path != NULL &&
|
||||
strlen(kve->kve_path) > 0) {
|
||||
|
||||
if (find_lib(ph, kve->kve_path) == false) {
|
||||
lib_info* lib;
|
||||
if ((lib = add_lib_info(ph, kve->kve_path,
|
||||
(uintptr_t) kve->kve_start)) == NULL)
|
||||
continue; // ignore, add_lib_info prints error
|
||||
|
||||
// we don't need to keep the library open, symtab is already
|
||||
// built. Only for core dump we need to keep the fd open.
|
||||
close(lib->fd);
|
||||
lib->fd = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(freep);
|
||||
|
||||
return true;
|
||||
#else
|
||||
char *l_name;
|
||||
struct link_map *lmap;
|
||||
uintptr_t lmap_addr;
|
||||
|
||||
if ((l_name = malloc(BUF_SIZE)) == NULL)
|
||||
return false;
|
||||
|
||||
if ((lmap = malloc(sizeof(*lmap))) == NULL) {
|
||||
free(l_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
lmap_addr = linkmap_addr(ph);
|
||||
|
||||
if (lmap_addr == 0) {
|
||||
free(l_name);
|
||||
free(lmap);
|
||||
return false;
|
||||
}
|
||||
|
||||
do {
|
||||
if (process_read_data(ph, lmap_addr, (char *)lmap, sizeof(*lmap)) != true) {
|
||||
print_debug("process_read_data failed for lmap_addr %p\n", lmap_addr);
|
||||
free (l_name);
|
||||
free (lmap);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (process_read_data(ph, (uintptr_t)lmap->l_name, l_name,
|
||||
BUF_SIZE) != true) {
|
||||
print_debug("process_read_data failed for lmap->l_name %p\n",
|
||||
lmap->l_name);
|
||||
free (l_name);
|
||||
free (lmap);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (find_lib(ph, l_name) == false) {
|
||||
lib_info* lib;
|
||||
if ((lib = add_lib_info(ph, l_name,
|
||||
(uintptr_t) lmap->l_addr)) == NULL)
|
||||
continue; // ignore, add_lib_info prints error
|
||||
|
||||
// we don't need to keep the library open, symtab is already
|
||||
// built. Only for core dump we need to keep the fd open.
|
||||
close(lib->fd);
|
||||
lib->fd = -1;
|
||||
}
|
||||
lmap_addr = (uintptr_t)lmap->l_next;
|
||||
} while (lmap->l_next != NULL);
|
||||
|
||||
free (l_name);
|
||||
free (lmap);
|
||||
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
// detach a given pid
|
||||
static bool ptrace_detach(pid_t pid) {
|
||||
if (pid && ptrace(PT_DETACH, pid, (caddr_t)1, 0) < 0) {
|
||||
print_debug("ptrace(PTRACE_DETACH, ..) failed for %d\n", pid);
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static void process_cleanup(struct ps_prochandle* ph) {
|
||||
ptrace_detach(ph->pid);
|
||||
}
|
||||
|
||||
static ps_prochandle_ops process_ops = {
|
||||
.release= process_cleanup,
|
||||
.p_pread= process_read_data,
|
||||
.p_pwrite= process_write_data,
|
||||
.get_lwp_regs= process_get_lwp_regs,
|
||||
.get_lwp_info= process_get_lwp_info
|
||||
};
|
||||
|
||||
// attach to the process. One and only one exposed stuff
|
||||
struct ps_prochandle* Pgrab(pid_t pid) {
|
||||
struct ps_prochandle* ph = NULL;
|
||||
|
||||
if ( (ph = (struct ps_prochandle*) calloc(1, sizeof(struct ps_prochandle))) == NULL) {
|
||||
print_debug("can't allocate memory for ps_prochandle\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ptrace_attach(pid) != true) {
|
||||
free(ph);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// initialize ps_prochandle
|
||||
ph->pid = pid;
|
||||
|
||||
// initialize vtable
|
||||
ph->ops = &process_ops;
|
||||
|
||||
// read library info and symbol tables, must do this before attaching threads,
|
||||
// as the symbols in the pthread library will be used to figure out
|
||||
// the list of threads within the same process.
|
||||
if (read_lib_info(ph) != true) {
|
||||
ptrace_detach(pid);
|
||||
free(ph);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// read thread info
|
||||
read_thread_info(ph, add_new_thread);
|
||||
|
||||
return ph;
|
||||
}
|
@ -1,126 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2006, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "salibelf.h"
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
extern void print_debug(const char*,...);
|
||||
|
||||
// ELF file parsing helpers. Note that we do *not* use libelf here.
|
||||
int read_elf_header(int fd, ELF_EHDR* ehdr) {
|
||||
if (pread(fd, ehdr, sizeof (ELF_EHDR), 0) != sizeof (ELF_EHDR) ||
|
||||
memcmp(&ehdr->e_ident[EI_MAG0], ELFMAG, SELFMAG) != 0 ||
|
||||
ehdr->e_version != EV_CURRENT) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool is_elf_file(int fd) {
|
||||
ELF_EHDR ehdr;
|
||||
return read_elf_header(fd, &ehdr);
|
||||
}
|
||||
|
||||
// read program header table of an ELF file
|
||||
ELF_PHDR* read_program_header_table(int fd, ELF_EHDR* hdr) {
|
||||
ELF_PHDR* phbuf = 0;
|
||||
// allocate memory for program header table
|
||||
size_t nbytes = hdr->e_phnum * hdr->e_phentsize;
|
||||
|
||||
if ((phbuf = (ELF_PHDR*) malloc(nbytes)) == NULL) {
|
||||
print_debug("can't allocate memory for reading program header table\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pread(fd, phbuf, nbytes, hdr->e_phoff) != nbytes) {
|
||||
print_debug("ELF file is truncated! can't read program header table\n");
|
||||
free(phbuf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return phbuf;
|
||||
}
|
||||
|
||||
// read section header table of an ELF file
|
||||
ELF_SHDR* read_section_header_table(int fd, ELF_EHDR* hdr) {
|
||||
ELF_SHDR* shbuf = 0;
|
||||
// allocate memory for section header table
|
||||
size_t nbytes = hdr->e_shnum * hdr->e_shentsize;
|
||||
|
||||
if ((shbuf = (ELF_SHDR*) malloc(nbytes)) == NULL) {
|
||||
print_debug("can't allocate memory for reading section header table\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pread(fd, shbuf, nbytes, hdr->e_shoff) != nbytes) {
|
||||
print_debug("ELF file is truncated! can't read section header table\n");
|
||||
free(shbuf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return shbuf;
|
||||
}
|
||||
|
||||
// read a particular section's data
|
||||
void* read_section_data(int fd, ELF_EHDR* ehdr, ELF_SHDR* shdr) {
|
||||
void *buf = NULL;
|
||||
if (shdr->sh_type == SHT_NOBITS || shdr->sh_size == 0) {
|
||||
return buf;
|
||||
}
|
||||
if ((buf = calloc(shdr->sh_size, 1)) == NULL) {
|
||||
print_debug("can't allocate memory for reading section data\n");
|
||||
return NULL;
|
||||
}
|
||||
if (pread(fd, buf, shdr->sh_size, shdr->sh_offset) != shdr->sh_size) {
|
||||
free(buf);
|
||||
print_debug("section data read failed\n");
|
||||
return NULL;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
uintptr_t find_base_address(int fd, ELF_EHDR* ehdr) {
|
||||
uintptr_t baseaddr = (uintptr_t)-1;
|
||||
int cnt;
|
||||
ELF_PHDR *phbuf, *phdr;
|
||||
|
||||
// read program header table
|
||||
if ((phbuf = read_program_header_table(fd, ehdr)) == NULL) {
|
||||
goto quit;
|
||||
}
|
||||
|
||||
// the base address of a shared object is the lowest vaddr of
|
||||
// its loadable segments (PT_LOAD)
|
||||
for (phdr = phbuf, cnt = 0; cnt < ehdr->e_phnum; cnt++, phdr++) {
|
||||
if (phdr->p_type == PT_LOAD && phdr->p_vaddr < baseaddr) {
|
||||
baseaddr = phdr->p_vaddr;
|
||||
}
|
||||
}
|
||||
|
||||
quit:
|
||||
if (phbuf) free(phbuf);
|
||||
return baseaddr;
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "libproc.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
struct ps_prochandle* ph;
|
||||
|
||||
init_libproc(true);
|
||||
switch (argc) {
|
||||
case 2: {
|
||||
// process
|
||||
ph = Pgrab(atoi(argv[1]));
|
||||
break;
|
||||
}
|
||||
|
||||
case 3: {
|
||||
// core
|
||||
ph = Pgrab_core(argv[1], argv[2]);
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
fprintf(stderr, "usage %s <pid> or %s <exec file> <core file>\n", argv[0], argv[0]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ph) {
|
||||
Prelease(ph);
|
||||
return 0;
|
||||
} else {
|
||||
printf("can't connect to debuggee\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2018, 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
|
||||
@ -510,7 +510,7 @@ public class WindbgDebuggerLocal extends DebuggerBase implements WindbgDebugger
|
||||
static {
|
||||
|
||||
/*
|
||||
* sawindbg.dll depends on dbgeng.dll which itself depends on
|
||||
* saproc.dll depends on dbgeng.dll which itself depends on
|
||||
* dbghelp.dll. We have to make sure that the dbgeng.dll and
|
||||
* dbghelp.dll that we load are compatible with each other. We
|
||||
* load both of those libraries from the same directory based
|
||||
@ -538,18 +538,18 @@ public class WindbgDebuggerLocal extends DebuggerBase implements WindbgDebugger
|
||||
|
||||
String dbgengPath = null;
|
||||
String dbghelpPath = null;
|
||||
String sawindbgPath = null;
|
||||
String saprocPath = null;
|
||||
List searchList = new ArrayList();
|
||||
|
||||
boolean loadLibraryDEBUG =
|
||||
System.getProperty("sun.jvm.hotspot.loadLibrary.DEBUG") != null;
|
||||
|
||||
{
|
||||
// First place to search is co-located with sawindbg.dll in
|
||||
// First place to search is co-located with saproc.dll in
|
||||
// $JAVA_HOME/jre/bin (java.home property is set to $JAVA_HOME/jre):
|
||||
searchList.add(System.getProperty("java.home") + File.separator + "bin");
|
||||
sawindbgPath = (String) searchList.get(0) + File.separator +
|
||||
"sawindbg.dll";
|
||||
saprocPath = (String) searchList.get(0) + File.separator +
|
||||
"saproc.dll";
|
||||
|
||||
// second place to search is specified by an environment variable:
|
||||
String DTFWHome = System.getenv("DEBUGGINGTOOLSFORWINDOWS");
|
||||
@ -646,11 +646,11 @@ public class WindbgDebuggerLocal extends DebuggerBase implements WindbgDebugger
|
||||
}
|
||||
System.load(dbgengPath);
|
||||
|
||||
// Now, load sawindbg.dll
|
||||
// Now, load saproc.dll
|
||||
if (loadLibraryDEBUG) {
|
||||
System.err.println("DEBUG: loading '" + sawindbgPath + "'.");
|
||||
System.err.println("DEBUG: loading '" + saprocPath + "'.");
|
||||
}
|
||||
System.load(sawindbgPath);
|
||||
System.load(saprocPath);
|
||||
|
||||
// where do I find '.exe', '.dll' files?
|
||||
imagePath = System.getProperty("sun.jvm.hotspot.debugger.windbg.imagePath");
|
||||
|
@ -1,98 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <link.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <varargs.h>
|
||||
|
||||
// This class sets up an interposer on open calls from libproc.so to
|
||||
// support a pathmap facility in the SA.
|
||||
|
||||
static uintptr_t* libproc_cookie;
|
||||
static uintptr_t* libc_cookie;
|
||||
static uintptr_t* libsaproc_cookie;
|
||||
|
||||
|
||||
uint_t
|
||||
la_version(uint_t version)
|
||||
{
|
||||
return (LAV_CURRENT);
|
||||
}
|
||||
|
||||
|
||||
uint_t
|
||||
la_objopen(Link_map * lmp, Lmid_t lmid, uintptr_t * cookie)
|
||||
{
|
||||
if (strstr(lmp->l_name, "/libproc.so") != NULL) {
|
||||
libproc_cookie = cookie;
|
||||
return LA_FLG_BINDFROM;
|
||||
}
|
||||
if (strstr(lmp->l_name, "/libc.so") != NULL) {
|
||||
libc_cookie = cookie;
|
||||
return LA_FLG_BINDTO;
|
||||
}
|
||||
if (strstr(lmp->l_name, "/libsaproc.so") != NULL) {
|
||||
libsaproc_cookie = cookie;
|
||||
return LA_FLG_BINDTO | LA_FLG_BINDFROM;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#if defined(_LP64)
|
||||
uintptr_t
|
||||
la_symbind64(Elf64_Sym *symp, uint_t symndx, uintptr_t *refcook,
|
||||
uintptr_t *defcook, uint_t *sb_flags, const char *sym_name)
|
||||
#else
|
||||
uintptr_t
|
||||
la_symbind32(Elf32_Sym *symp, uint_t symndx, uintptr_t *refcook,
|
||||
uintptr_t *defcook, uint_t *sb_flags)
|
||||
#endif
|
||||
{
|
||||
#if !defined(_LP64)
|
||||
const char *sym_name = (const char *)symp->st_name;
|
||||
#endif
|
||||
if (strcmp(sym_name, "open") == 0 && refcook == libproc_cookie) {
|
||||
// redirect all open calls from libproc.so through libsaproc_open which will
|
||||
// try the alternate library locations first.
|
||||
void* handle = dlmopen(LM_ID_BASE, "libsaproc.so", RTLD_NOLOAD);
|
||||
if (handle == NULL) {
|
||||
fprintf(stderr, "libsaproc_audit.so: didn't find libsaproc.so during linking\n");
|
||||
} else {
|
||||
uintptr_t libsaproc_open = (uintptr_t)dlsym(handle, "libsaproc_open");
|
||||
if (libsaproc_open == 0) {
|
||||
fprintf(stderr, "libsaproc_audit.so: didn't find libsaproc_open during linking\n");
|
||||
} else {
|
||||
return libsaproc_open;
|
||||
}
|
||||
}
|
||||
}
|
||||
return symp->st_value;
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2018, 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,10 +43,6 @@
|
||||
#include <limits.h>
|
||||
#include <windows.h>
|
||||
|
||||
#ifndef STDMETHODV
|
||||
#define STDMETHODV(method) virtual HRESULT STDMETHODVCALLTYPE method
|
||||
#endif
|
||||
|
||||
#define DEBUG_NO_IMPLEMENTATION
|
||||
#include <dbgeng.h>
|
||||
#include <dbghelp.h>
|
||||
|
Loading…
x
Reference in New Issue
Block a user