1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
|
/* State will store states of variables for a function's single execution path.
It will be used for bit-level symbolic execution to determine values of bits
of function's return value and symbolic marked arguments.
Copyright (C) 2022-2024 Free Software Foundation, Inc.
Contributed by Matevos Mehrabyan <matevosmehrabyan@gmail.com>
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#ifndef SYM_EXEC_STATE_H
#define SYM_EXEC_STATE_H
#define MAX_VALUE_SIZE 64
#include "sym-exec-expr-is-a-helper.h"
/* Struct used for representing values. */
struct value {
private:
/* bit-vector that represents the value. */
vec<value_bit *> number;
public:
/* Used for denoting whether the number is unsigned. */
const bool is_unsigned;
/* Constructor for value. The first argument is the size of the bit-vector
and the second argument is the sign of the number. */
value (unsigned size, bool is_unsigned);
/* Copy constructor for value. */
value (const value &other);
/* Pushes the given bit to the end of the bit-vector. */
value_bit **push (value_bit *elem);
/* Returns pushed bits count. */
unsigned length () const;
/* Returns a reference the last bit. */
value_bit *&last ();
/* Returns the size in bits. */
unsigned allocated () const;
/* Wrapper of vec<..>.exists for the bit-vector. */
bool exists () const;
/* Wrapper of vec<..>::operator[] for the bit-vector. */
value_bit *&operator[] (unsigned i);
/* Assignment operator. If the specified value's size is smaller,
then 0 constant bit will be assigned to the remaining upper bits. */
value &operator= (const value &other);
/* Wrapper of vec<..>::operator[] const for the bit-vector. */
value_bit *operator[] (unsigned i) const;
/* Destructor for value. */
~value ();
/* Removes given sequence of bits. */
void free_bits ();
};
/* Stores states of variables' values on bit-level. */
class state {
typedef void (state::*binary_func) (value *arg1, value *arg2, tree dest);
typedef value_bit *(*bit_func) (value_bit *bit1, value_bit *bit2);
typedef value_bit *(*bit_func3) (value_bit *var1, value_bit *var2,
value_bit **var3);
typedef void (state::*binary_cond_func) (value *arg1, value *arg2);
private:
/* Here is stored values by bits of each variable. */
hash_map<tree, value> var_states;
/* Here is stored conditions of symbolic bits. */
hash_set<bit_expression *> conditions;
/* The result of last added condition. */
condition_status last_cond_status = condition_status::CS_NO_COND;
/* Creates value for given constant tree. */
static value create_val_for_const (tree var, size_t size);
/* Checks if sizes of arguments and destination are compatible. */
bool check_args_compatibility (tree arg1, tree arg2, tree dest);
/* Adds equality condition for two values. */
void add_equal_cond (value *arg1, value *arg2);
/* Adds not equal condition for two values. */
void add_not_equal_cond (value *arg1, value *arg2);
/* Adds greater than condition for two values. */
void add_greater_than_cond (value *arg1, value *arg2);
/* Adds less than condition for two values. */
void add_less_than_cond (value *arg1, value *arg2);
/* Adds greater or equal condition for two values. */
void add_greater_or_equal_cond (value *arg1, value *arg2);
/* Adds less or equal condition for two values. */
void add_less_or_equal_cond (value *arg1, value *arg2);
/* Does preprocessing and postprocessing for condition adding.
Handles value creation for constants and their removement in the end. */
bool add_binary_cond (tree arg1, tree arg2, binary_cond_func cond_func);
/* Constructs expression trees of greater than condition for given values. */
bit_expression *construct_great_than_cond (value *arg1, value *arg2);
/* Constructs expression trees of less than condition for given values. */
bit_expression *construct_less_than_cond (value *arg1, value *arg2);
/* Constructs expression trees of equal condition for given values. */
bit_expression *construct_equal_cond (value *arg1, value *arg2);
/* A wrapper for operations on two bits.
Operation and operands are passed as arguments. */
static value_bit *operate_bits (bit_func bit_op, value_bit *bit1,
value_bit *bit2, value_bit **bit3);
/* A wrapper for operations on three bits.
Operation and operands are passed as arguments. */
static value_bit *operate_bits (bit_func3 bit_op, value_bit *bit1,
value_bit *bit2, value_bit **bit3);
/* Performs the given operation on passed arguments.
The result is stored in dest. */
template<class func>
void operate (value *arg1, value *arg2, value_bit **bit_arg, tree dest,
func bit_op);
/* Does preprocessing and postprocessing for expressions with tree operands.
Handles value creation for constant and their removement in the end. */
bool do_binary_operation (tree arg1, tree arg2, tree dest,
binary_func bin_func);
/* Performs AND operation on given values. The result is stored in dest. */
void do_and (value *arg1, value *arg2, tree dest);
/* Performs OR operation on given values. The result is stored in dest. */
void do_or (value *arg1, value *arg2, tree dest);
/* Performs XOR operation on given values. The result is stored in dest. */
void do_xor (value *arg1, value *arg2, tree dest);
/* Performs shift right operation on given values.
The result is stored in dest. */
void do_shift_right (value *arg1, value *arg2, tree dest);
/* Performs shift left operation on given values.
The result is stored in dest. */
void do_shift_left (value *arg1, value *arg2, tree dest);
/* Adds given values. The result is stored in dest. */
void do_add (value *arg1, value *arg2, tree dest);
/* Subtracks second value from the first. The result is stored in dest. */
void do_sub (value *arg1, value *arg2, tree dest);
/* Performs AND operation on two bits. */
static value_bit *and_two_bits (value_bit *arg1, value_bit *arg2);
/* ANDs every bit of the value with var_bit, stroes the result in var1. */
void and_number_bit (value *var1, value_bit *var_bit);
/* Multiplies given values. The result is stored in dest. */
void do_mul (value *arg1, value *arg2, tree dest);
/* Performs AND operation for 2 symbolic_bit operands. */
static value_bit *and_sym_bits (const value_bit *var1,
const value_bit *var2);
/* Performs AND operation for a symbolic_bit and const_bit operands. */
static value_bit *and_var_const (const value_bit *var1,
const bit *const_bit);
/* Performs AND operation for 2 constant bit operands. */
static bit *and_const_bits (const bit *const_bit1, const bit *const_bit2);
/* Performs OR operation on two bits. */
static value_bit *or_two_bits (value_bit *arg1_bit, value_bit *arg2_bit);
/* Performs OR operation for 2 symbolic_bit operands. */
static value_bit *or_sym_bits (const value_bit *var1,
const value_bit *var2);
/* Performs OR operation for a symbolic_bit and a constant bit operands. */
static value_bit *or_var_const (const value_bit *var1,
const bit *const_bit);
/* Performs OR operation for 2 constant bit operands. */
static bit *or_const_bits (const bit *const_bit1, const bit *const_bit2);
/* Performs complement operation on a bit. */
static value_bit *complement_a_bit (value_bit *var);
/* Performs NOT operation for constant bit. */
static bit *complement_const_bit (const bit *const_bit);
/* Performs NOT operation for symbolic_bit. */
static value_bit *complement_sym_bit (const value_bit *var);
/* Performs XOR operation on two bits. */
static value_bit *xor_two_bits (value_bit *var1, value_bit *var2);
/* Performs XOR operation for 2 symbolic_bit operands. */
static value_bit *xor_sym_bits (const value_bit *var1,
const value_bit *var2);
/* Performs XOR operation for 2 constant bit operands. */
static bit *xor_const_bits (const bit *const_bit1, const bit *const_bit2);
/* Performs XOR operation for a symbolic_bit and const_bit operands. */
static value_bit *xor_var_const (const value_bit *var,
const bit *const_bit);
/* Shift_right operation. Case: var2 is a symbolic value. */
static value_bit *shift_right_sym_bits (value_bit *var1, value_bit *var2);
/* Shift_left operation. Case: var2 is a symbolic value. */
static value_bit *shift_left_sym_bits (value_bit *var1, value_bit *var2);
/* Shifts var right by size of shift_value. */
value *shift_right_by_const (value *var, size_t shift_value);
/* Return node which has a const bit child. Traversal is done based
on safe branching. */
static void get_parent_with_const_child (value_bit *root,
bit_expression *&parent,
bit_expression *&parent_of_parent);
/* Checks whether state for variable with specified name already
exists or not. */
bool is_declared (tree var);
/* Declares given variable if it has not been declared yet. */
void declare_if_needed (tree var, size_t size);
/* Shifts number left by size of shift_value. */
value *shift_left_by_const (const value *number, size_t shift_value);
/* Adds two bits and carry value.
Resturn result and stores new carry bit in "carry". */
static value_bit *full_adder (value_bit *var1, value_bit *var2,
value_bit **carry);
/* Returns the additive inverse of the given number. */
value *additive_inverse (const value *number);
/* Adds two values, stores the result in the first one. */
void add_numbers (value *var1, const value *var2);
/* Make a copy of given bits. */
static vec<value_bit *> *make_copy (vec<value_bit *> *bits);
/* Create LFSR value for the reversed CRC. */
static void create_reversed_lfsr (value &lfsr, const value &crc,
const value &polynomial);
/* Create LFSR value for the forward CRC. */
static void create_forward_lfsr (value &lfsr, const value &crc,
const value &polynomial);
public:
/* Default constructor for state. */
state () = default;
/* Destructor for state. */
~state ();
/* Adds an empty state for the given variable. */
bool decl_var (tree name, unsigned size);
/* Copy constructor for state. It copies all variables and conditions
of the given state. */
state (const state &s);
/* Adds the given variable to state. */
bool add_var_state (tree var, value *state);
/* Remove all states from the states' vector. */
static void remove_states (vec<state *> *states);
/* Remove all states from the states' vector and release the vector. */
static void clear_states (vec<state *> *states);
/* Removes all variables added to the state. */
void clear_var_states ();
/* Removes all conditions added to the state. */
void clear_conditions ();
/* Adds the given condition to the state. */
bool add_condition (bit_expression *cond);
/* Bulk add the given conditions to the state. */
bool bulk_add_conditions (const hash_set<bit_expression *> &conds);
/* Get value of the given variable. */
value *get_value (tree var);
/* Get the value of the tree, which is in the beginning of the var_states. */
value *get_first_value ();
/* Returns the list of conditions in the state. */
const hash_set<bit_expression *> &get_conditions ();
/* Adds a variable with unknown value to state. Such variables are
represented as sequence of symbolic bits. */
bool make_symbolic (tree var, unsigned size);
/* Returns size of the given variable. */
unsigned get_var_size (tree var);
/* Prints the given value. */
static void print_value (value *var);
/* Prints added conditions. */
void print_conditions ();
/* Returns the number represented by the value. */
static unsigned HOST_WIDE_INT
make_number (const value *var);
/* Checks if all bits of the given value have constant bit type. */
static bool is_bit_vector (const value *var);
/* Performs the specified operation on passed variables. */
bool do_operation (tree_code op_code, tree arg1, tree arg2, tree dest);
/* Does Assignment. */
bool do_assign (tree arg, tree dest);
/* Assigns pow 2 value. */
bool do_assign_pow2 (tree dest, unsigned pow);
/* Negates given variable. */
bool do_complement (tree arg, tree dest);
/* Adds EQUAL condition of given variables to state. */
bool add_equal_cond (tree arg1, tree arg2);
/* Adds NOT EQUAL condition of given variables to state. */
bool add_not_equal_cond (tree arg1, tree arg2);
/* Adds GREATER THAN condition of given variables to state. */
bool add_greater_than_cond (tree arg1, tree arg2);
/* Adds LESS THAN condition of given variables to state. */
bool add_less_than_cond (tree arg1, tree arg2);
/* Adds GREATER OR EQUAL condition of given variables to state. */
bool add_greater_or_equal_cond (tree arg1, tree arg2);
/* Adds LESS OR EQUAL condition of given variables to state. */
bool add_less_or_equal_cond (tree arg1, tree arg2);
/* Adds a bool condition to state. */
bool add_bool_cond (tree arg);
/* Checks whether the given two constant values are equal. */
static bool check_const_value_equality (value *arg1, value *arg2);
/* Checks whether the given two constant values are not equal. */
static bool check_const_value_are_not_equal (value *arg1, value *arg2);
/* Checks whether the first given constant value
is greater than the second one. */
static bool check_const_value_is_greater_than (value *arg1, value *arg2);
/* Checks whether the first given constant value
is less than the second one. */
static bool check_const_value_is_less_than (value *arg1, value *arg2);
/* For the given value_bit, iterates over its expression tree, complements
those bit which came from the given origin. */
static value_bit *complement_bits_with_origin (value_bit *root, tree origin);
/* Iterates over every bit of the given value and complements their
expression trees' those bits, that came from the given origin. */
static void complement_val_bits_with_origin (value *val, tree origin);
/* Complements all bits of all values that came from the given origin. */
void complement_all_vars_bits_with_origin (tree origin);
/* Complements all bits with the given origin of all added conditions. */
void complement_conditions_with_origin (tree origin);
/* Complements all bits with the given origin of all values
and added conditions. */
void complement_state_with_origin (tree origin);
/* Returns status of last added condition. */
condition_status get_last_cond_status ();
/* Create LFSR value. */
static value *create_lfsr (tree crc, value *polynomial, bool is_bit_forward);
};
/* Returns the minimum of A, B, C. */
size_t min (size_t a, size_t b, size_t c);
/* Performs the given operation on passed arguments.
The result is stored in dest. */
template<class func>
void
state::operate (value *arg1, value *arg2, value_bit **bit_arg, tree dest,
func bit_op)
{
value *dest_var = var_states.get (dest);
size_t min_iter = min (arg1->length (), arg2->length (), dest_var->length ());
size_t i = 0;
for (; i < min_iter; i++)
{
value_bit *temp = (*var_states.get (dest))[i];
(*var_states.get (dest))[i] = operate_bits (bit_op, (*arg1)[i],
(*arg2)[i], bit_arg);
delete temp;
}
if (i >= dest_var->length ())
return;
value *biggest = arg1;
value_bit *sign_bit = (*arg2)[i - 1];
if (arg2->length () > arg1->length ())
{
biggest = arg2;
sign_bit = (*arg1)[i - 1];
}
min_iter = min (biggest->length (), dest_var->length (), dest_var->length ());
for (; i < min_iter; i++)
{
value_bit *temp = (*var_states.get (dest))[i];
(*var_states.get (dest))[i] = operate_bits (bit_op, (*biggest)[i],
sign_bit, bit_arg);
delete temp;
}
if (i >= dest_var->length ())
return;
sign_bit = (*biggest)[i - 1];
for (; i < dest_var->length (); i++)
{
value_bit *temp = (*var_states.get (dest))[i];
(*var_states.get (dest))[i] = operate_bits (bit_op, sign_bit, sign_bit,
bit_arg);
delete temp;
}
}
#endif /* SYM_EXEC_STATE_H. */
|