Wed, 27 Feb 2013 14:02:26 +0000
8008807: SA: jstack crash when target has mismatched bitness (Linux)
Reviewed-by: rbackman, sla, poonam
agent/src/os/linux/LinuxDebuggerLocal.c | file | annotate | diff | comparison | revisions |
1.1 --- a/agent/src/os/linux/LinuxDebuggerLocal.c Thu Feb 21 17:22:15 2013 +0100 1.2 +++ b/agent/src/os/linux/LinuxDebuggerLocal.c Wed Feb 27 14:02:26 2013 +0000 1.3 @@ -1,5 +1,5 @@ 1.4 /* 1.5 - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. 1.6 + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. 1.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.8 * 1.9 * This code is free software; you can redistribute it and/or modify it 1.10 @@ -25,6 +25,13 @@ 1.11 #include <jni.h> 1.12 #include "libproc.h" 1.13 1.14 +#include <elf.h> 1.15 +#include <sys/types.h> 1.16 +#include <sys/stat.h> 1.17 +#include <fcntl.h> 1.18 +#include <string.h> 1.19 +#include <limits.h> 1.20 + 1.21 #if defined(x86_64) && !defined(amd64) 1.22 #define amd64 1 1.23 #endif 1.24 @@ -154,6 +161,39 @@ 1.25 } 1.26 } 1.27 1.28 + 1.29 +/* 1.30 + * Verify that a named ELF binary file (core or executable) has the same 1.31 + * bitness as ourselves. 1.32 + * Throw an exception if there is a mismatch or other problem. 1.33 + * 1.34 + * If we proceed using a mismatched debugger/debuggee, the best to hope 1.35 + * for is a missing symbol, the worst is a crash searching for debug symbols. 1.36 + */ 1.37 +void verifyBitness(JNIEnv *env, const char *binaryName) { 1.38 + int fd = open(binaryName, O_RDONLY); 1.39 + if (fd < 0) { 1.40 + THROW_NEW_DEBUGGER_EXCEPTION("cannot open binary file"); 1.41 + } 1.42 + unsigned char elf_ident[EI_NIDENT]; 1.43 + int i = read(fd, &elf_ident, sizeof(elf_ident)); 1.44 + close(fd); 1.45 + 1.46 + if (i < 0) { 1.47 + THROW_NEW_DEBUGGER_EXCEPTION("cannot read binary file"); 1.48 + } 1.49 +#ifndef _LP64 1.50 + if (elf_ident[EI_CLASS] == ELFCLASS64) { 1.51 + THROW_NEW_DEBUGGER_EXCEPTION("debuggee is 64 bit, use 64-bit java for debugger"); 1.52 + } 1.53 +#else 1.54 + if (elf_ident[EI_CLASS] != ELFCLASS64) { 1.55 + THROW_NEW_DEBUGGER_EXCEPTION("debuggee is 32 bit, use 32 bit java for debugger"); 1.56 + } 1.57 +#endif 1.58 +} 1.59 + 1.60 + 1.61 /* 1.62 * Class: sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal 1.63 * Method: attach0 1.64 @@ -162,6 +202,12 @@ 1.65 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_attach0__I 1.66 (JNIEnv *env, jobject this_obj, jint jpid) { 1.67 1.68 + // For bitness checking, locate binary at /proc/jpid/exe 1.69 + char buf[PATH_MAX]; 1.70 + snprintf((char *) &buf, PATH_MAX, "/proc/%d/exe", jpid); 1.71 + verifyBitness(env, (char *) &buf); 1.72 + CHECK_EXCEPTION; 1.73 + 1.74 struct ps_prochandle* ph; 1.75 if ( (ph = Pgrab(jpid)) == NULL) { 1.76 THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the process"); 1.77 @@ -187,6 +233,9 @@ 1.78 coreName_cstr = (*env)->GetStringUTFChars(env, coreName, &isCopy); 1.79 CHECK_EXCEPTION; 1.80 1.81 + verifyBitness(env, execName_cstr); 1.82 + CHECK_EXCEPTION; 1.83 + 1.84 if ( (ph = Pgrab_core(execName_cstr, coreName_cstr)) == NULL) { 1.85 (*env)->ReleaseStringUTFChars(env, execName, execName_cstr); 1.86 (*env)->ReleaseStringUTFChars(env, coreName, coreName_cstr);