예제 #1
0
void java_bytecode_parsert::rmethod(classt &parsed_class)
{
  methodt &method=parsed_class.add_method();

  u2 access_flags=read_u2();
  u2 name_index=read_u2();
  u2 descriptor_index=read_u2();

  method.is_final=(access_flags&ACC_FINAL)!=0;
  method.is_static=(access_flags&ACC_STATIC)!=0;
  method.is_abstract=(access_flags&ACC_ABSTRACT)!=0;
  method.is_public=(access_flags&ACC_PUBLIC)!=0;
  method.is_protected=(access_flags&ACC_PROTECTED)!=0;
  method.is_private=(access_flags&ACC_PRIVATE)!=0;
  method.is_synchronized=(access_flags&ACC_SYNCHRONIZED)!=0;
  method.is_native=(access_flags&ACC_NATIVE)!=0;
  method.name=pool_entry(name_index).s;
  method.base_name=pool_entry(name_index).s;
  method.signature=id2string(pool_entry(descriptor_index).s);

  u2 attributes_count=read_u2();

  for(std::size_t j=0; j<attributes_count; j++)
    rmethod_attribute(method);
}
예제 #2
0
void java_bytecode_parsert::rinterfaces(classt &parsed_class)
{
  u2 interfaces_count=read_u2();

  for(std::size_t i=0; i<interfaces_count; i++)
    parsed_class.implements
      .push_back(constant(read_u2()).type().get(ID_C_base_name));
}
예제 #3
0
void java_bytecode_parsert::relement_value_pairs(
  annotationt::element_value_pairst &element_value_pairs)
{
  u2 num_element_value_pairs=read_u2();
  element_value_pairs.resize(num_element_value_pairs);

  for(auto &element_value_pair : element_value_pairs)
  {
    u2 element_name_index=read_u2();
    element_value_pair.element_name=pool_entry(element_name_index).s;

    relement_value_pair(element_value_pair);
  }
}
예제 #4
0
/* Read out a given typed element */
static jvalue
read_val(unsigned char **pp, HprofType ty)
{
    jvalue        val;
    static jvalue empty_val;

    val = empty_val;
    switch ( ty ) {
        case 0:
        case HPROF_ARRAY_OBJECT:
        case HPROF_NORMAL_OBJECT:
            val.i = read_id(pp);
            break;
        case HPROF_BYTE:
        case HPROF_BOOLEAN:
            val.b = read_u1(pp);
            break;
        case HPROF_CHAR:
        case HPROF_SHORT:
            val.s = read_u2(pp);
            break;
        case HPROF_FLOAT:
        case HPROF_INT:
            val.i = read_u4(pp);
            break;
        case HPROF_DOUBLE:
        case HPROF_LONG:
            val.j = read_u8(pp);
            break;
        default:
            HPROF_ERROR(JNI_TRUE, "bad type number");
            break;
    }
    return val;
}
예제 #5
0
void java_bytecode_parsert::rmethods(classt &parsed_class)
{
  u2 methods_count=read_u2();

  for(std::size_t j=0; j<methods_count; j++)
    rmethod(parsed_class);
}
예제 #6
0
void java_bytecode_parsert::rRuntimeAnnotation(
  annotationt &annotation)
{
  u2 type_index=read_u2();
  annotation.type=type_entry(type_index);
  relement_value_pairs(annotation.element_value_pairs);
}
예제 #7
0
void java_bytecode_parsert::rclass_attribute(classt &parsed_class)
{
  u2 attribute_name_index=read_u2();
  u4 attribute_length=read_u4();

  irep_idt attribute_name=pool_entry(attribute_name_index).s;

  if(attribute_name=="SourceFile")
  {
    u2 sourcefile_index=read_u2();
    irep_idt sourcefile_name;

    std::string fqn(id2string(parsed_class.name));
    size_t last_index=fqn.find_last_of(".");
    if(last_index==std::string::npos)
      sourcefile_name=pool_entry(sourcefile_index).s;
    else
    {
      std::string package_name=fqn.substr(0, last_index+1);
      std::replace(package_name.begin(), package_name.end(), '.', '/');
      const std::string &full_file_name=
        package_name+id2string(pool_entry(sourcefile_index).s);
      sourcefile_name=full_file_name;
    }

    for(methodst::iterator m_it=parsed_class.methods.begin();
        m_it!=parsed_class.methods.end();
        m_it++)
    {
      m_it->source_location.set_file(sourcefile_name);
      for(instructionst::iterator i_it=m_it->instructions.begin();
          i_it!=m_it->instructions.end();
          i_it++)
      {
        if(!i_it->source_location.get_line().empty())
          i_it->source_location.set_file(sourcefile_name);
      }
    }
  }
  else if(attribute_name=="RuntimeInvisibleAnnotations" ||
          attribute_name=="RuntimeVisibleAnnotations")
  {
    rRuntimeAnnotation_attribute(parsed_class.annotations);
  }
  else
    skip_bytes(attribute_length);
}
예제 #8
0
void java_bytecode_parsert::rRuntimeAnnotation_attribute(
  annotationst &annotations)
{
  u2 num_annotations=read_u2();

  for(u2 number=0; number<num_annotations; number++)
  {
    annotationt annotation;
    rRuntimeAnnotation(annotation);
    annotations.push_back(annotation);
  }
}
예제 #9
0
void java_bytecode_parsert::read_verification_type_info(
  methodt::verification_type_infot &v)
{
  u1 tag=read_u1();
  switch(tag)
  {
  case VTYPE_INFO_TOP:
    v.type=methodt::verification_type_infot::TOP;
    break;
  case VTYPE_INFO_INTEGER:
    v.type=methodt::verification_type_infot::INTEGER;
    break;
  case VTYPE_INFO_FLOAT:
    v.type=methodt::verification_type_infot::FLOAT;
    break;
  case VTYPE_INFO_LONG:
    v.type=methodt::verification_type_infot::LONG;
    break;
  case VTYPE_INFO_DOUBLE:
    v.type=methodt::verification_type_infot::DOUBLE;
    break;
  case VTYPE_INFO_ITEM_NULL:
    v.type=methodt::verification_type_infot::ITEM_NULL;
    break;
  case VTYPE_INFO_UNINIT_THIS:
    v.type=methodt::verification_type_infot::UNINITIALIZED_THIS;
    break;
  case VTYPE_INFO_OBJECT:
    v.type=methodt::verification_type_infot::OBJECT;
    v.cpool_index=read_u2();
    break;
  case VTYPE_INFO_UNINIT:
    v.type=methodt::verification_type_infot::UNINITIALIZED;
    v.offset=read_u2();
    break;
  default:
    throw "error: unknown verification type info encountered";
  }
}
예제 #10
0
void java_bytecode_parsert::relement_value_pair(
  annotationt::element_value_pairt &element_value_pair)
{
  u1 tag=read_u1();

  switch(tag)
  {
  case 'e':
    {
      UNUSED u2 type_name_index=read_u2();
      UNUSED u2 const_name_index=read_u2();
      // todo: enum
    }
    break;

  case 'c':
    {
      UNUSED u2 class_info_index=read_u2();
      // todo: class
    }
    break;

  case '@':
    {
      // another annotation, recursively
      annotationt annotation;
      rRuntimeAnnotation(annotation);
    }
    break;

  case '[':
    {
      u2 num_values=read_u2();
      for(std::size_t i=0; i<num_values; i++)
      {
        annotationt::element_value_pairt element_value;
        relement_value_pair(element_value); // recursive call
      }
    }
    break;

  case 's':
    {
      u2 const_value_index=read_u2();
      element_value_pair.value=string_constantt(
        pool_entry(const_value_index).s);
    }
    break;

  default:
    {
      u2 const_value_index=read_u2();
      element_value_pair.value=constant(const_value_index);
    }

  break;
  }
}
예제 #11
0
void java_bytecode_parsert::rfields(classt &parsed_class)
{
  u2 fields_count=read_u2();

  for(std::size_t i=0; i<fields_count; i++)
  {
    fieldt &field=parsed_class.add_field();

    u2 access_flags=read_u2();
    u2 name_index=read_u2();
    u2 descriptor_index=read_u2();
    u2 attributes_count=read_u2();

    field.name=pool_entry(name_index).s;
    field.is_static=(access_flags&ACC_STATIC)!=0;
    field.is_final=(access_flags&ACC_FINAL)!=0;
    field.is_enum=(access_flags&ACC_ENUM)!=0;
    field.signature=id2string(pool_entry(descriptor_index).s);

    for(std::size_t j=0; j<attributes_count; j++)
      rfield_attribute(field);
  }
}
예제 #12
0
void java_bytecode_parsert::rClassFile()
{
  parse_tree.loading_successful=false;

  u4 magic=read_u4();
  u2 UNUSED minor_version=read_u2();
  u2 major_version=read_u2();

  if(magic!=0xCAFEBABE)
  {
    error() << "wrong magic" << eom;
    throw 0;
  }

  if(major_version<44)
  {
    error() << "unexpected major version" << eom;
    throw 0;
  }

  rconstant_pool();

  classt &parsed_class=parse_tree.parsed_class;

  u2 access_flags=read_u2();
  u2 this_class=read_u2();
  u2 super_class=read_u2();

  parsed_class.is_abstract=(access_flags&ACC_ABSTRACT)!=0;
  parsed_class.is_enum=(access_flags&ACC_ENUM)!=0;
  parsed_class.name=
    constant(this_class).type().get(ID_C_base_name);

  if(super_class!=0)
    parsed_class.extends=
      constant(super_class).type().get(ID_C_base_name);

  rinterfaces(parsed_class);
  rfields(parsed_class);
  rmethods(parsed_class);

  // count elements of enum
  if(parsed_class.is_enum)
    for(fieldt &field : parse_tree.parsed_class.fields)
      if(field.is_enum)
        parse_tree.parsed_class.enum_elements++;

  u2 attributes_count=read_u2();

  for(std::size_t j=0; j<attributes_count; j++)
    rclass_attribute(parsed_class);

  get_class_refs();

  parse_tree.loading_successful=true;
}
예제 #13
0
void java_bytecode_parsert::rfield_attribute(fieldt &field)
{
  u2 attribute_name_index=read_u2();
  u4 attribute_length=read_u4();

  irep_idt attribute_name=pool_entry(attribute_name_index).s;

  if(attribute_name=="RuntimeInvisibleAnnotations" ||
     attribute_name=="RuntimeVisibleAnnotations")
  {
    rRuntimeAnnotation_attribute(field.annotations);
  }
  else
    skip_bytes(attribute_length);
}
예제 #14
0
/* Check all the heap tags in a heap dump */
static int
check_tags(unsigned char *pstart, int nbytes)
{
    unsigned char      *p;
    int                 nrecord;
    struct LookupTable *utab;
    UmapInfo            umap;

    check_printf("\nCHECK TAGS: starting\n");

    utab    = table_initialize("temp utf8 map", 64, 64, 512, sizeof(UmapInfo));

    /* Walk the tags, assumes UTF8 tags are defined before used */
    p       = pstart;
    nrecord = 0;
    while ( p < (pstart+nbytes) ) {
        unsigned     tag;
        unsigned     size;
        int          nheap_records;
        int          npos;
        char        *label;
        HprofId      id, nm, sg, so, gr, gn;
        int          i, li, num_elements;
        HprofType    ty;
        SerialNumber trace_serial_num;
        SerialNumber thread_serial_num;
        SerialNumber class_serial_num;
        unsigned     flags;
        unsigned     depth;
        float        cutoff;
        unsigned     temp;
        jint         nblive;
        jint         nilive;
        jlong        tbytes;
        jlong        tinsts;
        jint         total_samples;
        jint         trace_count;

        nrecord++;
        /*LINTED*/
        npos = (int)(p - pstart);
        tag = read_u1(&p);
        (void)read_u4(&p); /* microsecs */
        size = read_u4(&p);
        #define CASE_TAG(name) case name: label = #name;
        switch ( tag ) {
            CASE_TAG(HPROF_UTF8)
                CHECK_FOR_ERROR(size>=(int)sizeof(HprofId));
                id = read_id(&p);
                check_printf("#%d@%d: %s, sz=%d, name_id=0x%x, \"",
                                nrecord, npos, label, size, id);
                num_elements = size-(int)sizeof(HprofId);
                check_raw(p, num_elements);
                check_printf("\"\n");
                /* Create entry in umap */
                umap.str = HPROF_MALLOC(num_elements+1);
                (void)strncpy(umap.str, (char*)p, (size_t)num_elements);
                umap.str[num_elements] = 0;
                (void)table_create_entry(utab, &id, sizeof(id), &umap);
                p += num_elements;
                break;
            CASE_TAG(HPROF_LOAD_CLASS)
                CHECK_FOR_ERROR(size==2*4+2*(int)sizeof(HprofId));
                class_serial_num = read_u4(&p);
                CHECK_CLASS_SERIAL_NO(class_serial_num);
                id = read_id(&p);
                trace_serial_num = read_u4(&p);
                CHECK_TRACE_SERIAL_NO(trace_serial_num);
                nm = read_id(&p);
                check_printf("#%d@%d: %s, sz=%d, class_serial_num=%u,"
                             " id=0x%x, trace_serial_num=%u, name_id=0x%x\n",
                                nrecord, npos, label, size, class_serial_num,
                                id, trace_serial_num, nm);
                break;
            CASE_TAG(HPROF_UNLOAD_CLASS)
                CHECK_FOR_ERROR(size==4);
                class_serial_num = read_u4(&p);
                CHECK_CLASS_SERIAL_NO(class_serial_num);
                check_printf("#%d@%d: %s, sz=%d, class_serial_num=%u\n",
                                nrecord, npos, label, size, class_serial_num);
                break;
            CASE_TAG(HPROF_FRAME)
                CHECK_FOR_ERROR(size==2*4+4*(int)sizeof(HprofId));
                id = read_id(&p);
                nm = read_id(&p);
                sg = read_id(&p);
                so = read_id(&p);
                class_serial_num = read_u4(&p);
                CHECK_CLASS_SERIAL_NO(class_serial_num);
                li = read_u4(&p);
                check_printf("#%d@%d: %s, sz=%d, ", nrecord, npos, label, size);
                check_print_utf8(utab, "id=", id);
                check_printf(" name_id=0x%x, sig_id=0x%x, source_id=0x%x,"
                             " class_serial_num=%u, lineno=%d\n",
                                nm, sg, so, class_serial_num, li);
                break;
            CASE_TAG(HPROF_TRACE)
                CHECK_FOR_ERROR(size>=3*4);
                trace_serial_num = read_u4(&p);
                CHECK_TRACE_SERIAL_NO(trace_serial_num);
                thread_serial_num = read_u4(&p); /* Can be 0 */
                num_elements = read_u4(&p);
                check_printf("#%d@%d: %s, sz=%d, trace_serial_num=%u,"
                             " thread_serial_num=%u, nelems=%d [",
                                nrecord, npos, label, size,
                                trace_serial_num, thread_serial_num, num_elements);
                for(i=0; i< num_elements; i++) {
                    check_printf("0x%x,", read_id(&p));
                }
                check_printf("]\n");
                break;
            CASE_TAG(HPROF_ALLOC_SITES)
                CHECK_FOR_ERROR(size>=2+4*4+2*8);
                flags = read_u2(&p);
                temp  = read_u4(&p);
                cutoff = *((float*)&temp);
                nblive = read_u4(&p);
                nilive = read_u4(&p);
                tbytes = read_u8(&p);
                tinsts = read_u8(&p);
                num_elements     = read_u4(&p);
                check_printf("#%d@%d: %s, sz=%d, flags=0x%x, cutoff=%g,"
                             " nblive=%d, nilive=%d, tbytes=(%d,%d),"
                             " tinsts=(%d,%d), num_elements=%d\n",
                                nrecord, npos, label, size,
                                flags, cutoff, nblive, nilive,
                                jlong_high(tbytes), jlong_low(tbytes),
                                jlong_high(tinsts), jlong_low(tinsts),
                                num_elements);
                for(i=0; i< num_elements; i++) {
                    ty = read_u1(&p);
                    class_serial_num = read_u4(&p);
                    CHECK_CLASS_SERIAL_NO(class_serial_num);
                    trace_serial_num = read_u4(&p);
                    CHECK_TRACE_SERIAL_NO(trace_serial_num);
                    nblive = read_u4(&p);
                    nilive = read_u4(&p);
                    tbytes = read_u4(&p);
                    tinsts = read_u4(&p);
                    check_printf("\t %d: ty=%d, class_serial_num=%u,"
                                 " trace_serial_num=%u, nblive=%d, nilive=%d,"
                                 " tbytes=%d, tinsts=%d\n",
                                 i, ty, class_serial_num, trace_serial_num,
                                 nblive, nilive, (jint)tbytes, (jint)tinsts);
                }
                break;
            CASE_TAG(HPROF_HEAP_SUMMARY)
                CHECK_FOR_ERROR(size==2*4+2*8);
                nblive = read_u4(&p);
                nilive = read_u4(&p);
                tbytes = read_u8(&p);
                tinsts = read_u8(&p);
                check_printf("#%d@%d: %s, sz=%d,"
                             " nblive=%d, nilive=%d, tbytes=(%d,%d),"
                             " tinsts=(%d,%d)\n",
                                nrecord, npos, label, size,
                                nblive, nilive,
                                jlong_high(tbytes), jlong_low(tbytes),
                                jlong_high(tinsts), jlong_low(tinsts));
                break;
            CASE_TAG(HPROF_START_THREAD)
                CHECK_FOR_ERROR(size==2*4+4*(int)sizeof(HprofId));
                thread_serial_num = read_u4(&p);
                CHECK_THREAD_SERIAL_NO(thread_serial_num);
                id = read_id(&p);
                trace_serial_num = read_u4(&p);
                CHECK_TRACE_SERIAL_NO(trace_serial_num);
                nm = read_id(&p);
                gr = read_id(&p);
                gn = read_id(&p);
                check_printf("#%d@%d: %s, sz=%d, thread_serial_num=%u,"
                             " id=0x%x, trace_serial_num=%u, ",
                                nrecord, npos, label, size,
                                thread_serial_num, id, trace_serial_num);
                check_print_utf8(utab, "nm=", id);
                check_printf(" trace_serial_num=%u, nm=0x%x,"
                             " gr=0x%x, gn=0x%x\n",
                                trace_serial_num, nm, gr, gn);
                break;
            CASE_TAG(HPROF_END_THREAD)
                CHECK_FOR_ERROR(size==4);
                thread_serial_num = read_u4(&p);
                CHECK_THREAD_SERIAL_NO(thread_serial_num);
                check_printf("#%d@%d: %s, sz=%d, thread_serial_num=%u\n",
                                nrecord, npos, label, size, thread_serial_num);
                break;
            CASE_TAG(HPROF_HEAP_DUMP)
                check_printf("#%d@%d: BEGIN: %s, sz=%d\n",
                                nrecord, npos, label, size);
                nheap_records = check_heap_tags(utab, p, size);
                check_printf("#%d@%d: END: %s, sz=%d, nheap_recs=%d\n",
                                nrecord, npos, label, size, nheap_records);
                p += size;
                break;
            CASE_TAG(HPROF_HEAP_DUMP_SEGMENT) /* 1.0.2 */
                check_printf("#%d@%d: BEGIN SEGMENT: %s, sz=%d\n",
                                nrecord, npos, label, size);
                nheap_records = check_heap_tags(utab, p, size);
                check_printf("#%d@%d: END SEGMENT: %s, sz=%d, nheap_recs=%d\n",
                                nrecord, npos, label, size, nheap_records);
                p += size;
                break;
            CASE_TAG(HPROF_HEAP_DUMP_END) /* 1.0.2 */
                check_printf("#%d@%d: SEGMENT END: %s, sz=%d\n",
                                nrecord, npos, label, size);
                break;
            CASE_TAG(HPROF_CPU_SAMPLES)
                CHECK_FOR_ERROR(size>=2*4);
                total_samples = read_u4(&p);
                trace_count = read_u4(&p);
                check_printf("#%d@%d: %s, sz=%d, total_samples=%d,"
                             " trace_count=%d\n",
                                nrecord, npos, label, size,
                                total_samples, trace_count);
                for(i=0; i< trace_count; i++) {
                    num_elements = read_u4(&p);
                    trace_serial_num = read_u4(&p);
                    CHECK_TRACE_SERIAL_NO(trace_serial_num);
                    check_printf("\t %d: samples=%d, trace_serial_num=%u\n",
                                 trace_serial_num, num_elements);
                }
                break;
            CASE_TAG(HPROF_CONTROL_SETTINGS)
                CHECK_FOR_ERROR(size==4+2);
                flags = read_u4(&p);
                depth = read_u2(&p);
                check_printf("#%d@%d: %s, sz=%d, flags=0x%x, depth=%d\n",
                                nrecord, npos, label, size, flags, depth);
                break;
            default:
                label = "UNKNOWN";
                check_printf("#%d@%d: %s, sz=%d\n",
                                nrecord, npos, label, size);
                HPROF_ERROR(JNI_TRUE, "unknown record type");
                p += size;
                break;
        }
        CHECK_FOR_ERROR(p<=(pstart+nbytes));
    }
    check_flush();
    CHECK_FOR_ERROR(p==(pstart+nbytes));
    table_cleanup(utab, &utab_cleanup, NULL);
    return nrecord;
}
예제 #15
0
/* Given the heap dump data and the utf8 map, check/write the heap dump. */
static int
check_heap_tags(struct LookupTable *utab, unsigned char *pstart, int nbytes)
{
    int                 nrecords;
    unsigned char      *p;
    unsigned char      *psave;
    struct LookupTable *ctab;
    CmapInfo            cmap;
    char               *label;
    unsigned            tag;
    HprofType           ty;
    HprofId             id, id2, fr, sup;
    int                 num_elements;
    int                 num_bytes;
    SerialNumber        trace_serial_num;
    SerialNumber        thread_serial_num;
    int                 npos;
    int                 i;
    int                 inst_size;

    ctab     = table_initialize("temp ctab", 64, 64, 512, sizeof(CmapInfo));

    /* First pass over heap records just fills in the CmapInfo table */
    nrecords = 0;
    p        = pstart;
    while ( p < (pstart+nbytes) ) {
        nrecords++;
        /*LINTED*/
        npos = (int)(p - pstart);
        tag  = read_u1(&p);
        switch ( tag ) {
            CASE_HEAP(HPROF_GC_ROOT_UNKNOWN)
                id = read_id(&p);
                break;
            CASE_HEAP(HPROF_GC_ROOT_JNI_GLOBAL)
                id  = read_id(&p);
                id2 = read_id(&p);
                break;
            CASE_HEAP(HPROF_GC_ROOT_JNI_LOCAL)
                id = read_id(&p);
                thread_serial_num = read_u4(&p);
                fr = read_u4(&p);
                break;
            CASE_HEAP(HPROF_GC_ROOT_JAVA_FRAME)
                id = read_id(&p);
                thread_serial_num = read_u4(&p);
                fr = read_u4(&p);
                break;
            CASE_HEAP(HPROF_GC_ROOT_NATIVE_STACK)
                id = read_id(&p);
                thread_serial_num = read_u4(&p);
                break;
            CASE_HEAP(HPROF_GC_ROOT_STICKY_CLASS)
                id = read_id(&p);
                break;
            CASE_HEAP(HPROF_GC_ROOT_THREAD_BLOCK)
                id = read_id(&p);
                thread_serial_num = read_u4(&p);
                break;
            CASE_HEAP(HPROF_GC_ROOT_MONITOR_USED)
                id = read_id(&p);
                break;
            CASE_HEAP(HPROF_GC_ROOT_THREAD_OBJ)
                id = read_id(&p);
                thread_serial_num = read_u4(&p);
                trace_serial_num = read_u4(&p);
                break;
            CASE_HEAP(HPROF_GC_CLASS_DUMP)
                (void)memset((void*)&cmap, 0, sizeof(cmap));
                id = read_id(&p);
                trace_serial_num = read_u4(&p);
                {
                    HprofId ld, si, pr, re1, re2;

                    sup      = read_id(&p);
                    ld       = read_id(&p);
                    si       = read_id(&p);
                    pr       = read_id(&p);
                    re1      = read_id(&p);
                    re2      = read_id(&p);
                    cmap.sup = sup;
                }
                inst_size = read_u4(&p);
                cmap.inst_size = inst_size;
                num_elements = read_u2(&p);
                for(i=0; i<num_elements; i++) {
                    (void)read_u2(&p);
                    ty = read_u1(&p);
                    (void)read_val(&p, ty);
                }
                num_elements = read_u2(&p);
                for(i=0; i<num_elements; i++) {
                    (void)read_id(&p);
                    ty = read_u1(&p);
                    (void)read_val(&p, ty);
                }
                num_elements = read_u2(&p);
                for(i=0; i<num_elements; i++) {
                    HprofType ty;
                    HprofId   id;

                    id = read_id(&p);
                    ty = read_u1(&p);
                    add_inst_field_to_cmap(&cmap, id, ty);
                }
                (void)table_create_entry(ctab, &id, sizeof(id), &cmap);
                break;
            CASE_HEAP(HPROF_GC_INSTANCE_DUMP)
                id = read_id(&p);
                trace_serial_num = read_u4(&p);
                id2 = read_id(&p); /* class id */
                num_bytes = read_u4(&p);
                p += num_bytes;
                break;
            CASE_HEAP(HPROF_GC_OBJ_ARRAY_DUMP)
                id = read_id(&p);
                trace_serial_num = read_u4(&p);
                num_elements = read_u4(&p);
                id2 = read_id(&p);
                p += num_elements*(int)sizeof(HprofId);
                break;
            CASE_HEAP(HPROF_GC_PRIM_ARRAY_DUMP)
                id = read_id(&p);
                trace_serial_num = read_u4(&p);
                num_elements = read_u4(&p);
                ty = read_u1(&p);
                p += type_size[ty]*num_elements;
                break;
            default:
                label = "UNKNOWN";
                check_printf("H#%d@%d %s: ERROR!\n",
                                nrecords, npos, label);
                HPROF_ERROR(JNI_TRUE, "unknown heap record type");
                break;
        }
    }
    CHECK_FOR_ERROR(p==pstart+nbytes);

    /* Scan again once we have our cmap */
    nrecords = 0;
    p        = pstart;
    while ( p < (pstart+nbytes) ) {
        nrecords++;
        /*LINTED*/
        npos = (int)(p - pstart);
        tag  = read_u1(&p);
        switch ( tag ) {
            CASE_HEAP(HPROF_GC_ROOT_UNKNOWN)
                id = read_id(&p);
                check_printf("H#%d@%d %s: id=0x%x\n",
                        nrecords, npos, label, id);
                break;
            CASE_HEAP(HPROF_GC_ROOT_JNI_GLOBAL)
                id = read_id(&p);
                id2 = read_id(&p);
                check_printf("H#%d@%d %s: id=0x%x, id2=0x%x\n",
                        nrecords, npos, label, id, id2);
                break;
            CASE_HEAP(HPROF_GC_ROOT_JNI_LOCAL)
                id = read_id(&p);
                thread_serial_num = read_u4(&p);
                fr = read_u4(&p);
                check_printf("H#%d@%d %s: id=0x%x, thread_serial_num=%u, fr=0x%x\n",
                        nrecords, npos, label, id, thread_serial_num, fr);
                break;
            CASE_HEAP(HPROF_GC_ROOT_JAVA_FRAME)
                id = read_id(&p);
                thread_serial_num = read_u4(&p);
                fr = read_u4(&p);
                check_printf("H#%d@%d %s: id=0x%x, thread_serial_num=%u, fr=0x%x\n",
                        nrecords, npos, label, id, thread_serial_num, fr);
                break;
            CASE_HEAP(HPROF_GC_ROOT_NATIVE_STACK)
                id = read_id(&p);
                thread_serial_num = read_u4(&p);
                check_printf("H#%d@%d %s: id=0x%x, thread_serial_num=%u\n",
                        nrecords, npos, label, id, thread_serial_num);
                break;
            CASE_HEAP(HPROF_GC_ROOT_STICKY_CLASS)
                id = read_id(&p);
                check_printf("H#%d@%d %s: id=0x%x\n",
                        nrecords, npos, label, id);
                break;
            CASE_HEAP(HPROF_GC_ROOT_THREAD_BLOCK)
                id = read_id(&p);
                thread_serial_num = read_u4(&p);
                check_printf("H#%d@%d %s: id=0x%x, thread_serial_num=%u\n",
                        nrecords, npos, label, id, thread_serial_num);
                break;
            CASE_HEAP(HPROF_GC_ROOT_MONITOR_USED)
                id = read_id(&p);
                check_printf("H#%d@%d %s: id=0x%x\n",
                        nrecords, npos, label, id);
                break;
            CASE_HEAP(HPROF_GC_ROOT_THREAD_OBJ)
                id = read_id(&p);
                thread_serial_num = read_u4(&p);
                trace_serial_num = read_u4(&p);
                CHECK_TRACE_SERIAL_NO(trace_serial_num);
                check_printf("H#%d@%d %s: id=0x%x, thread_serial_num=%u,"
                             " trace_serial_num=%u\n",
                        nrecords, npos, label, id, thread_serial_num,
                        trace_serial_num);
                break;
            CASE_HEAP(HPROF_GC_CLASS_DUMP)
                id = read_id(&p);
                trace_serial_num = read_u4(&p);
                CHECK_TRACE_SERIAL_NO(trace_serial_num);
                check_printf("H#%d@%d %s: id=0x%x, trace_serial_num=%u\n",
                        nrecords, npos, label, id, trace_serial_num);
                {
                    HprofId ld, si, pr, re1, re2;

                    sup = read_id(&p);
                    ld  = read_id(&p);
                    si  = read_id(&p);
                    pr  = read_id(&p);
                    re1 = read_id(&p);
                    re2 = read_id(&p);
                    check_printf("  su=0x%x, ld=0x%x, si=0x%x,"
                                 " pr=0x%x, re1=0x%x, re2=0x%x\n",
                        sup, ld, si, pr, re1, re2);
                }
                inst_size = read_u4(&p);
                check_printf("  instance_size=%d\n", inst_size);

                num_elements = read_u2(&p);
                for(i=0; i<num_elements; i++) {
                    HprofType ty;
                    unsigned  cpi;
                    jvalue    val;

                    cpi = read_u2(&p);
                    ty  = read_u1(&p);
                    val = read_val(&p, ty);
                    check_printf("  constant_pool %d: cpi=%d, ty=%d, val=",
                                i, cpi, ty);
                    check_printf_val(ty, val, 1);
                    check_printf("\n");
                }

                num_elements = read_u2(&p);
                check_printf("  static_field_count=%d\n", num_elements);
                for(i=0; i<num_elements; i++) {
                    HprofType ty;
                    HprofId   id;
                    jvalue    val;

                    id  = read_id(&p);
                    ty  = read_u1(&p);
                    val = read_val(&p, ty);
                    check_printf("  static field %d: ", i);
                    check_print_utf8(utab, "id=", id);
                    check_printf(", ty=%d, val=", ty);
                    check_printf_val(ty, val, 1);
                    check_printf("\n");
                }

                num_elements = read_u2(&p);
                check_printf("  instance_field_count=%d\n", num_elements);
                for(i=0; i<num_elements; i++) {
                    HprofType ty;
                    HprofId   id;

                    id = read_id(&p);
                    ty = read_u1(&p);
                    check_printf("  instance_field %d: ", i);
                    check_print_utf8(utab, "id=", id);
                    check_printf(", ty=%d\n", ty);
                }
                break;
            CASE_HEAP(HPROF_GC_INSTANCE_DUMP)
                id = read_id(&p);
                trace_serial_num = read_u4(&p);
                CHECK_TRACE_SERIAL_NO(trace_serial_num);
                id2 = read_id(&p); /* class id */
                num_bytes = read_u4(&p);
                check_printf("H#%d@%d %s: id=0x%x, trace_serial_num=%u,"
                             " cid=0x%x, nbytes=%d\n",
                            nrecords, npos, label, id, trace_serial_num,
                            id2, num_bytes);
                /* This is a packed set of bytes for the instance fields */
                if ( num_bytes > 0 ) {
                    TableIndex cindex;
                    int        ifield;
                    CmapInfo  *map;

                    cindex = table_find_entry(ctab, &id2, sizeof(id2));
                    HPROF_ASSERT(cindex!=0);
                    map = (CmapInfo*)table_get_info(ctab, cindex);
                    HPROF_ASSERT(map!=NULL);
                    HPROF_ASSERT(num_bytes==map->inst_size);

                    psave  = p;
                    ifield = 0;

                    do {
                        for(i=0;i<map->n_finfo;i++) {
                            HprofType ty;
                            HprofId   id;
                            jvalue    val;

                            ty = map->finfo[i].ty;
                            id = map->finfo[i].id;
                            HPROF_ASSERT(ty!=0);
                            HPROF_ASSERT(id!=0);
                            val = read_val(&p, ty);
                            check_printf("  field %d: ", ifield);
                            check_print_utf8(utab, "id=", id);
                            check_printf(", ty=%d, val=", ty);
                            check_printf_val(ty, val, 1);
                            check_printf("\n");
                            ifield++;
                        }
                        id2    = map->sup;
                        map    = NULL;
                        cindex = 0;
                        if ( id2 != 0 ) {
                            cindex = table_find_entry(ctab, &id2, sizeof(id2));
                            HPROF_ASSERT(cindex!=0);
                            map = (CmapInfo*)table_get_info(ctab, cindex);
                            HPROF_ASSERT(map!=NULL);
                        }
                    } while ( map != NULL );
                    HPROF_ASSERT(num_bytes==(p-psave));
                }
                break;
            CASE_HEAP(HPROF_GC_OBJ_ARRAY_DUMP)
                id = read_id(&p);
                trace_serial_num = read_u4(&p);
                CHECK_TRACE_SERIAL_NO(trace_serial_num);
                num_elements = read_u4(&p);
                id2 = read_id(&p);
                check_printf("H#%d@%d %s: id=0x%x, trace_serial_num=%u, nelems=%d, eid=0x%x\n",
                                nrecords, npos, label, id, trace_serial_num, num_elements, id2);
                for(i=0; i<num_elements; i++) {
                    HprofId id;

                    id = read_id(&p);
                    check_printf("  [%d]: id=0x%x\n", i, id);
                }
                break;
            CASE_HEAP(HPROF_GC_PRIM_ARRAY_DUMP)
                id = read_id(&p);
                trace_serial_num = read_u4(&p);
                CHECK_TRACE_SERIAL_NO(trace_serial_num);
                num_elements = read_u4(&p);
                ty = read_u1(&p);
                psave = p;
                check_printf("H#%d@%d %s: id=0x%x, trace_serial_num=%u, "
                             "nelems=%d, ty=%d\n",
                                nrecords, npos, label, id, trace_serial_num, num_elements, ty);
                HPROF_ASSERT(HPROF_TYPE_IS_PRIMITIVE(ty));
                if ( num_elements > 0 ) {
                    int   count;
                    int   long_form;
                    int   max_count;
                    char *quote;

                    quote     = "";
                    long_form = 1;
                    max_count = 8;
                    count     = 0;
                    switch ( ty ) {
                        case HPROF_CHAR:
                            long_form = 0;
                            max_count = 72;
                            quote     = "\"";
                            /*FALLTHRU*/
                        case HPROF_INT:
                        case HPROF_DOUBLE:
                        case HPROF_LONG:
                        case HPROF_BYTE:
                        case HPROF_BOOLEAN:
                        case HPROF_SHORT:
                        case HPROF_FLOAT:
                            check_printf("  val=%s", quote);
                            for(i=0; i<num_elements; i++) {
                                jvalue val;

                                if ( i > 0 && count == 0 ) {
                                    check_printf("  %s", quote);
                                }
                                val = read_val(&p, ty);
                                check_printf_val(ty, val, long_form);
                                count += 1;
                                if ( count >= max_count ) {
                                    check_printf("\"\n");
                                    count = 0;
                                }
                            }
                            if ( count != 0 ) {
                                check_printf("%s\n", quote);
                            }
                            break;
                    }
                }
                HPROF_ASSERT(type_size[ty]*num_elements==(p-psave));
                break;
            default:
                label = "UNKNOWN";
                check_printf("H#%d@%d %s: ERROR!\n",
                                nrecords, npos, label);
                HPROF_ERROR(JNI_TRUE, "unknown heap record type");
                break;
        }
    }
    CHECK_FOR_ERROR(p==pstart+nbytes);

    table_cleanup(ctab, &cmap_cleanup, NULL);

    return nrecords;
}
예제 #16
0
void java_bytecode_parsert::rcode_attribute(methodt &method)
{
  u2 attribute_name_index=read_u2();
  u4 attribute_length=read_u4();

  irep_idt attribute_name=pool_entry(attribute_name_index).s;

  if(attribute_name=="LineNumberTable")
  {
    // address -> instructiont
    typedef std::map<unsigned,
                     methodt::instructionst::iterator> instruction_mapt;
    instruction_mapt instruction_map;

    for(methodt::instructionst::iterator
        it=method.instructions.begin();
        it!=method.instructions.end();
        it++)
    {
      instruction_map[it->address]=it;
    }

    u2 line_number_table_length=read_u2();

    for(std::size_t i=0; i<line_number_table_length; i++)
    {
      u2 start_pc=read_u2();
      u2 line_number=read_u2();

      // annotate the bytecode program
      instruction_mapt::const_iterator it=
        instruction_map.find(start_pc);

      if(it!=instruction_map.end())
        it->second->source_location.set_line(line_number);
    }
  }
  else if(attribute_name=="LocalVariableTable")
  {
    u2 local_variable_table_length=read_u2();

    method.local_variable_table.resize(local_variable_table_length);

    for(std::size_t i=0; i<local_variable_table_length; i++)
    {
      u2 start_pc=read_u2();
      u2 length=read_u2();
      u2 name_index=read_u2();
      u2 descriptor_index=read_u2();
      u2 index=read_u2();

      method.local_variable_table[i].index=index;
      method.local_variable_table[i].name=pool_entry(name_index).s;
      method.local_variable_table[i].signature=
        id2string(pool_entry(descriptor_index).s);
      method.local_variable_table[i].start_pc=start_pc;
      method.local_variable_table[i].length=length;
    }
  }
  else if(attribute_name=="StackMapTable")
  {
    u2 stack_map_entries=read_u2();

    method.stack_map_table.resize(stack_map_entries);

    for(size_t i=0; i<stack_map_entries; i++)
    {
      u1 frame_type=read_u1();
      if(0<=frame_type && frame_type<=63)
      {
        method.stack_map_table[i].type=methodt::stack_map_table_entryt::SAME;
        method.stack_map_table[i].locals.resize(0);
        method.stack_map_table[i].stack.resize(0);
      }
      else if(64<=frame_type && frame_type<=127)
      {
        method.stack_map_table[i].type=
          methodt::stack_map_table_entryt::SAME_LOCALS_ONE_STACK;
        method.stack_map_table[i].locals.resize(0);
        method.stack_map_table[i].stack.resize(1);
        methodt::verification_type_infot verification_type_info;
        read_verification_type_info(verification_type_info);
        method.stack_map_table[i].stack[0]=verification_type_info;
      }
      else if(frame_type==247)
      {
        method.stack_map_table[i].type=
          methodt::stack_map_table_entryt::SAME_LOCALS_ONE_STACK_EXTENDED;
        method.stack_map_table[i].locals.resize(0);
        method.stack_map_table[i].stack.resize(1);
        methodt::verification_type_infot verification_type_info;
        u2 offset_delta=read_u2();
        read_verification_type_info(verification_type_info);
        method.stack_map_table[i].stack[0]=verification_type_info;
        method.stack_map_table[i].offset_delta=offset_delta;
      }
      else if(248<=frame_type && frame_type<=250)
      {
        method.stack_map_table[i].type=methodt::stack_map_table_entryt::CHOP;
        method.stack_map_table[i].locals.resize(0);
        method.stack_map_table[i].stack.resize(0);
        u2 offset_delta=read_u2();
        method.stack_map_table[i].offset_delta=offset_delta;
      }
      else if(frame_type==251)
      {
        method.stack_map_table[i].type
          =methodt::stack_map_table_entryt::SAME_EXTENDED;
        method.stack_map_table[i].locals.resize(0);
        method.stack_map_table[i].stack.resize(0);
        u2 offset_delta=read_u2();
        method.stack_map_table[i].offset_delta=offset_delta;
      }
      else if(252<=frame_type && frame_type<=254)
      {
        size_t new_locals=(size_t) (frame_type-251);
        method.stack_map_table[i].type=methodt::stack_map_table_entryt::APPEND;
        method.stack_map_table[i].locals.resize(new_locals);
        method.stack_map_table[i].stack.resize(0);
        u2 offset_delta=read_u2();
        method.stack_map_table[i].offset_delta=offset_delta;
        for(size_t k=0; k<new_locals; k++)
        {
          method.stack_map_table[i].locals
            .push_back(methodt::verification_type_infot());
          methodt::verification_type_infot &v=
            method.stack_map_table[i].locals.back();
          read_verification_type_info(v);
        }
      }
      else if(frame_type==255)
      {
        method.stack_map_table[i].type=methodt::stack_map_table_entryt::FULL;
        u2 offset_delta=read_u2();
        method.stack_map_table[i].offset_delta=offset_delta;
        u2 number_locals=read_u2();
        method.stack_map_table[i].locals.resize(number_locals);
        for(size_t k=0; k<(size_t) number_locals; k++)
        {
          method.stack_map_table[i].locals
            .push_back(methodt::verification_type_infot());
          methodt::verification_type_infot &v=
            method.stack_map_table[i].locals.back();
          read_verification_type_info(v);
        }
        u2 number_stack_items=read_u2();
        method.stack_map_table[i].stack.resize(number_stack_items);
        for(size_t k=0; k<(size_t) number_stack_items; k++)
        {
          method.stack_map_table[i].stack
            .push_back(methodt::verification_type_infot());
          methodt::verification_type_infot &v=
            method.stack_map_table[i].stack.back();
          read_verification_type_info(v);
        }
      }
      else
        throw "error: unknown stack frame type encountered";
    }
  }
  else
    skip_bytes(attribute_length);
}
예제 #17
0
void java_bytecode_parsert::rmethod_attribute(methodt &method)
{
  u2 attribute_name_index=read_u2();
  u4 attribute_length=read_u4();

  irep_idt attribute_name=pool_entry(attribute_name_index).s;

  if(attribute_name=="Code")
  {
    u2 UNUSED max_stack=read_u2();
    u2 UNUSED max_locals=read_u2();

    rbytecode(method.instructions);

    u2 exception_table_length=read_u2();
    method.exception_table.resize(exception_table_length);

    for(std::size_t e=0; e<exception_table_length; e++)
    {
      u2 start_pc=read_u2();
      u2 end_pc=read_u2();
      u2 handler_pc=read_u2();
      u2 catch_type=read_u2();
      method.exception_table[e].start_pc=start_pc;
      method.exception_table[e].end_pc=end_pc;
      method.exception_table[e].handler_pc=handler_pc;
      if(catch_type!=0)
        method.exception_table[e].catch_type=
          to_symbol_type(pool_entry(catch_type).expr.type());
    }

    u2 attributes_count=read_u2();

    for(std::size_t j=0; j<attributes_count; j++)
      rcode_attribute(method);

    irep_idt line_number;

    // add missing line numbers
    for(methodt::instructionst::iterator
        it=method.instructions.begin();
        it!=method.instructions.end();
        it++)
    {
      if(!it->source_location.get_line().empty())
        line_number=it->source_location.get_line();
      else if(!line_number.empty())
        it->source_location.set_line(line_number);
      it->source_location
        .set_function(
          "java::"+id2string(parse_tree.parsed_class.name)+"."+
          id2string(method.name)+":"+method.signature);
    }

    // line number of method
    if(!method.instructions.empty())
      method.source_location.set_line(
        method.instructions.begin()->source_location.get_line());
  }
  else if(attribute_name=="RuntimeInvisibleAnnotations" ||
          attribute_name=="RuntimeVisibleAnnotations")
  {
    rRuntimeAnnotation_attribute(method.annotations);
  }
  else
    skip_bytes(attribute_length);
}
예제 #18
0
void java_bytecode_parsert::rbytecode(
  methodt::instructionst &instructions)
{
  u4 code_length=read_u4();

  u4 address;
  size_t bytecode_index=0; // index of bytecode instruction

  for(address=0; address<code_length; address++)
  {
    bool wide_instruction=false;
    u4 start_of_instruction=address;

    u1 bytecode=read_u1();

    if(bytecode==0xc4) // wide
    {
      wide_instruction=true;
      address++;
      bytecode=read_u1();
    }

    instructions.push_back(instructiont());
    instructiont &instruction=instructions.back();
    instruction.statement=bytecodes[bytecode].mnemonic;
    instruction.address=start_of_instruction;
    instruction.source_location
      .set_java_bytecode_index(std::to_string(bytecode_index));

    switch(bytecodes[bytecode].format)
    {
    case ' ': // no further bytes
      break;

    case 'c': // a constant_pool index (one byte)
      if(wide_instruction)
      {
        instruction.args.push_back(constant(read_u2()));
        address+=2;
      }
      else
      {
        instruction.args.push_back(constant(read_u1()));
        address+=1;
      }
      break;

    case 'C': // a constant_pool index (two bytes)
      instruction.args.push_back(constant(read_u2()));
      address+=2;
      break;

    case 'b': // a signed byte
      {
        s1 c=read_u1();
        instruction.args.push_back(from_integer(c, integer_typet()));
      }
      address+=1;

      break;

    case 'o': // two byte branch offset, signed
      {
        s2 offset=read_u2();
        instruction
          .args.push_back(from_integer(address+offset, integer_typet()));
      }
      address+=2;
      break;

    case 'O': // four byte branch offset, signed
      {
        s4 offset=read_u4();
        instruction
          .args.push_back(from_integer(address+offset, integer_typet()));
      }
      address+=4;
      break;

    case 'v': // local variable index (one byte)
      {
        u1 v=read_u1();
        instruction.args.push_back(from_integer(v, integer_typet()));
      }
      address+=1;
      break;

    case 'V':
      // local variable index (two bytes) plus two signed bytes
      if(wide_instruction)
      {
        u2 v=read_u2();
        instruction.args.push_back(from_integer(v, integer_typet()));
        s2 c=read_u2();
        instruction.args.push_back(from_integer(c, integer_typet()));
        address+=4;
      }
      else // local variable index (one byte) plus one signed byte
      {
        u1 v=read_u1();
        instruction.args.push_back(from_integer(v, integer_typet()));
        s1 c=read_u1();
        instruction.args.push_back(from_integer(c, integer_typet()));
        address+=2;
      }
      break;

    case 'I': // two byte constant_pool index plus two bytes
      {
        u2 c=read_u2();
        instruction.args.push_back(constant(c));
        u1 b1=read_u1();
        instruction.args.push_back(from_integer(b1, integer_typet()));
        u1 b2=read_u1();
        instruction.args.push_back(from_integer(b2, integer_typet()));
      }
      address+=4;
      break;

    case 'L': // lookupswitch
      {
        u4 base_offset=address;

        // first a pad to 32-bit align
        while(((address+1)&3)!=0) { read_u1(); address++; }

        // now default value
        s4 default_value=read_u4();
        instruction.args
          .push_back(from_integer(base_offset+default_value, integer_typet()));
        address+=4;

        // number of pairs
        u4 npairs=read_u4();
        address+=4;

        for(std::size_t i=0; i<npairs; i++)
        {
          s4 match=read_u4();
          s4 offset=read_u4();
          instruction.args.push_back(from_integer(match, integer_typet()));
          instruction.args
            .push_back(from_integer(base_offset+offset, integer_typet()));
          address+=8;
        }
      }
      break;

    case 'T': // tableswitch
      {
        size_t base_offset=address;

        // first a pad to 32-bit align
        while(((address+1)&3)!=0) { read_u1(); address++; }

        // now default value
        s4 default_value=read_u4();
        instruction.args
          .push_back(from_integer(base_offset+default_value, integer_typet()));
        address+=4;

        // now low value
        s4 low_value=read_u4();
        address+=4;

        // now high value
        s4 high_value=read_u4();
        address+=4;

        // there are high-low+1 offsets, and they are signed
        for(s4 i=low_value; i<=high_value; i++)
        {
          s4 offset=read_u4();
          instruction.args.push_back(from_integer(i, integer_typet()));
          instruction.args
            .push_back(from_integer(base_offset+offset, integer_typet()));
          address+=4;
        }
      }
      break;

    case 'm': // multianewarray: constant-pool index plus one unsigned byte
      {
        u2 c=read_u2(); // constant-pool index
        instruction.args.push_back(constant(c));
        u1 dimensions=read_u1(); // number of dimensions
        instruction.args.push_back(from_integer(dimensions, integer_typet()));
        address+=3;
      }
      break;

    case 't': // array subtype, one byte
      {
        typet t;
        switch(read_u1())
        {
        case T_BOOLEAN: t.id(ID_bool); break;
        case T_CHAR: t.id(ID_char); break;
        case T_FLOAT: t.id(ID_float); break;
        case T_DOUBLE: t.id(ID_double); break;
        case T_BYTE: t.id(ID_byte); break;
        case T_SHORT: t.id(ID_short); break;
        case T_INT: t.id(ID_int); break;
        case T_LONG: t.id(ID_long); break;
        default:{};
        }
        instruction.args.push_back(type_exprt(t));
      }
      address+=1;
      break;

    case 's': // a signed short
      {
        s2 s=read_u2();
        instruction.args.push_back(from_integer(s, integer_typet()));
      }
      address+=2;
      break;

    default:
      throw "unknown JVM bytecode instruction";
    }
    bytecode_index++;
  }

  if(address!=code_length)
  {
    error() << "bytecode length mismatch" << eom;
    throw 0;
  }
}
예제 #19
0
void java_bytecode_parsert::rconstant_pool()
{
  u2 constant_pool_count=read_u2();
  if(constant_pool_count==0)
  {
    error() << "invalid constant_pool_count" << eom;
    throw 0;
  }

  constant_pool.resize(constant_pool_count);

  for(constant_poolt::iterator
      it=constant_pool.begin();
      it!=constant_pool.end();
      it++)
  {
    // the first entry isn't used
    if(it==constant_pool.begin())
      continue;

    it->tag=read_u1();

    switch(it->tag)
    {
    case CONSTANT_Class:
      it->ref1=read_u2();
      break;

    case CONSTANT_Fieldref:
    case CONSTANT_Methodref:
    case CONSTANT_InterfaceMethodref:
    case CONSTANT_NameAndType:
    case CONSTANT_InvokeDynamic:
      it->ref1=read_u2();
      it->ref2=read_u2();
      break;

    case CONSTANT_String:
    case CONSTANT_MethodType:
      it->ref1=read_u2();
      break;

    case CONSTANT_Integer:
    case CONSTANT_Float:
      it->number=read_u4();
      break;

    case CONSTANT_Long:
    case CONSTANT_Double:
      it->number=read_u8();
      // Eight-byte constants take up two entires
      // in the constant_pool table, for annoying this programmer.
      if(it==constant_pool.end())
      {
        error() << "invalid double entry" << eom;
        throw 0;
      }
      it++;
      it->tag=0;
      break;

    case CONSTANT_Utf8:
      {
        u2 bytes=read_u2();
        std::string s;
        s.resize(bytes);
        for(std::string::iterator s_it=s.begin(); s_it!=s.end(); s_it++)
          *s_it=read_u1();
        it->s=s; // hashes
      }
      break;

    case CONSTANT_MethodHandle:
      it->ref1=read_u1();
      it->ref2=read_u2();
      break;

    default:
      error() << "unknown constant pool entry (" << it->tag << ")"
              << eom;
      throw 0;
    }
  }

  // we do a bit of post-processing after we have them all
  for(constant_poolt::iterator
      it=constant_pool.begin();
      it!=constant_pool.end();
      it++)
  {
    // the first entry isn't used
    if(it==constant_pool.begin())
      continue;

    switch(it->tag)
    {
    case CONSTANT_Class:
      {
        const std::string &s=id2string(pool_entry(it->ref1).s);
        it->expr=type_exprt(java_classname(s));
      }
      break;

    case CONSTANT_Fieldref:
      {
        const pool_entryt &nameandtype_entry=pool_entry(it->ref2);
        const pool_entryt &name_entry=pool_entry(nameandtype_entry.ref1);
        const pool_entryt &class_entry=pool_entry(it->ref1);
        const pool_entryt &class_name_entry=pool_entry(class_entry.ref1);
        typet type=type_entry(nameandtype_entry.ref2);

        symbol_typet class_symbol=
          java_classname(id2string(class_name_entry.s));

        exprt fieldref("fieldref", type);
        fieldref.set(ID_class, class_symbol.get_identifier());
        fieldref.set(ID_component_name, name_entry.s);

        it->expr=fieldref;
      }
      break;

    case CONSTANT_Methodref:
    case CONSTANT_InterfaceMethodref:
      {
        const pool_entryt &nameandtype_entry=pool_entry(it->ref2);
        const pool_entryt &name_entry=pool_entry(nameandtype_entry.ref1);
        const pool_entryt &class_entry=pool_entry(it->ref1);
        const pool_entryt &class_name_entry=pool_entry(class_entry.ref1);
        typet type=type_entry(nameandtype_entry.ref2);

        symbol_typet class_symbol=
          java_classname(id2string(class_name_entry.s));

        irep_idt component_name=
          id2string(name_entry.s)+
          ":"+id2string(pool_entry(nameandtype_entry.ref2).s);

        irep_idt class_name=
          class_symbol.get_identifier();

        irep_idt identifier=
          id2string(class_name)+"."+id2string(component_name);

        exprt virtual_function(ID_virtual_function, type);
        virtual_function.set(ID_component_name, component_name);
        virtual_function.set(ID_C_class, class_name);
        virtual_function.set(ID_C_base_name, name_entry.s);
        virtual_function.set(ID_identifier, identifier);

        it->expr=virtual_function;
      }
      break;

    case CONSTANT_String:
      {
        // ldc turns these into references to java.lang.String
        exprt string_literal(ID_java_string_literal);
        string_literal.set(ID_value, pool_entry(it->ref1).s);
        it->expr=string_literal;
      }
      break;

    case CONSTANT_Integer:
      it->expr=from_integer(it->number, java_int_type());
      break;

    case CONSTANT_Float:
      {
        ieee_floatt value(ieee_float_spect::single_precision());
        value.unpack(it->number);
        it->expr=value.to_expr();
      }
      break;

    case CONSTANT_Long:
      it->expr=from_integer(it->number, java_long_type());
      break;

    case CONSTANT_Double:
      {
        ieee_floatt value(ieee_float_spect::double_precision());
        value.unpack(it->number);
        it->expr=value.to_expr();
      }
      break;

    case CONSTANT_NameAndType:
      {
        it->expr.id("nameandtype");
      }
      break;

    case CONSTANT_MethodHandle:
      {
        it->expr.id("methodhandle");
      }
      break;

    case CONSTANT_MethodType:
      {
        it->expr.id("methodtype");
      }
      break;

    case CONSTANT_InvokeDynamic:
      {
        it->expr.id("invokedynamic");
        const pool_entryt &nameandtype_entry=pool_entry(it->ref2);
        typet type=type_entry(nameandtype_entry.ref2);
        it->expr.type()=type;
      }
      break;

    default:{};
    }
  }
}