21
21
static exprt unpack_rec (
22
22
const exprt &src,
23
23
bool little_endian,
24
+ const exprt &offset,
24
25
const exprt &max_bytes,
25
26
const namespacet &ns,
26
27
bool unpack_byte_array = false );
@@ -30,6 +31,7 @@ static exprt unpack_rec(
30
31
// / \param src_size: array/vector size
31
32
// / \param element_width: bit width of array/vector elements
32
33
// / \param little_endian: true, iff assumed endianness is little-endian
34
+ // / \param offset: if not nil, use as lower bound for non-nil bytes to return
33
35
// / \param max_bytes: if not nil, use as upper bound of the number of bytes to
34
36
// / unpack
35
37
// / \param ns: namespace for type lookups
@@ -39,6 +41,7 @@ static void unpack_array_vector(
39
41
const exprt &src_size,
40
42
const mp_integer &element_width,
41
43
bool little_endian,
44
+ const exprt &offset,
42
45
const exprt &max_bytes,
43
46
const namespacet &ns,
44
47
array_exprt &dest_array)
@@ -67,6 +70,17 @@ static void unpack_array_vector(
67
70
68
71
*max_bytes_int /= el_bytes;
69
72
}
73
+
74
+ if (auto offset_bytes = numeric_cast<mp_integer>(offset))
75
+ {
76
+ // compute offset as number of elements
77
+ first_element = *offset_bytes / el_bytes;
78
+ // insert offset_bytes-many nil bytes into the output array
79
+ *offset_bytes -= *offset_bytes % el_bytes;
80
+ dest_array.operands ().resize (
81
+ numeric_cast_v<std::size_t >(*offset_bytes),
82
+ from_integer (0 , unsignedbv_typet (8 )));
83
+ }
70
84
}
71
85
72
86
// the maximum number of bytes is an upper bound in case the size of the
@@ -91,7 +105,8 @@ static void unpack_array_vector(
91
105
element = src_simp.operands ()[index_int];
92
106
}
93
107
94
- exprt sub = unpack_rec (element, little_endian, max_bytes, ns, true );
108
+ exprt sub =
109
+ unpack_rec (element, little_endian, nil_exprt (), max_bytes, ns, true );
95
110
dest_array.operands ().insert (
96
111
dest_array.operands ().end (),
97
112
sub.operands ().begin (),
@@ -102,6 +117,7 @@ static void unpack_array_vector(
102
117
// / rewrite an object into its individual bytes
103
118
// / \param src: object to unpack
104
119
// / \param little_endian: true, iff assumed endianness is little-endian
120
+ // / \param offset: if not nil, use as lower bound for non-nil bytes to return
105
121
// / \param max_bytes: if not nil, use as upper bound of the number of bytes to
106
122
// / unpack
107
123
// / \param ns: namespace for type lookups
@@ -114,6 +130,7 @@ static void unpack_array_vector(
114
130
static exprt unpack_rec (
115
131
const exprt &src,
116
132
bool little_endian,
133
+ const exprt &offset,
117
134
const exprt &max_bytes,
118
135
const namespacet &ns,
119
136
bool unpack_byte_array)
@@ -141,6 +158,7 @@ static exprt unpack_rec(
141
158
array_type.size (),
142
159
*element_width,
143
160
little_endian,
161
+ offset,
144
162
max_bytes,
145
163
ns,
146
164
array);
@@ -161,6 +179,7 @@ static exprt unpack_rec(
161
179
vector_type.size (),
162
180
*element_width,
163
181
little_endian,
182
+ offset,
164
183
max_bytes,
165
184
ns,
166
185
array);
@@ -170,6 +189,8 @@ static exprt unpack_rec(
170
189
const struct_typet &struct_type=to_struct_type (ns.follow (src.type ()));
171
190
const struct_typet::componentst &components=struct_type.components ();
172
191
192
+ mp_integer member_offset_bits = 0 ;
193
+
173
194
for (const auto &comp : components)
174
195
{
175
196
auto element_width = pointer_offset_bits (comp.type (), ns);
@@ -182,11 +203,38 @@ static exprt unpack_rec(
182
203
throw non_byte_alignedt (struct_type, comp, *element_width);
183
204
}
184
205
206
+ exprt new_offset = nil_exprt ();
207
+ auto new_offset_int = numeric_cast<mp_integer>(offset);
208
+ exprt new_max_bytes = nil_exprt ();
209
+ auto new_max_bytes_int = numeric_cast<mp_integer>(max_bytes);
210
+
211
+ if (new_offset_int.has_value ())
212
+ {
213
+ *new_offset_int -= member_offset_bits / 8 ;
214
+ if (*new_offset_int >= 0 )
215
+ new_offset = from_integer (*new_offset_int, offset.type ());
216
+ }
217
+
218
+ if (new_max_bytes_int.has_value ())
219
+ {
220
+ *new_max_bytes_int -= member_offset_bits / 8 ;
221
+ if (*new_max_bytes_int >= 0 )
222
+ new_max_bytes = from_integer (*new_max_bytes_int, max_bytes.type ());
223
+ else
224
+ break ;
225
+ }
226
+
185
227
member_exprt member (src, comp.get_name (), comp.type ());
186
- exprt sub=unpack_rec (member, little_endian, max_bytes, ns, true );
228
+ if (src.id () == ID_struct)
229
+ simplify (member, ns);
230
+
231
+ exprt sub =
232
+ unpack_rec (member, little_endian, new_offset, new_max_bytes, ns, true );
187
233
188
234
for (const auto & op : sub.operands ())
189
235
array.copy_to_operands (op);
236
+
237
+ member_offset_bits += *element_width;
190
238
}
191
239
}
192
240
else if (src.type ().id ()!=ID_empty)
@@ -294,9 +342,12 @@ exprt lower_byte_extract(const byte_extract_exprt &src, const namespacet &ns)
294
342
typecast_exprt (src.offset (), upper_bound.type ())),
295
343
ns);
296
344
345
+ exprt lb = src.offset ();
346
+ if (!lb.is_constant ())
347
+ lb.make_nil ();
348
+
297
349
byte_extract_exprt unpacked (src);
298
- unpacked.op ()=
299
- unpack_rec (src.op (), little_endian, upper_bound, ns);
350
+ unpacked.op () = unpack_rec (src.op (), little_endian, lb, upper_bound, ns);
300
351
301
352
if (src.type ().id ()==ID_array)
302
353
{
0 commit comments