88 error() <<
"invalid constant pool index (" << index <<
")" <<
eom;
118 bytecodes[p->opcode].mnemonic=p->mnemonic;
154 for(std::size_t i=0; i<bytes; i++)
158 error() <<
"unexpected end of bytecode file" <<
eom;
168 for(
size_t i=0; i<bytes; i++)
172 error() <<
"unexpected end of bytecode file" <<
eom;
203 size_t bootstrap_method_index,
207 #define CONSTANT_Class 7
208 #define CONSTANT_Fieldref 9
209 #define CONSTANT_Methodref 10
210 #define CONSTANT_InterfaceMethodref 11
211 #define CONSTANT_String 8
212 #define CONSTANT_Integer 3
213 #define CONSTANT_Float 4
214 #define CONSTANT_Long 5
215 #define CONSTANT_Double 6
216 #define CONSTANT_NameAndType 12
217 #define CONSTANT_Utf8 1
218 #define CONSTANT_MethodHandle 15
219 #define CONSTANT_MethodType 16
220 #define CONSTANT_InvokeDynamic 18
222 #define VTYPE_INFO_TOP 0
223 #define VTYPE_INFO_INTEGER 1
224 #define VTYPE_INFO_FLOAT 2
225 #define VTYPE_INFO_LONG 3
226 #define VTYPE_INFO_DOUBLE 4
227 #define VTYPE_INFO_ITEM_NULL 5
228 #define VTYPE_INFO_UNINIT_THIS 6
229 #define VTYPE_INFO_OBJECT 7
230 #define VTYPE_INFO_UNINIT 8
339 "name_and_typeindex did not correspond to a name_and_type in the "
437 catch(
const char *message)
443 catch(
const std::string &message)
458 #define ACC_PUBLIC 0x0001
459 #define ACC_PRIVATE 0x0002
460 #define ACC_PROTECTED 0x0004
461 #define ACC_STATIC 0x0008
462 #define ACC_FINAL 0x0010
463 #define ACC_SYNCHRONIZED 0x0020
464 #define ACC_BRIDGE 0x0040
465 #define ACC_NATIVE 0x0100
466 #define ACC_INTERFACE 0x0200
467 #define ACC_ABSTRACT 0x0400
468 #define ACC_STRICT 0x0800
469 #define ACC_SYNTHETIC 0x1000
470 #define ACC_ANNOTATION 0x2000
471 #define ACC_ENUM 0x4000
473 #define UNUSED_u2(x) { const u2 x = read_u2(); (void)x; } (void)0
483 if(magic!=0xCAFEBABE)
491 error() <<
"unexpected major version" <<
eom;
530 for(std::size_t j=0; j<attributes_count; j++)
566 if(field.signature.has_value())
587 for(
const auto ¶meter_annotations : method.parameter_annotations)
590 if(method.signature.has_value())
603 for(
const auto &var : method.local_variable_table)
606 if(var.signature.has_value())
624 if(src.
id()==ID_code)
632 else if(src.
id() == ID_struct_tag)
637 const typet &element_type =
638 static_cast<const typet &
>(src.
find(ID_element_type));
644 else if(src.
id()==ID_struct)
650 else if(src.
id()==ID_pointer)
659 for(
const auto &annotation : annotations)
662 for(
const auto &element_value_pair : annotation.element_value_pairs)
672 if(
const auto &symbol_expr = expr_try_dynamic_cast<symbol_exprt>(value))
674 const irep_idt &value_id = symbol_expr->get_identifier();
678 else if(
const auto &array_expr = expr_try_dynamic_cast<array_exprt>(value))
692 if(constant_pool_count==0)
694 error() <<
"invalid constant_pool_count" <<
eom;
700 for(constant_poolt::iterator
743 error() <<
"invalid double entry" <<
eom;
755 for(std::string::iterator s_it=s.begin(); s_it!=s.end(); s_it++)
767 error() <<
"unknown constant pool entry (" << it->tag <<
")"
774 for(constant_poolt::iterator
802 fieldref_exprt fieldref(type, name_entry.
s, class_tag.get_identifier());
823 irep_idt class_name = class_tag.get_identifier();
828 exprt virtual_function(ID_virtual_function, type);
829 virtual_function.
set(ID_component_name, component_name);
830 virtual_function.
set(ID_C_class, class_name);
831 virtual_function.
set(ID_C_base_name, name_entry.
s);
832 virtual_function.
set(ID_identifier, identifier);
834 it->expr=virtual_function;
841 exprt string_literal(ID_java_string_literal);
843 it->expr=string_literal;
873 it->expr.id(
"nameandtype");
879 it->expr.id(
"methodhandle");
885 it->expr.id(
"methodtype");
891 it->expr.id(
"invokedynamic");
894 type.
set(ID_java_lambda_method_handle_index, it->ref1);
895 it->expr.type()=type;
908 for(std::size_t i=0; i<interfaces_count; i++)
917 for(std::size_t i=0; i<fields_count; i++)
935 const auto flags = (field.
is_public ? 1 : 0) +
938 DATA_INVARIANT(flags<=1,
"at most one of public, protected, private");
940 for(std::size_t j=0; j<attributes_count; j++)
958 bytecodes.size() == 256,
"bytecode mnemonics should have been populated");
963 size_t bytecode_index=0;
965 for(address=0; address<code_length; address++)
967 bool wide_instruction=
false;
968 u4 start_of_instruction=address;
974 wide_instruction=
true;
982 "Unexpected wide instruction: " +
989 instruction.
address=start_of_instruction;
1029 instruction.
args.push_back(
1040 instruction.
args.push_back(
1048 if(wide_instruction)
1066 if(wide_instruction)
1098 u4 base_offset=address;
1101 while(((address+1)&3)!=0) {
read_u1(); address++; }
1107 instruction.
args.push_back(
1115 for(std::size_t i=0; i<npairs; i++)
1119 instruction.
args.push_back(
1123 instruction.
args.push_back(
1132 size_t base_offset=address;
1135 while(((address+1)&3)!=0) {
read_u1(); address++; }
1139 instruction.
args.push_back(
1152 for(
s4 i=low_value; i<=high_value; i++)
1158 instruction.
args.push_back(
1170 instruction.
args.push_back(
1187 case T_INT: t.
id(ID_int);
break;
1205 throw "unknown JVM bytecode instruction";
1210 if(address!=code_length)
1212 error() <<
"bytecode length mismatch" <<
eom;
1234 for(std::size_t e=0; e<exception_table_length; e++)
1242 "The start_pc must be less than the end_pc as this is the range the "
1243 "exception is active");
1257 for(std::size_t j=0; j<attributes_count; j++)
1263 for(methodt::instructionst::iterator
1268 if(!it->source_location.get_line().empty())
1269 line_number=it->source_location.get_line();
1270 else if(!line_number.
empty())
1271 it->source_location.set_line(line_number);
1281 method.
instructions.begin()->source_location.get_line());
1283 else if(attribute_name==
"Signature")
1288 else if(attribute_name==
"RuntimeInvisibleAnnotations" ||
1289 attribute_name==
"RuntimeVisibleAnnotations")
1294 attribute_name ==
"RuntimeInvisibleParameterAnnotations" ||
1295 attribute_name ==
"RuntimeVisibleParameterAnnotations")
1305 for(
u2 param_no = 0; param_no < parameter_count; ++param_no)
1308 else if(attribute_name ==
"Exceptions")
1323 if(attribute_name==
"Signature")
1328 else if(attribute_name==
"RuntimeInvisibleAnnotations" ||
1329 attribute_name==
"RuntimeVisibleAnnotations")
1344 if(attribute_name==
"LineNumberTable")
1347 typedef std::map<unsigned,
1348 methodt::instructionst::iterator> instruction_mapt;
1349 instruction_mapt instruction_map;
1351 for(methodt::instructionst::iterator
1356 instruction_map[it->address]=it;
1361 for(std::size_t i=0; i<line_number_table_length; i++)
1367 instruction_mapt::const_iterator it=
1368 instruction_map.find(start_pc);
1370 if(it!=instruction_map.end())
1371 it->second->source_location.set_line(line_number);
1374 else if(attribute_name==
"LocalVariableTable")
1376 u2 local_variable_table_length=
read_u2();
1380 for(std::size_t i=0; i<local_variable_table_length; i++)
1396 else if(attribute_name==
"LocalVariableTypeTable")
1400 else if(attribute_name==
"StackMapTable")
1406 for(
size_t i=0; i<stack_map_entries; i++)
1415 else if(64<=frame_type && frame_type<=127)
1425 else if(frame_type==247)
1437 else if(248<=frame_type && frame_type<=250)
1445 else if(frame_type==251)
1454 else if(252<=frame_type && frame_type<=254)
1456 size_t new_locals=(size_t) (frame_type-251);
1462 for(
size_t k=0; k<new_locals; k++)
1471 else if(frame_type==255)
1478 for(
size_t k=0; k<(size_t) number_locals; k++)
1488 for(
size_t k=0; k<(size_t) number_stack_items; k++)
1498 throw "error: unknown stack frame type encountered";
1541 throw "error: unknown verification type info encountered";
1550 for(
u2 number=0; number<num_annotations; number++)
1554 annotations.push_back(annotation);
1570 element_value_pairs.resize(num_element_value_pairs);
1572 for(
auto &element_value_pair : element_value_pairs)
1575 element_value_pair.element_name=
pool_entry(element_name_index).
s;
1619 for(std::size_t i=0; i<num_values; i++)
1623 return std::move(values);
1635 return constant(const_value_index);
1653 const u4 &attribute_length)
1655 std::string name = parsed_class.
name.
c_str();
1657 u4 number_of_bytes_to_be_read = number_of_classes * 8 + 2;
1659 number_of_bytes_to_be_read == attribute_length,
1660 "The number of bytes to be read for the InnerClasses attribute does not "
1661 "match the attribute length.");
1663 const auto pool_entry_lambda = [
this](
u2 index) ->
pool_entryt & {
1666 const auto remove_separator_char = [](std::string str,
char ch) {
1667 str.erase(std::remove(str.begin(), str.end(), ch), str.end());
1671 for(
int i = 0; i < number_of_classes; i++)
1676 u2 inner_class_access_flags =
read_u2();
1678 std::string inner_class_info_name =
1681 bool is_private = (inner_class_access_flags &
ACC_PRIVATE) != 0;
1682 bool is_public = (inner_class_access_flags &
ACC_PUBLIC) != 0;
1683 bool is_protected = (inner_class_access_flags &
ACC_PROTECTED) != 0;
1684 bool is_static = (inner_class_access_flags &
ACC_STATIC) != 0;
1689 bool is_inner_class = remove_separator_char(
id2string(parsed_class.
name),
'.') ==
1690 remove_separator_char(inner_class_info_name,
'/');
1697 if(inner_name_index == 0)
1701 if(outer_class_info_index == 0)
1709 std::string outer_class_info_name =
1730 std::vector<irep_idt> exceptions;
1731 for(
size_t i = 0; i < number_of_exceptions; i++)
1736 exceptions.push_back(exception_name);
1748 if(attribute_name==
"SourceFile")
1754 size_t last_index=fqn.find_last_of(
".");
1755 if(last_index==std::string::npos)
1759 std::string package_name=fqn.substr(0, last_index+1);
1760 std::replace(package_name.begin(), package_name.end(),
'.',
'/');
1761 const std::string &full_file_name=
1763 sourcefile_name=full_file_name;
1766 for(methodst::iterator m_it=parsed_class.
methods.begin();
1767 m_it!=parsed_class.
methods.end();
1770 m_it->source_location.set_file(sourcefile_name);
1771 for(instructionst::iterator i_it=m_it->instructions.begin();
1772 i_it!=m_it->instructions.end();
1775 if(!i_it->source_location.get_line().empty())
1776 i_it->source_location.set_file(sourcefile_name);
1780 else if(attribute_name==
"Signature")
1788 else if(attribute_name==
"RuntimeInvisibleAnnotations" ||
1789 attribute_name==
"RuntimeVisibleAnnotations")
1793 else if(attribute_name ==
"BootstrapMethods")
1799 "only one BootstrapMethods argument is allowed in a class file");
1805 else if(attribute_name ==
"InnerClasses")
1808 parsed_class, attribute_length);
1818 for(std::size_t j=0; j<methods_count; j++)
1822 #define ACC_PUBLIC 0x0001
1823 #define ACC_PRIVATE 0x0002
1824 #define ACC_PROTECTED 0x0004
1825 #define ACC_STATIC 0x0008
1826 #define ACC_FINAL 0x0010
1827 #define ACC_VARARGS 0x0080
1828 #define ACC_SUPER 0x0020
1829 #define ACC_VOLATILE 0x0040
1830 #define ACC_TRANSIENT 0x0080
1831 #define ACC_INTERFACE 0x0200
1832 #define ACC_ABSTRACT 0x0400
1833 #define ACC_SYNTHETIC 0x1000
1834 #define ACC_ANNOTATION 0x2000
1835 #define ACC_ENUM 0x4000
1859 const auto flags = (method.
is_public ? 1 : 0) +
1862 DATA_INVARIANT(flags<=1,
"at most one of public, protected, private");
1865 for(std::size_t j=0; j<attributes_count; j++)
1871 std::istream &istream,
1873 bool skip_instructions)
1876 java_bytecode_parser.
in=&istream;
1879 bool parser_result=java_bytecode_parser.
parse();
1886 return std::move(java_bytecode_parser.
parse_tree);
1891 const std::string &
file,
1893 bool skip_instructions)
1900 message.
error() <<
"failed to open input file `"
1913 u2 local_variable_type_table_length=
read_u2();
1917 "Local variable type table cannot have more elements "
1918 "than the local variable table.");
1919 for(std::size_t i=0; i<local_variable_type_table_length; i++)
1931 if(lvar.index==index &&
1933 lvar.start_pc==start_pc &&
1934 lvar.length==length)
1943 "Entry in LocalVariableTypeTable must be present in LVT");
1964 std::string class_name = class_entry.
get_name(pool_entry_lambda);
1966 std::replace(class_name.begin(), class_name.end(),
'.',
'$');
1968 std::replace(class_name.begin(), class_name.end(),
'/',
'.');
1969 const std::string method_ref =
1970 class_name +
"." + name_and_type.
get_name(pool_entry_lambda) +
':' +
1982 name_and_type.
get_name(pool_entry_lambda);
1987 return lambda_method_handle;
1999 for(
size_t bootstrap_method_index = 0;
2000 bootstrap_method_index < num_bootstrap_methods;
2001 ++bootstrap_method_index)
2003 u2 bootstrap_methodhandle_ref =
read_u2();
2009 debug() <<
"INFO: parse BootstrapMethod handle " << num_bootstrap_arguments
2013 u2_valuest u2_values(num_bootstrap_arguments);
2014 for(
size_t i = 0; i < num_bootstrap_arguments; i++)
2047 if(num_bootstrap_arguments < 3)
2050 parsed_class, bootstrap_method_index, std::move(u2_values));
2052 <<
"format of BootstrapMethods entry not recognized: too few arguments"
2057 u2 interface_type_index = u2_values[0];
2058 u2 method_handle_index = u2_values[1];
2059 u2 method_type_index = u2_values[2];
2065 bool recognized =
true;
2066 for(
size_t i = 3; i < num_bootstrap_arguments; i++)
2068 u2 skipped_argument = u2_values[i];
2074 debug() <<
"format of BootstrapMethods entry not recognized: extra "
2075 "arguments of wrong type"
2078 parsed_class, bootstrap_method_index, std::move(u2_values));
2092 debug() <<
"format of BootstrapMethods entry not recognized: arguments "
2096 parsed_class, bootstrap_method_index, std::move(u2_values));
2100 debug() <<
"INFO: parse lambda handle" <<
eom;
2104 if(!lambda_method_handle.has_value())
2106 debug() <<
"format of BootstrapMethods entry not recognized: method "
2107 "handle not recognised"
2110 parsed_class, bootstrap_method_index, std::move(u2_values));
2118 lambda_method_handle->interface_type =
2120 lambda_method_handle->method_type =
pool_entry(method_type_argument.
ref1).
s;
2121 lambda_method_handle->u2_values = std::move(u2_values);
2122 debug() <<
"lambda function reference "
2123 <<
id2string(lambda_method_handle->lambda_method_name)
2124 <<
" in class \"" << parsed_class.
name <<
"\""
2125 <<
"\n interface type is "
2127 <<
"\n method type is "
2130 bootstrap_method_index, *lambda_method_handle);
2141 size_t bootstrap_method_index,