8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
Summary: Dl_info struct should only be used if dladdr() has returned non-zero (no errors) and always check the dladdr() return value; Dl_info.dli_sname and Dl_info.dli_saddr fields should only be used if non-NULL; update/improve runtime/6888954/vmerrors.sh test
Reviewed-by: dsamersoff, zgu, hseigel, coleenp
--- a/hotspot/src/os/bsd/vm/os_bsd.cpp Thu Jul 04 04:03:28 2013 -0700
+++ b/hotspot/src/os/bsd/vm/os_bsd.cpp Thu Jul 04 21:10:17 2013 -0700
@@ -1234,12 +1234,13 @@
Dl_info dlinfo;
if (libjvm_base_addr == NULL) {
- dladdr(CAST_FROM_FN_PTR(void *, os::address_is_in_vm), &dlinfo);
- libjvm_base_addr = (address)dlinfo.dli_fbase;
+ if (dladdr(CAST_FROM_FN_PTR(void *, os::address_is_in_vm), &dlinfo) != 0) {
+ libjvm_base_addr = (address)dlinfo.dli_fbase;
+ }
assert(libjvm_base_addr !=NULL, "Cannot obtain base address for libjvm");
}
- if (dladdr((void *)addr, &dlinfo)) {
+ if (dladdr((void *)addr, &dlinfo) != 0) {
if (libjvm_base_addr == (address)dlinfo.dli_fbase) return true;
}
@@ -1251,35 +1252,40 @@
bool os::dll_address_to_function_name(address addr, char *buf,
int buflen, int *offset) {
+ // buf is not optional, but offset is optional
+ assert(buf != NULL, "sanity check");
+
Dl_info dlinfo;
char localbuf[MACH_MAXSYMLEN];
- // dladdr will find names of dynamic functions only, but does
- // it set dli_fbase with mach_header address when it "fails" ?
- if (dladdr((void*)addr, &dlinfo) && dlinfo.dli_sname != NULL) {
- if (buf != NULL) {
- if(!Decoder::demangle(dlinfo.dli_sname, buf, buflen)) {
+ if (dladdr((void*)addr, &dlinfo) != 0) {
+ // see if we have a matching symbol
+ if (dlinfo.dli_saddr != NULL && dlinfo.dli_sname != NULL) {
+ if (!Decoder::demangle(dlinfo.dli_sname, buf, buflen)) {
jio_snprintf(buf, buflen, "%s", dlinfo.dli_sname);
}
+ if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr;
+ return true;
+ }
+ // no matching symbol so try for just file info
+ if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != NULL) {
+ if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
+ buf, buflen, offset, dlinfo.dli_fname)) {
+ return true;
+ }
}
- if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr;
- return true;
- } else if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != 0) {
- if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
- buf, buflen, offset, dlinfo.dli_fname)) {
- return true;
+
+ // Handle non-dynamic manually:
+ if (dlinfo.dli_fbase != NULL &&
+ Decoder::decode(addr, localbuf, MACH_MAXSYMLEN, offset,
+ dlinfo.dli_fbase)) {
+ if (!Decoder::demangle(localbuf, buf, buflen)) {
+ jio_snprintf(buf, buflen, "%s", localbuf);
+ }
+ return true;
}
}
-
- // Handle non-dymanic manually:
- if (dlinfo.dli_fbase != NULL &&
- Decoder::decode(addr, localbuf, MACH_MAXSYMLEN, offset, dlinfo.dli_fbase)) {
- if(!Decoder::demangle(localbuf, buf, buflen)) {
- jio_snprintf(buf, buflen, "%s", localbuf);
- }
- return true;
- }
- if (buf != NULL) buf[0] = '\0';
+ buf[0] = '\0';
if (offset != NULL) *offset = -1;
return false;
}
@@ -1287,17 +1293,24 @@
// ported from solaris version
bool os::dll_address_to_library_name(address addr, char* buf,
int buflen, int* offset) {
+ // buf is not optional, but offset is optional
+ assert(buf != NULL, "sanity check");
+
Dl_info dlinfo;
- if (dladdr((void*)addr, &dlinfo)){
- if (buf) jio_snprintf(buf, buflen, "%s", dlinfo.dli_fname);
- if (offset) *offset = addr - (address)dlinfo.dli_fbase;
- return true;
- } else {
- if (buf) buf[0] = '\0';
- if (offset) *offset = -1;
- return false;
+ if (dladdr((void*)addr, &dlinfo) != 0) {
+ if (dlinfo.dli_fname != NULL) {
+ jio_snprintf(buf, buflen, "%s", dlinfo.dli_fname);
+ }
+ if (dlinfo.dli_fbase != NULL && offset != NULL) {
+ *offset = addr - (address)dlinfo.dli_fbase;
+ }
+ return true;
}
+
+ buf[0] = '\0';
+ if (offset) *offset = -1;
+ return false;
}
// Loads .dll/.so and
@@ -1520,49 +1533,50 @@
}
void os::print_dll_info(outputStream *st) {
- st->print_cr("Dynamic libraries:");
+ st->print_cr("Dynamic libraries:");
#ifdef RTLD_DI_LINKMAP
- Dl_info dli;
- void *handle;
- Link_map *map;
- Link_map *p;
-
- if (!dladdr(CAST_FROM_FN_PTR(void *, os::print_dll_info), &dli)) {
- st->print_cr("Error: Cannot print dynamic libraries.");
- return;
- }
- handle = dlopen(dli.dli_fname, RTLD_LAZY);
- if (handle == NULL) {
- st->print_cr("Error: Cannot print dynamic libraries.");
- return;
- }
- dlinfo(handle, RTLD_DI_LINKMAP, &map);
- if (map == NULL) {
- st->print_cr("Error: Cannot print dynamic libraries.");
- return;
- }
-
- while (map->l_prev != NULL)
- map = map->l_prev;
-
- while (map != NULL) {
- st->print_cr(PTR_FORMAT " \t%s", map->l_addr, map->l_name);
- map = map->l_next;
- }
-
- dlclose(handle);
+ Dl_info dli;
+ void *handle;
+ Link_map *map;
+ Link_map *p;
+
+ if (dladdr(CAST_FROM_FN_PTR(void *, os::print_dll_info), &dli) == 0 ||
+ dli.dli_fname == NULL) {
+ st->print_cr("Error: Cannot print dynamic libraries.");
+ return;
+ }
+ handle = dlopen(dli.dli_fname, RTLD_LAZY);
+ if (handle == NULL) {
+ st->print_cr("Error: Cannot print dynamic libraries.");
+ return;
+ }
+ dlinfo(handle, RTLD_DI_LINKMAP, &map);
+ if (map == NULL) {
+ st->print_cr("Error: Cannot print dynamic libraries.");
+ return;
+ }
+
+ while (map->l_prev != NULL)
+ map = map->l_prev;
+
+ while (map != NULL) {
+ st->print_cr(PTR_FORMAT " \t%s", map->l_addr, map->l_name);
+ map = map->l_next;
+ }
+
+ dlclose(handle);
#elif defined(__APPLE__)
- uint32_t count;
- uint32_t i;
-
- count = _dyld_image_count();
- for (i = 1; i < count; i++) {
- const char *name = _dyld_get_image_name(i);
- intptr_t slide = _dyld_get_image_vmaddr_slide(i);
- st->print_cr(PTR_FORMAT " \t%s", slide, name);
- }
+ uint32_t count;
+ uint32_t i;
+
+ count = _dyld_image_count();
+ for (i = 1; i < count; i++) {
+ const char *name = _dyld_get_image_name(i);
+ intptr_t slide = _dyld_get_image_vmaddr_slide(i);
+ st->print_cr(PTR_FORMAT " \t%s", slide, name);
+ }
#else
- st->print_cr("Error: Cannot print dynamic libraries.");
+ st->print_cr("Error: Cannot print dynamic libraries.");
#endif
}
@@ -1707,8 +1721,11 @@
bool ret = dll_address_to_library_name(
CAST_FROM_FN_PTR(address, os::jvm_path),
dli_fname, sizeof(dli_fname), NULL);
- assert(ret != 0, "cannot locate libjvm");
- char *rp = realpath(dli_fname, buf);
+ assert(ret, "cannot locate libjvm");
+ char *rp = NULL;
+ if (ret && dli_fname[0] != '\0') {
+ rp = realpath(dli_fname, buf);
+ }
if (rp == NULL)
return;
@@ -3747,20 +3764,20 @@
bool os::find(address addr, outputStream* st) {
Dl_info dlinfo;
memset(&dlinfo, 0, sizeof(dlinfo));
- if (dladdr(addr, &dlinfo)) {
+ if (dladdr(addr, &dlinfo) != 0) {
st->print(PTR_FORMAT ": ", addr);
- if (dlinfo.dli_sname != NULL) {
+ if (dlinfo.dli_sname != NULL && dlinfo.dli_saddr != NULL) {
st->print("%s+%#x", dlinfo.dli_sname,
addr - (intptr_t)dlinfo.dli_saddr);
- } else if (dlinfo.dli_fname) {
+ } else if (dlinfo.dli_fbase != NULL) {
st->print("<offset %#x>", addr - (intptr_t)dlinfo.dli_fbase);
} else {
st->print("<absolute address>");
}
- if (dlinfo.dli_fname) {
+ if (dlinfo.dli_fname != NULL) {
st->print(" in %s", dlinfo.dli_fname);
}
- if (dlinfo.dli_fbase) {
+ if (dlinfo.dli_fbase != NULL) {
st->print(" at " PTR_FORMAT, dlinfo.dli_fbase);
}
st->cr();
@@ -3773,7 +3790,7 @@
if (!lowest) lowest = (address) dlinfo.dli_fbase;
if (begin < lowest) begin = lowest;
Dl_info dlinfo2;
- if (dladdr(end, &dlinfo2) && dlinfo2.dli_saddr != dlinfo.dli_saddr
+ if (dladdr(end, &dlinfo2) != 0 && dlinfo2.dli_saddr != dlinfo.dli_saddr
&& end > dlinfo2.dli_saddr && dlinfo2.dli_saddr > begin)
end = (address) dlinfo2.dli_saddr;
Disassembler::decode(begin, end, st);
--- a/hotspot/src/os/linux/vm/os_linux.cpp Thu Jul 04 04:03:28 2013 -0700
+++ b/hotspot/src/os/linux/vm/os_linux.cpp Thu Jul 04 21:10:17 2013 -0700
@@ -1682,12 +1682,13 @@
Dl_info dlinfo;
if (libjvm_base_addr == NULL) {
- dladdr(CAST_FROM_FN_PTR(void *, os::address_is_in_vm), &dlinfo);
- libjvm_base_addr = (address)dlinfo.dli_fbase;
+ if (dladdr(CAST_FROM_FN_PTR(void *, os::address_is_in_vm), &dlinfo) != 0) {
+ libjvm_base_addr = (address)dlinfo.dli_fbase;
+ }
assert(libjvm_base_addr !=NULL, "Cannot obtain base address for libjvm");
}
- if (dladdr((void *)addr, &dlinfo)) {
+ if (dladdr((void *)addr, &dlinfo) != 0) {
if (libjvm_base_addr == (address)dlinfo.dli_fbase) return true;
}
@@ -1696,24 +1697,30 @@
bool os::dll_address_to_function_name(address addr, char *buf,
int buflen, int *offset) {
+ // buf is not optional, but offset is optional
+ assert(buf != NULL, "sanity check");
+
Dl_info dlinfo;
- if (dladdr((void*)addr, &dlinfo) && dlinfo.dli_sname != NULL) {
- if (buf != NULL) {
- if(!Decoder::demangle(dlinfo.dli_sname, buf, buflen)) {
+ if (dladdr((void*)addr, &dlinfo) != 0) {
+ // see if we have a matching symbol
+ if (dlinfo.dli_saddr != NULL && dlinfo.dli_sname != NULL) {
+ if (!Decoder::demangle(dlinfo.dli_sname, buf, buflen)) {
jio_snprintf(buf, buflen, "%s", dlinfo.dli_sname);
}
+ if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr;
+ return true;
+ }
+ // no matching symbol so try for just file info
+ if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != NULL) {
+ if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
+ buf, buflen, offset, dlinfo.dli_fname)) {
+ return true;
+ }
}
- if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr;
- return true;
- } else if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != 0) {
- if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
- buf, buflen, offset, dlinfo.dli_fname)) {
- return true;
- }
- }
-
- if (buf != NULL) buf[0] = '\0';
+ }
+
+ buf[0] = '\0';
if (offset != NULL) *offset = -1;
return false;
}
@@ -1764,6 +1771,9 @@
bool os::dll_address_to_library_name(address addr, char* buf,
int buflen, int* offset) {
+ // buf is not optional, but offset is optional
+ assert(buf != NULL, "sanity check");
+
Dl_info dlinfo;
struct _address_to_library_name data;
@@ -1782,15 +1792,20 @@
// buf already contains library name
if (offset) *offset = addr - data.base;
return true;
- } else if (dladdr((void*)addr, &dlinfo)){
- if (buf) jio_snprintf(buf, buflen, "%s", dlinfo.dli_fname);
- if (offset) *offset = addr - (address)dlinfo.dli_fbase;
- return true;
- } else {
- if (buf) buf[0] = '\0';
- if (offset) *offset = -1;
- return false;
- }
+ }
+ if (dladdr((void*)addr, &dlinfo) != 0) {
+ if (dlinfo.dli_fname != NULL) {
+ jio_snprintf(buf, buflen, "%s", dlinfo.dli_fname);
+ }
+ if (dlinfo.dli_fbase != NULL && offset != NULL) {
+ *offset = addr - (address)dlinfo.dli_fbase;
+ }
+ return true;
+ }
+
+ buf[0] = '\0';
+ if (offset) *offset = -1;
+ return false;
}
// Loads .dll/.so and
@@ -2317,8 +2332,11 @@
bool ret = dll_address_to_library_name(
CAST_FROM_FN_PTR(address, os::jvm_path),
dli_fname, sizeof(dli_fname), NULL);
- assert(ret != 0, "cannot locate libjvm");
- char *rp = realpath(dli_fname, buf);
+ assert(ret, "cannot locate libjvm");
+ char *rp = NULL;
+ if (ret && dli_fname[0] != '\0') {
+ rp = realpath(dli_fname, buf);
+ }
if (rp == NULL)
return;
@@ -4730,20 +4748,20 @@
bool os::find(address addr, outputStream* st) {
Dl_info dlinfo;
memset(&dlinfo, 0, sizeof(dlinfo));
- if (dladdr(addr, &dlinfo)) {
+ if (dladdr(addr, &dlinfo) != 0) {
st->print(PTR_FORMAT ": ", addr);
- if (dlinfo.dli_sname != NULL) {
+ if (dlinfo.dli_sname != NULL && dlinfo.dli_saddr != NULL) {
st->print("%s+%#x", dlinfo.dli_sname,
addr - (intptr_t)dlinfo.dli_saddr);
- } else if (dlinfo.dli_fname) {
+ } else if (dlinfo.dli_fbase != NULL) {
st->print("<offset %#x>", addr - (intptr_t)dlinfo.dli_fbase);
} else {
st->print("<absolute address>");
}
- if (dlinfo.dli_fname) {
+ if (dlinfo.dli_fname != NULL) {
st->print(" in %s", dlinfo.dli_fname);
}
- if (dlinfo.dli_fbase) {
+ if (dlinfo.dli_fbase != NULL) {
st->print(" at " PTR_FORMAT, dlinfo.dli_fbase);
}
st->cr();
@@ -4756,7 +4774,7 @@
if (!lowest) lowest = (address) dlinfo.dli_fbase;
if (begin < lowest) begin = lowest;
Dl_info dlinfo2;
- if (dladdr(end, &dlinfo2) && dlinfo2.dli_saddr != dlinfo.dli_saddr
+ if (dladdr(end, &dlinfo2) != 0 && dlinfo2.dli_saddr != dlinfo.dli_saddr
&& end > dlinfo2.dli_saddr && dlinfo2.dli_saddr > begin)
end = (address) dlinfo2.dli_saddr;
Disassembler::decode(begin, end, st);
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp Thu Jul 04 04:03:28 2013 -0700
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp Thu Jul 04 21:10:17 2013 -0700
@@ -1924,12 +1924,13 @@
Dl_info dlinfo;
if (libjvm_base_addr == NULL) {
- dladdr(CAST_FROM_FN_PTR(void *, os::address_is_in_vm), &dlinfo);
- libjvm_base_addr = (address)dlinfo.dli_fbase;
+ if (dladdr(CAST_FROM_FN_PTR(void *, os::address_is_in_vm), &dlinfo) != 0) {
+ libjvm_base_addr = (address)dlinfo.dli_fbase;
+ }
assert(libjvm_base_addr !=NULL, "Cannot obtain base address for libjvm");
}
- if (dladdr((void *)addr, &dlinfo)) {
+ if (dladdr((void *)addr, &dlinfo) != 0) {
if (libjvm_base_addr == (address)dlinfo.dli_fbase) return true;
}
@@ -1941,114 +1942,133 @@
bool os::dll_address_to_function_name(address addr, char *buf,
int buflen, int * offset) {
+ // buf is not optional, but offset is optional
+ assert(buf != NULL, "sanity check");
+
Dl_info dlinfo;
// dladdr1_func was initialized in os::init()
- if (dladdr1_func){
- // yes, we have dladdr1
-
- // Support for dladdr1 is checked at runtime; it may be
- // available even if the vm is built on a machine that does
- // not have dladdr1 support. Make sure there is a value for
- // RTLD_DL_SYMENT.
- #ifndef RTLD_DL_SYMENT
- #define RTLD_DL_SYMENT 1
- #endif
+ if (dladdr1_func != NULL) {
+ // yes, we have dladdr1
+
+ // Support for dladdr1 is checked at runtime; it may be
+ // available even if the vm is built on a machine that does
+ // not have dladdr1 support. Make sure there is a value for
+ // RTLD_DL_SYMENT.
+ #ifndef RTLD_DL_SYMENT
+ #define RTLD_DL_SYMENT 1
+ #endif
#ifdef _LP64
- Elf64_Sym * info;
+ Elf64_Sym * info;
#else
- Elf32_Sym * info;
+ Elf32_Sym * info;
#endif
- if (dladdr1_func((void *)addr, &dlinfo, (void **)&info,
- RTLD_DL_SYMENT)) {
- if ((char *)dlinfo.dli_saddr + info->st_size > (char *)addr) {
- if (buf != NULL) {
- if (!Decoder::demangle(dlinfo.dli_sname, buf, buflen))
- jio_snprintf(buf, buflen, "%s", dlinfo.dli_sname);
- }
- if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr;
- return true;
- }
- }
- if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != 0) {
- if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
- buf, buflen, offset, dlinfo.dli_fname)) {
+ if (dladdr1_func((void *)addr, &dlinfo, (void **)&info,
+ RTLD_DL_SYMENT) != 0) {
+ // see if we have a matching symbol that covers our address
+ if (dlinfo.dli_saddr != NULL &&
+ (char *)dlinfo.dli_saddr + info->st_size > (char *)addr) {
+ if (dlinfo.dli_sname != NULL) {
+ if (!Decoder::demangle(dlinfo.dli_sname, buf, buflen)) {
+ jio_snprintf(buf, buflen, "%s", dlinfo.dli_sname);
+ }
+ if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr;
return true;
}
}
- if (buf != NULL) buf[0] = '\0';
- if (offset != NULL) *offset = -1;
- return false;
- } else {
- // no, only dladdr is available
- if (dladdr((void *)addr, &dlinfo)) {
- if (buf != NULL) {
- if (!Decoder::demangle(dlinfo.dli_sname, buf, buflen))
- jio_snprintf(buf, buflen, dlinfo.dli_sname);
- }
- if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr;
- return true;
- } else if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != 0) {
+ // no matching symbol so try for just file info
+ if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != NULL) {
if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
- buf, buflen, offset, dlinfo.dli_fname)) {
+ buf, buflen, offset, dlinfo.dli_fname)) {
return true;
}
}
- if (buf != NULL) buf[0] = '\0';
- if (offset != NULL) *offset = -1;
- return false;
- }
+ }
+ buf[0] = '\0';
+ if (offset != NULL) *offset = -1;
+ return false;
+ }
+
+ // no, only dladdr is available
+ if (dladdr((void *)addr, &dlinfo) != 0) {
+ // see if we have a matching symbol
+ if (dlinfo.dli_saddr != NULL && dlinfo.dli_sname != NULL) {
+ if (!Decoder::demangle(dlinfo.dli_sname, buf, buflen)) {
+ jio_snprintf(buf, buflen, dlinfo.dli_sname);
+ }
+ if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr;
+ return true;
+ }
+ // no matching symbol so try for just file info
+ if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != NULL) {
+ if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
+ buf, buflen, offset, dlinfo.dli_fname)) {
+ return true;
+ }
+ }
+ }
+ buf[0] = '\0';
+ if (offset != NULL) *offset = -1;
+ return false;
}
bool os::dll_address_to_library_name(address addr, char* buf,
int buflen, int* offset) {
+ // buf is not optional, but offset is optional
+ assert(buf != NULL, "sanity check");
+
Dl_info dlinfo;
- if (dladdr((void*)addr, &dlinfo)){
- if (buf) jio_snprintf(buf, buflen, "%s", dlinfo.dli_fname);
- if (offset) *offset = addr - (address)dlinfo.dli_fbase;
- return true;
- } else {
- if (buf) buf[0] = '\0';
- if (offset) *offset = -1;
- return false;
- }
+ if (dladdr((void*)addr, &dlinfo) != 0) {
+ if (dlinfo.dli_fname != NULL) {
+ jio_snprintf(buf, buflen, "%s", dlinfo.dli_fname);
+ }
+ if (dlinfo.dli_fbase != NULL && offset != NULL) {
+ *offset = addr - (address)dlinfo.dli_fbase;
+ }
+ return true;
+ }
+
+ buf[0] = '\0';
+ if (offset) *offset = -1;
+ return false;
}
// Prints the names and full paths of all opened dynamic libraries
// for current process
void os::print_dll_info(outputStream * st) {
- Dl_info dli;
- void *handle;
- Link_map *map;
- Link_map *p;
-
- st->print_cr("Dynamic libraries:"); st->flush();
-
- if (!dladdr(CAST_FROM_FN_PTR(void *, os::print_dll_info), &dli)) {
- st->print_cr("Error: Cannot print dynamic libraries.");
- return;
- }
- handle = dlopen(dli.dli_fname, RTLD_LAZY);
- if (handle == NULL) {
- st->print_cr("Error: Cannot print dynamic libraries.");
- return;
- }
- dlinfo(handle, RTLD_DI_LINKMAP, &map);
- if (map == NULL) {
- st->print_cr("Error: Cannot print dynamic libraries.");
- return;
- }
-
- while (map->l_prev != NULL)
- map = map->l_prev;
-
- while (map != NULL) {
- st->print_cr(PTR_FORMAT " \t%s", map->l_addr, map->l_name);
- map = map->l_next;
- }
-
- dlclose(handle);
+ Dl_info dli;
+ void *handle;
+ Link_map *map;
+ Link_map *p;
+
+ st->print_cr("Dynamic libraries:"); st->flush();
+
+ if (dladdr(CAST_FROM_FN_PTR(void *, os::print_dll_info), &dli) == 0 ||
+ dli.dli_fname == NULL) {
+ st->print_cr("Error: Cannot print dynamic libraries.");
+ return;
+ }
+ handle = dlopen(dli.dli_fname, RTLD_LAZY);
+ if (handle == NULL) {
+ st->print_cr("Error: Cannot print dynamic libraries.");
+ return;
+ }
+ dlinfo(handle, RTLD_DI_LINKMAP, &map);
+ if (map == NULL) {
+ st->print_cr("Error: Cannot print dynamic libraries.");
+ return;
+ }
+
+ while (map->l_prev != NULL)
+ map = map->l_prev;
+
+ while (map != NULL) {
+ st->print_cr(PTR_FORMAT " \t%s", map->l_addr, map->l_name);
+ map = map->l_next;
+ }
+
+ dlclose(handle);
}
// Loads .dll/.so and
@@ -2475,7 +2495,12 @@
Dl_info dlinfo;
int ret = dladdr(CAST_FROM_FN_PTR(void *, os::jvm_path), &dlinfo);
assert(ret != 0, "cannot locate libjvm");
- realpath((char *)dlinfo.dli_fname, buf);
+ if (ret != 0 && dlinfo.dli_fname != NULL) {
+ realpath((char *)dlinfo.dli_fname, buf);
+ } else {
+ buf[0] = '\0';
+ return;
+ }
if (Arguments::created_by_gamma_launcher()) {
// Support for the gamma launcher. Typical value for buf is
@@ -6077,24 +6102,20 @@
bool os::find(address addr, outputStream* st) {
Dl_info dlinfo;
memset(&dlinfo, 0, sizeof(dlinfo));
- if (dladdr(addr, &dlinfo)) {
-#ifdef _LP64
- st->print("0x%016lx: ", addr);
-#else
- st->print("0x%08x: ", addr);
-#endif
- if (dlinfo.dli_sname != NULL)
+ if (dladdr(addr, &dlinfo) != 0) {
+ st->print(PTR_FORMAT ": ", addr);
+ if (dlinfo.dli_sname != NULL && dlinfo.dli_saddr != NULL) {
st->print("%s+%#lx", dlinfo.dli_sname, addr-(intptr_t)dlinfo.dli_saddr);
- else if (dlinfo.dli_fname)
+ } else if (dlinfo.dli_fbase != NULL)
st->print("<offset %#lx>", addr-(intptr_t)dlinfo.dli_fbase);
else
st->print("<absolute address>");
- if (dlinfo.dli_fname) st->print(" in %s", dlinfo.dli_fname);
-#ifdef _LP64
- if (dlinfo.dli_fbase) st->print(" at 0x%016lx", dlinfo.dli_fbase);
-#else
- if (dlinfo.dli_fbase) st->print(" at 0x%08x", dlinfo.dli_fbase);
-#endif
+ if (dlinfo.dli_fname != NULL) {
+ st->print(" in %s", dlinfo.dli_fname);
+ }
+ if (dlinfo.dli_fbase != NULL) {
+ st->print(" at " PTR_FORMAT, dlinfo.dli_fbase);
+ }
st->cr();
if (Verbose) {
@@ -6105,7 +6126,7 @@
if (!lowest) lowest = (address) dlinfo.dli_fbase;
if (begin < lowest) begin = lowest;
Dl_info dlinfo2;
- if (dladdr(end, &dlinfo2) && dlinfo2.dli_saddr != dlinfo.dli_saddr
+ if (dladdr(end, &dlinfo2) != 0 && dlinfo2.dli_saddr != dlinfo.dli_saddr
&& end > dlinfo2.dli_saddr && dlinfo2.dli_saddr > begin)
end = (address) dlinfo2.dli_saddr;
Disassembler::decode(begin, end, st);
--- a/hotspot/src/os/windows/vm/os_windows.cpp Thu Jul 04 04:03:28 2013 -0700
+++ b/hotspot/src/os/windows/vm/os_windows.cpp Thu Jul 04 21:10:17 2013 -0700
@@ -1420,34 +1420,40 @@
bool os::dll_address_to_library_name(address addr, char* buf,
int buflen, int* offset) {
+ // buf is not optional, but offset is optional
+ assert(buf != NULL, "sanity check");
+
// NOTE: the reason we don't use SymGetModuleInfo() is it doesn't always
// return the full path to the DLL file, sometimes it returns path
// to the corresponding PDB file (debug info); sometimes it only
// returns partial path, which makes life painful.
- struct _modinfo mi;
- mi.addr = addr;
- mi.full_path = buf;
- mi.buflen = buflen;
- int pid = os::current_process_id();
- if (enumerate_modules(pid, _locate_module_by_addr, (void *)&mi)) {
- // buf already contains path name
- if (offset) *offset = addr - mi.base_addr;
- return true;
- } else {
- if (buf) buf[0] = '\0';
- if (offset) *offset = -1;
- return false;
- }
+ struct _modinfo mi;
+ mi.addr = addr;
+ mi.full_path = buf;
+ mi.buflen = buflen;
+ int pid = os::current_process_id();
+ if (enumerate_modules(pid, _locate_module_by_addr, (void *)&mi)) {
+ // buf already contains path name
+ if (offset) *offset = addr - mi.base_addr;
+ return true;
+ }
+
+ buf[0] = '\0';
+ if (offset) *offset = -1;
+ return false;
}
bool os::dll_address_to_function_name(address addr, char *buf,
int buflen, int *offset) {
+ // buf is not optional, but offset is optional
+ assert(buf != NULL, "sanity check");
+
if (Decoder::decode(addr, buf, buflen, offset)) {
return true;
}
if (offset != NULL) *offset = -1;
- if (buf != NULL) buf[0] = '\0';
+ buf[0] = '\0';
return false;
}
@@ -2689,6 +2695,19 @@
}
#endif
+#ifndef PRODUCT
+void os::win32::call_test_func_with_wrapper(void (*funcPtr)(void)) {
+ // Install a win32 structured exception handler around the test
+ // function call so the VM can generate an error dump if needed.
+ __try {
+ (*funcPtr)();
+ } __except(topLevelExceptionFilter(
+ (_EXCEPTION_POINTERS*)_exception_info())) {
+ // Nothing to do.
+ }
+}
+#endif
+
// Virtual Memory
int os::vm_page_size() { return os::win32::vm_page_size(); }
--- a/hotspot/src/os/windows/vm/os_windows.hpp Thu Jul 04 04:03:28 2013 -0700
+++ b/hotspot/src/os/windows/vm/os_windows.hpp Thu Jul 04 21:10:17 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -94,6 +94,10 @@
static address fast_jni_accessor_wrapper(BasicType);
#endif
+#ifndef PRODUCT
+ static void call_test_func_with_wrapper(void (*funcPtr)(void));
+#endif
+
// filter function to ignore faults on serializations page
static LONG WINAPI serialize_fault_filter(struct _EXCEPTION_POINTERS* e);
};
--- a/hotspot/src/os/windows/vm/os_windows.inline.hpp Thu Jul 04 04:03:28 2013 -0700
+++ b/hotspot/src/os/windows/vm/os_windows.inline.hpp Thu Jul 04 21:10:17 2013 -0700
@@ -106,4 +106,10 @@
inline int os::close(int fd) {
return ::close(fd);
}
+
+#ifndef PRODUCT
+ #define CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(f) \
+ os::win32::call_test_func_with_wrapper(f)
+#endif
+
#endif // OS_WINDOWS_VM_OS_WINDOWS_INLINE_HPP
--- a/hotspot/src/share/vm/prims/jni.cpp Thu Jul 04 04:03:28 2013 -0700
+++ b/hotspot/src/share/vm/prims/jni.cpp Thu Jul 04 21:10:17 2013 -0700
@@ -5138,9 +5138,21 @@
event.commit();
}
+#ifndef PRODUCT
+ #ifndef TARGET_OS_FAMILY_windows
+ #define CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(f) f()
+ #endif
+
// Check if we should compile all classes on bootclasspath
- NOT_PRODUCT(if (CompileTheWorld) ClassLoader::compile_the_world();)
- NOT_PRODUCT(if (ReplayCompiles) ciReplay::replay(thread);)
+ if (CompileTheWorld) ClassLoader::compile_the_world();
+ if (ReplayCompiles) ciReplay::replay(thread);
+
+ // Some platforms (like Win*) need a wrapper around these test
+ // functions in order to properly handle error conditions.
+ CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(test_error_handler);
+ CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(execute_internal_vm_tests);
+#endif
+
// Since this is not a JVM_ENTRY we have to set the thread state manually before leaving.
ThreadStateTransition::transition_and_fence(thread, _thread_in_vm, _thread_in_native);
} else {
@@ -5157,8 +5169,6 @@
OrderAccess::release_store(&vm_created, 0);
}
- NOT_PRODUCT(test_error_handler(ErrorHandlerTest));
- NOT_PRODUCT(execute_internal_vm_tests());
return result;
}
--- a/hotspot/src/share/vm/runtime/os.hpp Thu Jul 04 04:03:28 2013 -0700
+++ b/hotspot/src/share/vm/runtime/os.hpp Thu Jul 04 21:10:17 2013 -0700
@@ -507,16 +507,16 @@
// Symbol lookup, find nearest function name; basically it implements
// dladdr() for all platforms. Name of the nearest function is copied
- // to buf. Distance from its base address is returned as offset.
+ // to buf. Distance from its base address is optionally returned as offset.
// If function name is not found, buf[0] is set to '\0' and offset is
- // set to -1.
+ // set to -1 (if offset is non-NULL).
static bool dll_address_to_function_name(address addr, char* buf,
int buflen, int* offset);
// Locate DLL/DSO. On success, full path of the library is copied to
- // buf, and offset is set to be the distance between addr and the
- // library's base address. On failure, buf[0] is set to '\0' and
- // offset is set to -1.
+ // buf, and offset is optionally set to be the distance between addr
+ // and the library's base address. On failure, buf[0] is set to '\0'
+ // and offset is set to -1 (if offset is non-NULL).
static bool dll_address_to_library_name(address addr, char* buf,
int buflen, int* offset);
--- a/hotspot/src/share/vm/utilities/debug.cpp Thu Jul 04 04:03:28 2013 -0700
+++ b/hotspot/src/share/vm/utilities/debug.cpp Thu Jul 04 21:10:17 2013 -0700
@@ -314,8 +314,8 @@
#ifndef PRODUCT
#include <signal.h>
-void test_error_handler(size_t test_num)
-{
+void test_error_handler() {
+ uintx test_num = ErrorHandlerTest;
if (test_num == 0) return;
// If asserts are disabled, use the corresponding guarantee instead.
@@ -327,6 +327,8 @@
const char* const eol = os::line_separator();
const char* const msg = "this message should be truncated during formatting";
+ char * const dataPtr = NULL; // bad data pointer
+ const void (*funcPtr)(void) = (const void(*)()) 0xF; // bad function pointer
// Keep this in sync with test/runtime/6888954/vmerrors.sh.
switch (n) {
@@ -348,11 +350,16 @@
case 9: ShouldNotCallThis();
case 10: ShouldNotReachHere();
case 11: Unimplemented();
- // This is last because it does not generate an hs_err* file on Windows.
- case 12: os::signal_raise(SIGSEGV);
+ // There's no guarantee the bad data pointer will crash us
+ // so "break" out to the ShouldNotReachHere().
+ case 12: *dataPtr = '\0'; break;
+ // There's no guarantee the bad function pointer will crash us
+ // so "break" out to the ShouldNotReachHere().
+ case 13: (*funcPtr)(); break;
- default: ShouldNotReachHere();
+ default: tty->print_cr("ERROR: %d: unexpected test_num value.", n);
}
+ ShouldNotReachHere();
}
#endif // !PRODUCT
--- a/hotspot/src/share/vm/utilities/debug.hpp Thu Jul 04 04:03:28 2013 -0700
+++ b/hotspot/src/share/vm/utilities/debug.hpp Thu Jul 04 21:10:17 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -243,7 +243,7 @@
void set_error_reported();
/* Test assert(), fatal(), guarantee(), etc. */
-NOT_PRODUCT(void test_error_handler(size_t test_num);)
+NOT_PRODUCT(void test_error_handler();)
void pd_ps(frame f);
void pd_obfuscate_location(char *buf, size_t buflen);
--- a/hotspot/test/runtime/6888954/vmerrors.sh Thu Jul 04 04:03:28 2013 -0700
+++ b/hotspot/test/runtime/6888954/vmerrors.sh Thu Jul 04 21:10:17 2013 -0700
@@ -1,5 +1,6 @@
# @test
# @bug 6888954
+# @bug 8015884
# @summary exercise HotSpot error handling code
# @author John Coomes
# @run shell vmerrors.sh
@@ -27,9 +28,24 @@
rc=0
assert_re='(assert|guarantee)[(](str|num).*failed: *'
+# for bad_data_ptr_re:
+# EXCEPTION_ACCESS_VIOLATION - Win-*
+# SIGILL - MacOS X
+# SIGSEGV - Linux-*, Solaris SPARC-*, Solaris X86-*
+#
+bad_data_ptr_re='(SIGILL|SIGSEGV|EXCEPTION_ACCESS_VIOLATION).* at pc='
+#
+# for bad_func_ptr_re:
+# EXCEPTION_ACCESS_VIOLATION - Win-*
+# SIGBUS - Solaris SPARC-64
+# SIGSEGV - Linux-*, Solaris SPARC-32, Solaris X86-*
+#
+# Note: would like to use "pc=0x00*0f," in the pattern, but Solaris SPARC-*
+# gets its signal at a PC in test_error_handler().
+#
+bad_func_ptr_re='(SIGBUS|SIGSEGV|EXCEPTION_ACCESS_VIOLATION).* at pc='
guarantee_re='guarantee[(](str|num).*failed: *'
fatal_re='fatal error: *'
-signal_re='(SIGSEGV|EXCEPTION_ACCESS_VIOLATION).* at pc='
tail_1='.*expected null'
tail_2='.*num='
@@ -39,8 +55,9 @@
"${fatal_re}${tail_1}" "${fatal_re}${tail_2}" \
"${fatal_re}.*truncated" "ChunkPool::allocate" \
"ShouldNotCall" "ShouldNotReachHere" \
- "Unimplemented" "$signal_re"
-
+ "Unimplemented" "$bad_data_ptr_re" \
+ "$bad_func_ptr_re"
+
do
i2=$i
[ $i -lt 10 ] && i2=0$i