Skip to content

Commit 4d98795

Browse files
author
Matthias Güdemann
committed
Support altmetafactory reading
1 parent 7f05777 commit 4d98795

File tree

1 file changed

+44
-30
lines changed

1 file changed

+44
-30
lines changed

src/java_bytecode/java_bytecode_parser.cpp

Lines changed: 44 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ class java_bytecode_parsert:public parsert
135135
void get_class_refs();
136136
void get_class_refs_rec(const typet &);
137137
void parse_local_variable_type_table(methodt &method);
138-
void parse_methodhandle(u2, u2, lambda_method_handlet &);
138+
void parse_methodhandle(const pool_entryt &, lambda_method_handlet &);
139139

140140
void skip_bytes(std::size_t bytes)
141141
{
@@ -1402,23 +1402,22 @@ void java_bytecode_parsert::rclass_attribute(classt &parsed_class)
14021402
for(size_t i = 0; i < num_bootstrap_methods; i++)
14031403
{
14041404
u2 bootstrap_methodhandle_ref = read_u2();
1405+
const pool_entryt &entry = pool_entry(bootstrap_methodhandle_ref);
14051406
u2 num_bootstrap_arguments = read_u2();
14061407

14071408
lambda_method_handlet handle;
1408-
parse_methodhandle(bootstrap_methodhandle_ref, num_bootstrap_arguments, handle);
1409-
if(handle.handle_type != method_handle_typet::BOOTSTRAP_METHOD_HANDLE)
1410-
{
1411-
lambda_method_handlet empty_handle;
1412-
parsed_class.lambda_method_handle_map[parsed_class.name].push_back(
1413-
empty_handle);
1414-
error() << "ERROR: could not parse BootstrapMethods entry" << eom;
1415-
}
1416-
else
1409+
status() << "INFO: parse BootstrapMethod handle "
1410+
<< num_bootstrap_arguments << " #args"
1411+
<< eom;
1412+
parse_methodhandle(entry, handle);
1413+
if(
1414+
handle.handle_type ==
1415+
method_handle_typet::BOOTSTRAP_METHOD_HANDLE_ALT ||
1416+
handle.handle_type == method_handle_typet::BOOTSTRAP_METHOD_HANDLE)
14171417
{
14181418
// try parsing bootstrap method handle
1419-
if(num_bootstrap_arguments == 3)
1419+
if(num_bootstrap_arguments >= 3)
14201420
{
1421-
14221421
// each entry contains a MethodHandle structure
14231422
// u2 tag
14241423
// u2 reference kind which must be in the range from 1 to 9
@@ -1428,9 +1427,9 @@ void java_bytecode_parsert::rclass_attribute(classt &parsed_class)
14281427
// 1 to 4 must point to a CONSTANT_Fieldref structure
14291428
// 5 or 8 must point to a CONSTANT_Methodref structure
14301429
// 6 or 7 must point to a CONSTANT_Methodref or
1431-
// CONSTANT_InterfaceMethodref structure, if the class file version number
1432-
// is 52.0 or above, to a CONSTANT_Methodref only in the case of less than
1433-
// 52.0
1430+
// CONSTANT_InterfaceMethodref structure, if the class file version
1431+
// number is 52.0 or above, to a CONSTANT_Methodref only in the case
1432+
// of less than 52.0
14341433
// 9 must point to a CONSTANT_InterfaceMethodref structure
14351434

14361435
// the index must point to a CONSTANT_String
@@ -1445,26 +1444,23 @@ void java_bytecode_parsert::rclass_attribute(classt &parsed_class)
14451444
u2 arg_index2 = read_u2();
14461445
u2 arg_index3 = read_u2();
14471446

1447+
// skip rest
1448+
for(size_t i = 3; i < num_bootstrap_arguments; i++)
1449+
read_u2();
1450+
14481451
const pool_entryt &arg1 = pool_entry(arg_index1);
14491452
const pool_entryt &arg2 = pool_entry(arg_index2);
14501453
const pool_entryt &arg3 = pool_entry(arg_index3);
14511454

1452-
// std::cout << "bootstrap arg1 tag " << std::to_string(arg1.tag) << std::endl;
1453-
// std::cout << "bootstrap arg2 tag " << std::to_string(arg2.tag) << std::endl;
1454-
// std::cout << "bootstrap arg3 tag " << std::to_string(arg3.tag) << std::endl;
1455-
14561455
if(!(arg1.tag == CONSTANT_MethodType &&
14571456
arg2.tag == CONSTANT_MethodHandle &&
14581457
arg3.tag == CONSTANT_MethodType))
14591458
return;
14601459

1461-
// std::cout << "MethodType arg1 " << id2string(pool_entry(arg1.ref1).s)
1462-
// << "\nMethodType arg2 " << id2string(pool_entry(arg3.ref1).s)
1463-
// << std::endl;
1464-
// std::cout << std::endl;
1465-
14661460
lambda_method_handlet real_handle;
1467-
parse_methodhandle(arg_index2, 0, real_handle);
1461+
status() << "INFO: parse lambda handle" << eom;
1462+
const pool_entryt &lambda_entry = pool_entry(arg_index2);
1463+
parse_methodhandle(lambda_entry, real_handle);
14681464
if(
14691465
real_handle.handle_type !=
14701466
method_handle_typet::LAMBDA_METHOD_HANDLE)
@@ -1500,6 +1496,16 @@ void java_bytecode_parsert::rclass_attribute(classt &parsed_class)
15001496
error() << "ERROR: num_bootstrap_arguments must be 3" << eom;
15011497
}
15021498
}
1499+
else
1500+
{
1501+
lambda_method_handlet empty_handle;
1502+
parsed_class.lambda_method_handle_map[parsed_class.name].push_back(
1503+
empty_handle);
1504+
// skip arguments here
1505+
for(size_t i = 0; i < num_bootstrap_arguments; i++)
1506+
read_u2();
1507+
error() << "ERROR: could not parse BootstrapMethods entry" << eom;
1508+
}
15031509
}
15041510
}
15051511
else
@@ -1631,14 +1637,15 @@ void java_bytecode_parsert::parse_local_variable_type_table(methodt &method)
16311637
}
16321638
}
16331639

1634-
// read method handle pointed to from constant pool entry at index, supports
1635-
// reading method handles for bootstrap methods and lambda methods
1640+
/// Read method handle pointed to from constant pool entry at index, return type
1641+
/// of method handle and name if lambda function is found.
1642+
/// \param entry: the constant pool entry of the methodhandle_info structure
1643+
/// \param[out]: the method_handle type of the methodhandle_structure, either
1644+
/// for a recognized bootstrap method, for a lambda function or unknown
16361645
void java_bytecode_parsert::parse_methodhandle(
1637-
u2 index,
1638-
u2 num_bootstrap_arguments,
1646+
const pool_entryt &entry,
16391647
lambda_method_handlet &handle)
16401648
{
1641-
const pool_entryt entry = pool_entry(index);
16421649
INVARIANT(
16431650
entry.tag == CONSTANT_MethodHandle,
16441651
"constant pool entry must be a MethodHandle");
@@ -1672,4 +1679,11 @@ void java_bytecode_parsert::parse_methodhandle(
16721679
handle.lambda_method_name = pool_entry(nameandtype_entry.ref1).s;
16731680
handle.handle_type = method_handle_typet::LAMBDA_METHOD_HANDLE;
16741681
}
1682+
1683+
else if(
1684+
method_name ==
1685+
"java/lang/invoke/LambdaMetafactory.altMetafactory(Ljava/lang/invoke/"
1686+
"MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/"
1687+
"MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;")
1688+
handle.handle_type = method_handle_typet::BOOTSTRAP_METHOD_HANDLE_ALT;
16751689
}

0 commit comments

Comments
 (0)