src/share/vm/classfile/stackMapTable.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File hotspot Sdiff src/share/vm/classfile

src/share/vm/classfile/stackMapTable.cpp

Print this page
rev 3510 : 7116786: RFE: Detailed information on VerifyErrors
Summary: Provide additional detail in VerifyError messages
Reviewed-by:


  29 #include "oops/oop.inline.hpp"
  30 #include "runtime/fieldType.hpp"
  31 #include "runtime/handles.inline.hpp"
  32 
  33 StackMapTable::StackMapTable(StackMapReader* reader, StackMapFrame* init_frame,
  34                              u2 max_locals, u2 max_stack,
  35                              char* code_data, int code_len, TRAPS) {
  36   _code_length = code_len;
  37   _frame_count = reader->get_frame_count();
  38   if (_frame_count > 0) {
  39     _frame_array = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD,
  40                                                 StackMapFrame*, _frame_count);
  41     StackMapFrame* pre_frame = init_frame;
  42     for (int32_t i = 0; i < _frame_count; i++) {
  43       StackMapFrame* frame = reader->next(
  44         pre_frame, i == 0, max_locals, max_stack,
  45         CHECK_VERIFY(pre_frame->verifier()));
  46       _frame_array[i] = frame;
  47       int offset = frame->offset();
  48       if (offset >= code_len || code_data[offset] == 0) {
  49         frame->verifier()->verify_error("StackMapTable error: bad offset");


  50         return;
  51       }
  52       pre_frame = frame;
  53     }
  54   }
  55   reader->check_end(CHECK);
  56 }
  57 
  58 // This method is only called by method in StackMapTable.
  59 int StackMapTable::get_index_from_offset(int32_t offset) const {
  60   int i = 0;
  61   for (; i < _frame_count; i++) {
  62     if (_frame_array[i]->offset() == offset) {
  63       return i;
  64     }
  65   }
  66   return i;  // frame with offset doesn't exist in the array
  67 }
  68 
  69 bool StackMapTable::match_stackmap(
  70     StackMapFrame* frame, int32_t target,
  71     bool match, bool update, TRAPS) const {
  72   int index = get_index_from_offset(target);
  73 
  74   return match_stackmap(
  75     frame, target, index, match,
  76     update, CHECK_VERIFY_(frame->verifier(), false));
  77 }
  78 
  79 // Match and/or update current_frame to the frame in stackmap table with
  80 // specified offset and frame index. Return true if the two frames match.
  81 //
  82 // The values of match and update are:                  _match__update_
  83 //
  84 // checking a branch target/exception handler:           true   false
  85 // linear bytecode verification following an
  86 // unconditional branch:                                 false  true
  87 // linear bytecode verification not following an
  88 // unconditional branch:                                 true   true
  89 bool StackMapTable::match_stackmap(
  90     StackMapFrame* frame, int32_t target, int32_t frame_index,
  91     bool match, bool update, TRAPS) const {
  92   if (frame_index < 0 || frame_index >= _frame_count) {
  93     frame->verifier()->verify_error(frame->offset(),
  94       "Expecting a stackmap frame at branch target %d", target);

  95     return false;
  96   }
  97 
  98   bool result = true;
  99   StackMapFrame *stackmap_frame = _frame_array[frame_index];

 100   if (match) {
 101     // when checking handler target, match == true && update == false
 102     bool is_exception_handler = !update;
 103     // Has direct control flow from last instruction, need to match the two
 104     // frames.
 105     result = frame->is_assignable_to(
 106       stackmap_frame, is_exception_handler,
 107       CHECK_VERIFY_(frame->verifier(), false));
 108   }
 109   if (update) {
 110     // Use the frame in stackmap table as current frame
 111     int lsize = stackmap_frame->locals_size();
 112     int ssize = stackmap_frame->stack_size();
 113     if (frame->locals_size() > lsize || frame->stack_size() > ssize) {
 114       // Make sure unused type array items are all _bogus_type.
 115       frame->reset();
 116     }
 117     frame->set_locals_size(lsize);
 118     frame->copy_locals(stackmap_frame);
 119     frame->set_stack_size(ssize);
 120     frame->copy_stack(stackmap_frame);
 121     frame->set_flags(stackmap_frame->flags());
 122   }
 123   return result;
 124 }
 125 
 126 void StackMapTable::check_jump_target(
 127     StackMapFrame* frame, int32_t target, TRAPS) const {

 128   bool match = match_stackmap(
 129     frame, target, true, false, CHECK_VERIFY(frame->verifier()));
 130   if (!match || (target < 0 || target >= _code_length)) {
 131     frame->verifier()->verify_error(frame->offset(),
 132       "Inconsistent stackmap frames at branch target %d", target);
 133     return;
 134   }
 135   // check if uninitialized objects exist on backward branches
 136   check_new_object(frame, target, CHECK_VERIFY(frame->verifier()));
 137 }
 138 
 139 void StackMapTable::check_new_object(
 140     const StackMapFrame* frame, int32_t target, TRAPS) const {
 141   if (frame->offset() > target && frame->has_new_object()) {
 142     frame->verifier()->verify_error(frame->offset(),

 143       "Uninitialized object exists on backward branch %d", target);
 144     return;
 145   }
 146 }
 147 
 148 #ifndef PRODUCT
 149 
 150 void StackMapTable::print() const {
 151   tty->print_cr("StackMapTable: frame_count = %d", _frame_count);
 152   tty->print_cr("table = { ");
 153   for (int32_t i = 0; i < _frame_count; i++) {
 154     _frame_array[i]->print();

 155   }
 156   tty->print_cr(" }");
 157 }
 158 
 159 #endif
 160 
 161 int32_t StackMapReader::chop(
 162     VerificationType* locals, int32_t length, int32_t chops) {
 163   if (locals == NULL) return -1;
 164   int32_t pos = length - 1;
 165   for (int32_t i=0; i<chops; i++) {
 166     if (locals[pos].is_category2_2nd()) {
 167       pos -= 2;
 168     } else {
 169       pos --;
 170     }
 171     if (pos<0 && i<(chops-1)) return -1;
 172   }
 173   return pos+1;
 174 }
 175 
 176 VerificationType StackMapReader::parse_verification_type(u1* flags, TRAPS) {
 177   u1 tag = _stream->get_u1(THREAD);
 178   if (tag < (u1)ITEM_UninitializedThis) {
 179     return VerificationType::from_tag(tag);




  29 #include "oops/oop.inline.hpp"
  30 #include "runtime/fieldType.hpp"
  31 #include "runtime/handles.inline.hpp"
  32 
  33 StackMapTable::StackMapTable(StackMapReader* reader, StackMapFrame* init_frame,
  34                              u2 max_locals, u2 max_stack,
  35                              char* code_data, int code_len, TRAPS) {
  36   _code_length = code_len;
  37   _frame_count = reader->get_frame_count();
  38   if (_frame_count > 0) {
  39     _frame_array = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD,
  40                                                 StackMapFrame*, _frame_count);
  41     StackMapFrame* pre_frame = init_frame;
  42     for (int32_t i = 0; i < _frame_count; i++) {
  43       StackMapFrame* frame = reader->next(
  44         pre_frame, i == 0, max_locals, max_stack,
  45         CHECK_VERIFY(pre_frame->verifier()));
  46       _frame_array[i] = frame;
  47       int offset = frame->offset();
  48       if (offset >= code_len || code_data[offset] == 0) {
  49         frame->verifier()->verify_error(
  50             ErrorContext::bad_stackmap(i, frame),
  51             "StackMapTable error: bad offset");
  52         return;
  53       }
  54       pre_frame = frame;
  55     }
  56   }
  57   reader->check_end(CHECK);
  58 }
  59 
  60 // This method is only called by method in StackMapTable.
  61 int StackMapTable::get_index_from_offset(int32_t offset) const {
  62   int i = 0;
  63   for (; i < _frame_count; i++) {
  64     if (_frame_array[i]->offset() == offset) {
  65       return i;
  66     }
  67   }
  68   return i;  // frame with offset doesn't exist in the array
  69 }
  70 
  71 bool StackMapTable::match_stackmap(
  72     StackMapFrame* frame, int32_t target,
  73     bool match, bool update, ErrorContext* ctx, TRAPS) const {
  74   int index = get_index_from_offset(target);
  75   return match_stackmap(frame, target, index, match, update, ctx, THREAD);



  76 }
  77 
  78 // Match and/or update current_frame to the frame in stackmap table with
  79 // specified offset and frame index. Return true if the two frames match.
  80 //
  81 // The values of match and update are:                  _match__update_
  82 //
  83 // checking a branch target/exception handler:           true   false
  84 // linear bytecode verification following an
  85 // unconditional branch:                                 false  true
  86 // linear bytecode verification not following an
  87 // unconditional branch:                                 true   true
  88 bool StackMapTable::match_stackmap(
  89     StackMapFrame* frame, int32_t target, int32_t frame_index,
  90     bool match, bool update, ErrorContext* ctx, TRAPS) const {
  91   if (frame_index < 0 || frame_index >= _frame_count) {
  92     *ctx = ErrorContext::missing_stackmap(frame->offset());
  93     frame->verifier()->verify_error(
  94         *ctx, "Expecting a stackmap frame at branch target %d", target);
  95     return false;
  96   }
  97 

  98   StackMapFrame *stackmap_frame = _frame_array[frame_index];
  99   bool result = true;
 100   if (match) {
 101     // when checking handler target, match == true && update == false
 102     bool is_exception_handler = !update;
 103     // Has direct control flow from last instruction, need to match the two
 104     // frames.
 105     result = frame->is_assignable_to(stackmap_frame, is_exception_handler,
 106         ctx, CHECK_VERIFY_(frame->verifier(), result));

 107   }
 108   if (update) {
 109     // Use the frame in stackmap table as current frame
 110     int lsize = stackmap_frame->locals_size();
 111     int ssize = stackmap_frame->stack_size();
 112     if (frame->locals_size() > lsize || frame->stack_size() > ssize) {
 113       // Make sure unused type array items are all _bogus_type.
 114       frame->reset();
 115     }
 116     frame->set_locals_size(lsize);
 117     frame->copy_locals(stackmap_frame);
 118     frame->set_stack_size(ssize);
 119     frame->copy_stack(stackmap_frame);
 120     frame->set_flags(stackmap_frame->flags());
 121   }
 122   return result;
 123 }
 124 
 125 void StackMapTable::check_jump_target(
 126     StackMapFrame* frame, int32_t target, TRAPS) const {
 127   ErrorContext ctx;
 128   bool match = match_stackmap(
 129     frame, target, true, false, &ctx, CHECK_VERIFY(frame->verifier()));
 130   if (!match || (target < 0 || target >= _code_length)) {
 131     frame->verifier()->verify_error(ctx,
 132         "Inconsistent stackmap frames at branch target %d", target);
 133     return;
 134   }
 135   // check if uninitialized objects exist on backward branches
 136   check_new_object(frame, target, CHECK_VERIFY(frame->verifier()));
 137 }
 138 
 139 void StackMapTable::check_new_object(
 140     const StackMapFrame* frame, int32_t target, TRAPS) const {
 141   if (frame->offset() > target && frame->has_new_object()) {
 142     frame->verifier()->verify_error(
 143         ErrorContext::bad_code(frame->offset()),
 144         "Uninitialized object exists on backward branch %d", target);
 145     return;
 146   }
 147 }
 148 
 149 void StackMapTable::print(outputStream* str) const {
 150   str->indent().print_cr("StackMapTable: frame_count = %d", _frame_count);
 151   str->indent().print_cr("table = { ");
 152   {
 153     streamIndentor si(str);
 154     for (int32_t i = 0; i < _frame_count; i++) {
 155       _frame_array[i]->print(str);
 156     }
 157   }
 158   tty->print_cr(" }");
 159 }


 160 
 161 int32_t StackMapReader::chop(
 162     VerificationType* locals, int32_t length, int32_t chops) {
 163   if (locals == NULL) return -1;
 164   int32_t pos = length - 1;
 165   for (int32_t i=0; i<chops; i++) {
 166     if (locals[pos].is_category2_2nd()) {
 167       pos -= 2;
 168     } else {
 169       pos --;
 170     }
 171     if (pos<0 && i<(chops-1)) return -1;
 172   }
 173   return pos+1;
 174 }
 175 
 176 VerificationType StackMapReader::parse_verification_type(u1* flags, TRAPS) {
 177   u1 tag = _stream->get_u1(THREAD);
 178   if (tag < (u1)ITEM_UninitializedThis) {
 179     return VerificationType::from_tag(tag);


src/share/vm/classfile/stackMapTable.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File