提交 2e0b5e13 编写于 作者: K kamg

7116786: RFE: Detailed information on VerifyErrors

Summary: Provide additional detail in VerifyError messages
Reviewed-by: sspitsyn, acorn
上级 86ea1380
/*
* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2012, 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
......@@ -626,45 +626,6 @@ static void printDOF(void* dof) {
}
}
/**
* This prints out hex data in a 'windbg' or 'xxd' form, where each line is:
* <hex-address>: 8 * <hex-halfword> <ascii translation>
* example:
* 0000000: 7f44 4f46 0102 0102 0000 0000 0000 0000 .DOF............
* 0000010: 0000 0000 0000 0040 0000 0020 0000 0005 .......@... ....
* 0000020: 0000 0000 0000 0040 0000 0000 0000 015d .......@.......]
* ...
*/
static void printDOFRawData(void* dof) {
size_t size = ((dof_hdr_t*)dof)->dofh_loadsz;
size_t limit = (size + 16) / 16 * 16;
for (size_t i = 0; i < limit; ++i) {
if (i % 16 == 0) {
tty->print("%07x:", i);
}
if (i % 2 == 0) {
tty->print(" ");
}
if (i < size) {
tty->print("%02x", ((unsigned char*)dof)[i]);
} else {
tty->print(" ");
}
if ((i + 1) % 16 == 0) {
tty->print(" ");
for (size_t j = 0; j < 16; ++j) {
size_t idx = i + j - 15;
char c = ((char*)dof)[idx];
if (idx < size) {
tty->print("%c", c >= 32 && c <= 126 ? c : '.');
}
}
tty->print_cr("");
}
}
tty->print_cr("");
}
static void printDOFHelper(dof_helper_t* helper) {
tty->print_cr("// dof_helper_t {");
tty->print_cr("// dofhp_mod = \"%s\"", helper->dofhp_mod);
......@@ -672,7 +633,8 @@ static void printDOFHelper(dof_helper_t* helper) {
tty->print_cr("// dofhp_dof = 0x%016llx", helper->dofhp_dof);
printDOF((void*)helper->dofhp_dof);
tty->print_cr("// }");
printDOFRawData((void*)helper->dofhp_dof);
size_t len = ((dof_hdr_t*)helper)->dofh_loadsz;
tty->print_data((void*)helper->dofhp_dof, len, true);
}
#else // ndef HAVE_DTRACE_H
......
/*
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2012, 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
......@@ -32,9 +32,9 @@
#include "utilities/globalDefinitions.hpp"
StackMapFrame::StackMapFrame(u2 max_locals, u2 max_stack, ClassVerifier* v) :
_offset(0), _locals_size(0), _stack_size(0), _flags(0),
_max_locals(max_locals), _max_stack(max_stack),
_verifier(v) {
_offset(0), _locals_size(0), _stack_size(0),
_stack_mark(0), _flags(0), _max_locals(max_locals),
_max_stack(max_stack), _verifier(v) {
Thread* thr = v->thread();
_locals = NEW_RESOURCE_ARRAY_IN_THREAD(thr, VerificationType, max_locals);
_stack = NEW_RESOURCE_ARRAY_IN_THREAD(thr, VerificationType, max_stack);
......@@ -157,17 +157,17 @@ void StackMapFrame::copy_stack(const StackMapFrame* src) {
}
}
bool StackMapFrame::is_assignable_to(
// Returns the location of the first mismatch, or 'len' if there are no
// mismatches
int StackMapFrame::is_assignable_to(
VerificationType* from, VerificationType* to, int32_t len, TRAPS) const {
for (int32_t i = 0; i < len; i++) {
bool subtype = to[i].is_assignable_from(
from[i], verifier(), THREAD);
if (!subtype) {
return false;
int32_t i = 0;
for (i = 0; i < len; i++) {
if (!to[i].is_assignable_from(from[i], verifier(), THREAD)) {
break;
}
}
return true;
return i;
}
bool StackMapFrame::has_flag_match_exception(
......@@ -209,50 +209,84 @@ bool StackMapFrame::has_flag_match_exception(
}
bool StackMapFrame::is_assignable_to(
const StackMapFrame* target, bool is_exception_handler, TRAPS) const {
if (_max_locals != target->max_locals() ||
_stack_size != target->stack_size()) {
const StackMapFrame* target, bool is_exception_handler,
ErrorContext* ctx, TRAPS) const {
if (_max_locals != target->max_locals()) {
*ctx = ErrorContext::locals_size_mismatch(
_offset, (StackMapFrame*)this, (StackMapFrame*)target);
return false;
}
if (_stack_size != target->stack_size()) {
*ctx = ErrorContext::stack_size_mismatch(
_offset, (StackMapFrame*)this, (StackMapFrame*)target);
return false;
}
// Only need to compare type elements up to target->locals() or target->stack().
// The remaining type elements in this state can be ignored because they are
// assignable to bogus type.
bool match_locals = is_assignable_to(
_locals, target->locals(), target->locals_size(), CHECK_false);
bool match_stack = is_assignable_to(
_stack, target->stack(), _stack_size, CHECK_false);
bool match_flags = (_flags | target->flags()) == target->flags();
int mismatch_loc;
mismatch_loc = is_assignable_to(
_locals, target->locals(), target->locals_size(), THREAD);
if (mismatch_loc != target->locals_size()) {
*ctx = ErrorContext::bad_type(target->offset(),
TypeOrigin::local(mismatch_loc, (StackMapFrame*)this),
TypeOrigin::sm_local(mismatch_loc, (StackMapFrame*)target));
return false;
}
mismatch_loc = is_assignable_to(_stack, target->stack(), _stack_size, THREAD);
if (mismatch_loc != _stack_size) {
*ctx = ErrorContext::bad_type(target->offset(),
TypeOrigin::stack(mismatch_loc, (StackMapFrame*)this),
TypeOrigin::sm_stack(mismatch_loc, (StackMapFrame*)target));
return false;
}
return match_locals && match_stack &&
(match_flags || (is_exception_handler && has_flag_match_exception(target)));
bool match_flags = (_flags | target->flags()) == target->flags();
if (match_flags || is_exception_handler && has_flag_match_exception(target)) {
return true;
} else {
*ctx = ErrorContext::bad_flags(target->offset(),
(StackMapFrame*)this, (StackMapFrame*)target);
return false;
}
}
VerificationType StackMapFrame::pop_stack_ex(VerificationType type, TRAPS) {
if (_stack_size <= 0) {
verifier()->verify_error(_offset, "Operand stack underflow");
verifier()->verify_error(
ErrorContext::stack_underflow(_offset, this),
"Operand stack underflow");
return VerificationType::bogus_type();
}
VerificationType top = _stack[--_stack_size];
bool subtype = type.is_assignable_from(
top, verifier(), CHECK_(VerificationType::bogus_type()));
if (!subtype) {
verifier()->verify_error(_offset, "Bad type on operand stack");
verifier()->verify_error(
ErrorContext::bad_type(_offset, stack_top_ctx(),
TypeOrigin::implicit(type)),
"Bad type on operand stack");
return VerificationType::bogus_type();
}
NOT_PRODUCT( _stack[_stack_size] = VerificationType::bogus_type(); )
return top;
}
VerificationType StackMapFrame::get_local(
int32_t index, VerificationType type, TRAPS) {
if (index >= _max_locals) {
verifier()->verify_error(_offset, "Local variable table overflow");
verifier()->verify_error(
ErrorContext::bad_local_index(_offset, index),
"Local variable table overflow");
return VerificationType::bogus_type();
}
bool subtype = type.is_assignable_from(_locals[index],
verifier(), CHECK_(VerificationType::bogus_type()));
if (!subtype) {
verifier()->verify_error(_offset, "Bad local variable type");
verifier()->verify_error(
ErrorContext::bad_type(_offset,
TypeOrigin::local(index, this),
TypeOrigin::implicit(type)),
"Bad local variable type");
return VerificationType::bogus_type();
}
if(index >= _locals_size) { _locals_size = index + 1; }
......@@ -264,23 +298,37 @@ void StackMapFrame::get_local_2(
assert(type1.is_long() || type1.is_double(), "must be long/double");
assert(type2.is_long2() || type2.is_double2(), "must be long/double_2");
if (index >= _locals_size - 1) {
verifier()->verify_error(_offset, "get long/double overflows locals");
verifier()->verify_error(
ErrorContext::bad_local_index(_offset, index),
"get long/double overflows locals");
return;
}
bool subtype1 = type1.is_assignable_from(
_locals[index], verifier(), CHECK);
bool subtype2 = type2.is_assignable_from(
_locals[index+1], verifier(), CHECK);
if (!subtype1 || !subtype2) {
verifier()->verify_error(_offset, "Bad local variable type");
return;
bool subtype = type1.is_assignable_from(_locals[index], verifier(), CHECK);
if (!subtype) {
verifier()->verify_error(
ErrorContext::bad_type(_offset,
TypeOrigin::local(index, this), TypeOrigin::implicit(type1)),
"Bad local variable type");
} else {
subtype = type2.is_assignable_from(_locals[index + 1], verifier(), CHECK);
if (!subtype) {
/* Unreachable? All local store routines convert a split long or double
* into a TOP during the store. So we should never end up seeing an
* orphaned half. */
verifier()->verify_error(
ErrorContext::bad_type(_offset,
TypeOrigin::local(index + 1, this), TypeOrigin::implicit(type2)),
"Bad local variable type");
}
}
}
void StackMapFrame::set_local(int32_t index, VerificationType type, TRAPS) {
assert(!type.is_check(), "Must be a real type");
if (index >= _max_locals) {
verifier()->verify_error("Local variable table overflow", _offset);
verifier()->verify_error(
ErrorContext::bad_local_index(_offset, index),
"Local variable table overflow");
return;
}
// If type at index is double or long, set the next location to be unusable
......@@ -310,7 +358,9 @@ void StackMapFrame::set_local_2(
assert(type1.is_long() || type1.is_double(), "must be long/double");
assert(type2.is_long2() || type2.is_double2(), "must be long/double_2");
if (index >= _max_locals - 1) {
verifier()->verify_error("Local variable table overflow", _offset);
verifier()->verify_error(
ErrorContext::bad_local_index(_offset, index),
"Local variable table overflow");
return;
}
// If type at index+1 is double or long, set the next location to be unusable
......@@ -336,21 +386,30 @@ void StackMapFrame::set_local_2(
}
}
#ifndef PRODUCT
void StackMapFrame::print() const {
tty->print_cr("stackmap_frame[%d]:", _offset);
tty->print_cr("flags = 0x%x", _flags);
tty->print("locals[%d] = { ", _locals_size);
for (int32_t i = 0; i < _locals_size; i++) {
_locals[i].print_on(tty);
}
tty->print_cr(" }");
tty->print("stack[%d] = { ", _stack_size);
for (int32_t j = 0; j < _stack_size; j++) {
_stack[j].print_on(tty);
}
tty->print_cr(" }");
TypeOrigin StackMapFrame::stack_top_ctx() {
return TypeOrigin::stack(_stack_size, this);
}
#endif
void StackMapFrame::print_on(outputStream* str) const {
str->indent().print_cr("bci: @%d", _offset);
str->indent().print_cr("flags: {%s }",
flag_this_uninit() ? " flagThisUninit" : "");
str->indent().print("locals: {");
for (int32_t i = 0; i < _locals_size; ++i) {
str->print(" ");
_locals[i].print_on(str);
if (i != _locals_size - 1) {
str->print(",");
}
}
str->print_cr(" }");
str->indent().print("stack: {");
for (int32_t j = 0; j < _stack_size; ++j) {
str->print(" ");
_stack[j].print_on(str);
if (j != _stack_size - 1) {
str->print(",");
}
}
str->print_cr(" }");
}
/*
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2012, 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
......@@ -34,6 +34,8 @@
// A StackMapFrame represents one frame in the stack map attribute.
class TypeContext;
enum {
FLAG_THIS_UNINIT = 0x01
};
......@@ -47,6 +49,10 @@ class StackMapFrame : public ResourceObj {
int32_t _locals_size; // number of valid type elements in _locals
int32_t _stack_size; // number of valid type elements in _stack
int32_t _stack_mark; // Records the size of the stack prior to an
// instruction modification, to allow rewinding
// when/if an error occurs.
int32_t _max_locals;
int32_t _max_stack;
......@@ -56,6 +62,31 @@ class StackMapFrame : public ResourceObj {
ClassVerifier* _verifier; // the verifier verifying this method
StackMapFrame(const StackMapFrame& cp) :
_offset(cp._offset), _locals_size(cp._locals_size),
_stack_size(cp._stack_size), _stack_mark(cp._stack_mark),
_max_locals(cp._max_locals), _max_stack(cp._max_stack),
_flags(cp._flags) {
_locals = NEW_RESOURCE_ARRAY(VerificationType, _max_locals);
for (int i = 0; i < _max_locals; ++i) {
if (i < _locals_size) {
_locals[i] = cp._locals[i];
} else {
_locals[i] = VerificationType::bogus_type();
}
}
int ss = MAX2(_stack_size, _stack_mark);
_stack = NEW_RESOURCE_ARRAY(VerificationType, _max_stack);
for (int i = 0; i < _max_stack; ++i) {
if (i < ss) {
_stack[i] = cp._stack[i];
} else {
_stack[i] = VerificationType::bogus_type();
}
}
_verifier = NULL;
}
public:
// constructors
......@@ -77,16 +108,21 @@ class StackMapFrame : public ResourceObj {
ClassVerifier* v) : _offset(offset), _flags(flags),
_locals_size(locals_size),
_stack_size(stack_size),
_stack_mark(-1),
_max_locals(max_locals),
_max_stack(max_stack),
_locals(locals), _stack(stack),
_verifier(v) { }
static StackMapFrame* copy(StackMapFrame* smf) {
return new StackMapFrame(*smf);
}
inline void set_offset(int32_t offset) { _offset = offset; }
inline void set_verifier(ClassVerifier* v) { _verifier = v; }
inline void set_flags(u1 flags) { _flags = flags; }
inline void set_locals_size(u2 locals_size) { _locals_size = locals_size; }
inline void set_stack_size(u2 stack_size) { _stack_size = stack_size; }
inline void set_stack_size(u2 stack_size) { _stack_size = _stack_mark = stack_size; }
inline void clear_stack() { _stack_size = 0; }
inline int32_t offset() const { return _offset; }
inline ClassVerifier* verifier() const { return _verifier; }
......@@ -134,14 +170,37 @@ class StackMapFrame : public ResourceObj {
void copy_stack(const StackMapFrame* src);
// Return true if this stack map frame is assignable to target.
bool is_assignable_to(const StackMapFrame* target,
bool is_exception_handler, TRAPS) const;
bool is_assignable_to(
const StackMapFrame* target, bool is_exception_handler,
ErrorContext* ctx, TRAPS) const;
inline void set_mark() {
#ifdef DEBUG
// Put bogus type to indicate it's no longer valid.
if (_stack_mark != -1) {
for (int i = _stack_mark; i >= _stack_size; --i) {
_stack[i] = VerificationType::bogus_type();
}
}
#endif // def DEBUG
_stack_mark = _stack_size;
}
// Used when an error occurs and we want to reset the stack to the state
// it was before operands were popped off.
void restore() {
if (_stack_mark != -1) {
_stack_size = _stack_mark;
}
}
// Push type into stack type array.
inline void push_stack(VerificationType type, TRAPS) {
assert(!type.is_check(), "Must be a real type");
if (_stack_size >= _max_stack) {
verifier()->verify_error(_offset, "Operand stack overflow");
verifier()->verify_error(
ErrorContext::stack_overflow(_offset, this),
"Operand stack overflow");
return;
}
_stack[_stack_size++] = type;
......@@ -152,7 +211,9 @@ class StackMapFrame : public ResourceObj {
assert(type1.is_long() || type1.is_double(), "must be long/double");
assert(type2.is_long2() || type2.is_double2(), "must be long/double_2");
if (_stack_size >= _max_stack - 1) {
verifier()->verify_error(_offset, "Operand stack overflow");
verifier()->verify_error(
ErrorContext::stack_overflow(_offset, this),
"Operand stack overflow");
return;
}
_stack[_stack_size++] = type1;
......@@ -162,13 +223,12 @@ class StackMapFrame : public ResourceObj {
// Pop and return the top type on stack without verifying.
inline VerificationType pop_stack(TRAPS) {
if (_stack_size <= 0) {
verifier()->verify_error(_offset, "Operand stack underflow");
verifier()->verify_error(
ErrorContext::stack_underflow(_offset, this),
"Operand stack underflow");
return VerificationType::bogus_type();
}
// Put bogus type to indicate it's no longer valid.
// Added to make it consistent with the other pop_stack method.
VerificationType top = _stack[--_stack_size];
NOT_PRODUCT( _stack[_stack_size] = VerificationType::bogus_type(); )
return top;
}
......@@ -180,8 +240,7 @@ class StackMapFrame : public ResourceObj {
bool subtype = type.is_assignable_from(
top, verifier(), CHECK_(VerificationType::bogus_type()));
if (subtype) {
_stack_size --;
NOT_PRODUCT( _stack[_stack_size] = VerificationType::bogus_type(); )
--_stack_size;
return top;
}
}
......@@ -199,8 +258,6 @@ class StackMapFrame : public ResourceObj {
bool subtype2 = type2.is_assignable_from(top2, verifier(), CHECK);
if (subtype1 && subtype2) {
_stack_size -= 2;
NOT_PRODUCT( _stack[_stack_size] = VerificationType::bogus_type(); )
NOT_PRODUCT( _stack[_stack_size+1] = VerificationType::bogus_type(); )
return;
}
}
......@@ -208,6 +265,14 @@ class StackMapFrame : public ResourceObj {
pop_stack_ex(type2, THREAD);
}
VerificationType local_at(int index) {
return _locals[index];
}
VerificationType stack_at(int index) {
return _stack[index];
}
// Uncommon case that throws exceptions.
VerificationType pop_stack_ex(VerificationType type, TRAPS);
......@@ -226,13 +291,14 @@ class StackMapFrame : public ResourceObj {
// Private auxiliary method used only in is_assignable_to(StackMapFrame).
// Returns true if src is assignable to target.
bool is_assignable_to(
int is_assignable_to(
VerificationType* src, VerificationType* target, int32_t len, TRAPS) const;
bool has_flag_match_exception(const StackMapFrame* target) const;
// Debugging
void print() const PRODUCT_RETURN;
TypeOrigin stack_top_ctx();
void print_on(outputStream* str) const;
};
#endif // SHARE_VM_CLASSFILE_STACKMAPFRAME_HPP
/*
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2012, 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
......@@ -46,7 +46,9 @@ StackMapTable::StackMapTable(StackMapReader* reader, StackMapFrame* init_frame,
_frame_array[i] = frame;
int offset = frame->offset();
if (offset >= code_len || code_data[offset] == 0) {
frame->verifier()->verify_error("StackMapTable error: bad offset");
frame->verifier()->verify_error(
ErrorContext::bad_stackmap(i, frame),
"StackMapTable error: bad offset");
return;
}
pre_frame = frame;
......@@ -68,12 +70,9 @@ int StackMapTable::get_index_from_offset(int32_t offset) const {
bool StackMapTable::match_stackmap(
StackMapFrame* frame, int32_t target,
bool match, bool update, TRAPS) const {
bool match, bool update, ErrorContext* ctx, TRAPS) const {
int index = get_index_from_offset(target);
return match_stackmap(
frame, target, index, match,
update, CHECK_VERIFY_(frame->verifier(), false));
return match_stackmap(frame, target, index, match, update, ctx, THREAD);
}
// Match and/or update current_frame to the frame in stackmap table with
......@@ -88,23 +87,23 @@ bool StackMapTable::match_stackmap(
// unconditional branch: true true
bool StackMapTable::match_stackmap(
StackMapFrame* frame, int32_t target, int32_t frame_index,
bool match, bool update, TRAPS) const {
bool match, bool update, ErrorContext* ctx, TRAPS) const {
if (frame_index < 0 || frame_index >= _frame_count) {
frame->verifier()->verify_error(frame->offset(),
"Expecting a stackmap frame at branch target %d", target);
*ctx = ErrorContext::missing_stackmap(frame->offset());
frame->verifier()->verify_error(
*ctx, "Expecting a stackmap frame at branch target %d", target);
return false;
}
bool result = true;
StackMapFrame *stackmap_frame = _frame_array[frame_index];
bool result = true;
if (match) {
// when checking handler target, match == true && update == false
bool is_exception_handler = !update;
// Has direct control flow from last instruction, need to match the two
// frames.
result = frame->is_assignable_to(
stackmap_frame, is_exception_handler,
CHECK_VERIFY_(frame->verifier(), false));
result = frame->is_assignable_to(stackmap_frame, is_exception_handler,
ctx, CHECK_VERIFY_(frame->verifier(), result));
}
if (update) {
// Use the frame in stackmap table as current frame
......@@ -125,11 +124,12 @@ bool StackMapTable::match_stackmap(
void StackMapTable::check_jump_target(
StackMapFrame* frame, int32_t target, TRAPS) const {
ErrorContext ctx;
bool match = match_stackmap(
frame, target, true, false, CHECK_VERIFY(frame->verifier()));
frame, target, true, false, &ctx, CHECK_VERIFY(frame->verifier()));
if (!match || (target < 0 || target >= _code_length)) {
frame->verifier()->verify_error(frame->offset(),
"Inconsistent stackmap frames at branch target %d", target);
frame->verifier()->verify_error(ctx,
"Inconsistent stackmap frames at branch target %d", target);
return;
}
// check if uninitialized objects exist on backward branches
......@@ -139,25 +139,25 @@ void StackMapTable::check_jump_target(
void StackMapTable::check_new_object(
const StackMapFrame* frame, int32_t target, TRAPS) const {
if (frame->offset() > target && frame->has_new_object()) {
frame->verifier()->verify_error(frame->offset(),
"Uninitialized object exists on backward branch %d", target);
frame->verifier()->verify_error(
ErrorContext::bad_code(frame->offset()),
"Uninitialized object exists on backward branch %d", target);
return;
}
}
#ifndef PRODUCT
void StackMapTable::print() const {
tty->print_cr("StackMapTable: frame_count = %d", _frame_count);
tty->print_cr("table = { ");
for (int32_t i = 0; i < _frame_count; i++) {
_frame_array[i]->print();
void StackMapTable::print_on(outputStream* str) const {
str->indent().print_cr("StackMapTable: frame_count = %d", _frame_count);
str->indent().print_cr("table = { ");
{
streamIndentor si(str);
for (int32_t i = 0; i < _frame_count; ++i) {
_frame_array[i]->print_on(str);
}
}
tty->print_cr(" }");
str->print_cr(" }");
}
#endif
int32_t StackMapReader::chop(
VerificationType* locals, int32_t length, int32_t chops) {
if (locals == NULL) return -1;
......
/*
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2012, 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
......@@ -26,6 +26,7 @@
#define SHARE_VM_CLASSFILE_STACKMAPTABLE_HPP
#include "classfile/stackMapFrame.hpp"
#include "classfile/verifier.hpp"
#include "memory/allocation.hpp"
#include "oops/constantPoolOop.hpp"
#include "oops/methodOop.hpp"
......@@ -73,12 +74,12 @@ class StackMapTable : public StackObj {
// specified offset. Return true if the two frames match.
bool match_stackmap(
StackMapFrame* current_frame, int32_t offset,
bool match, bool update, TRAPS) const;
bool match, bool update, ErrorContext* ctx, TRAPS) const;
// Match and/or update current_frame to the frame in stackmap table with
// specified offset and frame index. Return true if the two frames match.
bool match_stackmap(
StackMapFrame* current_frame, int32_t offset, int32_t frame_index,
bool match, bool update, TRAPS) const;
bool match, bool update, ErrorContext* ctx, TRAPS) const;
// Check jump instructions. Make sure there are no uninitialized
// instances on backward branch.
......@@ -93,8 +94,7 @@ class StackMapTable : public StackObj {
void check_new_object(
const StackMapFrame* frame, int32_t target, TRAPS) const;
// Debugging
void print() const PRODUCT_RETURN;
void print_on(outputStream* str) const;
};
class StackMapStream : StackObj {
......
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2010, 2012, 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
......@@ -135,7 +135,6 @@ class verification_type_info {
!is_object() && !is_uninitialized()));
}
#ifdef ASSERT
void print_on(outputStream* st) {
switch (tag()) {
case ITEM_Top: st->print("Top"); break;
......@@ -154,14 +153,13 @@ class verification_type_info {
assert(false, "Bad verification_type_info");
}
}
#endif
};
#define FOR_EACH_STACKMAP_FRAME_TYPE(macro, arg1, arg2) \
macro(same_frame, arg1, arg2) \
macro(same_frame_extended, arg1, arg2) \
macro(same_frame_1_stack_item_frame, arg1, arg2) \
macro(same_frame_1_stack_item_extended, arg1, arg2) \
macro(same_locals_1_stack_item_frame, arg1, arg2) \
macro(same_locals_1_stack_item_extended, arg1, arg2) \
macro(chop_frame, arg1, arg2) \
macro(append_frame, arg1, arg2) \
macro(full_frame, arg1, arg2)
......@@ -203,9 +201,8 @@ class stack_map_frame {
// that we don't read past a particular memory limit. It returns false
// if any part of the data structure is outside the specified memory bounds.
inline bool verify(address start, address end) const;
#ifdef ASSERT
inline void print_on(outputStream* st) const;
#endif
inline void print_on(outputStream* st, int current_offset) const;
// Create as_xxx and is_xxx methods for the subtypes
#define FRAME_TYPE_DECL(stackmap_frame_type, arg1, arg2) \
......@@ -263,11 +260,9 @@ class same_frame : public stack_map_frame {
return true;
}
#ifdef ASSERT
void print_on(outputStream* st) const {
st->print("same_frame(%d)", offset_delta());
void print_on(outputStream* st, int current_offset = -1) const {
st->print("same_frame(@%d)", offset_delta() + current_offset);
}
#endif
};
class same_frame_extended : public stack_map_frame {
......@@ -311,14 +306,12 @@ class same_frame_extended : public stack_map_frame {
return frame_type_addr() + size() <= end;
}
#ifdef ASSERT
void print_on(outputStream* st) const {
st->print("same_frame_extended(%d)", offset_delta());
void print_on(outputStream* st, int current_offset = -1) const {
st->print("same_frame_extended(@%d)", offset_delta() + current_offset);
}
#endif
};
class same_frame_1_stack_item_frame : public stack_map_frame {
class same_locals_1_stack_item_frame : public stack_map_frame {
private:
address type_addr() const { return frame_type_addr() + sizeof(u1); }
......@@ -332,14 +325,14 @@ class same_frame_1_stack_item_frame : public stack_map_frame {
return tag >= 64 && tag < 128;
}
static same_frame_1_stack_item_frame* at(address addr) {
static same_locals_1_stack_item_frame* at(address addr) {
assert(is_frame_type(*addr), "Wrong frame id");
return (same_frame_1_stack_item_frame*)addr;
return (same_locals_1_stack_item_frame*)addr;
}
static same_frame_1_stack_item_frame* create_at(
static same_locals_1_stack_item_frame* create_at(
address addr, int offset_delta, verification_type_info* vti) {
same_frame_1_stack_item_frame* sm = (same_frame_1_stack_item_frame*)addr;
same_locals_1_stack_item_frame* sm = (same_locals_1_stack_item_frame*)addr;
sm->set_offset_delta(offset_delta);
if (vti != NULL) {
sm->set_type(vti);
......@@ -382,16 +375,15 @@ class same_frame_1_stack_item_frame : public stack_map_frame {
return types()->verify(start, end);
}
#ifdef ASSERT
void print_on(outputStream* st) const {
st->print("same_frame_1_stack_item_frame(%d,", offset_delta());
void print_on(outputStream* st, int current_offset = -1) const {
st->print("same_locals_1_stack_item_frame(@%d,",
offset_delta() + current_offset);
types()->print_on(st);
st->print(")");
}
#endif
};
class same_frame_1_stack_item_extended : public stack_map_frame {
class same_locals_1_stack_item_extended : public stack_map_frame {
private:
address offset_delta_addr() const { return frame_type_addr() + sizeof(u1); }
address type_addr() const { return offset_delta_addr() + sizeof(u2); }
......@@ -403,15 +395,15 @@ class same_frame_1_stack_item_extended : public stack_map_frame {
return tag == _frame_id;
}
static same_frame_1_stack_item_extended* at(address addr) {
static same_locals_1_stack_item_extended* at(address addr) {
assert(is_frame_type(*addr), "Wrong frame id");
return (same_frame_1_stack_item_extended*)addr;
return (same_locals_1_stack_item_extended*)addr;
}
static same_frame_1_stack_item_extended* create_at(
static same_locals_1_stack_item_extended* create_at(
address addr, int offset_delta, verification_type_info* vti) {
same_frame_1_stack_item_extended* sm =
(same_frame_1_stack_item_extended*)addr;
same_locals_1_stack_item_extended* sm =
(same_locals_1_stack_item_extended*)addr;
sm->set_frame_type(_frame_id);
sm->set_offset_delta(offset_delta);
if (vti != NULL) {
......@@ -448,13 +440,12 @@ class same_frame_1_stack_item_extended : public stack_map_frame {
return type_addr() < end && types()->verify(start, end);
}
#ifdef ASSERT
void print_on(outputStream* st) const {
st->print("same_frame_1_stack_item_extended(%d,", offset_delta());
void print_on(outputStream* st, int current_offset = -1) const {
st->print("same_locals_1_stack_item_extended(@%d,",
offset_delta() + current_offset);
types()->print_on(st);
st->print(")");
}
#endif
};
class chop_frame : public stack_map_frame {
......@@ -517,11 +508,9 @@ class chop_frame : public stack_map_frame {
return frame_type_addr() + size() <= end;
}
#ifdef ASSERT
void print_on(outputStream* st) const {
st->print("chop_frame(%d,%d)", offset_delta(), chops());
void print_on(outputStream* st, int current_offset = -1) const {
st->print("chop_frame(@%d,%d)", offset_delta() + current_offset, chops());
}
#endif
};
class append_frame : public stack_map_frame {
......@@ -618,9 +607,8 @@ class append_frame : public stack_map_frame {
return false;
}
#ifdef ASSERT
void print_on(outputStream* st) const {
st->print("append_frame(%d,", offset_delta());
void print_on(outputStream* st, int current_offset = -1) const {
st->print("append_frame(@%d,", offset_delta() + current_offset);
verification_type_info* vti = types();
for (int i = 0; i < number_of_types(); ++i) {
vti->print_on(st);
......@@ -631,7 +619,6 @@ class append_frame : public stack_map_frame {
}
st->print(")");
}
#endif
};
class full_frame : public stack_map_frame {
......@@ -774,9 +761,8 @@ class full_frame : public stack_map_frame {
return true;
}
#ifdef ASSERT
void print_on(outputStream* st) const {
st->print("full_frame(%d,{", offset_delta());
void print_on(outputStream* st, int current_offset = -1) const {
st->print("full_frame(@%d,{", offset_delta() + current_offset);
verification_type_info* vti = locals();
for (int i = 0; i < num_locals(); ++i) {
vti->print_on(st);
......@@ -798,7 +784,6 @@ class full_frame : public stack_map_frame {
}
st->print("})");
}
#endif
};
#define VIRTUAL_DISPATCH(stack_frame_type, func_name, args) \
......@@ -852,11 +837,9 @@ bool stack_map_frame::verify(address start, address end) const {
return false;
}
#ifdef ASSERT
void stack_map_frame::print_on(outputStream* st) const {
FOR_EACH_STACKMAP_FRAME_TYPE(VOID_VIRTUAL_DISPATCH, print_on, (st));
void stack_map_frame::print_on(outputStream* st, int offs = -1) const {
FOR_EACH_STACKMAP_FRAME_TYPE(VOID_VIRTUAL_DISPATCH, print_on, (st, offs));
}
#endif
#undef VIRTUAL_DISPATCH
#undef VOID_VIRTUAL_DISPATCH
......@@ -873,16 +856,46 @@ stack_frame_type* stack_map_frame::as_##stack_frame_type() const { \
FOR_EACH_STACKMAP_FRAME_TYPE(AS_SUBTYPE_DEF, x, x)
#undef AS_SUBTYPE_DEF
class stack_map_table {
private:
address number_of_entries_addr() const {
return (address)this;
}
address entries_addr() const {
return number_of_entries_addr() + sizeof(u2);
}
protected:
// No constructors - should be 'private', but GCC issues a warning if it is
stack_map_table() {}
stack_map_table(const stack_map_table&) {}
public:
static stack_map_table* at(address addr) {
return (stack_map_table*)addr;
}
u2 number_of_entries() const {
return Bytes::get_Java_u2(number_of_entries_addr());
}
stack_map_frame* entries() const {
return stack_map_frame::at(entries_addr());
}
void set_number_of_entries(u2 num) {
Bytes::put_Java_u2(number_of_entries_addr(), num);
}
};
class stack_map_table_attribute {
private:
address name_index_addr() const {
return (address)this; }
address attribute_length_addr() const {
return name_index_addr() + sizeof(u2); }
address number_of_entries_addr() const {
address stack_map_table_addr() const {
return attribute_length_addr() + sizeof(u4); }
address entries_addr() const {
return number_of_entries_addr() + sizeof(u2); }
protected:
// No constructors - should be 'private', but GCC issues a warning if it is
......@@ -896,17 +909,11 @@ class stack_map_table_attribute {
}
u2 name_index() const {
return Bytes::get_Java_u2(name_index_addr()); }
return Bytes::get_Java_u2(name_index_addr()); }
u4 attribute_length() const {
return Bytes::get_Java_u4(attribute_length_addr()); }
u2 number_of_entries() const {
return Bytes::get_Java_u2(number_of_entries_addr()); }
stack_map_frame* entries() const {
return stack_map_frame::at(entries_addr());
}
static size_t header_size() {
return sizeof(u2) + sizeof(u4);
return Bytes::get_Java_u4(attribute_length_addr()); }
stack_map_table* table() const {
return stack_map_table::at(stack_map_table_addr());
}
void set_name_index(u2 idx) {
......@@ -915,9 +922,8 @@ class stack_map_table_attribute {
void set_attribute_length(u4 len) {
Bytes::put_Java_u4(attribute_length_addr(), len);
}
void set_number_of_entries(u2 num) {
Bytes::put_Java_u2(number_of_entries_addr(), num);
}
};
#undef FOR_EACH_STACKMAP_FRAME_TYPE
#endif // SHARE_VM_CLASSFILE_STACKMAPTABLEFORMAT_HPP
/*
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2012, 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
......@@ -110,34 +110,34 @@ VerificationType VerificationType::get_component(ClassVerifier *context, TRAPS)
}
}
#ifndef PRODUCT
void VerificationType::print_on(outputStream* st) const {
switch (_u._data) {
case Bogus: st->print(" bogus "); break;
case Category1: st->print(" category1 "); break;
case Category2: st->print(" category2 "); break;
case Category2_2nd: st->print(" category2_2nd "); break;
case Boolean: st->print(" boolean "); break;
case Byte: st->print(" byte "); break;
case Short: st->print(" short "); break;
case Char: st->print(" char "); break;
case Integer: st->print(" integer "); break;
case Float: st->print(" float "); break;
case Long: st->print(" long "); break;
case Double: st->print(" double "); break;
case Long_2nd: st->print(" long_2nd "); break;
case Double_2nd: st->print(" double_2nd "); break;
case Null: st->print(" null "); break;
case Bogus: st->print("top"); break;
case Category1: st->print("category1"); break;
case Category2: st->print("category2"); break;
case Category2_2nd: st->print("category2_2nd"); break;
case Boolean: st->print("boolean"); break;
case Byte: st->print("byte"); break;
case Short: st->print("short"); break;
case Char: st->print("char"); break;
case Integer: st->print("integer"); break;
case Float: st->print("float"); break;
case Long: st->print("long"); break;
case Double: st->print("double"); break;
case Long_2nd: st->print("long_2nd"); break;
case Double_2nd: st->print("double_2nd"); break;
case Null: st->print("null"); break;
case ReferenceQuery: st->print("reference type"); break;
case Category1Query: st->print("category1 type"); break;
case Category2Query: st->print("category2 type"); break;
case Category2_2ndQuery: st->print("category2_2nd type"); break;
default:
if (is_uninitialized_this()) {
st->print(" uninitializedThis ");
st->print("uninitializedThis");
} else if (is_uninitialized()) {
st->print(" uninitialized %d ", bci());
st->print("uninitialized %d", bci());
} else {
st->print(" class %s ", name()->as_klass_external_name());
name()->print_value_on(st);
}
}
}
#endif
/*
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2012, 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
......@@ -157,7 +157,7 @@ class VerificationType VALUE_OBJ_CLASS_SPEC {
// For reference types, store the actual Symbol
static VerificationType reference_type(Symbol* sh) {
assert(((uintptr_t)sh & 0x3) == 0, "Oops must be aligned");
assert(((uintptr_t)sh & 0x3) == 0, "Symbols must be aligned");
// If the above assert fails in the future because oop* isn't aligned,
// then this type encoding system will have to change to have a tag value
// to descriminate between oops and primitives.
......@@ -303,7 +303,7 @@ class VerificationType VALUE_OBJ_CLASS_SPEC {
return index;
}
void print_on(outputStream* st) const PRODUCT_RETURN;
void print_on(outputStream* st) const;
private:
......
此差异已折叠。
/*
* Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2012, 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
......@@ -88,18 +88,178 @@ class StackMapTable;
#define CHECK_VERIFY_(verifier, result) \
CHECK_(result)); if ((verifier)->has_error()) return (result); (0
class TypeOrigin VALUE_OBJ_CLASS_SPEC {
private:
typedef enum {
CF_LOCALS, // Comes from the current frame locals
CF_STACK, // Comes from the current frame expression stack
SM_LOCALS, // Comes from stackmap locals
SM_STACK, // Comes from stackmap expression stack
CONST_POOL, // Comes from the constant pool
SIG, // Comes from method signature
IMPLICIT, // Comes implicitly from code or context
BAD_INDEX, // No type, but the index is bad
FRAME_ONLY, // No type, context just contains the frame
NONE
} Origin;
Origin _origin;
u2 _index; // local, stack, or constant pool index
StackMapFrame* _frame; // source frame if CF or SM
VerificationType _type; // The actual type
TypeOrigin(
Origin origin, u2 index, StackMapFrame* frame, VerificationType type)
: _origin(origin), _index(index), _frame(frame), _type(type) {}
public:
TypeOrigin() : _origin(NONE), _index(0), _frame(NULL) {}
static TypeOrigin null();
static TypeOrigin local(u2 index, StackMapFrame* frame);
static TypeOrigin stack(u2 index, StackMapFrame* frame);
static TypeOrigin sm_local(u2 index, StackMapFrame* frame);
static TypeOrigin sm_stack(u2 index, StackMapFrame* frame);
static TypeOrigin cp(u2 index, VerificationType vt);
static TypeOrigin signature(VerificationType vt);
static TypeOrigin bad_index(u2 index);
static TypeOrigin implicit(VerificationType t);
static TypeOrigin frame(StackMapFrame* frame);
void reset_frame();
void details(outputStream* ss) const;
void print_frame(outputStream* ss) const;
const StackMapFrame* frame() const { return _frame; }
bool is_valid() const { return _origin != NONE; }
u2 index() const { return _index; }
#ifdef ASSERT
void print_on(outputStream* str) const;
#endif
};
class ErrorContext VALUE_OBJ_CLASS_SPEC {
private:
typedef enum {
INVALID_BYTECODE, // There was a problem with the bytecode
WRONG_TYPE, // Type value was not as expected
FLAGS_MISMATCH, // Frame flags are not assignable
BAD_CP_INDEX, // Invalid constant pool index
BAD_LOCAL_INDEX, // Invalid local index
LOCALS_SIZE_MISMATCH, // Frames have differing local counts
STACK_SIZE_MISMATCH, // Frames have different stack sizes
STACK_OVERFLOW, // Attempt to push onto a full expression stack
STACK_UNDERFLOW, // Attempt to pop and empty expression stack
MISSING_STACKMAP, // No stackmap for this location and there should be
BAD_STACKMAP, // Format error in stackmap
NO_FAULT, // No error
UNKNOWN
} FaultType;
int _bci;
FaultType _fault;
TypeOrigin _type;
TypeOrigin _expected;
ErrorContext(int bci, FaultType fault) :
_bci(bci), _fault(fault) {}
ErrorContext(int bci, FaultType fault, TypeOrigin type) :
_bci(bci), _fault(fault), _type(type) {}
ErrorContext(int bci, FaultType fault, TypeOrigin type, TypeOrigin exp) :
_bci(bci), _fault(fault), _type(type), _expected(exp) {}
public:
ErrorContext() : _bci(-1), _fault(NO_FAULT) {}
static ErrorContext bad_code(u2 bci) {
return ErrorContext(bci, INVALID_BYTECODE);
}
static ErrorContext bad_type(u2 bci, TypeOrigin type) {
return ErrorContext(bci, WRONG_TYPE, type);
}
static ErrorContext bad_type(u2 bci, TypeOrigin type, TypeOrigin exp) {
return ErrorContext(bci, WRONG_TYPE, type, exp);
}
static ErrorContext bad_flags(u2 bci, StackMapFrame* frame) {
return ErrorContext(bci, FLAGS_MISMATCH, TypeOrigin::frame(frame));
}
static ErrorContext bad_flags(u2 bci, StackMapFrame* cur, StackMapFrame* sm) {
return ErrorContext(bci, FLAGS_MISMATCH,
TypeOrigin::frame(cur), TypeOrigin::frame(sm));
}
static ErrorContext bad_cp_index(u2 bci, u2 index) {
return ErrorContext(bci, BAD_CP_INDEX, TypeOrigin::bad_index(index));
}
static ErrorContext bad_local_index(u2 bci, u2 index) {
return ErrorContext(bci, BAD_LOCAL_INDEX, TypeOrigin::bad_index(index));
}
static ErrorContext locals_size_mismatch(
u2 bci, StackMapFrame* frame0, StackMapFrame* frame1) {
return ErrorContext(bci, LOCALS_SIZE_MISMATCH,
TypeOrigin::frame(frame0), TypeOrigin::frame(frame1));
}
static ErrorContext stack_size_mismatch(
u2 bci, StackMapFrame* frame0, StackMapFrame* frame1) {
return ErrorContext(bci, STACK_SIZE_MISMATCH,
TypeOrigin::frame(frame0), TypeOrigin::frame(frame1));
}
static ErrorContext stack_overflow(u2 bci, StackMapFrame* frame) {
return ErrorContext(bci, STACK_OVERFLOW, TypeOrigin::frame(frame));
}
static ErrorContext stack_underflow(u2 bci, StackMapFrame* frame) {
return ErrorContext(bci, STACK_UNDERFLOW, TypeOrigin::frame(frame));
}
static ErrorContext missing_stackmap(u2 bci) {
return ErrorContext(bci, MISSING_STACKMAP);
}
static ErrorContext bad_stackmap(int index, StackMapFrame* frame) {
return ErrorContext(0, BAD_STACKMAP, TypeOrigin::frame(frame));
}
bool is_valid() const { return _fault != NO_FAULT; }
int bci() const { return _bci; }
void reset_frames() {
_type.reset_frame();
_expected.reset_frame();
}
void details(outputStream* ss, methodOop method) const;
#ifdef ASSERT
void print_on(outputStream* str) const {
str->print("error_context(%d, %d,", _bci, _fault);
_type.print_on(str);
str->print(",");
_expected.print_on(str);
str->print(")");
}
#endif
private:
void location_details(outputStream* ss, methodOop method) const;
void reason_details(outputStream* ss) const;
void frame_details(outputStream* ss) const;
void bytecode_details(outputStream* ss, methodOop method) const;
void handler_details(outputStream* ss, methodOop method) const;
void stackmap_details(outputStream* ss, methodOop method) const;
};
// A new instance of this class is created for each class being verified
class ClassVerifier : public StackObj {
private:
Thread* _thread;
GrowableArray<Symbol*>* _symbols; // keep a list of symbols created
Symbol* _exception_type;
char* _message;
size_t _message_buffer_len;
GrowableArray<Symbol*>* _symbols; // keep a list of symbols created
ErrorContext _error_context; // contains information about an error
void verify_method(methodHandle method, TRAPS);
char* generate_code_data(methodHandle m, u4 code_length, TRAPS);
void verify_exception_handler_table(u4 code_length, char* code_data, int& min, int& max, TRAPS);
void verify_exception_handler_table(u4 code_length, char* code_data,
int& min, int& max, TRAPS);
void verify_local_variable_table(u4 code_length, char* code_data, TRAPS);
VerificationType cp_ref_index_to_type(
......@@ -111,10 +271,10 @@ class ClassVerifier : public StackObj {
instanceKlassHandle this_class, klassOop target_class,
Symbol* field_name, Symbol* field_sig, bool is_method);
void verify_cp_index(constantPoolHandle cp, int index, TRAPS);
void verify_cp_type(
int index, constantPoolHandle cp, unsigned int types, TRAPS);
void verify_cp_class_type(int index, constantPoolHandle cp, TRAPS);
void verify_cp_index(u2 bci, constantPoolHandle cp, int index, TRAPS);
void verify_cp_type(u2 bci, int index, constantPoolHandle cp,
unsigned int types, TRAPS);
void verify_cp_class_type(u2 bci, int index, constantPoolHandle cp, TRAPS);
u2 verify_stackmap_table(
u2 stackmap_index, u2 bci, StackMapFrame* current_frame,
......@@ -137,7 +297,7 @@ class ClassVerifier : public StackObj {
constantPoolHandle cp, TRAPS);
void verify_invoke_init(
RawBytecodeStream* bcs, VerificationType ref_class_type,
RawBytecodeStream* bcs, u2 ref_index, VerificationType ref_class_type,
StackMapFrame* current_frame, u4 code_length, bool* this_uninit,
constantPoolHandle cp, TRAPS);
......@@ -147,10 +307,11 @@ class ClassVerifier : public StackObj {
constantPoolHandle cp, TRAPS);
VerificationType get_newarray_type(u2 index, u2 bci, TRAPS);
void verify_anewarray(
u2 index, constantPoolHandle cp, StackMapFrame* current_frame, TRAPS);
void verify_anewarray(u2 bci, u2 index, constantPoolHandle cp,
StackMapFrame* current_frame, TRAPS);
void verify_return_value(
VerificationType return_type, VerificationType type, u2 offset, TRAPS);
VerificationType return_type, VerificationType type, u2 offset,
StackMapFrame* current_frame, TRAPS);
void verify_iload (u2 index, StackMapFrame* current_frame, TRAPS);
void verify_lload (u2 index, StackMapFrame* current_frame, TRAPS);
......@@ -189,7 +350,7 @@ class ClassVerifier : public StackObj {
};
// constructor
ClassVerifier(instanceKlassHandle klass, char* msg, size_t msg_len, TRAPS);
ClassVerifier(instanceKlassHandle klass, TRAPS);
// destructor
~ClassVerifier();
......@@ -207,13 +368,17 @@ class ClassVerifier : public StackObj {
// Return status modes
Symbol* result() const { return _exception_type; }
bool has_error() const { return result() != NULL; }
char* exception_message() {
stringStream ss;
ss.print(_message);
_error_context.details(&ss, _method());
return ss.as_string();
}
// Called when verify or class format errors are encountered.
// May throw an exception based upon the mode.
void verify_error(u2 offset, const char* fmt, ...);
void verify_error(const char* fmt, ...);
void verify_error(ErrorContext ctx, const char* fmt, ...);
void class_format_error(const char* fmt, ...);
void format_error_message(const char* fmt, int offset, va_list args);
klassOop load_class(Symbol* name, TRAPS);
......@@ -228,10 +393,11 @@ class ClassVerifier : public StackObj {
// their reference counts need to be decrememented when the verifier object
// goes out of scope. Since these symbols escape the scope in which they're
// created, we can't use a TempNewSymbol.
Symbol* create_temporary_symbol(const Symbol* s, int begin, int end, TRAPS);
Symbol* create_temporary_symbol(
const Symbol* s, int begin, int end, TRAPS);
Symbol* create_temporary_symbol(const char *s, int length, TRAPS);
static bool _verify_verbose; // for debugging
TypeOrigin ref_ctx(const char* str, TRAPS);
};
inline int ClassVerifier::change_sig_to_verificationType(
......
......@@ -829,6 +829,9 @@ class CommandLineFlags {
product(bool, PrintGCApplicationStoppedTime, false, \
"Print the time the application has been stopped") \
\
diagnostic(bool, VerboseVerification, false, \
"Display detailed verification details") \
\
notproduct(uintx, ErrorHandlerTest, 0, \
"If > 0, provokes an error after VM initialization; the value" \
"determines which error to provoke. See test_error_handler()" \
......
......@@ -465,13 +465,12 @@ static typeArrayOop insert_hole_at(
void Relocator::adjust_stack_map_table(int bci, int delta) {
if (method()->has_stackmap_table()) {
typeArrayOop data = method()->stackmap_data();
// The data in the array is a classfile representation of the stackmap
// table attribute, less the initial u2 tag and u4 attribute_length fields.
stack_map_table_attribute* attr = stack_map_table_attribute::at(
(address)data->byte_at_addr(0) - (sizeof(u2) + sizeof(u4)));
// The data in the array is a classfile representation of the stackmap table
stack_map_table* sm_table =
stack_map_table::at((address)data->byte_at_addr(0));
int count = attr->number_of_entries();
stack_map_frame* frame = attr->entries();
int count = sm_table->number_of_entries();
stack_map_frame* frame = sm_table->entries();
int bci_iter = -1;
bool offset_adjusted = false; // only need to adjust one offset
......@@ -486,7 +485,7 @@ void Relocator::adjust_stack_map_table(int bci, int delta) {
frame->set_offset_delta(new_offset_delta);
} else {
assert(frame->is_same_frame() ||
frame->is_same_frame_1_stack_item_frame(),
frame->is_same_locals_1_stack_item_frame(),
"Frame must be one of the compressed forms");
// The new delta exceeds the capacity of the 'same_frame' or
// 'same_frame_1_stack_item_frame' frame types. We need to
......@@ -513,7 +512,7 @@ void Relocator::adjust_stack_map_table(int bci, int delta) {
if (frame->is_same_frame()) {
same_frame_extended::create_at(frame_addr, new_offset_delta);
} else {
same_frame_1_stack_item_extended::create_at(
same_locals_1_stack_item_extended::create_at(
frame_addr, new_offset_delta, NULL);
// the verification_info_type should already be at the right spot
}
......
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2012, 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
......@@ -237,8 +237,9 @@ void outputStream::date_stamp(bool guard,
return;
}
void outputStream::indent() {
outputStream& outputStream::indent() {
while (_position < _indentation) sp();
return *this;
}
void outputStream::print_jlong(jlong value) {
......@@ -251,6 +252,47 @@ void outputStream::print_julong(julong value) {
print(os::julong_format_specifier(), value);
}
/**
* This prints out hex data in a 'windbg' or 'xxd' form, where each line is:
* <hex-address>: 8 * <hex-halfword> <ascii translation (optional)>
* example:
* 0000000: 7f44 4f46 0102 0102 0000 0000 0000 0000 .DOF............
* 0000010: 0000 0000 0000 0040 0000 0020 0000 0005 .......@... ....
* 0000020: 0000 0000 0000 0040 0000 0000 0000 015d .......@.......]
* ...
*
* indent is applied to each line. Ends with a CR.
*/
void outputStream::print_data(void* data, size_t len, bool with_ascii) {
size_t limit = (len + 16) / 16 * 16;
for (size_t i = 0; i < limit; ++i) {
if (i % 16 == 0) {
indent().print("%07x:", i);
}
if (i % 2 == 0) {
print(" ");
}
if (i < len) {
print("%02x", ((unsigned char*)data)[i]);
} else {
print(" ");
}
if ((i + 1) % 16 == 0) {
if (with_ascii) {
print(" ");
for (size_t j = 0; j < 16; ++j) {
size_t idx = i + j - 15;
if (idx < len) {
char c = ((char*)data)[idx];
print("%c", c >= 32 && c <= 126 ? c : '.');
}
}
}
print_cr("");
}
}
}
stringStream::stringStream(size_t initial_size) : outputStream() {
buffer_length = initial_size;
buffer = NEW_RESOURCE_ARRAY(char, buffer_length);
......
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2012, 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
......@@ -59,9 +59,11 @@ class outputStream : public ResourceObj {
outputStream(int width, bool has_time_stamps);
// indentation
void indent();
outputStream& indent();
void inc() { _indentation++; };
void dec() { _indentation--; };
void inc(int n) { _indentation += n; };
void dec(int n) { _indentation -= n; };
int indentation() const { return _indentation; }
void set_indentation(int i) { _indentation = i; }
void fill_to(int col);
......@@ -84,6 +86,7 @@ class outputStream : public ResourceObj {
void print_raw(const char* str, int len) { write(str, len); }
void print_raw_cr(const char* str) { write(str, strlen(str)); cr(); }
void print_raw_cr(const char* str, int len){ write(str, len); cr(); }
void print_data(void* data, size_t len, bool with_ascii);
void put(char ch);
void sp(int count = 1);
void cr();
......@@ -122,6 +125,19 @@ class outputStream : public ResourceObj {
extern outputStream* tty; // tty output
extern outputStream* gclog_or_tty; // stream for gc log if -Xloggc:<f>, or tty
class streamIndentor : public StackObj {
private:
outputStream* _str;
int _amount;
public:
streamIndentor(outputStream* str, int amt = 2) : _str(str), _amount(amt) {
_str->inc(_amount);
}
~streamIndentor() { _str->dec(_amount); }
};
// advisory locking for the shared tty stream:
class ttyLocker: StackObj {
friend class ttyUnlocker;
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册