# HG changeset patch # User fparain # Date 1373036980 25200 # Node ID cc5b7915104e3a1be16a19b141e921e47541e358 # Parent ea4d24c1e0c61b1d7d288e0346817ca0c7d04e1a# Parent 93e6dce53ba78efa2987f7c0e2d160811ce51f82 Merge diff -r ea4d24c1e0c6 -r cc5b7915104e src/os/bsd/vm/os_bsd.cpp --- a/src/os/bsd/vm/os_bsd.cpp Thu Jul 04 14:56:49 2013 -0700 +++ b/src/os/bsd/vm/os_bsd.cpp Fri Jul 05 08:09:40 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("", addr - (intptr_t)dlinfo.dli_fbase); } else { st->print(""); } - 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); diff -r ea4d24c1e0c6 -r cc5b7915104e src/os/linux/vm/os_linux.cpp --- a/src/os/linux/vm/os_linux.cpp Thu Jul 04 14:56:49 2013 -0700 +++ b/src/os/linux/vm/os_linux.cpp Fri Jul 05 08:09:40 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("", addr - (intptr_t)dlinfo.dli_fbase); } else { st->print(""); } - 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); diff -r ea4d24c1e0c6 -r cc5b7915104e src/os/solaris/vm/os_solaris.cpp --- a/src/os/solaris/vm/os_solaris.cpp Thu Jul 04 14:56:49 2013 -0700 +++ b/src/os/solaris/vm/os_solaris.cpp Fri Jul 05 08:09:40 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("", addr-(intptr_t)dlinfo.dli_fbase); else st->print(""); - 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); diff -r ea4d24c1e0c6 -r cc5b7915104e src/os/windows/vm/os_windows.cpp --- a/src/os/windows/vm/os_windows.cpp Thu Jul 04 14:56:49 2013 -0700 +++ b/src/os/windows/vm/os_windows.cpp Fri Jul 05 08:09:40 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(); } diff -r ea4d24c1e0c6 -r cc5b7915104e src/os/windows/vm/os_windows.hpp --- a/src/os/windows/vm/os_windows.hpp Thu Jul 04 14:56:49 2013 -0700 +++ b/src/os/windows/vm/os_windows.hpp Fri Jul 05 08:09:40 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); }; diff -r ea4d24c1e0c6 -r cc5b7915104e src/os/windows/vm/os_windows.inline.hpp --- a/src/os/windows/vm/os_windows.inline.hpp Thu Jul 04 14:56:49 2013 -0700 +++ b/src/os/windows/vm/os_windows.inline.hpp Fri Jul 05 08:09:40 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 diff -r ea4d24c1e0c6 -r cc5b7915104e src/share/vm/prims/jni.cpp --- a/src/share/vm/prims/jni.cpp Thu Jul 04 14:56:49 2013 -0700 +++ b/src/share/vm/prims/jni.cpp Fri Jul 05 08:09:40 2013 -0700 @@ -5097,7 +5097,7 @@ // function used to determine this will always return false. Atomic::xchg // does not have this problem. if (Atomic::xchg(1, &vm_created) == 1) { - return JNI_ERR; // already created, or create attempt in progress + return JNI_EEXIST; // already created, or create attempt in progress } if (Atomic::xchg(0, &safe_to_recreate_vm) == 0) { return JNI_ERR; // someone tried and failed and retry not allowed. @@ -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; } diff -r ea4d24c1e0c6 -r cc5b7915104e src/share/vm/runtime/os.hpp --- a/src/share/vm/runtime/os.hpp Thu Jul 04 14:56:49 2013 -0700 +++ b/src/share/vm/runtime/os.hpp Fri Jul 05 08:09:40 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); diff -r ea4d24c1e0c6 -r cc5b7915104e src/share/vm/services/memTracker.hpp --- a/src/share/vm/services/memTracker.hpp Thu Jul 04 14:56:49 2013 -0700 +++ b/src/share/vm/services/memTracker.hpp Fri Jul 05 08:09:40 2013 -0700 @@ -470,7 +470,21 @@ static void check_NMT_load(Thread* thr) { assert(thr != NULL, "Sanity check"); if (_slowdown_calling_thread && thr != _worker_thread) { +#ifdef _WINDOWS + // On Windows, os::NakedYield() does not work as well + // as os::yield_all() os::yield_all(); +#else + // On Solaris, os::yield_all() depends on os::sleep() + // which requires JavaTherad in _thread_in_vm state. + // Transits thread to _thread_in_vm state can be dangerous + // if caller holds lock, as it may deadlock with Threads_lock. + // So use NaKedYield instead. + // + // Linux and BSD, NakedYield() and yield_all() implementations + // are the same. + os::NakedYield(); +#endif } } diff -r ea4d24c1e0c6 -r cc5b7915104e src/share/vm/utilities/debug.cpp --- a/src/share/vm/utilities/debug.cpp Thu Jul 04 14:56:49 2013 -0700 +++ b/src/share/vm/utilities/debug.cpp Fri Jul 05 08:09:40 2013 -0700 @@ -314,8 +314,8 @@ #ifndef PRODUCT #include -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 diff -r ea4d24c1e0c6 -r cc5b7915104e src/share/vm/utilities/debug.hpp --- a/src/share/vm/utilities/debug.hpp Thu Jul 04 14:56:49 2013 -0700 +++ b/src/share/vm/utilities/debug.hpp Fri Jul 05 08:09:40 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); diff -r ea4d24c1e0c6 -r cc5b7915104e src/share/vm/utilities/vmError.cpp --- a/src/share/vm/utilities/vmError.cpp Thu Jul 04 14:56:49 2013 -0700 +++ b/src/share/vm/utilities/vmError.cpp Fri Jul 05 08:09:40 2013 -0700 @@ -908,10 +908,11 @@ // This is not the first error, see if it happened in a different thread // or in the same thread during error reporting. if (first_error_tid != mytid) { - jio_snprintf(buffer, sizeof(buffer), + char msgbuf[64]; + jio_snprintf(msgbuf, sizeof(msgbuf), "[thread " INT64_FORMAT " also had an error]", mytid); - out.print_raw_cr(buffer); + out.print_raw_cr(msgbuf); // error reporting is not MT-safe, block current thread os::infinite_sleep(); diff -r ea4d24c1e0c6 -r cc5b7915104e test/runtime/6888954/vmerrors.sh --- a/test/runtime/6888954/vmerrors.sh Thu Jul 04 14:56:49 2013 -0700 +++ b/test/runtime/6888954/vmerrors.sh Fri Jul 05 08:09:40 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