1 /* UndefinedBehaviorSanitizer, undefined behavior detector.
2 Copyright (C) 2013 Free Software Foundation, Inc.
3 Contributed by Marek Polacek <polacek@redhat.com>
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
28 #include "pointer-set.h"
33 #include "c-family/c-common.h"
35 /* Map from a tree to a VAR_DECL tree. */
37 struct GTY(()) tree_type_map
{
38 struct tree_map_base type
;
42 #define tree_type_map_eq tree_map_base_eq
43 #define tree_type_map_hash tree_map_base_hash
44 #define tree_type_map_marked_p tree_map_base_marked_p
46 static GTY ((if_marked ("tree_type_map_marked_p"), param_is (struct tree_type_map
)))
47 htab_t decl_tree_for_type
;
49 /* Lookup a VAR_DECL for TYPE, and return it if we find one. */
52 decl_for_type_lookup (tree type
)
54 /* If the hash table is not initialized yet, create it now. */
55 if (decl_tree_for_type
== NULL
)
57 decl_tree_for_type
= htab_create_ggc (10, tree_type_map_hash
,
59 /* That also means we don't have to bother with the lookup. */
63 struct tree_type_map
*h
, in
;
66 h
= (struct tree_type_map
*)
67 htab_find_with_hash (decl_tree_for_type
, &in
, TYPE_UID (type
));
68 return h
? h
->decl
: NULL_TREE
;
71 /* Insert a mapping TYPE->DECL in the VAR_DECL for type hashtable. */
74 decl_for_type_insert (tree type
, tree decl
)
76 struct tree_type_map
*h
;
79 h
= ggc_alloc_tree_type_map ();
82 slot
= htab_find_slot_with_hash (decl_tree_for_type
, h
, TYPE_UID (type
),
84 *(struct tree_type_map
**) slot
= h
;
87 /* Helper routine, which encodes a value in the pointer_sized_int_node.
88 Arguments with precision <= POINTER_SIZE are passed directly,
89 the rest is passed by reference. T is a value we are to encode. */
92 ubsan_encode_value (tree t
)
94 tree type
= TREE_TYPE (t
);
95 switch (TREE_CODE (type
))
98 if (TYPE_PRECISION (type
) <= POINTER_SIZE
)
99 return fold_build1 (NOP_EXPR
, pointer_sized_int_node
, t
);
101 return build_fold_addr_expr (t
);
104 unsigned int bitsize
= GET_MODE_BITSIZE (TYPE_MODE (type
));
105 if (bitsize
<= POINTER_SIZE
)
107 tree itype
= build_nonstandard_integer_type (bitsize
, true);
108 t
= fold_build1 (VIEW_CONVERT_EXPR
, itype
, t
);
109 return fold_convert (pointer_sized_int_node
, t
);
113 if (!TREE_ADDRESSABLE (t
))
115 /* The reason for this is that we don't want to pessimize
116 code by making vars unnecessarily addressable. */
117 tree var
= create_tmp_var (TREE_TYPE (t
), NULL
);
118 tree tem
= build2 (MODIFY_EXPR
, void_type_node
, var
, t
);
119 t
= build_fold_addr_expr (var
);
120 return build2 (COMPOUND_EXPR
, TREE_TYPE (t
), tem
, t
);
123 return build_fold_addr_expr (t
);
132 struct __ubsan_type_descriptor
134 unsigned short __typekind;
135 unsigned short __typeinfo;
141 ubsan_type_descriptor_type (void)
143 static const char *field_names
[3]
144 = { "__typekind", "__typeinfo", "__typename" };
146 tree itype
= build_range_type (sizetype
, size_zero_node
, NULL_TREE
);
147 tree flex_arr_type
= build_array_type (char_type_node
, itype
);
149 ret
= make_node (RECORD_TYPE
);
150 for (int i
= 0; i
< 3; i
++)
152 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
,
153 get_identifier (field_names
[i
]),
154 (i
== 2) ? flex_arr_type
155 : short_unsigned_type_node
);
156 DECL_CONTEXT (fields
[i
]) = ret
;
158 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
160 TYPE_FIELDS (ret
) = fields
[0];
161 TYPE_NAME (ret
) = get_identifier ("__ubsan_type_descriptor");
167 struct __ubsan_source_location
169 const char *__filename;
171 unsigned int __column;
176 ubsan_source_location_type (void)
178 static const char *field_names
[3]
179 = { "__filename", "__line", "__column" };
181 tree const_char_type
= build_qualified_type (char_type_node
,
184 ret
= make_node (RECORD_TYPE
);
185 for (int i
= 0; i
< 3; i
++)
187 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
,
188 get_identifier (field_names
[i
]),
189 (i
== 0) ? build_pointer_type (const_char_type
)
190 : unsigned_type_node
);
191 DECL_CONTEXT (fields
[i
]) = ret
;
193 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
195 TYPE_FIELDS (ret
) = fields
[0];
196 TYPE_NAME (ret
) = get_identifier ("__ubsan_source_location");
201 /* Helper routine that returns a CONSTRUCTOR of __ubsan_source_location
202 type with its fields filled from a location_t LOC. */
205 ubsan_source_location (location_t loc
)
207 expanded_location xloc
;
208 tree type
= ubsan_source_location_type ();
210 xloc
= expand_location (loc
);
212 /* Fill in the values from LOC. */
213 size_t len
= strlen (xloc
.file
);
214 tree str
= build_string (len
+ 1, xloc
.file
);
215 TREE_TYPE (str
) = build_array_type (char_type_node
,
216 build_index_type (size_int (len
)));
217 TREE_READONLY (str
) = 1;
218 TREE_STATIC (str
) = 1;
219 str
= build_fold_addr_expr_loc (loc
, str
);
220 tree ctor
= build_constructor_va (type
, 3, NULL_TREE
, str
, NULL_TREE
,
221 build_int_cst (unsigned_type_node
,
222 xloc
.line
), NULL_TREE
,
223 build_int_cst (unsigned_type_node
,
225 TREE_CONSTANT (ctor
) = 1;
226 TREE_STATIC (ctor
) = 1;
231 /* This routine returns a magic number for TYPE. */
233 static unsigned short
234 get_ubsan_type_info_for_type (tree type
)
236 int prec
= exact_log2 (TYPE_PRECISION (type
));
238 error ("unexpected size of type %qT", type
);
240 return (prec
<< 1) | !TYPE_UNSIGNED (type
);
243 /* Helper routine that returns ADDR_EXPR of a VAR_DECL of a type
244 descriptor. It first looks into the pointer map; if not found,
245 create the VAR_DECL, put it into the pointer map and return the
246 ADDR_EXPR of it. TYPE describes a particular type. */
249 ubsan_type_descriptor (tree type
)
251 /* See through any typedefs. */
252 type
= TYPE_MAIN_VARIANT (type
);
254 tree decl
= decl_for_type_lookup (type
);
255 if (decl
!= NULL_TREE
)
258 tree dtype
= ubsan_type_descriptor_type ();
260 unsigned short tkind
, tinfo
;
262 /* At least for INTEGER_TYPE/REAL_TYPE/COMPLEX_TYPE, this should work.
263 ??? For e.g. type_unsigned_for (type), the TYPE_NAME would be NULL. */
264 if (TYPE_NAME (type
) != NULL
)
265 tname
= IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type
)));
268 if (TREE_CODE (type
) == INTEGER_TYPE
)
270 /* For INTEGER_TYPE, this is 0x0000. */
272 tinfo
= get_ubsan_type_info_for_type (type
);
274 else if (TREE_CODE (type
) == REAL_TYPE
)
275 /* We don't have float support yet. */
280 /* Create a new VAR_DECL of type descriptor. */
282 static unsigned int type_var_id_num
;
283 ASM_GENERATE_INTERNAL_LABEL (tmp_name
, "Lubsan_type", type_var_id_num
++);
284 decl
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
, get_identifier (tmp_name
),
286 TREE_STATIC (decl
) = 1;
287 TREE_PUBLIC (decl
) = 0;
288 DECL_ARTIFICIAL (decl
) = 1;
289 DECL_IGNORED_P (decl
) = 1;
290 DECL_EXTERNAL (decl
) = 0;
292 size_t len
= strlen (tname
);
293 tree str
= build_string (len
+ 1, tname
);
294 TREE_TYPE (str
) = build_array_type (char_type_node
,
295 build_index_type (size_int (len
)));
296 TREE_READONLY (str
) = 1;
297 TREE_STATIC (str
) = 1;
298 tree ctor
= build_constructor_va (dtype
, 3, NULL_TREE
,
299 build_int_cst (short_unsigned_type_node
,
301 build_int_cst (short_unsigned_type_node
,
302 tinfo
), NULL_TREE
, str
);
303 TREE_CONSTANT (ctor
) = 1;
304 TREE_STATIC (ctor
) = 1;
305 DECL_INITIAL (decl
) = ctor
;
306 rest_of_decl_compilation (decl
, 1, 0);
308 /* Save the address of the VAR_DECL into the pointer map. */
309 decl
= build_fold_addr_expr (decl
);
310 decl_for_type_insert (type
, decl
);
315 /* Create a structure for the ubsan library. NAME is a name of the new
316 structure. The arguments in ... are of __ubsan_type_descriptor type
317 and there are at most two of them. */
320 ubsan_create_data (const char *name
, location_t loc
, ...)
325 vec
<tree
, va_gc
> *saved_args
= NULL
;
328 /* Firstly, create a pointer to type descriptor type. */
329 tree td_type
= ubsan_type_descriptor_type ();
330 TYPE_READONLY (td_type
) = 1;
331 td_type
= build_pointer_type (td_type
);
333 /* Create the structure type. */
334 ret
= make_node (RECORD_TYPE
);
335 if (loc
!= UNKNOWN_LOCATION
)
337 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
, NULL_TREE
,
338 ubsan_source_location_type ());
339 DECL_CONTEXT (fields
[i
]) = ret
;
343 va_start (args
, loc
);
344 for (t
= va_arg (args
, tree
); t
!= NULL_TREE
;
345 i
++, t
= va_arg (args
, tree
))
347 gcc_checking_assert (i
< 3);
348 /* Save the tree argument for later use. */
349 vec_safe_push (saved_args
, t
);
350 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
, NULL_TREE
,
352 DECL_CONTEXT (fields
[i
]) = ret
;
354 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
356 TYPE_FIELDS (ret
) = fields
[0];
357 TYPE_NAME (ret
) = get_identifier (name
);
361 /* Now, fill in the type. */
363 static unsigned int ubsan_var_id_num
;
364 ASM_GENERATE_INTERNAL_LABEL (tmp_name
, "Lubsan_data", ubsan_var_id_num
++);
365 tree var
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
, get_identifier (tmp_name
),
367 TREE_STATIC (var
) = 1;
368 TREE_PUBLIC (var
) = 0;
369 DECL_ARTIFICIAL (var
) = 1;
370 DECL_IGNORED_P (var
) = 1;
371 DECL_EXTERNAL (var
) = 0;
373 vec
<constructor_elt
, va_gc
> *v
;
375 tree ctor
= build_constructor (ret
, v
);
377 /* If desirable, set the __ubsan_source_location element. */
378 if (loc
!= UNKNOWN_LOCATION
)
379 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, ubsan_source_location (loc
));
381 size_t nelts
= vec_safe_length (saved_args
);
382 for (i
= 0; i
< nelts
; i
++)
384 t
= (*saved_args
)[i
];
385 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, t
);
388 TREE_CONSTANT (ctor
) = 1;
389 TREE_STATIC (ctor
) = 1;
390 DECL_INITIAL (var
) = ctor
;
391 rest_of_decl_compilation (var
, 1, 0);
396 /* Instrument the __builtin_unreachable call. We just call the libubsan
400 ubsan_instrument_unreachable (location_t loc
)
402 tree data
= ubsan_create_data ("__ubsan_unreachable_data", loc
, NULL_TREE
);
403 tree t
= builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE
);
404 return build_call_expr_loc (loc
, t
, 1, build_fold_addr_expr_loc (loc
, data
));
407 /* Return true if T is a call to a libubsan routine. */
410 is_ubsan_builtin_p (tree t
)
412 gcc_checking_assert (TREE_CODE (t
) == FUNCTION_DECL
);
413 return strncmp (IDENTIFIER_POINTER (DECL_NAME (t
)),
414 "__builtin___ubsan_", 18) == 0;
417 #include "gt-ubsan.h"