提交 7bf95bd1 编写于 作者: M mdoerr

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
上级 24880df8
......@@ -49,16 +49,3 @@ void MiscUtils::leave_critsect(MiscUtils::critsect_t* cs) {
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);
}
......@@ -88,13 +88,6 @@ namespace MiscUtils {
_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
......
......@@ -142,7 +142,7 @@ bool AixSymbols::get_function_name (
// 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 @@ bool AixSymbols::get_function_name (
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 @@ static void print_info_for_pc (outputStream* st, codeptr_t pc, char* buf,
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 @@ void AixNativeCallstack::print_callstack_for_context(outputStream* st, const uco
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 @@ void AixNativeCallstack::print_callstack_for_context(outputStream* st, const uco
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 @@ void AixNativeCallstack::print_callstack_for_context(outputStream* st, const uco
// 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)");
......
......@@ -603,7 +603,9 @@ void os::print_register_info(outputStream *st, const void *context) {
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]);
......
......@@ -628,7 +628,19 @@ void os::print_context(outputStream *st, const void *context) {
}
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
......
......@@ -2129,8 +2129,8 @@ void CodeHeapState::print_names(outputStream* out, CodeHeap* heap) {
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 @@ void CodeHeapState::print_names(outputStream* out, CodeHeap* heap) {
}
// 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 @@ void CodeHeapState::print_names(outputStream* out, CodeHeap* heap) {
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 @@ void CodeHeapState::print_line_delim(outputStream* out, bufferedStream* ast, cha
}
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 @@ CodeHeapState::blobType CodeHeapState::get_cbType(CodeBlob* cb) {
}
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);
}
......@@ -95,7 +95,6 @@ class CodeHeapState : public CHeapObj<mtCode> {
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);
......
......@@ -995,6 +995,22 @@ void os::print_date_and_time(outputStream *st, char* buf, size_t buflen) {
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 @@ void os::print_location(outputStream* st, intptr_t x, bool verbose) {
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;
}
// 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 @@ void os::print_location(outputStream* st, intptr_t x, bool verbose) {
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));
}
......
......@@ -412,6 +412,9 @@ class os: AllStatic {
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();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册