mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-25 13:54:38 +02:00
Merge
This commit is contained in:
commit
2a2b10342e
22 changed files with 223 additions and 59 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright 2013 SAP AG. All rights reserved.
|
* Copyright 2013 SAP AG. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
|
@ -38,8 +38,8 @@ class AIXDecoder: public AbstractDecoder {
|
||||||
|
|
||||||
virtual bool demangle(const char* symbol, char* buf, int buflen) { return false; } // demangled by getFuncName
|
virtual bool demangle(const char* symbol, char* buf, int buflen) { return false; } // demangled by getFuncName
|
||||||
|
|
||||||
virtual bool decode(address addr, char* buf, int buflen, int* offset, const char* modulepath) {
|
virtual bool decode(address addr, char* buf, int buflen, int* offset, const char* modulepath, bool demangle) {
|
||||||
return (::getFuncName((codeptr_t)addr, buf, buflen, offset, 0, 0, 0) == 0);
|
return (::getFuncName((codeptr_t)addr, buf, buflen, offset, 0, 0, 0, demangle) == 0);
|
||||||
}
|
}
|
||||||
virtual bool decode(address addr, char *buf, int buflen, int* offset, const void *base) {
|
virtual bool decode(address addr, char *buf, int buflen, int* offset, const void *base) {
|
||||||
ShouldNotReachHere();
|
ShouldNotReachHere();
|
||||||
|
|
|
@ -1439,7 +1439,8 @@ static address resolve_function_descriptor_to_code_pointer(address p) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool os::dll_address_to_function_name(address addr, char *buf,
|
bool os::dll_address_to_function_name(address addr, char *buf,
|
||||||
int buflen, int *offset) {
|
int buflen, int *offset,
|
||||||
|
bool demangle) {
|
||||||
if (offset) {
|
if (offset) {
|
||||||
*offset = -1;
|
*offset = -1;
|
||||||
}
|
}
|
||||||
|
@ -1454,7 +1455,7 @@ bool os::dll_address_to_function_name(address addr, char *buf,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go through Decoder::decode to call getFuncName which reads the name from the traceback table.
|
// Go through Decoder::decode to call getFuncName which reads the name from the traceback table.
|
||||||
return Decoder::decode(addr, buf, buflen, offset);
|
return Decoder::decode(addr, buf, buflen, offset, demangle);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int getModuleName(codeptr_t pc, // [in] program counter
|
static int getModuleName(codeptr_t pc, // [in] program counter
|
||||||
|
|
|
@ -114,7 +114,8 @@ extern "C" int getFuncName(
|
||||||
int* p_displacement, // [out] optional: displacement (-1 if not available)
|
int* p_displacement, // [out] optional: displacement (-1 if not available)
|
||||||
const struct tbtable** p_tb, // [out] optional: ptr to traceback table to get further
|
const struct tbtable** p_tb, // [out] optional: ptr to traceback table to get further
|
||||||
// information (NULL if not available)
|
// information (NULL if not available)
|
||||||
char* p_errmsg, size_t errmsglen // [out] optional: user provided buffer for error messages
|
char* p_errmsg, size_t errmsglen,// [out] optional: user provided buffer for error messages
|
||||||
|
bool demangle // [in] whether to demangle the name
|
||||||
) {
|
) {
|
||||||
struct tbtable* tb = 0;
|
struct tbtable* tb = 0;
|
||||||
unsigned int searchcount = 0;
|
unsigned int searchcount = 0;
|
||||||
|
@ -216,15 +217,17 @@ extern "C" int getFuncName(
|
||||||
p_name[0] = '\0';
|
p_name[0] = '\0';
|
||||||
|
|
||||||
// If it is a C++ name, try and demangle it using the Demangle interface (see demangle.h).
|
// If it is a C++ name, try and demangle it using the Demangle interface (see demangle.h).
|
||||||
char* rest;
|
if (demangle) {
|
||||||
Name* const name = Demangle(buf, rest);
|
char* rest;
|
||||||
if (name) {
|
Name* const name = Demangle(buf, rest);
|
||||||
const char* const demangled_name = name->Text();
|
if (name) {
|
||||||
if (demangled_name) {
|
const char* const demangled_name = name->Text();
|
||||||
strncpy(p_name, demangled_name, namelen-1);
|
if (demangled_name) {
|
||||||
p_name[namelen-1] = '\0';
|
strncpy(p_name, demangled_name, namelen-1);
|
||||||
|
p_name[namelen-1] = '\0';
|
||||||
|
}
|
||||||
|
delete name;
|
||||||
}
|
}
|
||||||
delete name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback: if demangling did not work, just provide the unmangled name.
|
// Fallback: if demangling did not work, just provide the unmangled name.
|
||||||
|
@ -325,7 +328,7 @@ int dladdr(void* addr, Dl_info* info) {
|
||||||
int displacement = 0;
|
int displacement = 0;
|
||||||
|
|
||||||
if (getFuncName((codeptr_t) p, funcname, sizeof(funcname), &displacement,
|
if (getFuncName((codeptr_t) p, funcname, sizeof(funcname), &displacement,
|
||||||
NULL, NULL, 0) == 0) {
|
NULL, NULL, 0, true /* demangle */) == 0) {
|
||||||
if (funcname[0] != '\0') {
|
if (funcname[0] != '\0') {
|
||||||
const char* const interned = dladdr_fixed_strings.intern(funcname);
|
const char* const interned = dladdr_fixed_strings.intern(funcname);
|
||||||
info->dli_sname = interned;
|
info->dli_sname = interned;
|
||||||
|
|
|
@ -87,7 +87,8 @@ int getFuncName(
|
||||||
char* p_name, size_t namelen, // [out] optional: user provided buffer for the function name
|
char* p_name, size_t namelen, // [out] optional: user provided buffer for the function name
|
||||||
int* p_displacement, // [out] optional: displacement
|
int* p_displacement, // [out] optional: displacement
|
||||||
const struct tbtable** p_tb, // [out] optional: ptr to traceback table to get further information
|
const struct tbtable** p_tb, // [out] optional: ptr to traceback table to get further information
|
||||||
char* p_errmsg, size_t errmsglen // [out] optional: user provided buffer for error messages
|
char* p_errmsg, size_t errmsglen,// [out] optional: user provided buffer for error messages
|
||||||
|
bool demangle = true // [in] whether to demangle the name
|
||||||
);
|
);
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -42,7 +42,7 @@ class MachODecoder : public AbstractDecoder {
|
||||||
virtual bool decode(address pc, char* buf, int buflen, int* offset,
|
virtual bool decode(address pc, char* buf, int buflen, int* offset,
|
||||||
const void* base);
|
const void* base);
|
||||||
virtual bool decode(address pc, char* buf, int buflen, int* offset,
|
virtual bool decode(address pc, char* buf, int buflen, int* offset,
|
||||||
const char* module_path = NULL) {
|
const char* module_path, bool demangle) {
|
||||||
ShouldNotReachHere();
|
ShouldNotReachHere();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1339,7 +1339,8 @@ bool os::address_is_in_vm(address addr) {
|
||||||
#define MACH_MAXSYMLEN 256
|
#define MACH_MAXSYMLEN 256
|
||||||
|
|
||||||
bool os::dll_address_to_function_name(address addr, char *buf,
|
bool os::dll_address_to_function_name(address addr, char *buf,
|
||||||
int buflen, int *offset) {
|
int buflen, int *offset,
|
||||||
|
bool demangle) {
|
||||||
// buf is not optional, but offset is optional
|
// buf is not optional, but offset is optional
|
||||||
assert(buf != NULL, "sanity check");
|
assert(buf != NULL, "sanity check");
|
||||||
|
|
||||||
|
@ -1349,7 +1350,7 @@ bool os::dll_address_to_function_name(address addr, char *buf,
|
||||||
if (dladdr((void*)addr, &dlinfo) != 0) {
|
if (dladdr((void*)addr, &dlinfo) != 0) {
|
||||||
// see if we have a matching symbol
|
// see if we have a matching symbol
|
||||||
if (dlinfo.dli_saddr != NULL && dlinfo.dli_sname != NULL) {
|
if (dlinfo.dli_saddr != NULL && dlinfo.dli_sname != NULL) {
|
||||||
if (!Decoder::demangle(dlinfo.dli_sname, buf, buflen)) {
|
if (!(demangle && Decoder::demangle(dlinfo.dli_sname, buf, buflen))) {
|
||||||
jio_snprintf(buf, buflen, "%s", dlinfo.dli_sname);
|
jio_snprintf(buf, buflen, "%s", dlinfo.dli_sname);
|
||||||
}
|
}
|
||||||
if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr;
|
if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr;
|
||||||
|
@ -1358,15 +1359,16 @@ bool os::dll_address_to_function_name(address addr, char *buf,
|
||||||
// no matching symbol so try for just file info
|
// no matching symbol so try for just file info
|
||||||
if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != NULL) {
|
if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != NULL) {
|
||||||
if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
|
if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
|
||||||
buf, buflen, offset, dlinfo.dli_fname)) {
|
buf, buflen, offset, dlinfo.dli_fname, demangle)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle non-dynamic manually:
|
// Handle non-dynamic manually:
|
||||||
if (dlinfo.dli_fbase != NULL &&
|
if (dlinfo.dli_fbase != NULL &&
|
||||||
Decoder::decode(addr, localbuf, MACH_MAXSYMLEN, offset, dlinfo.dli_fbase)) {
|
Decoder::decode(addr, localbuf, MACH_MAXSYMLEN, offset,
|
||||||
if (!Decoder::demangle(localbuf, buf, buflen)) {
|
dlinfo.dli_fbase)) {
|
||||||
|
if (!(demangle && Decoder::demangle(localbuf, buf, buflen))) {
|
||||||
jio_snprintf(buf, buflen, "%s", localbuf);
|
jio_snprintf(buf, buflen, "%s", localbuf);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1623,7 +1623,8 @@ bool os::address_is_in_vm(address addr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool os::dll_address_to_function_name(address addr, char *buf,
|
bool os::dll_address_to_function_name(address addr, char *buf,
|
||||||
int buflen, int *offset) {
|
int buflen, int *offset,
|
||||||
|
bool demangle) {
|
||||||
// buf is not optional, but offset is optional
|
// buf is not optional, but offset is optional
|
||||||
assert(buf != NULL, "sanity check");
|
assert(buf != NULL, "sanity check");
|
||||||
|
|
||||||
|
@ -1632,7 +1633,7 @@ bool os::dll_address_to_function_name(address addr, char *buf,
|
||||||
if (dladdr((void*)addr, &dlinfo) != 0) {
|
if (dladdr((void*)addr, &dlinfo) != 0) {
|
||||||
// see if we have a matching symbol
|
// see if we have a matching symbol
|
||||||
if (dlinfo.dli_saddr != NULL && dlinfo.dli_sname != NULL) {
|
if (dlinfo.dli_saddr != NULL && dlinfo.dli_sname != NULL) {
|
||||||
if (!Decoder::demangle(dlinfo.dli_sname, buf, buflen)) {
|
if (!(demangle && Decoder::demangle(dlinfo.dli_sname, buf, buflen))) {
|
||||||
jio_snprintf(buf, buflen, "%s", dlinfo.dli_sname);
|
jio_snprintf(buf, buflen, "%s", dlinfo.dli_sname);
|
||||||
}
|
}
|
||||||
if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr;
|
if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr;
|
||||||
|
@ -1641,7 +1642,7 @@ bool os::dll_address_to_function_name(address addr, char *buf,
|
||||||
// no matching symbol so try for just file info
|
// no matching symbol so try for just file info
|
||||||
if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != NULL) {
|
if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != NULL) {
|
||||||
if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
|
if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
|
||||||
buf, buflen, offset, dlinfo.dli_fname)) {
|
buf, buflen, offset, dlinfo.dli_fname, demangle)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1627,7 +1627,8 @@ typedef int (*dladdr1_func_type)(void *, Dl_info *, void **, int);
|
||||||
static dladdr1_func_type dladdr1_func = NULL;
|
static dladdr1_func_type dladdr1_func = NULL;
|
||||||
|
|
||||||
bool os::dll_address_to_function_name(address addr, char *buf,
|
bool os::dll_address_to_function_name(address addr, char *buf,
|
||||||
int buflen, int * offset) {
|
int buflen, int * offset,
|
||||||
|
bool demangle) {
|
||||||
// buf is not optional, but offset is optional
|
// buf is not optional, but offset is optional
|
||||||
assert(buf != NULL, "sanity check");
|
assert(buf != NULL, "sanity check");
|
||||||
|
|
||||||
|
@ -1655,7 +1656,7 @@ bool os::dll_address_to_function_name(address addr, char *buf,
|
||||||
if (dlinfo.dli_saddr != NULL &&
|
if (dlinfo.dli_saddr != NULL &&
|
||||||
(char *)dlinfo.dli_saddr + info->st_size > (char *)addr) {
|
(char *)dlinfo.dli_saddr + info->st_size > (char *)addr) {
|
||||||
if (dlinfo.dli_sname != NULL) {
|
if (dlinfo.dli_sname != NULL) {
|
||||||
if (!Decoder::demangle(dlinfo.dli_sname, buf, buflen)) {
|
if (!(demangle && Decoder::demangle(dlinfo.dli_sname, buf, buflen))) {
|
||||||
jio_snprintf(buf, buflen, "%s", dlinfo.dli_sname);
|
jio_snprintf(buf, buflen, "%s", dlinfo.dli_sname);
|
||||||
}
|
}
|
||||||
if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr;
|
if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr;
|
||||||
|
@ -1665,7 +1666,7 @@ bool os::dll_address_to_function_name(address addr, char *buf,
|
||||||
// no matching symbol so try for just file info
|
// no matching symbol so try for just file info
|
||||||
if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != NULL) {
|
if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != NULL) {
|
||||||
if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
|
if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
|
||||||
buf, buflen, offset, dlinfo.dli_fname)) {
|
buf, buflen, offset, dlinfo.dli_fname, demangle)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1679,7 +1680,7 @@ bool os::dll_address_to_function_name(address addr, char *buf,
|
||||||
if (dladdr((void *)addr, &dlinfo) != 0) {
|
if (dladdr((void *)addr, &dlinfo) != 0) {
|
||||||
// see if we have a matching symbol
|
// see if we have a matching symbol
|
||||||
if (dlinfo.dli_saddr != NULL && dlinfo.dli_sname != NULL) {
|
if (dlinfo.dli_saddr != NULL && dlinfo.dli_sname != NULL) {
|
||||||
if (!Decoder::demangle(dlinfo.dli_sname, buf, buflen)) {
|
if (!(demangle && Decoder::demangle(dlinfo.dli_sname, buf, buflen))) {
|
||||||
jio_snprintf(buf, buflen, dlinfo.dli_sname);
|
jio_snprintf(buf, buflen, dlinfo.dli_sname);
|
||||||
}
|
}
|
||||||
if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr;
|
if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr;
|
||||||
|
@ -1688,7 +1689,7 @@ bool os::dll_address_to_function_name(address addr, char *buf,
|
||||||
// no matching symbol so try for just file info
|
// no matching symbol so try for just file info
|
||||||
if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != NULL) {
|
if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != NULL) {
|
||||||
if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
|
if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
|
||||||
buf, buflen, offset, dlinfo.dli_fname)) {
|
buf, buflen, offset, dlinfo.dli_fname, demangle)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -162,7 +162,7 @@ void WindowsDecoder::initialize() {
|
||||||
// current function and comparing the result
|
// current function and comparing the result
|
||||||
address addr = (address)Decoder::demangle;
|
address addr = (address)Decoder::demangle;
|
||||||
char buf[MAX_PATH];
|
char buf[MAX_PATH];
|
||||||
if (decode(addr, buf, sizeof(buf), NULL)) {
|
if (decode(addr, buf, sizeof(buf), NULL, NULL, true /* demangle */)) {
|
||||||
_can_decode_in_vm = !strcmp(buf, "Decoder::demangle");
|
_can_decode_in_vm = !strcmp(buf, "Decoder::demangle");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -187,7 +187,7 @@ bool WindowsDecoder::can_decode_C_frame_in_vm() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool WindowsDecoder::decode(address addr, char *buf, int buflen, int* offset, const char* modulepath) {
|
bool WindowsDecoder::decode(address addr, char *buf, int buflen, int* offset, const char* modulepath, bool demangle_name) {
|
||||||
if (_pfnSymGetSymFromAddr64 != NULL) {
|
if (_pfnSymGetSymFromAddr64 != NULL) {
|
||||||
PIMAGEHLP_SYMBOL64 pSymbol;
|
PIMAGEHLP_SYMBOL64 pSymbol;
|
||||||
char symbolInfo[MAX_PATH + sizeof(IMAGEHLP_SYMBOL64)];
|
char symbolInfo[MAX_PATH + sizeof(IMAGEHLP_SYMBOL64)];
|
||||||
|
@ -197,7 +197,7 @@ bool WindowsDecoder::decode(address addr, char *buf, int buflen, int* offset, co
|
||||||
DWORD64 displacement;
|
DWORD64 displacement;
|
||||||
if (_pfnSymGetSymFromAddr64(::GetCurrentProcess(), (DWORD64)addr, &displacement, pSymbol)) {
|
if (_pfnSymGetSymFromAddr64(::GetCurrentProcess(), (DWORD64)addr, &displacement, pSymbol)) {
|
||||||
if (buf != NULL) {
|
if (buf != NULL) {
|
||||||
if (demangle(pSymbol->Name, buf, buflen)) {
|
if (!(demangle_name && demangle(pSymbol->Name, buf, buflen))) {
|
||||||
jio_snprintf(buf, buflen, "%s", pSymbol->Name);
|
jio_snprintf(buf, buflen, "%s", pSymbol->Name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -60,7 +60,7 @@ public:
|
||||||
|
|
||||||
bool can_decode_C_frame_in_vm() const;
|
bool can_decode_C_frame_in_vm() const;
|
||||||
bool demangle(const char* symbol, char *buf, int buflen);
|
bool demangle(const char* symbol, char *buf, int buflen);
|
||||||
bool decode(address addr, char *buf, int buflen, int* offset, const char* modulepath = NULL);
|
bool decode(address addr, char *buf, int buflen, int* offset, const char* modulepath, bool demangle);
|
||||||
bool decode(address addr, char *buf, int buflen, int* offset, const void* base) {
|
bool decode(address addr, char *buf, int buflen, int* offset, const void* base) {
|
||||||
ShouldNotReachHere();
|
ShouldNotReachHere();
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -1369,11 +1369,12 @@ bool os::dll_address_to_library_name(address addr, char* buf,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool os::dll_address_to_function_name(address addr, char *buf,
|
bool os::dll_address_to_function_name(address addr, char *buf,
|
||||||
int buflen, int *offset) {
|
int buflen, int *offset,
|
||||||
|
bool demangle) {
|
||||||
// buf is not optional, but offset is optional
|
// buf is not optional, but offset is optional
|
||||||
assert(buf != NULL, "sanity check");
|
assert(buf != NULL, "sanity check");
|
||||||
|
|
||||||
if (Decoder::decode(addr, buf, buflen, offset)) {
|
if (Decoder::decode(addr, buf, buflen, offset, demangle)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (offset != NULL) *offset = -1;
|
if (offset != NULL) *offset = -1;
|
||||||
|
|
|
@ -363,9 +363,6 @@ class CompilerInterfaceVC10 extends CompilerInterface {
|
||||||
|
|
||||||
// Set /On option
|
// Set /On option
|
||||||
addAttr(rv, "Optimization", opt);
|
addAttr(rv, "Optimization", opt);
|
||||||
// Set /FR option.
|
|
||||||
addAttr(rv, "BrowseInformation", "true");
|
|
||||||
addAttr(rv, "BrowseInformationFile", "$(IntDir)");
|
|
||||||
// Set /MD option.
|
// Set /MD option.
|
||||||
addAttr(rv, "RuntimeLibrary", "MultiThreadedDLL");
|
addAttr(rv, "RuntimeLibrary", "MultiThreadedDLL");
|
||||||
// Set /Oy- option
|
// Set /Oy- option
|
||||||
|
|
|
@ -208,7 +208,7 @@ void GenMarkSweep::mark_sweep_phase1(int level,
|
||||||
level,
|
level,
|
||||||
false, // Younger gens are not roots.
|
false, // Younger gens are not roots.
|
||||||
GenCollectedHeap::SO_None,
|
GenCollectedHeap::SO_None,
|
||||||
GenCollectedHeap::StrongRootsOnly,
|
ClassUnloading,
|
||||||
&follow_root_closure,
|
&follow_root_closure,
|
||||||
&follow_root_closure,
|
&follow_root_closure,
|
||||||
&follow_cld_closure);
|
&follow_cld_closure);
|
||||||
|
|
|
@ -381,6 +381,9 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) {
|
||||||
if (!constants()->is_shared()) {
|
if (!constants()->is_shared()) {
|
||||||
MetadataFactory::free_metadata(loader_data, constants());
|
MetadataFactory::free_metadata(loader_data, constants());
|
||||||
}
|
}
|
||||||
|
// Delete any cached resolution errors for the constant pool
|
||||||
|
SystemDictionary::delete_resolution_error(constants());
|
||||||
|
|
||||||
set_constants(NULL);
|
set_constants(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4089,9 +4089,6 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass,
|
||||||
mnt->adjust_method_entries(the_class(), &trace_name_printed);
|
mnt->adjust_method_entries(the_class(), &trace_name_printed);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fix Resolution Error table also to remove old constant pools
|
|
||||||
SystemDictionary::delete_resolution_error(old_constants);
|
|
||||||
|
|
||||||
if (the_class->oop_map_cache() != NULL) {
|
if (the_class->oop_map_cache() != NULL) {
|
||||||
// Flush references to any obsolete methods from the oop map cache
|
// Flush references to any obsolete methods from the oop map cache
|
||||||
// so that obsolete methods are not pinned.
|
// so that obsolete methods are not pinned.
|
||||||
|
|
|
@ -1384,6 +1384,12 @@ void Arguments::set_cms_and_parnew_gc_flags() {
|
||||||
if (!FLAG_IS_DEFAULT(OldPLABSize) || !FLAG_IS_DEFAULT(OldPLABWeight)) {
|
if (!FLAG_IS_DEFAULT(OldPLABSize) || !FLAG_IS_DEFAULT(OldPLABWeight)) {
|
||||||
CFLS_LAB::modify_initialization(OldPLABSize, OldPLABWeight);
|
CFLS_LAB::modify_initialization(OldPLABSize, OldPLABWeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!ClassUnloading) {
|
||||||
|
FLAG_SET_CMDLINE(bool, CMSClassUnloadingEnabled, false);
|
||||||
|
FLAG_SET_CMDLINE(bool, ExplicitGCInvokesConcurrentAndUnloadsClasses, false);
|
||||||
|
}
|
||||||
|
|
||||||
if (PrintGCDetails && Verbose) {
|
if (PrintGCDetails && Verbose) {
|
||||||
tty->print_cr("MarkStackSize: %uk MarkStackSizeMax: %uk",
|
tty->print_cr("MarkStackSize: %uk MarkStackSizeMax: %uk",
|
||||||
(unsigned int) (MarkStackSize / K), (uint) (MarkStackSizeMax / K));
|
(unsigned int) (MarkStackSize / K), (uint) (MarkStackSizeMax / K));
|
||||||
|
|
|
@ -539,7 +539,8 @@ class os: AllStatic {
|
||||||
// If function name is not found, buf[0] is set to '\0' and offset is
|
// If function name is not found, buf[0] is set to '\0' and offset is
|
||||||
// set to -1 (if offset is non-NULL).
|
// set to -1 (if offset is non-NULL).
|
||||||
static bool dll_address_to_function_name(address addr, char* buf,
|
static bool dll_address_to_function_name(address addr, char* buf,
|
||||||
int buflen, int* offset);
|
int buflen, int* offset,
|
||||||
|
bool demangle = true);
|
||||||
|
|
||||||
// Locate DLL/DSO. On success, full path of the library is copied to
|
// Locate DLL/DSO. On success, full path of the library is copied to
|
||||||
// buf, and offset is optionally set to be the distance between addr
|
// buf, and offset is optionally set to be the distance between addr
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -102,7 +102,7 @@ Mutex* Decoder::shared_decoder_lock() {
|
||||||
return _shared_decoder_lock;
|
return _shared_decoder_lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Decoder::decode(address addr, char* buf, int buflen, int* offset, const char* modulepath) {
|
bool Decoder::decode(address addr, char* buf, int buflen, int* offset, const char* modulepath, bool demangle) {
|
||||||
assert(_shared_decoder_lock != NULL, "Just check");
|
assert(_shared_decoder_lock != NULL, "Just check");
|
||||||
bool error_handling_thread = os::current_thread_id() == VMError::first_error_tid;
|
bool error_handling_thread = os::current_thread_id() == VMError::first_error_tid;
|
||||||
MutexLockerEx locker(error_handling_thread ? NULL : _shared_decoder_lock, true);
|
MutexLockerEx locker(error_handling_thread ? NULL : _shared_decoder_lock, true);
|
||||||
|
@ -110,7 +110,7 @@ bool Decoder::decode(address addr, char* buf, int buflen, int* offset, const cha
|
||||||
get_error_handler_instance(): get_shared_instance();
|
get_error_handler_instance(): get_shared_instance();
|
||||||
assert(decoder != NULL, "null decoder");
|
assert(decoder != NULL, "null decoder");
|
||||||
|
|
||||||
return decoder->decode(addr, buf, buflen, offset, modulepath);
|
return decoder->decode(addr, buf, buflen, offset, modulepath, demangle);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Decoder::decode(address addr, char* buf, int buflen, int* offset, const void* base) {
|
bool Decoder::decode(address addr, char* buf, int buflen, int* offset, const void* base) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -46,8 +46,12 @@ public:
|
||||||
|
|
||||||
// decode an pc address to corresponding function name and an offset from the beginning of
|
// decode an pc address to corresponding function name and an offset from the beginning of
|
||||||
// the function
|
// the function
|
||||||
|
//
|
||||||
|
// Note: the 'base' variant does not demangle names. The
|
||||||
|
// demangling that was done systematically in the 'modulepath' variant
|
||||||
|
// is now optional.
|
||||||
virtual bool decode(address pc, char* buf, int buflen, int* offset,
|
virtual bool decode(address pc, char* buf, int buflen, int* offset,
|
||||||
const char* modulepath = NULL) = 0;
|
const char* modulepath = NULL, bool demangle = true) = 0;
|
||||||
virtual bool decode(address pc, char* buf, int buflen, int* offset, const void* base) = 0;
|
virtual bool decode(address pc, char* buf, int buflen, int* offset, const void* base) = 0;
|
||||||
|
|
||||||
// demangle a C++ symbol
|
// demangle a C++ symbol
|
||||||
|
@ -81,7 +85,7 @@ public:
|
||||||
~NullDecoder() {};
|
~NullDecoder() {};
|
||||||
|
|
||||||
virtual bool decode(address pc, char* buf, int buflen, int* offset,
|
virtual bool decode(address pc, char* buf, int buflen, int* offset,
|
||||||
const char* modulepath = NULL) {
|
const char* modulepath, bool demangle) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,7 +105,10 @@ public:
|
||||||
|
|
||||||
class Decoder : AllStatic {
|
class Decoder : AllStatic {
|
||||||
public:
|
public:
|
||||||
static bool decode(address pc, char* buf, int buflen, int* offset, const char* modulepath = NULL);
|
static bool decode(address pc, char* buf, int buflen, int* offset, const char* modulepath = NULL, bool demangle = true);
|
||||||
|
static bool decode(address pc, char* buf, int buflen, int* offset, bool demangle) {
|
||||||
|
return decode(pc, buf, buflen, offset, (const char*) NULL, demangle);
|
||||||
|
}
|
||||||
static bool decode(address pc, char* buf, int buflen, int* offset, const void* base);
|
static bool decode(address pc, char* buf, int buflen, int* offset, const void* base);
|
||||||
static bool demangle(const char* symbol, char* buf, int buflen);
|
static bool demangle(const char* symbol, char* buf, int buflen);
|
||||||
static bool can_decode_C_frame_in_vm();
|
static bool can_decode_C_frame_in_vm();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -34,7 +34,7 @@ ElfDecoder::~ElfDecoder() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ElfDecoder::decode(address addr, char *buf, int buflen, int* offset, const char* filepath) {
|
bool ElfDecoder::decode(address addr, char *buf, int buflen, int* offset, const char* filepath, bool demangle_name) {
|
||||||
assert(filepath, "null file path");
|
assert(filepath, "null file path");
|
||||||
assert(buf != NULL && buflen > 0, "Invalid buffer");
|
assert(buf != NULL && buflen > 0, "Invalid buffer");
|
||||||
if (has_error()) return false;
|
if (has_error()) return false;
|
||||||
|
@ -46,7 +46,7 @@ bool ElfDecoder::decode(address addr, char *buf, int buflen, int* offset, const
|
||||||
if (!file->decode(addr, buf, buflen, offset)) {
|
if (!file->decode(addr, buf, buflen, offset)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (buf[0] != '\0') {
|
if (demangle_name && (buf[0] != '\0')) {
|
||||||
demangle(buf, buf, buflen);
|
demangle(buf, buf, buflen);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -42,7 +42,7 @@ public:
|
||||||
bool can_decode_C_frame_in_vm() const { return true; }
|
bool can_decode_C_frame_in_vm() const { return true; }
|
||||||
|
|
||||||
bool demangle(const char* symbol, char *buf, int buflen);
|
bool demangle(const char* symbol, char *buf, int buflen);
|
||||||
bool decode(address addr, char *buf, int buflen, int* offset, const char* filepath = NULL);
|
bool decode(address addr, char *buf, int buflen, int* offset, const char* filepath, bool demangle);
|
||||||
bool decode(address addr, char *buf, int buflen, int* offset, const void *base) {
|
bool decode(address addr, char *buf, int buflen, int* offset, const void *base) {
|
||||||
ShouldNotReachHere();
|
ShouldNotReachHere();
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -0,0 +1,143 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 2015, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 8076110
|
||||||
|
* @summary Redefine running methods that have cached resolution errors
|
||||||
|
* @library /testlibrary
|
||||||
|
* @modules java.instrument
|
||||||
|
* java.base/jdk.internal.org.objectweb.asm
|
||||||
|
* @build RedefineClassHelper
|
||||||
|
* @run main RedefineClassHelper
|
||||||
|
* @run main/othervm -javaagent:redefineagent.jar -XX:TraceRedefineClasses=0x600 RedefineRunningMethodsWithResolutionErrors
|
||||||
|
*/
|
||||||
|
|
||||||
|
import jdk.internal.org.objectweb.asm.ClassWriter;
|
||||||
|
import jdk.internal.org.objectweb.asm.Label;
|
||||||
|
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
||||||
|
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
|
||||||
|
public class RedefineRunningMethodsWithResolutionErrors extends ClassLoader implements Opcodes {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?> findClass(String name) throws ClassNotFoundException {
|
||||||
|
if (name.equals("C")) {
|
||||||
|
byte[] b = loadC(false);
|
||||||
|
return defineClass(name, b, 0, b.length);
|
||||||
|
} else {
|
||||||
|
return super.findClass(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] loadC(boolean redefine) {
|
||||||
|
ClassWriter cw = new ClassWriter(0);
|
||||||
|
|
||||||
|
cw.visit(52, ACC_SUPER | ACC_PUBLIC, "C", null, "java/lang/Object", null);
|
||||||
|
{
|
||||||
|
MethodVisitor mv;
|
||||||
|
|
||||||
|
mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "m", "()V", null, null);
|
||||||
|
mv.visitCode();
|
||||||
|
|
||||||
|
// First time we run we will:
|
||||||
|
// 1) Cache resolution errors
|
||||||
|
// 2) Redefine the class / method
|
||||||
|
// 3) Try to read the resolution errors that were cached
|
||||||
|
//
|
||||||
|
// The redefined method will never run, throw error to be sure
|
||||||
|
if (redefine) {
|
||||||
|
createThrowRuntimeExceptionCode(mv, "The redefined method was called");
|
||||||
|
} else {
|
||||||
|
createMethodBody(mv);
|
||||||
|
}
|
||||||
|
mv.visitMaxs(3, 0);
|
||||||
|
mv.visitEnd();
|
||||||
|
}
|
||||||
|
cw.visitEnd();
|
||||||
|
return cw.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void createMethodBody(MethodVisitor mv) {
|
||||||
|
Label classExists = new Label();
|
||||||
|
|
||||||
|
// Cache resolution errors
|
||||||
|
createLoadNonExistentClassCode(mv, classExists);
|
||||||
|
|
||||||
|
// Redefine our own class and method
|
||||||
|
mv.visitMethodInsn(INVOKESTATIC, "RedefineRunningMethodsWithResolutionErrors", "redefine", "()V");
|
||||||
|
|
||||||
|
// Provoke the same error again to make sure the resolution error cache works
|
||||||
|
createLoadNonExistentClassCode(mv, classExists);
|
||||||
|
|
||||||
|
// Test passed
|
||||||
|
mv.visitInsn(RETURN);
|
||||||
|
|
||||||
|
mv.visitFrame(F_SAME, 0, new Object[0], 0, new Object[0]);
|
||||||
|
mv.visitLabel(classExists);
|
||||||
|
|
||||||
|
createThrowRuntimeExceptionCode(mv, "Loaded class that shouldn't exist (\"NonExistentClass\")");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void createLoadNonExistentClassCode(MethodVisitor mv, Label classExists) {
|
||||||
|
Label tryLoadBegin = new Label();
|
||||||
|
Label tryLoadEnd = new Label();
|
||||||
|
Label catchLoadBlock = new Label();
|
||||||
|
mv.visitTryCatchBlock(tryLoadBegin, tryLoadEnd, catchLoadBlock, "java/lang/NoClassDefFoundError");
|
||||||
|
|
||||||
|
// Try to load a class that does not exist to provoke resolution errors
|
||||||
|
mv.visitLabel(tryLoadBegin);
|
||||||
|
mv.visitMethodInsn(INVOKESTATIC, "NonExistentClass", "nonExistentMethod", "()V");
|
||||||
|
mv.visitLabel(tryLoadEnd);
|
||||||
|
|
||||||
|
// No NoClassDefFoundError means NonExistentClass existed, which shouldn't happen
|
||||||
|
mv.visitJumpInsn(GOTO, classExists);
|
||||||
|
|
||||||
|
mv.visitFrame(F_SAME1, 0, new Object[0], 1, new Object[] { "java/lang/NoClassDefFoundError" });
|
||||||
|
mv.visitLabel(catchLoadBlock);
|
||||||
|
|
||||||
|
// Ignore the expected NoClassDefFoundError
|
||||||
|
mv.visitInsn(POP);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void createThrowRuntimeExceptionCode(MethodVisitor mv, String msg) {
|
||||||
|
mv.visitTypeInsn(NEW, "java/lang/RuntimeException");
|
||||||
|
mv.visitInsn(DUP);
|
||||||
|
mv.visitLdcInsn(msg);
|
||||||
|
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/RuntimeException", "<init>", "(Ljava/lang/String;)V");
|
||||||
|
mv.visitInsn(ATHROW);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Class<?> c;
|
||||||
|
|
||||||
|
public static void redefine() throws Exception {
|
||||||
|
RedefineClassHelper.redefineClass(c, loadC(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
|
||||||
|
c = Class.forName("C", true, new RedefineRunningMethodsWithResolutionErrors());
|
||||||
|
c.getMethod("m").invoke(null);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue