Skip to content

Commit 3fb40e7

Browse files
committed
Include annotations in Java class loading
For every class, field and method annotation that we see in our initial dependency analysis, we load the class that the annotation is defined in as well as all types of the values it stores. This can be useful for when we use annotations to analyze properties related to certain classes, or to force-load certain classes.
1 parent 01f9d40 commit 3fb40e7

File tree

1 file changed

+44
-0
lines changed

1 file changed

+44
-0
lines changed

jbmc/src/java_bytecode/java_bytecode_parser.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,9 @@ class java_bytecode_parsert:public parsert
134134
void rbytecode(methodt::instructionst &);
135135
void get_class_refs();
136136
void get_class_refs_rec(const typet &);
137+
void get_annotation_class_refs(
138+
const java_bytecode_parse_treet::annotationst &annotations);
139+
void get_annotation_value_class_refs(const exprt &value);
137140
void parse_local_variable_type_table(methodt &method);
138141
optionalt<lambda_method_handlet>
139142
parse_method_handle(const class method_handle_infot &entry);
@@ -547,8 +550,11 @@ void java_bytecode_parsert::get_class_refs()
547550
}
548551
}
549552

553+
get_annotation_class_refs(parse_tree.parsed_class.annotations);
554+
550555
for(const auto &field : parse_tree.parsed_class.fields)
551556
{
557+
get_annotation_class_refs(field.annotations);
552558
typet field_type;
553559
if(field.signature.has_value())
554560
{
@@ -570,6 +576,9 @@ void java_bytecode_parsert::get_class_refs()
570576

571577
for(const auto &method : parse_tree.parsed_class.methods)
572578
{
579+
get_annotation_class_refs(method.annotations);
580+
for(const auto &parameter_annotations : method.parameter_annotations)
581+
get_annotation_class_refs(parameter_annotations);
573582
typet method_type;
574583
if(method.signature.has_value())
575584
{
@@ -635,6 +644,41 @@ void java_bytecode_parsert::get_class_refs_rec(const typet &src)
635644
get_class_refs_rec(src.subtype());
636645
}
637646

647+
/// For each of the given annotations, get a reference to its class and
648+
/// recursively get class references of the values it stores.
649+
void java_bytecode_parsert::get_annotation_class_refs(
650+
const java_bytecode_parse_treet::annotationst &annotations)
651+
{
652+
for(const auto &annotation : annotations)
653+
{
654+
get_class_refs_rec(annotation.type);
655+
for(const auto &element_value_pair : annotation.element_value_pairs)
656+
get_annotation_value_class_refs(element_value_pair.value);
657+
}
658+
}
659+
660+
/// See \ref java_bytecode_parsert::get_annotation_class_refs.
661+
/// For the different cases of `exprt`, see \ref
662+
/// java_bytecode_parsert::get_relement_value.
663+
void java_bytecode_parsert::get_annotation_value_class_refs(const exprt &value)
664+
{
665+
if(const auto &symbol_expr = expr_try_dynamic_cast<symbol_exprt>(value))
666+
{
667+
const irep_idt &value_id = symbol_expr->get_identifier();
668+
const typet value_type = java_type_from_string(id2string(value_id));
669+
get_class_refs_rec(value_type);
670+
}
671+
else if(const auto &array_expr = expr_try_dynamic_cast<array_exprt>(value))
672+
{
673+
for(const exprt &operand : array_expr->operands())
674+
get_annotation_value_class_refs(operand);
675+
}
676+
// TODO: enum and nested annotation cases (once these are correctly parsed by
677+
// get_relement_value).
678+
// Note that in the cases where expr is a string or primitive type, no
679+
// additional class references are needed.
680+
}
681+
638682
void java_bytecode_parsert::rconstant_pool()
639683
{
640684
u2 constant_pool_count=read_u2();

0 commit comments

Comments
 (0)