OpenJDK / jdk / jdk
changeset 51139:c95334202a14
8207342: error occurred during error reporting (printing register info)
Summary: os::print_location misses a check if the pointer is readable.
Reviewed-by: goetz, coleenp
author | mdoerr |
---|---|
date | Wed, 18 Jul 2018 11:27:14 +0200 |
parents | 914f305ba6fa |
children | 1edcf36fe15f |
files | src/hotspot/os/aix/misc_aix.cpp src/hotspot/os/aix/misc_aix.hpp src/hotspot/os/aix/porting_aix.cpp src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp src/hotspot/share/code/codeHeapState.cpp src/hotspot/share/code/codeHeapState.hpp src/hotspot/share/runtime/os.cpp src/hotspot/share/runtime/os.hpp |
diffstat | 9 files changed, 70 insertions(+), 62 deletions(-) [+] |
line wrap: on
line diff
--- a/src/hotspot/os/aix/misc_aix.cpp Tue Jul 17 19:59:38 2018 -0700 +++ b/src/hotspot/os/aix/misc_aix.cpp Wed Jul 18 11:27:14 2018 +0200 @@ -49,16 +49,3 @@ const int rc = pthread_mutex_unlock(cs); assert0(rc == 0); } - -bool MiscUtils::is_readable_pointer(const void* p) { - if (!CanUseSafeFetch32()) { - return true; - } - int* const aligned = (int*) align_down(p, 4); - int cafebabe = 0xcafebabe; - int deadbeef = 0xdeadbeef; - return (SafeFetch32(aligned, cafebabe) != cafebabe) || - (SafeFetch32(aligned, deadbeef) != deadbeef); -} - -
--- a/src/hotspot/os/aix/misc_aix.hpp Tue Jul 17 19:59:38 2018 -0700 +++ b/src/hotspot/os/aix/misc_aix.hpp Wed Jul 18 11:27:14 2018 +0200 @@ -88,13 +88,6 @@ _pcsobj->leave(); } }; - - // Returns true if pointer can be dereferenced without triggering a segment - // violation. Returns false if pointer is invalid. - // Note: Depends on stub routines; prior to stub routine generation, will - // always return true. Use CanUseSafeFetch32 to handle this case. - bool is_readable_pointer(const void* p); - } #endif // OS_AIX_VM_MISC_AIX_HPP
--- a/src/hotspot/os/aix/porting_aix.cpp Tue Jul 17 19:59:38 2018 -0700 +++ b/src/hotspot/os/aix/porting_aix.cpp Wed Jul 18 11:27:14 2018 +0200 @@ -142,7 +142,7 @@ // in that case I try reading the traceback table unsafe - I rather risk secondary crashes in // error files than not having a callstack.) #define CHECK_POINTER_READABLE(p) \ - if (!MiscUtils::is_readable_pointer(p)) { \ + if (!os::is_readable_pointer(p)) { \ trcVerbose("pc not readable"); \ return false; \ } @@ -230,7 +230,7 @@ const short l = MIN2<short>(*((short*)pc2), namelen - 1); // Be very careful. int i = 0; char* const p = (char*)pc2 + sizeof(short); - while (i < l && MiscUtils::is_readable_pointer(p + i)) { + while (i < l && os::is_readable_pointer(p + i)) { p_name[i] = p[i]; i++; } @@ -489,7 +489,7 @@ const struct tbtable* tb = NULL; int displacement = -1; - if (!MiscUtils::is_readable_pointer(pc)) { + if (!os::is_readable_pointer(pc)) { st->print("(invalid)"); return; } @@ -697,7 +697,7 @@ print_info_for_pc(st, cur_iar, buf, buf_size, demangle); st->cr(); - if (cur_iar && MiscUtils::is_readable_pointer(cur_iar)) { + if (cur_iar && os::is_readable_pointer(cur_iar)) { decode_instructions_at_pc( "Decoded instructions at iar:", cur_iar, 32, 16, st); @@ -710,7 +710,7 @@ print_info_for_pc(st, cur_lr, buf, buf_size, demangle); st->cr(); - if (cur_lr && MiscUtils::is_readable_pointer(cur_lr)) { + if (cur_lr && os::is_readable_pointer(cur_lr)) { decode_instructions_at_pc( "Decoded instructions at lr:", cur_lr, 32, 16, st); @@ -729,7 +729,7 @@ // Check and print rtoc. st->print("rtoc: " PTR64_FORMAT " ", p2i(cur_rtoc)); if (cur_rtoc == NULL || cur_rtoc == (codeptr_t)-1 || - !MiscUtils::is_readable_pointer(cur_rtoc)) { + !os::is_readable_pointer(cur_rtoc)) { st->print("(invalid)"); } else if (((uintptr_t)cur_rtoc) & 0x7) { st->print("(unaligned)");
--- a/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp Tue Jul 17 19:59:38 2018 -0700 +++ b/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp Wed Jul 18 11:27:14 2018 +0200 @@ -603,7 +603,9 @@ st->print_cr("Register to memory mapping:"); st->cr(); - // this is only for the "general purpose" registers + st->print("pc ="); print_location(st, (intptr_t)uc->uc_mcontext.regs->nip); + st->print("lr ="); print_location(st, (intptr_t)uc->uc_mcontext.regs->link); + st->print("ctr ="); print_location(st, (intptr_t)uc->uc_mcontext.regs->ctr); for (int i = 0; i < 32; i++) { st->print("r%-2d=", i); print_location(st, uc->uc_mcontext.regs->gpr[i]);
--- a/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp Tue Jul 17 19:59:38 2018 -0700 +++ b/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp Wed Jul 18 11:27:14 2018 +0200 @@ -628,7 +628,19 @@ } void os::print_register_info(outputStream *st, const void *context) { - st->print("Not ported\n"); + if (context == NULL) return; + + const ucontext_t *uc = (const ucontext_t*)context; + + st->print_cr("Register to memory mapping:"); + st->cr(); + + st->print("pc ="); print_location(st, (intptr_t)uc->uc_mcontext.psw.addr); + for (int i = 0; i < 16; i++) { + st->print("r%-2d=", i); + print_location(st, uc->uc_mcontext.gregs[i]); + } + st->cr(); } #ifndef PRODUCT
--- a/src/hotspot/share/code/codeHeapState.cpp Tue Jul 17 19:59:38 2018 -0700 +++ b/src/hotspot/share/code/codeHeapState.cpp Wed Jul 18 11:27:14 2018 +0200 @@ -2129,8 +2129,8 @@ bool blob_initialized = (this_blob != NULL) && (this_blob->header_size() >= 0) && (this_blob->relocation_size() >= 0) && ((address)this_blob + this_blob->header_size() == (address)(this_blob->relocation_begin())) && ((address)this_blob + CodeBlob::align_code_offset(this_blob->header_size() + this_blob->relocation_size()) == (address)(this_blob->content_begin())) && - is_readable_pointer((address)(this_blob->relocation_begin())) && - is_readable_pointer(this_blob->content_begin()); + os::is_readable_pointer((address)(this_blob->relocation_begin())) && + os::is_readable_pointer(this_blob->content_begin()); // blob could have been flushed, freed, and merged. // this_blob < last_blob is an indicator for that. if (blob_initialized && (this_blob > last_blob)) { @@ -2145,7 +2145,7 @@ } // this_blob->name() could return NULL if no name was given to CTOR. Inlined, maybe invisible on stack const char* blob_name = this_blob->name(); - if ((blob_name == NULL) || !is_readable_pointer(blob_name)) { + if ((blob_name == NULL) || !os::is_readable_pointer(blob_name)) { blob_name = "<unavailable>"; } @@ -2170,7 +2170,7 @@ nmethod* nm = this_blob->as_nmethod_or_null(); Method* method = (nm == NULL) ? NULL : nm->method(); // may be uninitialized, i.e. != NULL, but invalid if ((nm != NULL) && (method != NULL) && (cbType != nMethod_dead) && (cbType != nMethod_inconstruction) && - is_readable_pointer(method) && is_readable_pointer(method->constants())) { + os::is_readable_pointer(method) && os::is_readable_pointer(method->constants())) { ResourceMark rm; //---< collect all data to locals as quickly as possible >--- unsigned int total_size = nm->total_size(); @@ -2369,7 +2369,7 @@ } CodeHeapState::blobType CodeHeapState::get_cbType(CodeBlob* cb) { - if ((cb != NULL) && is_readable_pointer(cb)) { + if ((cb != NULL) && os::is_readable_pointer(cb)) { if (cb->is_runtime_stub()) return runtimeStub; if (cb->is_deoptimization_stub()) return deoptimizationStub; if (cb->is_uncommon_trap_stub()) return uncommonTrapStub; @@ -2392,17 +2392,3 @@ } return noType; } - -// Check if pointer can be read from (4-byte read access). -// Helps to prove validity of a not-NULL pointer. -// Returns true in very early stages of VM life when stub is not yet generated. -#define SAFEFETCH_DEFAULT true -bool CodeHeapState::is_readable_pointer(const void* p) { - if (!CanUseSafeFetch32()) { - return SAFEFETCH_DEFAULT; - } - int* const aligned = (int*) align_down((intptr_t)p, 4); - int cafebabe = 0xcafebabe; // tester value 1 - int deadbeef = 0xdeadbeef; // tester value 2 - return (SafeFetch32(aligned, cafebabe) != cafebabe) || (SafeFetch32(aligned, deadbeef) != deadbeef); -}
--- a/src/hotspot/share/code/codeHeapState.hpp Tue Jul 17 19:59:38 2018 -0700 +++ b/src/hotspot/share/code/codeHeapState.hpp Wed Jul 18 11:27:14 2018 +0200 @@ -95,7 +95,6 @@ static void print_line_delim(outputStream* out, bufferedStream *sst, char* low_bound, unsigned int ix, unsigned int gpl); static void print_line_delim(outputStream* out, outputStream *sst, char* low_bound, unsigned int ix, unsigned int gpl); static blobType get_cbType(CodeBlob* cb); - static bool is_readable_pointer(const void* p); public: static void discard(outputStream* out, CodeHeap* heap);
--- a/src/hotspot/share/runtime/os.cpp Tue Jul 17 19:59:38 2018 -0700 +++ b/src/hotspot/share/runtime/os.cpp Wed Jul 18 11:27:14 2018 +0200 @@ -995,6 +995,22 @@ st->print_cr(" elapsed time: %d seconds (%dd %dh %dm %ds)", eltime, eldays, elhours, elmins, elsecs); } + +// Check if pointer can be read from (4-byte read access). +// Helps to prove validity of a not-NULL pointer. +// Returns true in very early stages of VM life when stub is not yet generated. +#define SAFEFETCH_DEFAULT true +bool os::is_readable_pointer(const void* p) { + if (!CanUseSafeFetch32()) { + return SAFEFETCH_DEFAULT; + } + int* const aligned = (int*) align_down((intptr_t)p, 4); + int cafebabe = 0xcafebabe; // tester value 1 + int deadbeef = 0xdeadbeef; // tester value 2 + return (SafeFetch32(aligned, cafebabe) != cafebabe) || (SafeFetch32(aligned, deadbeef) != deadbeef); +} + + // moved from debug.cpp (used to be find()) but still called from there // The verbose parameter is only set by the debug code in one case void os::print_location(outputStream* st, intptr_t x, bool verbose) { @@ -1094,21 +1110,26 @@ return; } } - if (JNIHandles::is_global_handle((jobject) addr)) { - st->print_cr(INTPTR_FORMAT " is a global jni handle", p2i(addr)); - return; - } - if (JNIHandles::is_weak_global_handle((jobject) addr)) { - st->print_cr(INTPTR_FORMAT " is a weak global jni handle", p2i(addr)); - return; + + bool accessible = is_readable_pointer(addr); + + if (align_down((intptr_t)addr, sizeof(intptr_t)) != 0 && accessible) { + if (JNIHandles::is_global_handle((jobject) addr)) { + st->print_cr(INTPTR_FORMAT " is a global jni handle", p2i(addr)); + return; + } + if (JNIHandles::is_weak_global_handle((jobject) addr)) { + st->print_cr(INTPTR_FORMAT " is a weak global jni handle", p2i(addr)); + return; + } +#ifndef PRODUCT + // we don't keep the block list in product mode + if (JNIHandles::is_local_handle((jobject) addr)) { + st->print_cr(INTPTR_FORMAT " is a local jni handle", p2i(addr)); + return; + } +#endif } -#ifndef PRODUCT - // we don't keep the block list in product mode - if (JNIHandles::is_local_handle((jobject) addr)) { - st->print_cr(INTPTR_FORMAT " is a local jni handle", p2i(addr)); - return; - } -#endif for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thread = jtiwh.next(); ) { // Check for privilege stack @@ -1155,6 +1176,11 @@ return; } + if (accessible) { + st->print_cr(INTPTR_FORMAT " points into unknown readable memory", p2i(addr)); + return; + } + st->print_cr(INTPTR_FORMAT " is an unknown value", p2i(addr)); }
--- a/src/hotspot/share/runtime/os.hpp Tue Jul 17 19:59:38 2018 -0700 +++ b/src/hotspot/share/runtime/os.hpp Wed Jul 18 11:27:14 2018 +0200 @@ -412,6 +412,9 @@ static void make_polling_page_unreadable(); static void make_polling_page_readable(); + // Check if pointer points to readable memory (by 4-byte read access) + static bool is_readable_pointer(const void* p); + // Routines used to serialize the thread state without using membars static void serialize_thread_states();