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