xref: /aosp_15_r20/external/AFLplusplus/instrumentation/afl-gcc-cmptrs-pass.so.cc (revision 08b48e0b10e97b33e7b60c5b6e2243bd915777f2)
1*08b48e0bSAndroid Build Coastguard Worker /* GCC plugin for cmplog routines instrumentation of code for AFL++.
2*08b48e0bSAndroid Build Coastguard Worker 
3*08b48e0bSAndroid Build Coastguard Worker    Copyright 2014-2019 Free Software Foundation, Inc
4*08b48e0bSAndroid Build Coastguard Worker    Copyright 2015, 2016 Google Inc. All rights reserved.
5*08b48e0bSAndroid Build Coastguard Worker    Copyright 2019-2020 AFLplusplus Project. All rights reserved.
6*08b48e0bSAndroid Build Coastguard Worker    Copyright 2019-2024 AdaCore
7*08b48e0bSAndroid Build Coastguard Worker 
8*08b48e0bSAndroid Build Coastguard Worker    Written by Alexandre Oliva <[email protected]>, based on the AFL++
9*08b48e0bSAndroid Build Coastguard Worker    LLVM CmpLog Routines pass by Andrea Fioraldi
10*08b48e0bSAndroid Build Coastguard Worker    <[email protected]>, and on the AFL GCC CmpLog pass.
11*08b48e0bSAndroid Build Coastguard Worker 
12*08b48e0bSAndroid Build Coastguard Worker    This program is free software: you can redistribute it and/or modify
13*08b48e0bSAndroid Build Coastguard Worker    it under the terms of the GNU General Public License as published by
14*08b48e0bSAndroid Build Coastguard Worker    the Free Software Foundation, either version 3 of the License, or
15*08b48e0bSAndroid Build Coastguard Worker    (at your option) any later version.
16*08b48e0bSAndroid Build Coastguard Worker 
17*08b48e0bSAndroid Build Coastguard Worker    This program is distributed in the hope that it will be useful,
18*08b48e0bSAndroid Build Coastguard Worker    but WITHOUT ANY WARRANTY; without even the implied warranty of
19*08b48e0bSAndroid Build Coastguard Worker    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20*08b48e0bSAndroid Build Coastguard Worker    GNU General Public License for more details.
21*08b48e0bSAndroid Build Coastguard Worker 
22*08b48e0bSAndroid Build Coastguard Worker    You should have received a copy of the GNU General Public License
23*08b48e0bSAndroid Build Coastguard Worker    along with this program.  If not, see <http://www.gnu.org/licenses/>.
24*08b48e0bSAndroid Build Coastguard Worker 
25*08b48e0bSAndroid Build Coastguard Worker  */
26*08b48e0bSAndroid Build Coastguard Worker 
27*08b48e0bSAndroid Build Coastguard Worker #include "afl-gcc-common.h"
28*08b48e0bSAndroid Build Coastguard Worker 
29*08b48e0bSAndroid Build Coastguard Worker /* This plugin, being under the same license as GCC, satisfies the
30*08b48e0bSAndroid Build Coastguard Worker    "GPL-compatible Software" definition in the GCC RUNTIME LIBRARY
31*08b48e0bSAndroid Build Coastguard Worker    EXCEPTION, so it can be part of an "Eligible" "Compilation
32*08b48e0bSAndroid Build Coastguard Worker    Process".  */
33*08b48e0bSAndroid Build Coastguard Worker int plugin_is_GPL_compatible = 1;
34*08b48e0bSAndroid Build Coastguard Worker 
35*08b48e0bSAndroid Build Coastguard Worker namespace {
36*08b48e0bSAndroid Build Coastguard Worker 
37*08b48e0bSAndroid Build Coastguard Worker static const struct pass_data afl_cmptrs_pass_data = {
38*08b48e0bSAndroid Build Coastguard Worker 
39*08b48e0bSAndroid Build Coastguard Worker     .type = GIMPLE_PASS,
40*08b48e0bSAndroid Build Coastguard Worker     .name = "aflcmptrs",
41*08b48e0bSAndroid Build Coastguard Worker     .optinfo_flags = OPTGROUP_NONE,
42*08b48e0bSAndroid Build Coastguard Worker     .tv_id = TV_NONE,
43*08b48e0bSAndroid Build Coastguard Worker     .properties_required = 0,
44*08b48e0bSAndroid Build Coastguard Worker     .properties_provided = 0,
45*08b48e0bSAndroid Build Coastguard Worker     .properties_destroyed = 0,
46*08b48e0bSAndroid Build Coastguard Worker     .todo_flags_start = 0,
47*08b48e0bSAndroid Build Coastguard Worker     .todo_flags_finish = (TODO_update_ssa | TODO_cleanup_cfg | TODO_verify_il |
48*08b48e0bSAndroid Build Coastguard Worker                           TODO_rebuild_cgraph_edges),
49*08b48e0bSAndroid Build Coastguard Worker 
50*08b48e0bSAndroid Build Coastguard Worker };
51*08b48e0bSAndroid Build Coastguard Worker 
52*08b48e0bSAndroid Build Coastguard Worker struct afl_cmptrs_pass : afl_base_pass {
53*08b48e0bSAndroid Build Coastguard Worker 
afl_cmptrs_pass__anon21d00caf0111::afl_cmptrs_pass54*08b48e0bSAndroid Build Coastguard Worker   afl_cmptrs_pass(bool quiet)
55*08b48e0bSAndroid Build Coastguard Worker       : afl_base_pass(quiet, /*debug=*/false, afl_cmptrs_pass_data),
56*08b48e0bSAndroid Build Coastguard Worker         tp8u(),
57*08b48e0bSAndroid Build Coastguard Worker         cmptrs_hooks() {
58*08b48e0bSAndroid Build Coastguard Worker 
59*08b48e0bSAndroid Build Coastguard Worker   }
60*08b48e0bSAndroid Build Coastguard Worker 
61*08b48e0bSAndroid Build Coastguard Worker   /* A pointer type to a unsigned 8-bit integral type.  */
62*08b48e0bSAndroid Build Coastguard Worker   tree tp8u;
63*08b48e0bSAndroid Build Coastguard Worker 
64*08b48e0bSAndroid Build Coastguard Worker   /* Declarations for the various cmptrs hook functions, allocated on
65*08b48e0bSAndroid Build Coastguard Worker      demand..  [0] is for compares between any pointers, [1] is for
66*08b48e0bSAndroid Build Coastguard Worker      compares between G++ std::string, [2] is for compares between G++
67*08b48e0bSAndroid Build Coastguard Worker      std::string and GCC C strings, [3] and [4] are analogous to [1]
68*08b48e0bSAndroid Build Coastguard Worker      and [2] but for LLVM C++ strings.  */
69*08b48e0bSAndroid Build Coastguard Worker   tree cmptrs_hooks[5];
70*08b48e0bSAndroid Build Coastguard Worker 
cmptrs_hook__anon21d00caf0111::afl_cmptrs_pass71*08b48e0bSAndroid Build Coastguard Worker   tree cmptrs_hook(unsigned i) {
72*08b48e0bSAndroid Build Coastguard Worker 
73*08b48e0bSAndroid Build Coastguard Worker     if (!tp8u) {
74*08b48e0bSAndroid Build Coastguard Worker 
75*08b48e0bSAndroid Build Coastguard Worker       tree t8u;
76*08b48e0bSAndroid Build Coastguard Worker       if (BITS_PER_UNIT == 8)
77*08b48e0bSAndroid Build Coastguard Worker         t8u = unsigned_char_type_node;
78*08b48e0bSAndroid Build Coastguard Worker       else
79*08b48e0bSAndroid Build Coastguard Worker         t8u = build_nonstandard_integer_type(8, 1);
80*08b48e0bSAndroid Build Coastguard Worker       tp8u = build_pointer_type(t8u);
81*08b48e0bSAndroid Build Coastguard Worker 
82*08b48e0bSAndroid Build Coastguard Worker     }
83*08b48e0bSAndroid Build Coastguard Worker 
84*08b48e0bSAndroid Build Coastguard Worker     if (i <= ARRAY_SIZE(cmptrs_hooks) && cmptrs_hooks[i])
85*08b48e0bSAndroid Build Coastguard Worker       return cmptrs_hooks[i];
86*08b48e0bSAndroid Build Coastguard Worker 
87*08b48e0bSAndroid Build Coastguard Worker     const char *n = NULL;
88*08b48e0bSAndroid Build Coastguard Worker 
89*08b48e0bSAndroid Build Coastguard Worker     switch (i) {
90*08b48e0bSAndroid Build Coastguard Worker 
91*08b48e0bSAndroid Build Coastguard Worker       case 0:
92*08b48e0bSAndroid Build Coastguard Worker         n = "__cmplog_rtn_hook";
93*08b48e0bSAndroid Build Coastguard Worker         break;
94*08b48e0bSAndroid Build Coastguard Worker 
95*08b48e0bSAndroid Build Coastguard Worker       case 1:
96*08b48e0bSAndroid Build Coastguard Worker         n = "__cmplog_rtn_gcc_stdstring_stdstring";
97*08b48e0bSAndroid Build Coastguard Worker         break;
98*08b48e0bSAndroid Build Coastguard Worker 
99*08b48e0bSAndroid Build Coastguard Worker       case 2:
100*08b48e0bSAndroid Build Coastguard Worker         n = "__cmplog_rtn_gcc_stdstring_cstring";
101*08b48e0bSAndroid Build Coastguard Worker         break;
102*08b48e0bSAndroid Build Coastguard Worker 
103*08b48e0bSAndroid Build Coastguard Worker       case 3:
104*08b48e0bSAndroid Build Coastguard Worker         n = "__cmplog_rtn_llvm_stdstring_stdstring";
105*08b48e0bSAndroid Build Coastguard Worker         break;
106*08b48e0bSAndroid Build Coastguard Worker 
107*08b48e0bSAndroid Build Coastguard Worker       case 4:
108*08b48e0bSAndroid Build Coastguard Worker         n = "__cmplog_rtn_llvm_stdstring_cstring";
109*08b48e0bSAndroid Build Coastguard Worker         break;
110*08b48e0bSAndroid Build Coastguard Worker 
111*08b48e0bSAndroid Build Coastguard Worker       default:
112*08b48e0bSAndroid Build Coastguard Worker         gcc_unreachable();
113*08b48e0bSAndroid Build Coastguard Worker 
114*08b48e0bSAndroid Build Coastguard Worker     }
115*08b48e0bSAndroid Build Coastguard Worker 
116*08b48e0bSAndroid Build Coastguard Worker     tree fnt = build_function_type_list(void_type_node, tp8u, tp8u, NULL_TREE);
117*08b48e0bSAndroid Build Coastguard Worker     tree t = cmptrs_hooks[i] = build_fn_decl(n, fnt);
118*08b48e0bSAndroid Build Coastguard Worker 
119*08b48e0bSAndroid Build Coastguard Worker     /* Mark the newly-created decl as non-throwing, so that we can
120*08b48e0bSAndroid Build Coastguard Worker        insert call within basic blocks.  */
121*08b48e0bSAndroid Build Coastguard Worker     TREE_NOTHROW(t) = 1;
122*08b48e0bSAndroid Build Coastguard Worker 
123*08b48e0bSAndroid Build Coastguard Worker     return t;
124*08b48e0bSAndroid Build Coastguard Worker 
125*08b48e0bSAndroid Build Coastguard Worker   }
126*08b48e0bSAndroid Build Coastguard Worker 
127*08b48e0bSAndroid Build Coastguard Worker   /* Return true if T is the char* type.  */
is_c_string__anon21d00caf0111::afl_cmptrs_pass128*08b48e0bSAndroid Build Coastguard Worker   bool is_c_string(tree t) {
129*08b48e0bSAndroid Build Coastguard Worker 
130*08b48e0bSAndroid Build Coastguard Worker     return (POINTER_TYPE_P(t) &&
131*08b48e0bSAndroid Build Coastguard Worker             TYPE_MAIN_VARIANT(TREE_TYPE(t)) == char_type_node);
132*08b48e0bSAndroid Build Coastguard Worker 
133*08b48e0bSAndroid Build Coastguard Worker   }
134*08b48e0bSAndroid Build Coastguard Worker 
135*08b48e0bSAndroid Build Coastguard Worker   /* Return true if T is an indirect std::string type.  The LLVM pass
136*08b48e0bSAndroid Build Coastguard Worker      tests portions of the mangled name of the callee.  We could do
137*08b48e0bSAndroid Build Coastguard Worker      that in GCC too, but computing the mangled name may cause
138*08b48e0bSAndroid Build Coastguard Worker      template instantiations and get symbols defined that could
139*08b48e0bSAndroid Build Coastguard Worker      otherwise be considered unused.  We check for compatible layout,
140*08b48e0bSAndroid Build Coastguard Worker      and class, namespace, and field names.  These have been unchanged
141*08b48e0bSAndroid Build Coastguard Worker      since at least GCC 7, probably longer, up to GCC 11.  Odds are
142*08b48e0bSAndroid Build Coastguard Worker      that, if it were to change in significant ways, mangling would
143*08b48e0bSAndroid Build Coastguard Worker      also change to flag the incompatibility, and we'd have to use a
144*08b48e0bSAndroid Build Coastguard Worker      different hook anyway.  */
is_gxx_std_string__anon21d00caf0111::afl_cmptrs_pass145*08b48e0bSAndroid Build Coastguard Worker   bool is_gxx_std_string(tree t) {
146*08b48e0bSAndroid Build Coastguard Worker 
147*08b48e0bSAndroid Build Coastguard Worker     /* We need a pointer or reference type.  */
148*08b48e0bSAndroid Build Coastguard Worker     if (!POINTER_TYPE_P(t)) return false;
149*08b48e0bSAndroid Build Coastguard Worker 
150*08b48e0bSAndroid Build Coastguard Worker     /* Get to the pointed-to type.  */
151*08b48e0bSAndroid Build Coastguard Worker     t = TREE_TYPE(t);
152*08b48e0bSAndroid Build Coastguard Worker     if (!t) return false;
153*08b48e0bSAndroid Build Coastguard Worker 
154*08b48e0bSAndroid Build Coastguard Worker     /* Select the main variant, so that can compare types with pointers.  */
155*08b48e0bSAndroid Build Coastguard Worker     t = TYPE_MAIN_VARIANT(t);
156*08b48e0bSAndroid Build Coastguard Worker 
157*08b48e0bSAndroid Build Coastguard Worker     /* We expect it to be a record type.  */
158*08b48e0bSAndroid Build Coastguard Worker     if (TREE_CODE(t) != RECORD_TYPE) return false;
159*08b48e0bSAndroid Build Coastguard Worker 
160*08b48e0bSAndroid Build Coastguard Worker     /* The type has an identifier.  */
161*08b48e0bSAndroid Build Coastguard Worker     if (!TYPE_IDENTIFIER(t)) return false;
162*08b48e0bSAndroid Build Coastguard Worker 
163*08b48e0bSAndroid Build Coastguard Worker     /* The type of the template is basic_string.  */
164*08b48e0bSAndroid Build Coastguard Worker     if (strcmp(IDENTIFIER_POINTER(TYPE_IDENTIFIER(t)), "basic_string") != 0)
165*08b48e0bSAndroid Build Coastguard Worker       return false;
166*08b48e0bSAndroid Build Coastguard Worker 
167*08b48e0bSAndroid Build Coastguard Worker     /* It's declared in an internal namespace named __cxx11.  */
168*08b48e0bSAndroid Build Coastguard Worker     tree c = DECL_CONTEXT(TYPE_NAME(t));
169*08b48e0bSAndroid Build Coastguard Worker     if (!c || TREE_CODE(c) != NAMESPACE_DECL ||
170*08b48e0bSAndroid Build Coastguard Worker         strcmp(IDENTIFIER_POINTER(DECL_NAME(c)), "__cxx11") != 0)
171*08b48e0bSAndroid Build Coastguard Worker       return false;
172*08b48e0bSAndroid Build Coastguard Worker 
173*08b48e0bSAndroid Build Coastguard Worker     /* The __cxx11 namespace is a member of namespace std.  */
174*08b48e0bSAndroid Build Coastguard Worker     c = DECL_CONTEXT(c);
175*08b48e0bSAndroid Build Coastguard Worker     if (!c || TREE_CODE(c) != NAMESPACE_DECL ||
176*08b48e0bSAndroid Build Coastguard Worker         strcmp(IDENTIFIER_POINTER(DECL_NAME(c)), "std") != 0)
177*08b48e0bSAndroid Build Coastguard Worker       return false;
178*08b48e0bSAndroid Build Coastguard Worker 
179*08b48e0bSAndroid Build Coastguard Worker     /* And the std namespace is in the global namespace.  */
180*08b48e0bSAndroid Build Coastguard Worker     c = DECL_CONTEXT(c);
181*08b48e0bSAndroid Build Coastguard Worker     if (c && TREE_CODE(c) != TRANSLATION_UNIT_DECL) return false;
182*08b48e0bSAndroid Build Coastguard Worker 
183*08b48e0bSAndroid Build Coastguard Worker     /* Check that the first nonstatic data member of the record type
184*08b48e0bSAndroid Build Coastguard Worker        is named _M_dataplus.  */
185*08b48e0bSAndroid Build Coastguard Worker     for (c = TYPE_FIELDS(t); c; c = DECL_CHAIN(c))
186*08b48e0bSAndroid Build Coastguard Worker       if (TREE_CODE(c) == FIELD_DECL) break;
187*08b48e0bSAndroid Build Coastguard Worker     if (!c || !integer_zerop(DECL_FIELD_BIT_OFFSET(c)) ||
188*08b48e0bSAndroid Build Coastguard Worker         strcmp(IDENTIFIER_POINTER(DECL_NAME(c)), "_M_dataplus") != 0)
189*08b48e0bSAndroid Build Coastguard Worker       return false;
190*08b48e0bSAndroid Build Coastguard Worker 
191*08b48e0bSAndroid Build Coastguard Worker     /* Check that the second nonstatic data member of the record type
192*08b48e0bSAndroid Build Coastguard Worker        is named _M_string_length.  */
193*08b48e0bSAndroid Build Coastguard Worker     tree f2;
194*08b48e0bSAndroid Build Coastguard Worker     for (f2 = DECL_CHAIN(c); f2; f2 = DECL_CHAIN(f2))
195*08b48e0bSAndroid Build Coastguard Worker       if (TREE_CODE(f2) == FIELD_DECL) break;
196*08b48e0bSAndroid Build Coastguard Worker     if (!f2                       /* No need to check this field's offset.  */
197*08b48e0bSAndroid Build Coastguard Worker         || strcmp(IDENTIFIER_POINTER(DECL_NAME(f2)), "_M_string_length") != 0)
198*08b48e0bSAndroid Build Coastguard Worker       return false;
199*08b48e0bSAndroid Build Coastguard Worker 
200*08b48e0bSAndroid Build Coastguard Worker     /* The type of the second data member is size_t.  */
201*08b48e0bSAndroid Build Coastguard Worker     if (!TREE_TYPE(f2) || TYPE_MAIN_VARIANT(TREE_TYPE(f2)) != size_type_node)
202*08b48e0bSAndroid Build Coastguard Worker       return false;
203*08b48e0bSAndroid Build Coastguard Worker 
204*08b48e0bSAndroid Build Coastguard Worker     /* Now go back to the first data member.  Its type should be a
205*08b48e0bSAndroid Build Coastguard Worker        record type named _Alloc_hider.  */
206*08b48e0bSAndroid Build Coastguard Worker     c = TREE_TYPE(c);
207*08b48e0bSAndroid Build Coastguard Worker     if (!c || TREE_CODE(c) != RECORD_TYPE || !TYPE_IDENTIFIER(t) ||
208*08b48e0bSAndroid Build Coastguard Worker         strcmp(IDENTIFIER_POINTER(TYPE_IDENTIFIER(c)), "_Alloc_hider") != 0)
209*08b48e0bSAndroid Build Coastguard Worker       return false;
210*08b48e0bSAndroid Build Coastguard Worker 
211*08b48e0bSAndroid Build Coastguard Worker     /* And its first data member is named _M_p.  */
212*08b48e0bSAndroid Build Coastguard Worker     for (c = TYPE_FIELDS(c); c; c = DECL_CHAIN(c))
213*08b48e0bSAndroid Build Coastguard Worker       if (TREE_CODE(c) == FIELD_DECL) break;
214*08b48e0bSAndroid Build Coastguard Worker     if (!c || !integer_zerop(DECL_FIELD_BIT_OFFSET(c)) ||
215*08b48e0bSAndroid Build Coastguard Worker         strcmp(IDENTIFIER_POINTER(DECL_NAME(c)), "_M_p") != 0)
216*08b48e0bSAndroid Build Coastguard Worker       return false;
217*08b48e0bSAndroid Build Coastguard Worker 
218*08b48e0bSAndroid Build Coastguard Worker     /* For the basic_string<char> type we're interested in, the type
219*08b48e0bSAndroid Build Coastguard Worker        of the data member is the C string type.  */
220*08b48e0bSAndroid Build Coastguard Worker     if (!is_c_string(TREE_TYPE(c))) return false;
221*08b48e0bSAndroid Build Coastguard Worker 
222*08b48e0bSAndroid Build Coastguard Worker     /* This might not be the real thing, but the bits that matter for
223*08b48e0bSAndroid Build Coastguard Worker        the hook are there.  */
224*08b48e0bSAndroid Build Coastguard Worker 
225*08b48e0bSAndroid Build Coastguard Worker     return true;
226*08b48e0bSAndroid Build Coastguard Worker 
227*08b48e0bSAndroid Build Coastguard Worker   }
228*08b48e0bSAndroid Build Coastguard Worker 
229*08b48e0bSAndroid Build Coastguard Worker   /* ??? This is not implemented.  What would the point be of
230*08b48e0bSAndroid Build Coastguard Worker      recognizing LLVM's string type in GCC?  */
is_llvm_std_string__anon21d00caf0111::afl_cmptrs_pass231*08b48e0bSAndroid Build Coastguard Worker   bool is_llvm_std_string(tree t) {
232*08b48e0bSAndroid Build Coastguard Worker 
233*08b48e0bSAndroid Build Coastguard Worker     return false;
234*08b48e0bSAndroid Build Coastguard Worker 
235*08b48e0bSAndroid Build Coastguard Worker   }
236*08b48e0bSAndroid Build Coastguard Worker 
execute__anon21d00caf0111::afl_cmptrs_pass237*08b48e0bSAndroid Build Coastguard Worker   virtual unsigned int execute(function *fn) {
238*08b48e0bSAndroid Build Coastguard Worker 
239*08b48e0bSAndroid Build Coastguard Worker     if (!isInInstrumentList(fn)) return 0;
240*08b48e0bSAndroid Build Coastguard Worker 
241*08b48e0bSAndroid Build Coastguard Worker     basic_block bb;
242*08b48e0bSAndroid Build Coastguard Worker     FOR_EACH_BB_FN(bb, fn) {
243*08b48e0bSAndroid Build Coastguard Worker 
244*08b48e0bSAndroid Build Coastguard Worker       for (gimple_stmt_iterator gsi = gsi_after_labels(bb); !gsi_end_p(gsi);
245*08b48e0bSAndroid Build Coastguard Worker            gsi_next(&gsi)) {
246*08b48e0bSAndroid Build Coastguard Worker 
247*08b48e0bSAndroid Build Coastguard Worker         gimple stmt = gsi_stmt(gsi);
248*08b48e0bSAndroid Build Coastguard Worker 
249*08b48e0bSAndroid Build Coastguard Worker         /* We're only interested in GIMPLE_CALLs.  */
250*08b48e0bSAndroid Build Coastguard Worker         if (gimple_code(stmt) != GIMPLE_CALL) continue;
251*08b48e0bSAndroid Build Coastguard Worker 
252*08b48e0bSAndroid Build Coastguard Worker         if (gimple_call_num_args(stmt) < 2) continue;
253*08b48e0bSAndroid Build Coastguard Worker 
254*08b48e0bSAndroid Build Coastguard Worker         gcall *c = as_a<gcall *>(stmt);
255*08b48e0bSAndroid Build Coastguard Worker 
256*08b48e0bSAndroid Build Coastguard Worker         tree callee_type = gimple_call_fntype(c);
257*08b48e0bSAndroid Build Coastguard Worker 
258*08b48e0bSAndroid Build Coastguard Worker         if (!callee_type || !TYPE_ARG_TYPES(callee_type) ||
259*08b48e0bSAndroid Build Coastguard Worker             !TREE_CHAIN(TYPE_ARG_TYPES(callee_type)))
260*08b48e0bSAndroid Build Coastguard Worker           continue;
261*08b48e0bSAndroid Build Coastguard Worker 
262*08b48e0bSAndroid Build Coastguard Worker         tree arg_type[2] = {
263*08b48e0bSAndroid Build Coastguard Worker 
264*08b48e0bSAndroid Build Coastguard Worker             TYPE_MAIN_VARIANT(TREE_VALUE(TYPE_ARG_TYPES(callee_type))),
265*08b48e0bSAndroid Build Coastguard Worker             TYPE_MAIN_VARIANT(
266*08b48e0bSAndroid Build Coastguard Worker                 TREE_VALUE(TREE_CHAIN(TYPE_ARG_TYPES(callee_type))))};
267*08b48e0bSAndroid Build Coastguard Worker 
268*08b48e0bSAndroid Build Coastguard Worker         tree fn = NULL;
269*08b48e0bSAndroid Build Coastguard Worker         /* Callee arglist starts with two GCC std::string arguments.  */
270*08b48e0bSAndroid Build Coastguard Worker         if (arg_type[0] == arg_type[1] && is_gxx_std_string(arg_type[0]))
271*08b48e0bSAndroid Build Coastguard Worker           fn = cmptrs_hook(1);
272*08b48e0bSAndroid Build Coastguard Worker         /* Callee arglist starts with GCC std::string and C string.  */
273*08b48e0bSAndroid Build Coastguard Worker         else if (is_gxx_std_string(arg_type[0]) && is_c_string(arg_type[1]))
274*08b48e0bSAndroid Build Coastguard Worker           fn = cmptrs_hook(2);
275*08b48e0bSAndroid Build Coastguard Worker         /* Callee arglist starts with two LLVM std::string arguments.  */
276*08b48e0bSAndroid Build Coastguard Worker         else if (arg_type[0] == arg_type[1] && is_llvm_std_string(arg_type[0]))
277*08b48e0bSAndroid Build Coastguard Worker           fn = cmptrs_hook(3);
278*08b48e0bSAndroid Build Coastguard Worker         /* Callee arglist starts with LLVM std::string and C string.  */
279*08b48e0bSAndroid Build Coastguard Worker         else if (is_llvm_std_string(arg_type[0]) && is_c_string(arg_type[1]))
280*08b48e0bSAndroid Build Coastguard Worker           fn = cmptrs_hook(4);
281*08b48e0bSAndroid Build Coastguard Worker         /* Callee arglist starts with two pointers to the same type,
282*08b48e0bSAndroid Build Coastguard Worker            and callee returns a value.  */
283*08b48e0bSAndroid Build Coastguard Worker         else if (arg_type[0] == arg_type[1] && POINTER_TYPE_P(arg_type[0]) &&
284*08b48e0bSAndroid Build Coastguard Worker                  (TYPE_MAIN_VARIANT(gimple_call_return_type(c)) !=
285*08b48e0bSAndroid Build Coastguard Worker                   void_type_node))
286*08b48e0bSAndroid Build Coastguard Worker           fn = cmptrs_hook(0);
287*08b48e0bSAndroid Build Coastguard Worker         else
288*08b48e0bSAndroid Build Coastguard Worker           continue;
289*08b48e0bSAndroid Build Coastguard Worker 
290*08b48e0bSAndroid Build Coastguard Worker         tree arg[2] = {gimple_call_arg(c, 0), gimple_call_arg(c, 1)};
291*08b48e0bSAndroid Build Coastguard Worker 
292*08b48e0bSAndroid Build Coastguard Worker         for (unsigned i = 0; i < ARRAY_SIZE(arg); i++) {
293*08b48e0bSAndroid Build Coastguard Worker 
294*08b48e0bSAndroid Build Coastguard Worker           tree c = fold_convert_loc(UNKNOWN_LOCATION, tp8u, arg[i]);
295*08b48e0bSAndroid Build Coastguard Worker           if (!is_gimple_val(c)) {
296*08b48e0bSAndroid Build Coastguard Worker 
297*08b48e0bSAndroid Build Coastguard Worker             tree   s = make_ssa_name(tp8u);
298*08b48e0bSAndroid Build Coastguard Worker             gimple g = gimple_build_assign(s, c);
299*08b48e0bSAndroid Build Coastguard Worker             c = s;
300*08b48e0bSAndroid Build Coastguard Worker             gsi_insert_before(&gsi, g, GSI_SAME_STMT);
301*08b48e0bSAndroid Build Coastguard Worker 
302*08b48e0bSAndroid Build Coastguard Worker           }
303*08b48e0bSAndroid Build Coastguard Worker 
304*08b48e0bSAndroid Build Coastguard Worker           arg[i] = c;
305*08b48e0bSAndroid Build Coastguard Worker 
306*08b48e0bSAndroid Build Coastguard Worker         }
307*08b48e0bSAndroid Build Coastguard Worker 
308*08b48e0bSAndroid Build Coastguard Worker         gimple call = gimple_build_call(fn, 2, arg[0], arg[1]);
309*08b48e0bSAndroid Build Coastguard Worker         gsi_insert_before(&gsi, call, GSI_SAME_STMT);
310*08b48e0bSAndroid Build Coastguard Worker 
311*08b48e0bSAndroid Build Coastguard Worker       }
312*08b48e0bSAndroid Build Coastguard Worker 
313*08b48e0bSAndroid Build Coastguard Worker     }
314*08b48e0bSAndroid Build Coastguard Worker 
315*08b48e0bSAndroid Build Coastguard Worker     return 0;
316*08b48e0bSAndroid Build Coastguard Worker 
317*08b48e0bSAndroid Build Coastguard Worker   }
318*08b48e0bSAndroid Build Coastguard Worker 
319*08b48e0bSAndroid Build Coastguard Worker };
320*08b48e0bSAndroid Build Coastguard Worker 
321*08b48e0bSAndroid Build Coastguard Worker static struct plugin_info afl_cmptrs_plugin = {
322*08b48e0bSAndroid Build Coastguard Worker 
323*08b48e0bSAndroid Build Coastguard Worker     .version = "20220420",
324*08b48e0bSAndroid Build Coastguard Worker     .help = G_("AFL gcc cmptrs plugin\n\
325*08b48e0bSAndroid Build Coastguard Worker \n\
326*08b48e0bSAndroid Build Coastguard Worker Set AFL_QUIET in the environment to silence it.\n\
327*08b48e0bSAndroid Build Coastguard Worker "),
328*08b48e0bSAndroid Build Coastguard Worker 
329*08b48e0bSAndroid Build Coastguard Worker };
330*08b48e0bSAndroid Build Coastguard Worker 
331*08b48e0bSAndroid Build Coastguard Worker }  // namespace
332*08b48e0bSAndroid Build Coastguard Worker 
333*08b48e0bSAndroid Build Coastguard Worker /* This is the function GCC calls when loading a plugin.  Initialize
334*08b48e0bSAndroid Build Coastguard Worker    and register further callbacks.  */
plugin_init(struct plugin_name_args * info,struct plugin_gcc_version * version)335*08b48e0bSAndroid Build Coastguard Worker int plugin_init(struct plugin_name_args   *info,
336*08b48e0bSAndroid Build Coastguard Worker                 struct plugin_gcc_version *version) {
337*08b48e0bSAndroid Build Coastguard Worker 
338*08b48e0bSAndroid Build Coastguard Worker   if (!plugin_default_version_check(version, &gcc_version))
339*08b48e0bSAndroid Build Coastguard Worker     FATAL(G_("GCC and plugin have incompatible versions, expected GCC %s, "
340*08b48e0bSAndroid Build Coastguard Worker              "is %s"),
341*08b48e0bSAndroid Build Coastguard Worker           gcc_version.basever, version->basever);
342*08b48e0bSAndroid Build Coastguard Worker 
343*08b48e0bSAndroid Build Coastguard Worker   /* Show a banner.  */
344*08b48e0bSAndroid Build Coastguard Worker   bool quiet = false;
345*08b48e0bSAndroid Build Coastguard Worker   if (isatty(2) && !getenv("AFL_QUIET"))
346*08b48e0bSAndroid Build Coastguard Worker     SAYF(cCYA "afl-gcc-cmptrs-pass " cBRI VERSION cRST
347*08b48e0bSAndroid Build Coastguard Worker               " by <[email protected]>\n");
348*08b48e0bSAndroid Build Coastguard Worker   else
349*08b48e0bSAndroid Build Coastguard Worker     quiet = true;
350*08b48e0bSAndroid Build Coastguard Worker 
351*08b48e0bSAndroid Build Coastguard Worker   const char *name = info->base_name;
352*08b48e0bSAndroid Build Coastguard Worker   register_callback(name, PLUGIN_INFO, NULL, &afl_cmptrs_plugin);
353*08b48e0bSAndroid Build Coastguard Worker 
354*08b48e0bSAndroid Build Coastguard Worker   afl_cmptrs_pass          *aflp = new afl_cmptrs_pass(quiet);
355*08b48e0bSAndroid Build Coastguard Worker   struct register_pass_info pass_info = {
356*08b48e0bSAndroid Build Coastguard Worker 
357*08b48e0bSAndroid Build Coastguard Worker       .pass = aflp,
358*08b48e0bSAndroid Build Coastguard Worker       .reference_pass_name = "ssa",
359*08b48e0bSAndroid Build Coastguard Worker       .ref_pass_instance_number = 1,
360*08b48e0bSAndroid Build Coastguard Worker       .pos_op = PASS_POS_INSERT_AFTER,
361*08b48e0bSAndroid Build Coastguard Worker 
362*08b48e0bSAndroid Build Coastguard Worker   };
363*08b48e0bSAndroid Build Coastguard Worker 
364*08b48e0bSAndroid Build Coastguard Worker   register_callback(name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info);
365*08b48e0bSAndroid Build Coastguard Worker 
366*08b48e0bSAndroid Build Coastguard Worker   return 0;
367*08b48e0bSAndroid Build Coastguard Worker 
368*08b48e0bSAndroid Build Coastguard Worker }
369*08b48e0bSAndroid Build Coastguard Worker 
370