void CodeSection::relocate(address at, RelocationHolder const& spec, int format) {
  Relocation* reloc = spec.reloc();
  relocInfo::relocType rtype = (relocInfo::relocType) reloc->type();
  if (rtype == relocInfo::none)  return;

  // The assertion below has been adjusted, to also work for
  // relocation for fixup.  Sometimes we want to put relocation
  // information for the next instruction, since it will be patched
  // with a call.
  assert(start() <= at && at <= end()+1,
         "cannot relocate data outside code boundaries");

  if (!has_locs()) {
    // no space for relocation information provided => code cannot be
    // relocated.  Make sure that relocate is only called with rtypes
    // that can be ignored for this kind of code.
    assert(rtype == relocInfo::none              ||
           rtype == relocInfo::runtime_call_type ||
           rtype == relocInfo::internal_word_type||
           rtype == relocInfo::section_word_type ||
           rtype == relocInfo::external_word_type,
           "code needs relocation information");
    // leave behind an indication that we attempted a relocation
    DEBUG_ONLY(_locs_start = _locs_limit = (relocInfo*)badAddress);
    return;
  }

  // Advance the point, noting the offset we'll have to record.
  csize_t offset = at - locs_point();
  set_locs_point(at);

  // Test for a couple of overflow conditions; maybe expand the buffer.
  relocInfo* end = locs_end();
  relocInfo* req = end + relocInfo::length_limit;
  // Check for (potential) overflow
  if (req >= locs_limit() || offset >= relocInfo::offset_limit()) {
    req += (uint)offset / (uint)relocInfo::offset_limit();
    if (req >= locs_limit()) {
      // Allocate or reallocate.
      expand_locs(locs_count() + (req - end));
      // reload pointer
      end = locs_end();
    }
  }

  // If the offset is giant, emit filler relocs, of type 'none', but
  // each carrying the largest possible offset, to advance the locs_point.
  while (offset >= relocInfo::offset_limit()) {
    assert(end < locs_limit(), "adjust previous paragraph of code");
    *end++ = filler_relocInfo();
    offset -= filler_relocInfo().addr_offset();
  }

  // If it's a simple reloc with no data, we'll just write (rtype | offset).
  (*end) = relocInfo(rtype, offset, format);

  // If it has data, insert the prefix, as (data_prefix_tag | data1), data2.
  end->initialize(this, reloc);
}
예제 #2
0
 // Verify that there is enough space remaining for one instruction
 void force_space_in_buffer(int inst_size, int stubs_size, int const_size, int locs_size) {
   if ( allow_resizing() &&
        ( ((address)  code_end() + inst_size  >= (address)  code_limit()) ||
          ((address)  stub_end() + stubs_size >= (address)  stub_limit()) ||
          ((address)ctable_end() + const_size >= (address)ctable_limit()) ||
          ((address)  locs_end() + locs_size  >= (address)  locs_limit())) )
     resize();
 }
예제 #3
0
 int        locs_capacity() const    { return (char*)locs_limit() - (char*)locs_start(); }