@@ -18,7 +18,7 @@ Author: Peter Schrammel
18
18
#include < util/format_expr.h>
19
19
#include < util/invariant.h>
20
20
#include < util/namespace.h>
21
- #include < util/pointer_expr .h>
21
+ #include < util/pointer_offset_size .h>
22
22
#include < util/ssa_expr.h>
23
23
#include < util/std_expr.h>
24
24
@@ -54,6 +54,16 @@ static void remove_array_type_l2(typet &type)
54
54
size.remove_level_2 ();
55
55
}
56
56
57
+ exprt deref_expr (const exprt &expr)
58
+ {
59
+ if (expr.id () == ID_address_of)
60
+ {
61
+ return to_address_of_expr (expr).object ();
62
+ }
63
+
64
+ return dereference_exprt (expr);
65
+ }
66
+
57
67
void clean_pointer_expr (exprt &expr, const typet &type)
58
68
{
59
69
if (
@@ -81,6 +91,21 @@ void clean_pointer_expr(exprt &expr, const typet &type)
81
91
POSTCONDITION (expr.type ().id () == ID_pointer);
82
92
}
83
93
94
+ void log_set_field (
95
+ const namespacet &ns,
96
+ const messaget &log,
97
+ const irep_idt &field_name,
98
+ const exprt &expr,
99
+ const exprt &value)
100
+ {
101
+ log.conditional_output (
102
+ log.debug (), [field_name, ns, expr, value](messaget::mstreamt &mstream) {
103
+ mstream << " Shadow memory: set_field: " << id2string (field_name)
104
+ << " for " << format (expr) << " to " << format (value)
105
+ << messaget::eom;
106
+ });
107
+ }
108
+
84
109
void log_get_field (
85
110
const namespacet &ns,
86
111
const messaget &log,
@@ -828,3 +853,239 @@ std::vector<std::pair<exprt, exprt>> get_shadow_dereference_candidates(
828
853
}
829
854
return result;
830
855
}
856
+
857
+ // TODO: doxygen?
858
+ // Unfortunately.
859
+ static object_descriptor_exprt
860
+ normalize (const object_descriptor_exprt &expr, const namespacet &ns)
861
+ {
862
+ if (expr.object ().id () == ID_symbol)
863
+ {
864
+ return expr;
865
+ }
866
+ if (expr.offset ().id () == ID_unknown)
867
+ {
868
+ return expr;
869
+ }
870
+
871
+ object_descriptor_exprt result = expr;
872
+ mp_integer offset =
873
+ numeric_cast_v<mp_integer>(to_constant_expr (expr.offset ()));
874
+ exprt object = expr.object ();
875
+
876
+ while (true )
877
+ {
878
+ if (object.id () == ID_index)
879
+ {
880
+ const index_exprt &index_expr = to_index_expr (object);
881
+ mp_integer index =
882
+ numeric_cast_v<mp_integer>(to_constant_expr (index_expr.index ()));
883
+
884
+ offset += *pointer_offset_size (index_expr.type (), ns) * index;
885
+ object = index_expr.array ();
886
+ }
887
+ else if (object.id () == ID_member)
888
+ {
889
+ const member_exprt &member_expr = to_member_expr (object);
890
+ const struct_typet &struct_type =
891
+ to_struct_type (ns.follow (member_expr.struct_op ().type ()));
892
+ offset +=
893
+ *member_offset (struct_type, member_expr.get_component_name (), ns);
894
+ object = member_expr.struct_op ();
895
+ }
896
+ else
897
+ {
898
+ break ;
899
+ }
900
+ }
901
+ result.object () = object;
902
+ result.offset () = from_integer (offset, expr.offset ().type ());
903
+ return result;
904
+ }
905
+
906
+ bool set_field_check_null (
907
+ const namespacet &ns,
908
+ const messaget &log,
909
+ const std::vector<exprt> &value_set,
910
+ const exprt &expr)
911
+ {
912
+ const null_pointer_exprt null_pointer (to_pointer_type (expr.type ()));
913
+ if (value_set.size () == 1 && contains_null_or_invalid (value_set, null_pointer))
914
+ {
915
+ // TODO: duplicated in log_value_set_match
916
+ #ifdef DEBUG_SM
917
+ log.conditional_output (
918
+ log.debug (), [ns, null_pointer, expr](messaget::mstreamt &mstream) {
919
+ mstream << " Shadow memory: value set match: " << format (null_pointer)
920
+ << " <-- " << format (expr) << messaget::eom;
921
+ mstream << " Shadow memory: ignoring set field on NULL object"
922
+ << messaget::eom;
923
+ });
924
+ #endif
925
+ return true ;
926
+ }
927
+ return false ;
928
+ }
929
+
930
+ // / Used for set_field and shadow memory copy
931
+ static std::vector<std::pair<exprt, exprt>>
932
+ get_shadow_memory_for_matched_object (
933
+ const exprt &expr,
934
+ const exprt &matched_object,
935
+ const std::vector<shadow_memory_statet::shadowed_addresst> &addresses,
936
+ const namespacet &ns,
937
+ const messaget &log,
938
+ bool &exact_match)
939
+ {
940
+ std::vector<std::pair<exprt, exprt>> result;
941
+ for (const auto &shadowed_address : addresses)
942
+ {
943
+ log_try_shadow_address (ns, log, shadowed_address);
944
+
945
+ if (!are_types_compatible (expr.type (), shadowed_address.address .type ()))
946
+ {
947
+ #ifdef DEBUG_SM
948
+ log.debug () << " Shadow memory: incompatible types "
949
+ << from_type (ns, " " , expr.type ()) << " , "
950
+ << from_type (ns, " " , shadowed_address.address .type ())
951
+ << messaget::eom;
952
+ #endif
953
+ continue ;
954
+ }
955
+
956
+ object_descriptor_exprt matched_base_descriptor =
957
+ normalize (to_object_descriptor_expr (matched_object), ns);
958
+
959
+ value_set_dereferencet::valuet dereference =
960
+ value_set_dereferencet::build_reference_to (
961
+ matched_base_descriptor, expr, ns);
962
+
963
+ exprt matched_base_address =
964
+ address_of_exprt (matched_base_descriptor.object ());
965
+ clean_string_constant (to_address_of_expr (matched_base_address).op ());
966
+
967
+ // NULL has already been handled in the caller; skip.
968
+ if (matched_base_descriptor.object ().id () == ID_null_object)
969
+ {
970
+ continue ;
971
+ }
972
+ const value_set_dereferencet::valuet shadow_dereference =
973
+ get_shadow_dereference (
974
+ shadowed_address.shadow , matched_base_descriptor, expr, ns, log);
975
+ log_value_set_match (
976
+ ns,
977
+ log,
978
+ shadowed_address,
979
+ matched_base_address,
980
+ dereference,
981
+ expr,
982
+ shadow_dereference);
983
+
984
+ const exprt base_cond = get_matched_base_cond (
985
+ shadowed_address.address , matched_base_address, ns, log);
986
+ log_cond (ns, log, " base_cond" , base_cond);
987
+ if (base_cond.is_false ())
988
+ {
989
+ continue ;
990
+ }
991
+
992
+ const exprt expr_cond =
993
+ get_matched_expr_cond (dereference.pointer , expr, ns, log);
994
+ if (expr_cond.is_false ())
995
+ {
996
+ continue ;
997
+ }
998
+
999
+ if (base_cond.is_true () && expr_cond.is_true ())
1000
+ {
1001
+ #ifdef DEBUG_SM
1002
+ log.debug () << " exact match" << messaget::eom;
1003
+ #endif
1004
+ exact_match = true ;
1005
+ result.clear ();
1006
+ result.push_back ({base_cond, shadow_dereference.pointer });
1007
+ break ;
1008
+ }
1009
+
1010
+ if (base_cond.is_true ())
1011
+ {
1012
+ // No point looking at further shadow addresses
1013
+ // as only one of them can match.
1014
+ #ifdef DEBUG_SM
1015
+ log.debug () << " base match" << messaget::eom;
1016
+ #endif
1017
+ result.clear ();
1018
+ result.emplace_back (expr_cond, shadow_dereference.pointer );
1019
+ break ;
1020
+ }
1021
+ else
1022
+ {
1023
+ #ifdef DEBUG_SM
1024
+ log.debug () << " conditional match" << messaget::eom;
1025
+ #endif
1026
+ result.emplace_back (
1027
+ and_exprt (base_cond, expr_cond), shadow_dereference.pointer );
1028
+ }
1029
+ }
1030
+ return result;
1031
+ }
1032
+
1033
+ optionalt<exprt> get_shadow_memory (
1034
+ const exprt &expr,
1035
+ const std::vector<exprt> &value_set,
1036
+ const std::vector<shadow_memory_statet::shadowed_addresst> &addresses,
1037
+ const namespacet &ns,
1038
+ const messaget &log,
1039
+ size_t &mux_size)
1040
+ {
1041
+ std::vector<std::pair<exprt, exprt>> conds_values;
1042
+ for (const auto &matched_object : value_set)
1043
+ {
1044
+ if (matched_object.id () != ID_object_descriptor)
1045
+ {
1046
+ log.warning () << " Shadow memory: value set contains unknown for "
1047
+ << format (expr) << messaget::eom;
1048
+ continue ;
1049
+ }
1050
+ if (
1051
+ to_object_descriptor_expr (matched_object).root_object ().id () ==
1052
+ ID_integer_address)
1053
+ {
1054
+ log.warning () << " Shadow memory: value set contains integer_address for "
1055
+ << format (expr) << messaget::eom;
1056
+ continue ;
1057
+ }
1058
+ if (matched_object.type ().get_bool (ID_C_is_failed_symbol))
1059
+ {
1060
+ log.warning () << " Shadow memory: value set contains failed symbol for "
1061
+ << format (expr) << messaget::eom;
1062
+ continue ;
1063
+ }
1064
+
1065
+ bool exact_match = false ;
1066
+ auto per_value_set_conds_values = get_shadow_memory_for_matched_object (
1067
+ expr, matched_object, addresses, ns, log, exact_match);
1068
+
1069
+ if (!per_value_set_conds_values.empty ())
1070
+ {
1071
+ if (exact_match)
1072
+ {
1073
+ conds_values.clear ();
1074
+ }
1075
+ conds_values.insert (
1076
+ conds_values.begin (),
1077
+ per_value_set_conds_values.begin (),
1078
+ per_value_set_conds_values.end ());
1079
+ mux_size += conds_values.size () - 1 ;
1080
+ if (exact_match)
1081
+ {
1082
+ break ;
1083
+ }
1084
+ }
1085
+ }
1086
+ if (!conds_values.empty ())
1087
+ {
1088
+ return build_if_else_expr (conds_values);
1089
+ }
1090
+ return {};
1091
+ }
0 commit comments