1 /* EfficiencySanitizer.
2 Copyright (C) 2011-2018 Free Software Foundation, Inc.
3 Contributed by Denis Khalikov.
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"
29 #include "tree-pass.h"
31 #include "fold-const.h"
33 #include "gimple-iterator.h"
34 #include "gimplify-me.h"
36 #include "tree-iterator.h"
38 #include "stringpool.h"
43 #include "stor-layout.h"
45 #include "gimple-fold.h"
47 /* The size taken from llvm part. */
48 static const unsigned max_struct_field_counter_name_size = 512;
49 static char field_counter_name[max_struct_field_counter_name_size];
50 static char counter_prefix[] = "struct.";
52 /* Struct represents internal information about processed
57 : type (NULL_TREE), array_type (NULL_TREE), field_counter_name (NULL),
62 esan_type (tree t, tree a)
63 : type (t), array_type (a), field_counter_name (NULL), fields_count (0)
67 esan_type (const int value)
70 type = array_type = NULL_TREE;
75 char *field_counter_name;
79 /* Represents the type, field and index related to them.
80 Why do we need this type at all ?
82 Assume we have following classes A, B, C as A <- B <- C,
83 and field access load %reg, &C->A_field, so we should
84 go recurively and find actual type A and field index
86 This struct hepls to solve that problem.
88 struct esan_field_index
90 esan_field_index () : type (NULL_TREE), field (NULL_TREE), index (0) {}
92 esan_field_index (tree base_type, tree base_field, size_t base_index)
93 : type (base_type), field (base_field), index (base_index)
97 esan_field_index (const esan_field_index &other)
105 operator= (const esan_field_index &other)
121 /* FIXME: use hash_set<K, K_Traits> instead vec<T>
122 to improve search from O(n) to O(1). */
123 static vec<esan_type> vec_esan_type;
126 get_memory_access_decl (bool is_store, unsigned size)
128 /* Choose an appropriate builtin. */
129 enum built_in_function fcode;
132 = is_store ? BUILT_IN_ESAN_ALIGNED_STORE1 : BUILT_IN_ESAN_ALIGNED_LOAD1;
135 = is_store ? BUILT_IN_ESAN_ALIGNED_STORE2 : BUILT_IN_ESAN_ALIGNED_LOAD2;
138 = is_store ? BUILT_IN_ESAN_ALIGNED_STORE4 : BUILT_IN_ESAN_ALIGNED_LOAD4;
141 = is_store ? BUILT_IN_ESAN_ALIGNED_STORE8 : BUILT_IN_ESAN_ALIGNED_LOAD8;
144 = is_store ? BUILT_IN_ESAN_ALIGNED_STORE16 : BUILT_IN_ESAN_ALIGNED_LOAD16;
145 return builtin_decl_implicit (fcode);
149 instrument_expr (gimple_stmt_iterator gsi, tree expr, bool is_store)
159 size = int_size_in_bytes (TREE_TYPE (expr));
160 /* Can't instrument memory accesses in case of size <= 0. */
164 HOST_WIDE_INT unused_bitsize, unused_bitpos;
167 int unsignedp, reversep, volatilep = 0;
169 base = get_inner_reference (expr, &unused_bitsize, &unused_bitpos, &offset,
170 &mode, &unsignedp, &reversep, &volatilep, false);
172 if (TREE_READONLY (base) || (VAR_P (base) && DECL_HARD_REGISTER (base)))
175 stmt = gsi_stmt (gsi);
176 loc = gimple_location (stmt);
177 align = get_object_alignment (expr);
178 /* In this case we can't instrument memmory access. */
179 if (align < BITS_PER_UNIT)
182 /* In this case we need folded ptr to expression. */
183 expr_ptr = build_fold_addr_expr (unshare_expr (expr));
185 expr_ptr = force_gimple_operand (expr_ptr, &seq, true, NULL_TREE);
186 /* Build the esan's builtin. */
187 g = gimple_build_call (get_memory_access_decl (is_store, size), 1, expr_ptr);
189 gimple_set_location (g, loc);
190 gimple_seq_add_stmt_without_update (&seq, g);
192 if (is_gimple_call (stmt) && is_store)
194 /* Could be a fallthrough edge. */
195 if (is_ctrl_altering_stmt (stmt))
200 e = find_fallthru_edge (bb->succs);
202 gsi_insert_seq_on_edge_immediate (e, seq);
205 /* Insert after the call on store. */
206 gsi_insert_seq_after (&gsi, seq, GSI_NEW_STMT);
210 gsi_insert_seq_before (&gsi, seq, GSI_SAME_STMT);
214 maybe_instrument_working_set_gimple (gimple_stmt_iterator *gsi)
219 stmt = gsi_stmt (*gsi);
221 if (is_gimple_call (stmt))
224 if (is_gimple_assign (stmt) && !gimple_clobber_p (stmt))
226 if (gimple_store_p (stmt))
228 lhs = gimple_assign_lhs (stmt);
229 instrument_expr (*gsi, lhs, true);
231 if (gimple_assign_load_p (stmt))
233 rhs = gimple_assign_rhs1 (stmt);
234 instrument_expr (*gsi, rhs, false);
239 static size_t type_count;
240 static size_t default_count;
242 /* Function generates unique id. */
244 gen_unique_id (char *buff, size_t *t_count)
247 size_t count = *t_count;
250 *buff++ = '0' + count % 10;
259 convert_to_type_id (char *buff, tree field_type)
261 switch (TREE_CODE (field_type))
284 return gen_unique_id (buff, &type_count);
289 return gen_unique_id (buff, &default_count);
295 reverse (char *buff, size_t len)
302 for (start = 0, end = len - 1; start < end; ++start, --end)
304 char temp = buff[end];
305 buff[end] = buff[start];
311 unique_id_size (size_t t_count)
323 field_type_size (tree field)
325 if (TREE_CODE (field) == FIELD_DECL)
327 switch (TREE_CODE (TREE_TYPE (field)))
338 return unique_id_size (type_count);
342 return unique_id_size (default_count);
346 /* Skip nested types. */
350 /* Functions creates struct field counter name consistent with
351 llvm part, because runtime relies on it. */
353 create_struct_field_counter_name (tree type, size_t *count)
356 size_t offset, start;
357 const char *type_name;
359 /* Could be NULL type identifier. */
360 if (!TYPE_IDENTIFIER (type))
363 type_name = IDENTIFIER_POINTER (TYPE_IDENTIFIER (type));
364 *count = offset = start = 0;
366 memset (field_counter_name, 0, max_struct_field_counter_name_size);
368 size_t counter_prefix_len = strlen (counter_prefix);
369 memcpy (field_counter_name, counter_prefix, counter_prefix_len);
370 offset += counter_prefix_len;
372 size_t type_name_len = strlen (type_name);
374 if (type_name_len + counter_prefix_len >= max_struct_field_counter_name_size)
377 memcpy (field_counter_name + offset, type_name, type_name_len);
378 offset += type_name_len;
382 for (field = TYPE_FIELDS (type); field
383 /* offset + sizeof (field) + sizeof ($). */
384 && (offset + field_type_size (field) + 1)
385 < max_struct_field_counter_name_size;
386 field = DECL_CHAIN (field))
388 if (TREE_CODE (field) == FIELD_DECL)
390 offset += convert_to_type_id (field_counter_name + offset,
392 field_counter_name[offset++] = '$';
393 /* Don't count nested types as a field. */
394 if (TREE_CODE (TREE_TYPE (field)) != RECORD_TYPE)
399 /* This is strangely, but llvm part writes fields id in reverse order. */
400 reverse (field_counter_name + start, offset - start);
404 /* This should be kept consistent with LLVM's EfficiencySanitizer StructInfo.
406 const char *StructName;
409 u32 *FieldOffset; // auxiliary struct field info.
410 u32 *FieldSize; // auxiliary struct field info.
411 const char **FieldTypeName; // auxiliary struct field info.
416 /* Cached strcut_info_type tree. */
417 static tree esan_struct_info_type;
419 /* Returns struct_info_type tree. */
421 esan_get_struct_info_type (void)
423 /* Decription taken from llvm. */
424 static const unsigned int count = 8;
425 static const char *field_names[count]
426 = {"StructName", "Size", "NumFields", "FieldOffset",
427 "FieldSize", "FieldTypeName", "FieldCounters", "ArrayCounters"};
428 tree fields[count], ret;
430 if (esan_struct_info_type)
431 return esan_struct_info_type;
433 tree range_type = build_range_type (sizetype, size_zero_node, NULL_TREE);
434 /* StructName is a ptr to char with flex size. */
435 tree flex_char_arr_type = build_array_type (char_type_node, range_type);
436 /* FieldOffset and FieldSize ptrs. */
437 tree flex_uint_arr_type = build_array_type (unsigned_type_node, range_type);
438 /* FieldCounter and ArrayCounter. */
439 tree flex_luint_arr_type
440 = build_array_type (long_long_unsigned_type_node, range_type);
442 ret = make_node (RECORD_TYPE);
443 for (unsigned int i = 0; i < count; ++i)
449 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
450 get_identifier (field_names[i]),
451 build_pointer_type (flex_char_arr_type));
456 = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
457 get_identifier (field_names[i]), unsigned_type_node);
461 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
462 get_identifier (field_names[i]),
463 build_pointer_type (flex_uint_arr_type));
467 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
468 get_identifier (field_names[i]),
469 build_pointer_type (flex_luint_arr_type));
475 DECL_CONTEXT (fields[i]) = ret;
477 DECL_CHAIN (fields[i - 1]) = fields[i];
480 tree type_decl = build_decl (input_location, TYPE_DECL,
481 get_identifier ("__esan_strcut_type_info"), ret);
483 DECL_IGNORED_P (type_decl) = 1;
484 DECL_ARTIFICIAL (type_decl) = 1;
485 TYPE_FIELDS (ret) = fields[0];
486 TYPE_NAME (ret) = type_decl;
487 TYPE_STUB_DECL (ret) = type_decl;
489 esan_struct_info_type = ret;
493 /* This should be kept consistent with LLVM's EfficiencySanitizer CacheFragInfo.
494 The tool-specific information per compilation unit (module).
495 struct CacheFragInfo {
496 const char *UnitName;
501 static tree esan_cache_frag_info_type;
504 esan_get_cache_frag_info_type (void)
506 static const unsigned int count = 3;
507 static const char *field_names[count] = {"UnitName", "NumStructs", "Structs"};
508 tree fields[count], ret;
510 if (esan_cache_frag_info_type)
511 return esan_cache_frag_info_type;
513 tree esan_struct_type_info = esan_get_struct_info_type ();
515 tree range_type = build_range_type (sizetype, size_zero_node, NULL_TREE);
516 /* StructInfo Array Type. */
517 tree struct_info_arr_type
518 = build_array_type (esan_struct_type_info, range_type);
521 tree flex_char_arr_type = build_array_type (char_type_node, range_type);
523 ret = make_node (RECORD_TYPE);
525 for (unsigned int i = 0; i < count; ++i)
530 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
531 get_identifier (field_names[i]),
532 build_pointer_type (flex_char_arr_type));
536 = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
537 get_identifier (field_names[i]), unsigned_type_node);
540 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
541 get_identifier (field_names[i]),
542 build_pointer_type (struct_info_arr_type));
547 DECL_CONTEXT (fields[i]) = ret;
549 DECL_CHAIN (fields[i - 1]) = fields[i];
553 = build_decl (input_location, TYPE_DECL,
554 get_identifier ("__esan_cache_frag_info_type"), ret);
556 DECL_IGNORED_P (type_decl) = 1;
557 DECL_ARTIFICIAL (type_decl) = 1;
558 TYPE_FIELDS (ret) = fields[0];
559 TYPE_NAME (ret) = type_decl;
560 TYPE_STUB_DECL (ret) = type_decl;
562 esan_cache_frag_info_type = ret;
566 static unsigned int esan_ids[2];
567 static tree esan_array_counter_type;
570 esan_get_array_counter_type (void)
574 if (esan_array_counter_type)
575 return esan_array_counter_type;
577 tree range_type = build_range_type (sizetype, size_zero_node, NULL_TREE);
578 ret = build_array_type (long_long_unsigned_type_node, range_type);
580 esan_array_counter_type = ret;
585 esan_add_struct (tree array_addr, vec<constructor_elt, va_gc> *v,
586 size_t fields_count, char *field_counter_name_type,
589 /* Create StructName. */
590 const char *struct_name = field_counter_name_type;
591 size_t struct_name_len = strlen (struct_name) + 1;
592 tree struct_name_tree = build_string (struct_name_len, struct_name);
593 TREE_TYPE (struct_name_tree)
594 = build_array_type_nelts (char_type_node, struct_name_len);
595 TREE_READONLY (struct_name_tree) = 1;
596 TREE_STATIC (struct_name_tree) = 1;
598 /* Create StructInfo type. */
599 tree dtype = esan_get_struct_info_type ();
601 /* Create an instance of StructInfo. */
603 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lesan_type", esan_ids[0]++);
605 = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name), dtype);
606 TREE_STATIC (decl) = 1;
607 TREE_PUBLIC (decl) = 0;
608 TREE_READONLY (decl) = 1;
609 DECL_ARTIFICIAL (decl) = 1;
610 DECL_IGNORED_P (decl) = 1;
611 DECL_EXTERNAL (decl) = 0;
613 /* Initialize created struct. */
614 tree ctor = build_constructor_va (
615 dtype, 8, NULL_TREE, build_fold_addr_expr (struct_name_tree), NULL_TREE,
616 build_int_cst (unsigned_type_node, struct_size), NULL_TREE,
617 build_int_cst (unsigned_type_node, fields_count), NULL_TREE,
618 build_zero_cst (long_long_unsigned_type_node), NULL_TREE,
619 build_zero_cst (long_long_unsigned_type_node), NULL_TREE,
620 build_zero_cst (long_long_unsigned_type_node), NULL_TREE, array_addr,
621 NULL_TREE, build_zero_cst (long_long_unsigned_type_node));
623 TREE_CONSTANT (ctor) = 1;
624 TREE_STATIC (ctor) = 1;
625 DECL_INITIAL (decl) = ctor;
626 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, ctor);
629 /* Go recursively and find the actual class type and field index inside it. */
630 static esan_field_index
631 esan_get_field_index_internal (tree base_type, tree field, bool *found)
633 tree field_it = TYPE_FIELDS (base_type);
634 esan_field_index field_index (base_type, field, 0);
636 for (; field_it && !*found; field_it = DECL_CHAIN (field_it))
638 if (TREE_CODE (field_it) == FIELD_DECL)
640 if (TREE_CODE (TREE_TYPE (field_it)) == RECORD_TYPE)
642 esan_field_index nested_field_index
643 = esan_get_field_index_internal (TREE_TYPE (field_it), field,
646 return nested_field_index;
648 else if (field_it == field)
654 return *found ? field_index : esan_field_index (NULL_TREE, NULL_TREE, 0);
658 esan_get_field_index (tree base_type, tree field, esan_field_index *field_index)
661 /* At this momet we don't really know the record type where field is defined,
662 so can't cash the previous search. */
663 *field_index = esan_get_field_index_internal (base_type, field, &found);
668 esan_vec_contains_type (tree type)
672 if (type == NULL_TREE)
675 esan_type esan_type_instance;
676 /* This is O(n) cost, but I think we can improve it to ~ O(1)
677 by using a hash_set. */
678 while (vec_esan_type.iterate (index, &esan_type_instance))
680 if ((TYPE_IDENTIFIER (type)) == TYPE_IDENTIFIER (esan_type_instance.type))
688 esan_expand_record_access_ifn (gimple_stmt_iterator *gsip)
692 esan_field_index field_index_internal;
694 tree base, base_type;
695 gimple_stmt_iterator gsi, gsi_origin;
699 /* Expand internal ESAN_ACCESS. */
700 gsi_origin = gsi = *gsip;
701 stmt = gsi_stmt (gsi);
702 loc = gimple_location (stmt);
703 base = gimple_call_arg (stmt, 0);
704 field = gimple_call_arg (stmt, 1);
705 esan_type esan_type_instance;
707 tree array = NULL_TREE;
708 tree ptr = NULL_TREE;
710 /* In case we packed pointer type into integer to allow some level of
711 optimization work properly. */
712 base_type = TREE_CODE (base) == INTEGER_CST ? TREE_TYPE (TREE_TYPE (base))
715 /* Don't forget to verify field index, before creating the fields counter
718 || !esan_get_field_index (base_type, field, &field_index_internal))
720 unlink_stmt_vdef (stmt);
721 return gsi_remove (&gsi_origin, true);
724 size_t field_index = field_index_internal.index;
725 base_type = TYPE_MAIN_VARIANT (field_index_internal.type);
727 ssize_t index = esan_vec_contains_type (base_type);
729 /* In case we have not found type in the pool of types
730 and field has valid index, we should
731 create fields counter array and add type to the pool of types. */
735 ssize_t field_counter_name_len
736 = create_struct_field_counter_name (base_type, &fields_count);
738 if (field_counter_name_len == -1)
741 char *field_counter_name_type
742 = (char *) xmalloc (field_counter_name_len + 1);
743 memset (field_counter_name_type, 0, field_counter_name_len + 1);
744 memcpy (field_counter_name_type, field_counter_name,
745 field_counter_name_len + 1);
747 tree atype = esan_get_array_counter_type ();
748 array = build_decl (UNKNOWN_LOCATION, VAR_DECL,
749 get_identifier (field_counter_name), atype);
751 TREE_STATIC (array) = 1;
752 TREE_PUBLIC (array) = 1;
753 DECL_ARTIFICIAL (array) = 1;
754 DECL_IGNORED_P (array) = 1;
755 DECL_WEAK (array) = 1;
756 DECL_SIZE (array) = build_int_cst (
758 fields_count * tree_to_uhwi (TYPE_SIZE (long_long_unsigned_type_node)));
760 DECL_SIZE_UNIT (array)
761 = build_int_cst (integer_type_node,
764 TYPE_SIZE_UNIT (long_long_unsigned_type_node)));
765 DECL_EXTERNAL (array) = 0;
768 = build_constructor_va (atype, 1, NULL_TREE, build_zero_cst (atype));
769 TREE_CONSTANT (counter_ctor) = 1;
770 TREE_STATIC (counter_ctor) = 1;
771 DECL_INITIAL (array) = counter_ctor;
772 varpool_node::finalize_decl (array);
774 ptr = build_fold_addr_expr (array);
775 esan_type_instance.type = base_type;
776 esan_type_instance.array_type = array;
777 esan_type_instance.field_counter_name = field_counter_name_type;
778 esan_type_instance.fields_count = fields_count;
779 vec_esan_type.safe_push (esan_type_instance);
781 /* We have already added the type into the pool, so fields counter
782 array was created. */
785 if (vec_esan_type.iterate (index, &esan_type_instance))
786 ptr = build_fold_addr_expr (esan_type_instance.array_type);
792 /* Field number + sizeof (long int). */
793 tree offset = build_int_cst (unsigned_type_node,
795 * tree_to_uhwi (TYPE_SIZE_UNIT (
796 long_long_unsigned_type_node)));
797 /* array + offset. */
798 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node), PLUS_EXPR,
800 gimple_set_location (g, loc);
801 gsi_insert_before (gsip, g, GSI_SAME_STMT);
802 ptr = gimple_assign_lhs (g);
804 tree call_decl = builtin_decl_implicit (BUILT_IN_ESAN_INCREMENT);
806 g = gimple_build_call (call_decl, 1, ptr);
807 gimple_set_location (g, loc);
808 gsi_insert_before (gsip, g, GSI_SAME_STMT);
809 /* FIXME Inline __esan_increment for the better performance. */
812 unlink_stmt_vdef (stmt);
813 return gsi_remove (&gsi_origin, true);
817 instrument_record_field_access (tree mem, tree base, gimple_stmt_iterator *iter,
818 tree field, const enum tree_code code)
823 t = TREE_OPERAND (base, 0);
825 if ((code == MEM_REF && !POINTER_TYPE_P (TREE_TYPE (t))) || !field)
828 /* Don't instrument union accesses. */
829 if ((TREE_CODE (TREE_TYPE (base)) != RECORD_TYPE) || mem == base)
832 /* Pack the pointer to integer, so other pass will keep it the same. */
833 g = gimple_build_call_internal (
834 IFN_ESAN_RECORD_ACCESS, 2,
835 (code == MEM_REF && POINTER_TYPE_P (TREE_TYPE (t)))
836 ? build_int_cst (build_pointer_type (TREE_TYPE (base)), 0)
840 gimple_set_location (g, gimple_location (gsi_stmt (*iter)));
841 gsi_insert_before (iter, g, GSI_SAME_STMT);
845 instrument_record_access (gimple_stmt_iterator *gsi, tree expr, bool is_store)
848 HOST_WIDE_INT unused_bitsize, unused_bitpos;
851 int unsignedp, reversep, volatilep = 0;
853 gimple *stmt = gsi_stmt (*gsi);
855 HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (expr));
861 = get_inner_reference (expr, &unused_bitsize, &unused_bitpos, &offset,
862 &mode, &unsignedp, &reversep, &volatilep, false);
864 if (TREE_READONLY (base_tree)
865 || (VAR_P (base_tree) && DECL_HARD_REGISTER (base_tree)))
868 if (get_object_alignment (expr) < BITS_PER_UNIT)
871 t = is_store ? gimple_get_lhs (stmt) : gimple_assign_rhs1 (stmt);
872 base = get_base_address (t);
876 if (TREE_CODE (t) == COMPONENT_REF)
877 field = TREE_OPERAND (t, 1);
879 const enum tree_code code = TREE_CODE (base);
881 if ((code == MEM_REF && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
883 instrument_record_field_access (t, base, gsi, field, code);
887 maybe_instrument_cache_frag_gimple (gimple_stmt_iterator *gsi)
891 stmt = gsi_stmt (*gsi);
893 if (is_gimple_call (stmt))
896 if (is_gimple_assign (stmt) && !gimple_clobber_p (stmt))
898 if (gimple_store_p (stmt))
900 lhs = gimple_assign_lhs (stmt);
901 instrument_record_access (gsi, lhs, true);
903 else if (gimple_assign_load_p (stmt))
905 rhs = gimple_assign_rhs1 (stmt);
906 instrument_record_access (gsi, rhs, false);
912 instrument_memory_accesses (void)
915 gimple_stmt_iterator gsi;
917 /* So, walk through all basic blocks
918 and try to instrument memory accesses. */
919 FOR_EACH_BB_FN (bb, cfun)
921 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
923 if (flag_sanitize & SANITIZE_EFFICIENCY_WORKING_SET)
924 maybe_instrument_working_set_gimple (&gsi);
925 else if (flag_sanitize & SANITIZE_EFFICIENCY_CACHE_FRAG)
926 maybe_instrument_cache_frag_gimple (&gsi);
931 /* EfficiencySanitizer instrumentation pass. */
936 initialize_sanitizer_builtins ();
937 instrument_memory_accesses ();
941 /* Creates an arrray of StructInfo structs and CacheInfo struct.
942 Inserts __esan_init () into the list of CTORs and
943 __esan_exit() into the listof DCTORs. */
946 esan_finish_file (void)
948 tree ctor_statements = NULL_TREE;
949 tree dctor_statements = NULL_TREE;
950 initialize_sanitizer_builtins ();
951 tree tool_id = NULL_TREE;
953 tree init_decl = builtin_decl_implicit (BUILT_IN_ESAN_INIT);
954 tree exit_decl = builtin_decl_implicit (BUILT_IN_ESAN_EXIT);
956 if (flag_sanitize & SANITIZE_EFFICIENCY_CACHE_FRAG)
958 esan_type esan_type_instance;
960 size_t num_types = vec_esan_type.length ();
961 vec<constructor_elt, va_gc> *v;
962 vec_alloc (v, num_types);
964 /* Create StructInfo struct for the every struct we have instrumented. */
965 while (vec_esan_type.iterate (index, &esan_type_instance))
967 tree ptr = build_fold_addr_expr (esan_type_instance.array_type);
968 esan_add_struct (ptr, v, esan_type_instance.fields_count,
969 esan_type_instance.field_counter_name,
970 int_size_in_bytes (esan_type_instance.type));
972 /* Was allocated by xmalloc, so free the memory. */
973 free (esan_type_instance.field_counter_name);
977 /* Create module name string. */
978 size_t module_name_len = strlen (main_input_filename) + 1;
980 = build_string (module_name_len, main_input_filename);
981 TREE_TYPE (module_name_str)
982 = build_array_type_nelts (char_type_node, module_name_len);
983 TREE_READONLY (module_name_str) = 1;
984 TREE_STATIC (module_name_str) = 1;
986 tool_id = build_int_cst (unsigned_type_node, 1);
987 /* First, create the array of struct info type. */
988 tree stype = esan_get_struct_info_type ();
990 stype = build_array_type_nelts (stype, num_types);
992 char tmp_info_name[32];
993 ASM_GENERATE_INTERNAL_LABEL (tmp_info_name, "Lesan_info", 0);
995 tree var = build_decl (UNKNOWN_LOCATION, VAR_DECL,
996 get_identifier (tmp_info_name), stype);
998 TREE_STATIC (var) = 1;
999 TREE_PUBLIC (var) = 0;
1000 TREE_READONLY (var) = 1;
1001 DECL_ARTIFICIAL (var) = 1;
1002 DECL_IGNORED_P (var) = 1;
1003 DECL_EXTERNAL (var) = 0;
1005 tree ctor = build_constructor (stype, v);
1007 TREE_CONSTANT (ctor) = 1;
1008 TREE_STATIC (ctor) = 1;
1009 DECL_INITIAL (var) = ctor;
1011 varpool_node::finalize_decl (var);
1013 tree ctype = esan_get_cache_frag_info_type ();
1014 char tmp_cache_name[32];
1015 ASM_GENERATE_INTERNAL_LABEL (tmp_cache_name, "Lesan_cache", 0);
1017 tree c_var = build_decl (UNKNOWN_LOCATION, VAR_DECL,
1018 get_identifier (tmp_cache_name), ctype);
1019 TREE_STATIC (c_var) = 1;
1020 TREE_PUBLIC (c_var) = 0;
1021 DECL_ARTIFICIAL (c_var) = 1;
1022 DECL_IGNORED_P (c_var) = 1;
1023 DECL_EXTERNAL (c_var) = 0;
1026 = build_constructor_va (ctype, 3, NULL_TREE,
1027 build_fold_addr_expr (module_name_str),
1029 build_int_cst (unsigned_type_node, num_types),
1030 NULL_TREE, build_fold_addr_expr (var));
1032 TREE_CONSTANT (c_ctor) = 1;
1033 TREE_STATIC (c_ctor) = 1;
1034 DECL_INITIAL (c_var) = c_ctor;
1035 varpool_node::finalize_decl (c_var);
1037 append_to_statement_list (
1038 build_call_expr (init_decl, 2, build_int_cst (unsigned_type_node, 1),
1039 build_fold_addr_expr (c_var)),
1041 cgraph_build_static_cdtor ('I', ctor_statements,
1042 MAX_RESERVED_INIT_PRIORITY - 1);
1044 append_to_statement_list (build_call_expr (exit_decl, 1,
1045 build_fold_addr_expr (c_var)),
1047 cgraph_build_static_cdtor ('D', dctor_statements,
1048 MAX_RESERVED_INIT_PRIORITY - 1);
1050 else if (flag_sanitize & SANITIZE_EFFICIENCY_WORKING_SET)
1052 tool_id = build_int_cst (unsigned_type_node, 2);
1053 append_to_statement_list (
1054 build_call_expr (init_decl, 2, build_int_cst (unsigned_type_node, 2),
1055 build_zero_cst (long_unsigned_type_node)),
1057 cgraph_build_static_cdtor ('I', ctor_statements,
1058 MAX_RESERVED_INIT_PRIORITY - 1);
1059 append_to_statement_list (build_call_expr (exit_decl, 0),
1061 cgraph_build_static_cdtor ('D', dctor_statements,
1062 MAX_RESERVED_INIT_PRIORITY - 1);
1065 tree tool_id_type = build_array_type_nelts (unsigned_type_node, 1);
1067 /* Runtime part relies on __esan_which_tool global, which
1068 informs the runtime about what part of runtime library should run. */
1070 = build_decl (UNKNOWN_LOCATION, VAR_DECL,
1071 get_identifier ("__esan_which_tool"), tool_id_type);
1072 TREE_STATIC (tool_id_decl) = 1;
1073 TREE_PUBLIC (tool_id_decl) = 1;
1074 DECL_WEAK (tool_id_decl) = 1;
1075 DECL_ARTIFICIAL (tool_id_decl) = 1;
1076 DECL_IGNORED_P (tool_id_decl) = 1;
1077 DECL_EXTERNAL (tool_id_decl) = 0;
1080 = build_constructor_va (TREE_TYPE (tool_id_decl), 1, NULL_TREE, tool_id);
1081 TREE_CONSTANT (tool_id_ctor) = 1;
1082 TREE_STATIC (tool_id_ctor) = 1;
1083 DECL_INITIAL (tool_id_decl) = tool_id_ctor;
1084 varpool_node::finalize_decl (tool_id_decl);
1087 /* The pass descriptor. */
1091 const pass_data pass_data_esan = {
1092 GIMPLE_PASS, /* type */
1094 OPTGROUP_NONE, /* optinfo_flags */
1095 TV_NONE, /* tv_id */
1096 (PROP_ssa | PROP_cfg), /* properties_required */
1097 0, /* properties_provided */
1098 0, /* properties_destroyed */
1099 0, /* todo_flags_start */
1100 TODO_update_ssa, /* todo_flags_finish */
1103 class pass_esan : public gimple_opt_pass
1106 pass_esan (gcc::context *ctxt)
1107 : gimple_opt_pass (pass_data_esan, ctxt) {}
1109 /* opt_pass methods: */
1111 clone () { return new pass_esan (m_ctxt); }
1118 & (SANITIZE_EFFICIENCY_WORKING_SET | SANITIZE_EFFICIENCY_CACHE_FRAG))
1122 virtual unsigned int
1123 execute (function *) { return esan_pass (); }
1125 }; // class pass_esan
1130 make_pass_esan (gcc::context *ctxt)
1132 return new pass_esan (ctxt);
1137 const pass_data pass_data_esan_O0 = {
1138 GIMPLE_PASS, /* type */
1140 OPTGROUP_NONE, /* optinfo_flags */
1141 TV_NONE, /* tv_id */
1142 (PROP_ssa | PROP_cfg), /* properties_required */
1143 0, /* properties_provided */
1144 0, /* properties_destroyed */
1145 0, /* todo_flags_start */
1146 TODO_update_ssa, /* todo_flags_finish */
1149 class pass_esan_O0 : public gimple_opt_pass
1152 pass_esan_O0 (gcc::context *ctxt)
1153 : gimple_opt_pass (pass_data_esan_O0, ctxt) {}
1155 /* opt_pass methods: */
1161 & (SANITIZE_EFFICIENCY_WORKING_SET | SANITIZE_EFFICIENCY_CACHE_FRAG))
1166 virtual unsigned int
1167 execute (function *) { return esan_pass (); }
1169 }; // class pass_esan_O0
1174 make_pass_esan_O0 (gcc::context *ctxt)
1176 return new pass_esan_O0 (ctxt);