@@ -135,7 +135,7 @@ class java_bytecode_parsert:public parsert
135
135
void get_class_refs ();
136
136
void get_class_refs_rec (const typet &);
137
137
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 &);
139
139
140
140
void skip_bytes (std::size_t bytes)
141
141
{
@@ -1402,23 +1402,22 @@ void java_bytecode_parsert::rclass_attribute(classt &parsed_class)
1402
1402
for (size_t i = 0 ; i < num_bootstrap_methods; i++)
1403
1403
{
1404
1404
u2 bootstrap_methodhandle_ref = read_u2 ();
1405
+ const pool_entryt &entry = pool_entry (bootstrap_methodhandle_ref);
1405
1406
u2 num_bootstrap_arguments = read_u2 ();
1406
1407
1407
1408
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)
1417
1417
{
1418
1418
// try parsing bootstrap method handle
1419
- if (num_bootstrap_arguments = = 3 )
1419
+ if (num_bootstrap_arguments > = 3 )
1420
1420
{
1421
-
1422
1421
// each entry contains a MethodHandle structure
1423
1422
// u2 tag
1424
1423
// 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)
1428
1427
// 1 to 4 must point to a CONSTANT_Fieldref structure
1429
1428
// 5 or 8 must point to a CONSTANT_Methodref structure
1430
1429
// 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
1434
1433
// 9 must point to a CONSTANT_InterfaceMethodref structure
1435
1434
1436
1435
// the index must point to a CONSTANT_String
@@ -1445,26 +1444,23 @@ void java_bytecode_parsert::rclass_attribute(classt &parsed_class)
1445
1444
u2 arg_index2 = read_u2 ();
1446
1445
u2 arg_index3 = read_u2 ();
1447
1446
1447
+ // skip rest
1448
+ for (size_t i = 3 ; i < num_bootstrap_arguments; i++)
1449
+ read_u2 ();
1450
+
1448
1451
const pool_entryt &arg1 = pool_entry (arg_index1);
1449
1452
const pool_entryt &arg2 = pool_entry (arg_index2);
1450
1453
const pool_entryt &arg3 = pool_entry (arg_index3);
1451
1454
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
-
1456
1455
if (!(arg1.tag == CONSTANT_MethodType &&
1457
1456
arg2.tag == CONSTANT_MethodHandle &&
1458
1457
arg3.tag == CONSTANT_MethodType))
1459
1458
return ;
1460
1459
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
-
1466
1460
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);
1468
1464
if (
1469
1465
real_handle.handle_type !=
1470
1466
method_handle_typet::LAMBDA_METHOD_HANDLE)
@@ -1500,6 +1496,16 @@ void java_bytecode_parsert::rclass_attribute(classt &parsed_class)
1500
1496
error () << " ERROR: num_bootstrap_arguments must be 3" << eom;
1501
1497
}
1502
1498
}
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
+ }
1503
1509
}
1504
1510
}
1505
1511
else
@@ -1631,14 +1637,15 @@ void java_bytecode_parsert::parse_local_variable_type_table(methodt &method)
1631
1637
}
1632
1638
}
1633
1639
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
1636
1645
void java_bytecode_parsert::parse_methodhandle (
1637
- u2 index,
1638
- u2 num_bootstrap_arguments,
1646
+ const pool_entryt &entry,
1639
1647
lambda_method_handlet &handle)
1640
1648
{
1641
- const pool_entryt entry = pool_entry (index);
1642
1649
INVARIANT (
1643
1650
entry.tag == CONSTANT_MethodHandle,
1644
1651
" constant pool entry must be a MethodHandle" );
@@ -1672,4 +1679,11 @@ void java_bytecode_parsert::parse_methodhandle(
1672
1679
handle.lambda_method_name = pool_entry (nameandtype_entry.ref1 ).s ;
1673
1680
handle.handle_type = method_handle_typet::LAMBDA_METHOD_HANDLE;
1674
1681
}
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;
1675
1689
}
0 commit comments