blob: 9db970f9095b9556e94174a54a3b838f3b47f31a [file] [log] [blame]
Karl Zhang3de5ab12021-05-31 11:45:48 +08001/*
Nik Dewallybacae6c2024-07-30 16:58:14 +01002 * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
Karl Zhang3de5ab12021-05-31 11:45:48 +08003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8#ifndef TF_FUZZ_HPP
9#define TF_FUZZ_HPP
10
Nik Dewallybacae6c2024-07-30 16:58:14 +010011#include <stdint.h>
12#include <stdio.h>
13#include <stdlib.h>
Karl Zhang3de5ab12021-05-31 11:45:48 +080014#include <string>
15#include <vector>
16#include <iostream>
17#include <fstream>
18
Nik Dewallybacae6c2024-07-30 16:58:14 +010019#include "class_forwards.hpp"
20#include "compute.hpp"
21#include "data_blocks.hpp"
22#include "find_or_create_asset.hpp"
23#include "gibberish.hpp"
24#include "template_line.hpp"
25#include "variables.hpp"
Karl Zhang3de5ab12021-05-31 11:45:48 +080026
Nik Dewallybacae6c2024-07-30 16:58:14 +010027class boilerplate;
28class psa_asset;
29class psa_call;
30class variable_info;
31class tf_fuzz_info;
32
Karl Zhang3de5ab12021-05-31 11:45:48 +080033
34/* Shortcuts, to reduce code clutter, and reduce risk of coding errors. */
35#define IVM(content) if(rsrc->verbose_mode){content} // IVM = "If Verbose Mode"
36#define IV(content) if(verbose_mode){content} // Same, but for use by tf_fuzz methods
37
38
39// consts to help readability:
40const bool add_to_end = true; // add a call to the end of the call vector
41const bool add_random_after_barrier = false;
42 /* add to the call list randomly after the latest barrier for this asset, and
43 as late as the end of the list. */
44const bool yes_set_barrier = true; // create the call and set a barrier for that asset
45const bool dont_set_barrier = false;
46 // inserted call does not preclude calls related to that asset being placed earlier
47
48using namespace std;
49
50// class tf_fuzz_info mostly just groups together everything needed generate the test.
51class tf_fuzz_info
52{
53 /* In creating a test, TF-Fuzz parses the test template, creating a vector of
54 PSA-call-tracker objects. TF-Fuzz then performs a simulation of those calls
55 -- simulation only in enough detail to predict expected results of those PSA
56 calls. After that simulation phase, write_test() writes it all out. The
57 process of creating these structures also requires the boilerplate text
58 strings. */
59
60public:
61 // Data members (this class is mostly just to group stuff together, so public):
62 vector<string> prep_code; // variable declarations to write out to test file
63 vector<psa_call*> calls;
64 /* the calls to perform: Note: must be vector *psa_call; a vector of
65 psa_call does not allow (run-time) polymorphism. */
66 boilerplate *bplate; // the boilerplate text for building the test
67 gibberish gibbergen; // the gibberish asset-data generator
68 crc32 hashgen; // simple 32-bit LFSR-based hashing generator
69 /* Note: The following asset-lists are kept in base-class type to allow a
70 common template-line processing function in tf_fuzz_grammar.y. */
71 vector<psa_asset*> active_sst_asset; // list of known and usable SST assets
72 vector<psa_asset*> deleted_sst_asset; // deleted SST assets
73 vector<psa_asset*> invalid_sst_asset; // SST assets with invalid attributes
74 vector<psa_asset*> active_key_asset; // list of known and usable keys
75 vector<psa_asset*> deleted_key_asset; // deleted keys
76 vector<psa_asset*> invalid_key_asset; // keys with invalid attributes
77 vector<psa_asset*> active_policy_asset; // list of known, usable policies
78 vector<psa_asset*> deleted_policy_asset; // deleted policies
79 vector<psa_asset*> invalid_policy_asset; // policies with invalid attrs
80 /* The "variable" vector tracks variables in the generated code. Actually,
81 it tracks variables explicitly named in the test template, and actual-data
82 holder variables from reading an asset. It does not track asset set-data
83 or asset expect-data variables, because there are multiple versions of
84 those, and it's easier to just to "count off" those multiple versions.
85 Notice that, unlike the above vectors, the variable vector is not a
86 vector of pointers to variable_info objects, but of the objects themselves.
87 This is because polymorphism is not of concern here. */
88 vector<variable_info> variable;
89 string test_purpose; // what the test tests
90 long rand_seed; // the original random seed, whether passed in or defaulted
91 string template_file_name, test_output_file_name;
92 FILE *template_file;
93 /* handle to the test-template input file. Unfortunately I can't seem to
94 get lex/yacc to understand C++ file references, probably because I'm
95 "extern C"ing the Lex content (Yacc/Bison turns out to be a lot easier
96 to coerce into generating C++ code than (F)Lex). */
97 ofstream output_C_file; // handle to the output C test file
98 bool verbose_mode; // true to "think aloud"
99 bool include_hashing_code; // true to instantiate the hashing code
100 // Methods:
101 asset_search find_or_create_sst_asset (
102 psa_asset_search criterion, // what to search on
103 psa_asset_usage where, // where to search
104 string target_name, // ignored if not searching on name
105 uint64_t target_id, // ignored if not searching on ID (e.g., SST UID)
106 long &serial_no, // search by asset's unique serial number
107 bool create_asset, // true to create the asset if it doesn't exist
108 vector<psa_asset*>::iterator &asset // returns a pointer to asset
109 );
110 asset_search find_or_create_key_asset (
111 psa_asset_search criterion, // what to search on
112 psa_asset_usage where, // where to search
113 string target_name, // ignored if not searching on name
114 uint64_t target_id, // ignored if not searching on ID (e.g., SST UID)
115 long &serial_no, // search by asset's unique serial number
116 bool create_asset, // true to create the asset if it doesn't exist
117 vector<psa_asset*>:: iterator &asset // returns iterator to asset
118 );
119 asset_search find_or_create_policy_asset (
120 psa_asset_search criterion, // what to search on
121 psa_asset_usage where, // where to search
122 string target_name, // ignored if not searching on name
123 uint64_t target_id, // also ignored if not searching on ID (e.g., SST UID)
124 long &serial_no, // search by asset's unique serial number
125 bool create_asset, // true to create the asset if it doesn't exist
126 vector<psa_asset*>::iterator &asset // returns iterator to asset
127 );
128 asset_search find_or_create_psa_asset (
129 psa_asset_type asset_type, // what type of asset to find
130 psa_asset_search criterion, // what to search on
131 psa_asset_usage where, // where to search
132 string target_name, // ignored if not searching on name
133 uint64_t target_id, // also ignored if not searching on ID (e.g., SST UID)
134 long &serial_no, // search by asset's unique serial number
135 bool create_asset, // true to create the asset if it doesn't exist
136 vector<psa_asset*>::iterator &asset // returns iterator to asset
137 );
138 vector<variable_info>::iterator find_var (string var_name);
139 void parse_cmd_line_params (int argc, char* argv[]);
140 // parse command-line parameters, and open files
141 void add_call (psa_call *the_call, bool to_end, bool set_barrier_bool);
142 /* stuffs a new call into the call list, either sequentially or at a random
143 place after a "barrier" for that particular asset. If set_barrier_bool
144 is true, it will prevent calls related to this asset from going before
145 this call. */
146 bool make_var (string var_name);
147 void simulate_calls (void);
148 // goes through generated calls calculating expected results
149 void write_test (void); // writes out the test's .c file
150 void teardown_test(void); // removes any PSA resources used in the test
151 tf_fuzz_info (void); // (constructor)
152 ~tf_fuzz_info (void);
153
154protected:
155 // Data members:
156 vector<string> teardown_calls;
157 // list of PSA commands to remove assets left over upon test completion
158 // Methods:
159
160private:
161 // Data members:
162 // Methods:
163};
164
165
166/*--------------------------------------------------------------
167 Helper functions:
168--------------------------------------------------------------*/
169
170
171template<typename CALL_TYPE>
172void define_call (set_data_info set_data, bool random_data, bool fill_in_template,
173 bool create_call, template_line *temLin, tf_fuzz_info *rsrc,
174 bool to_end_bool, bool set_barrier_bool) {
175 CALL_TYPE *the_call;
176 gibberish gib;
177 char gib_buff[1000];
178 string t_string;
179
180 if (fill_in_template) {
181 if (set_data.literal_data_not_file) {
182 if (random_data) {
183 int rand_data_length = 12 + (rand() % 800);
184 gib.sentence (gib_buff, gib_buff + rand_data_length - 1);
185 t_string = gib_buff;
186 temLin->set_data.set_calculated (t_string);
187 }
188 } else {
189 if (set_data.file_path == "") { // catch the most likely failure at least!
190 cerr << "Error: Tool-internal: Please report error "
191 << "#407 to the TF-Fuzz developers." << endl;
192 exit(407);
193 }
194 temLin->set_data.set_file (set_data.file_path);
195 // set in sst_asset_make_file_path
196 }
197 }
198 if (create_call) {
199 the_call = new CALL_TYPE (rsrc, temLin->call_ser_no,
200 temLin->asset_info.how_asset_found);
201 if (!temLin->copy_template_to_call (the_call)) {
202 cerr << "Error: Tool-internal: Please report error "
203 << "#402 to the TF-Fuzz developers." << endl;
204 exit(402);
205 }
206 rsrc->add_call (the_call, to_end_bool, set_barrier_bool);
207 }
208}
209
210#endif // #ifndef TF_FUZZ_HPP