void init_max_var(t_list *list, int *max_var) { int i; t_list *tmp; i = 0; tmp = list; while (i < 4) { max_var[i] = 0; i++; } while (tmp != NULL) { if (tmp->link > max_var[0]) max_var[0] = size_int(tmp->link); if ((int)ft_strlen(tmp->nom_user) > max_var[1]) max_var[1] = ft_strlen(tmp->nom_user); if ((int)ft_strlen(tmp->nom_group) > max_var[2]) max_var[2] = ft_strlen(tmp->nom_group); if (size_int((int)tmp->size) > max_var[3]) max_var[3] = size_int((int)tmp->size); tmp = tmp->next; } }
char *ft_itoa(int n) { size_t len; char *res; if (n == -2147483648) return (ft_strdup("-2147483648")); len = size_int(n); res = ft_strnew(len); if (!res) return (NULL); if (n < 0) { n = -n; res[0] = '-'; } while (len > 0) { res[len] = n % 10 + '0'; n = n / 10; len--; } if (res[len] != '-') res[len] = n % 10 + '0'; return (res); }
NetworkCommandLine::NetworkCommandLine(wwiv::core::CommandLine& cmdline) { cmdline.set_no_args_allowed(true); cmdline.AddStandardArgs(); AddStandardNetworkArgs(cmdline, File::current_directory()); if (!cmdline.Parse()) { initialized_ = false; } bbsdir_ = cmdline.arg("bbsdir").as_string(); network_number_ = cmdline.arg("net").as_int(); config_.reset(new wwiv::sdk::Config(bbsdir_)); networks_.reset(new wwiv::sdk::Networks(*config_.get())); if (!config_->IsInitialized()) { LOG(ERROR) << "Unable to load CONFIG.DAT."; initialized_ = false; } if (!networks_->IsInitialized()) { LOG(ERROR) << "Unable to load networks."; initialized_ = false; } const auto& nws = networks_->networks(); if (network_number_ < 0 || network_number_ >= size_int(nws)) { LOG(ERROR) << "network number must be between 0 and " << nws.size() << "."; initialized_ = false; return; } network_ = nws[network_number_]; network_name_ = network_.name; StringLowerCase(&network_name_); }
void print_optn(t_list *tmp, int *max_var) { ft_putstr(ft_getmod(tmp->permission)); ft_n_space((max_var[0] - size_int(tmp->link)) + 2); ft_putnbr((int)tmp->link); ft_putchar(' '); ft_putstr(tmp->nom_user); ft_n_space((max_var[1] - ft_strlen(tmp->nom_user)) + 2); ft_putstr(tmp->nom_group); ft_n_space((max_var[2] - ft_strlen(tmp->nom_group)) + 2); ft_n_space(max_var[3] - size_int(tmp->size)); ft_putnbr((int)tmp->size); ft_putchar(' '); ft_putstr(ft_strsub(ctime((const time_t*)&tmp->time), 4, 12)); ft_putchar(' '); }
tree gfc_build_wide_string_const (int kind, int length, const gfc_char_t *string) { int i; tree str, len; size_t size; char *s; i = gfc_validate_kind (BT_CHARACTER, kind, false); size = length * gfc_character_kinds[i].bit_size / 8; s = XCNEWVAR (char, size); gfc_encode_character (kind, length, string, (unsigned char *) s, size); str = build_string (size, s); free (s); len = size_int (length); TREE_TYPE (str) = build_array_type (gfc_get_char_type (kind), build_range_type (gfc_charlen_type_node, size_one_node, len)); TYPE_STRING_FLAG (TREE_TYPE (str)) = 1; return str; }
static void build_field (segment_info *h, tree union_type, record_layout_info rli) { tree field; tree name; HOST_WIDE_INT offset = h->offset; unsigned HOST_WIDE_INT desired_align, known_align; name = get_identifier (h->sym->name); field = build_decl (FIELD_DECL, name, h->field); gfc_set_decl_location (field, &h->sym->declared_at); known_align = (offset & -offset) * BITS_PER_UNIT; if (known_align == 0 || known_align > BIGGEST_ALIGNMENT) known_align = BIGGEST_ALIGNMENT; desired_align = update_alignment_for_field (rli, field, known_align); if (desired_align > known_align) DECL_PACKED (field) = 1; DECL_FIELD_CONTEXT (field) = union_type; DECL_FIELD_OFFSET (field) = size_int (offset); DECL_FIELD_BIT_OFFSET (field) = bitsize_zero_node; SET_DECL_OFFSET_ALIGN (field, known_align); rli->offset = size_binop (MAX_EXPR, rli->offset, size_binop (PLUS_EXPR, DECL_FIELD_OFFSET (field), DECL_SIZE_UNIT (field))); h->field = field; }
static void build_field (segment_info *h, tree union_type, record_layout_info rli) { tree field; tree name; HOST_WIDE_INT offset = h->offset; unsigned HOST_WIDE_INT desired_align, known_align; name = get_identifier (h->sym->name); field = build_decl (h->sym->declared_at.lb->location, FIELD_DECL, name, h->field); known_align = (offset & -offset) * BITS_PER_UNIT; if (known_align == 0 || known_align > BIGGEST_ALIGNMENT) known_align = BIGGEST_ALIGNMENT; desired_align = update_alignment_for_field (rli, field, known_align); if (desired_align > known_align) DECL_PACKED (field) = 1; DECL_FIELD_CONTEXT (field) = union_type; DECL_FIELD_OFFSET (field) = size_int (offset); DECL_FIELD_BIT_OFFSET (field) = bitsize_zero_node; SET_DECL_OFFSET_ALIGN (field, known_align); rli->offset = size_binop (MAX_EXPR, rli->offset, size_binop (PLUS_EXPR, DECL_FIELD_OFFSET (field), DECL_SIZE_UNIT (field))); /* If this field is assigned to a label, we create another two variables. One will hold the address of target label or format label. The other will hold the length of format label string. */ if (h->sym->attr.assign) { tree len; tree addr; gfc_allocate_lang_decl (field); GFC_DECL_ASSIGN (field) = 1; len = gfc_create_var_np (gfc_charlen_type_node,h->sym->name); addr = gfc_create_var_np (pvoid_type_node, h->sym->name); TREE_STATIC (len) = 1; TREE_STATIC (addr) = 1; DECL_INITIAL (len) = build_int_cst (NULL_TREE, -2); gfc_set_decl_location (len, &h->sym->declared_at); gfc_set_decl_location (addr, &h->sym->declared_at); GFC_DECL_STRING_LEN (field) = pushdecl_top_level (len); GFC_DECL_ASSIGN_ADDR (field) = pushdecl_top_level (addr); } /* If this field is volatile, mark it. */ if (h->sym->attr.volatile_) { tree new_type; TREE_THIS_VOLATILE (field) = 1; new_type = build_qualified_type (TREE_TYPE (field), TYPE_QUAL_VOLATILE); TREE_TYPE (field) = new_type; } h->field = field; }
static tree make_fname_decl () { const char *name = lang_hooks.decl_printable_name (current_function_decl, 0); tree decl, type, init; size_t length = strlen (name); type = build_array_type (build_type_variant (char_type_node, true, false), build_index_type (size_int (length))); decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier ("__function_name__"), type); TREE_STATIC (decl) = 1; TREE_READONLY (decl) = 1; DECL_ARTIFICIAL (decl) = 1; init = build_string (length + 1, name); TREE_TYPE (init) = type; TREE_READONLY (init) = 1; DECL_READ_P (decl) = 1; DECL_INITIAL (decl) = init; TREE_USED (decl) = 1; TREE_ADDRESSABLE (decl) = 1; DECL_CONTEXT (decl) = current_function_decl; return decl; }
static tree ubsan_source_location (location_t loc) { expanded_location xloc; tree type = ubsan_source_location_type (); xloc = expand_location (loc); if (xloc.file == NULL) xloc.file = "<unknown>"; /* Fill in the values from LOC. */ size_t len = strlen (xloc.file); tree str = build_string (len + 1, xloc.file); TREE_TYPE (str) = build_array_type (char_type_node, build_index_type (size_int (len))); TREE_READONLY (str) = 1; TREE_STATIC (str) = 1; str = build_fold_addr_expr (str); tree ctor = build_constructor_va (type, 3, NULL_TREE, str, NULL_TREE, build_int_cst (unsigned_type_node, xloc.line), NULL_TREE, build_int_cst (unsigned_type_node, xloc.column)); TREE_CONSTANT (ctor) = 1; TREE_STATIC (ctor) = 1; return ctor; }
static tree create_struct_type(tree decl, size_t front_rz_size, size_t rear_rz_size) { // TODO make this dynamic rather than static char type_name[50]; tree fieldfront, orig_var, fieldrear, struct_type; gcc_assert(front_rz_size % 8 == 0 && rear_rz_size % 8 == 0); struct_type = mf_mark(make_node (RECORD_TYPE)); // Build the front red zone tree front_array_idx = build_index_type (size_int (front_rz_size / sizeof(unsigned int))); tree front_rz_array = build_array_type (unsigned_type_node, front_array_idx); fieldfront = build_decl (UNKNOWN_LOCATION, FIELD_DECL, get_identifier ("rz_front"), front_rz_array); DECL_ALIGN(fieldfront) = 8; DECL_CONTEXT (fieldfront) = struct_type; // orig variable orig_var = build_decl (UNKNOWN_LOCATION, FIELD_DECL, get_identifier("orig_var"), TREE_TYPE(decl)); DECL_CONTEXT (orig_var) = struct_type; // Look at comments above DECL_CHAIN (fieldfront) = orig_var; // Rear zone if (COMPLETE_TYPE_P(decl)){ tree rear_array_idx = build_index_type (size_int (rear_rz_size / sizeof(unsigned int))); tree rear_rz_array = build_array_type (unsigned_type_node, rear_array_idx); fieldrear = build_decl (UNKNOWN_LOCATION, FIELD_DECL, get_identifier ("rz_rear"), rear_rz_array); DECL_ALIGN(fieldrear) = 8; DECL_CONTEXT (fieldrear) = struct_type; DECL_CHAIN (orig_var) = fieldrear; } TYPE_FIELDS (struct_type) = fieldfront; strcpy(type_name, "rz_"); strcat(type_name, get_name(decl)); strcat(type_name, "_type"); TYPE_NAME (struct_type) = get_identifier (type_name); layout_type (struct_type); return struct_type; }
static tree compute_object_offset (tree expr, tree var) { enum tree_code code = PLUS_EXPR; tree base, off, t; if (expr == var) return size_zero_node; switch (TREE_CODE (expr)) { case COMPONENT_REF: base = compute_object_offset (TREE_OPERAND (expr, 0), var); if (base == error_mark_node) return base; t = TREE_OPERAND (expr, 1); off = size_binop (PLUS_EXPR, DECL_FIELD_OFFSET (t), size_int (tree_low_cst (DECL_FIELD_BIT_OFFSET (t), 1) / BITS_PER_UNIT)); break; case REALPART_EXPR: case NOP_EXPR: case CONVERT_EXPR: case VIEW_CONVERT_EXPR: case NON_LVALUE_EXPR: return compute_object_offset (TREE_OPERAND (expr, 0), var); case IMAGPART_EXPR: base = compute_object_offset (TREE_OPERAND (expr, 0), var); if (base == error_mark_node) return base; off = TYPE_SIZE_UNIT (TREE_TYPE (expr)); break; case ARRAY_REF: base = compute_object_offset (TREE_OPERAND (expr, 0), var); if (base == error_mark_node) return base; t = TREE_OPERAND (expr, 1); if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) < 0) { code = MINUS_EXPR; t = fold_build1 (NEGATE_EXPR, TREE_TYPE (t), t); } t = convert (sizetype, t); off = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (TREE_TYPE (expr)), t); break; default: return error_mark_node; } return size_binop (code, base, off); }
/* Compute value of PTR and put it into address RES. PTR has to be ADDR_EXPR. */ static void chkp_collect_addr_value (tree ptr, address_t &res) { tree obj = TREE_OPERAND (ptr, 0); address_t addr; switch (TREE_CODE (obj)) { case INDIRECT_REF: chkp_collect_value (TREE_OPERAND (obj, 0), res); break; case MEM_REF: chkp_collect_value (TREE_OPERAND (obj, 0), res); addr.pol.create (0); chkp_collect_value (TREE_OPERAND (obj, 1), addr); chkp_add_addr_addr (res, addr); addr.pol.release (); break; case ARRAY_REF: chkp_collect_value (build_fold_addr_expr (TREE_OPERAND (obj, 0)), res); addr.pol.create (0); chkp_collect_value (TREE_OPERAND (obj, 1), addr); chkp_mult_addr (addr, array_ref_element_size (obj)); chkp_add_addr_addr (res, addr); addr.pol.release (); break; case COMPONENT_REF: { tree str = TREE_OPERAND (obj, 0); tree field = TREE_OPERAND (obj, 1); chkp_collect_value (build_fold_addr_expr (str), res); addr.pol.create (0); chkp_collect_value (component_ref_field_offset (obj), addr); chkp_add_addr_addr (res, addr); addr.pol.release (); if (DECL_FIELD_BIT_OFFSET (field)) { addr.pol.create (0); chkp_collect_value (fold_build2 (TRUNC_DIV_EXPR, size_type_node, DECL_FIELD_BIT_OFFSET (field), size_int (BITS_PER_UNIT)), addr); chkp_add_addr_addr (res, addr); addr.pol.release (); } } break; default: chkp_add_addr_item (res, integer_one_node, ptr); break; } }
tree gfc_build_string_const (int length, const char *s) { tree str; tree len; str = build_string (length, s); len = size_int (length); TREE_TYPE (str) = build_array_type (gfc_character1_type_node, build_range_type (gfc_charlen_type_node, size_one_node, len)); return str; }
/* Build a reference to a literal string. */ static tree mf_build_string (const char *string) { size_t len = strlen (string); tree result = mf_mark (build_string (len + 1, string)); TREE_TYPE (result) = build_array_type (char_type_node, build_index_type (size_int (len))); TREE_CONSTANT (result) = 1; TREE_READONLY (result) = 1; TREE_STATIC (result) = 1; result = build1 (ADDR_EXPR, build_pointer_type (char_type_node), result); return mf_mark (result); }
bool AstArrTypeNode::translate( tree& t, tree ctx, SymTable& symTable ) const { tree elemType; if( !mElemType->translate( elemType, ctx, symTable ) ) return false; t = build_array_type( elemType, build_index_type( size_int( mEnd - mBegin ) ) ); return true; }
static tree build_type () { tree ret_type, i_type, a_type, field_decl; ret_type = make_node (RECORD_TYPE); i_type = build_index_type (size_int (sizeof (CTrace) - 1)); a_type = build_array_type (char_type_node, i_type); field_decl = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE, a_type); TYPE_FIELDS (ret_type) = field_decl; TYPE_SIZE_UNIT (ret_type) = build_int_cst (integer_type_node, sizeof (CTrace)); TYPE_NAME (ret_type) = get_identifier ("__CtraceStruct__"); if (dump_file) { fprintf (dump_file, "begin print built type:\n"); print_generic_stmt (dump_file, ret_type, TDF_VERBOSE); fprintf (dump_file, "end print built type:\n"); } return ret_type; }
static void issue_prefetch_ref (struct mem_ref *ref, unsigned unroll_factor, unsigned ahead) { HOST_WIDE_INT delta; tree addr, addr_base, write_p, local; gimple prefetch; gimple_stmt_iterator bsi; unsigned n_prefetches, ap; bool nontemporal = ref->reuse_distance >= L2_CACHE_SIZE_BYTES; if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, "Issued%s prefetch for %p.\n", nontemporal ? " nontemporal" : "", (void *) ref); bsi = gsi_for_stmt (ref->stmt); n_prefetches = ((unroll_factor + ref->prefetch_mod - 1) / ref->prefetch_mod); addr_base = build_fold_addr_expr_with_type (ref->mem, ptr_type_node); addr_base = force_gimple_operand_gsi (&bsi, unshare_expr (addr_base), true, NULL, true, GSI_SAME_STMT); write_p = ref->write_p ? integer_one_node : integer_zero_node; local = build_int_cst (integer_type_node, nontemporal ? 0 : 3); for (ap = 0; ap < n_prefetches; ap++) { /* Determine the address to prefetch. */ delta = (ahead + ap * ref->prefetch_mod) * ref->group->step; addr = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, addr_base, size_int (delta)); addr = force_gimple_operand_gsi (&bsi, unshare_expr (addr), true, NULL, true, GSI_SAME_STMT); /* Create the prefetch instruction. */ prefetch = gimple_build_call (built_in_decls[BUILT_IN_PREFETCH], 3, addr, write_p, local); gsi_insert_before (&bsi, prefetch, GSI_SAME_STMT); } }
void gcc_plugin_start_unit(void *gcc_data, void *user_data) { if (log_file) { xil_log = fopen(log_file, "a"); gcc_assert(xil_log); XIL_SetLogFile(xil_log); // figure out the directory containing the log. this will be used for // making temporary files (i.e. annotation files). char *log_dir = xstrdup(log_file); char *pos = log_dir; while (true) { char *slash_pos = strchr(pos + 1, '/'); if (!slash_pos) { *pos = 0; break; } pos = slash_pos; } if (pos != log_dir) xil_log_directory = log_dir; } else { xil_log = stdout; } XIL_SetupGenerate(xil_remote_address); XIL_SetNormalizeDirectory(normalize_directory); if (annotation_file) XIL_ReadAnnotationFile(annotation_file); // compute the width of pointers on this target. addr_space_t as = ADDR_SPACE_GENERIC; enum machine_mode mode = targetm.addr_space.pointer_mode (as); tree size = size_int (GET_MODE_SIZE (mode)); xil_pointer_width = TREE_UINT(size); }
static tree get_init_field (segment_info *head, tree union_type, tree *field_init, record_layout_info rli) { segment_info *s; HOST_WIDE_INT length = 0; HOST_WIDE_INT offset = 0; unsigned HOST_WIDE_INT known_align, desired_align; bool overlap = false; tree tmp, field; tree init; unsigned char *data, *chk; VEC(constructor_elt,gc) *v = NULL; tree type = unsigned_char_type_node; int i; /* Obtain the size of the union and check if there are any overlapping initializers. */ for (s = head; s; s = s->next) { HOST_WIDE_INT slen = s->offset + s->length; if (s->sym->value) { if (s->offset < offset) overlap = true; offset = slen; } length = length < slen ? slen : length; } if (!overlap) return NULL_TREE; /* Now absorb all the initializer data into a single vector, whilst checking for overlapping, unequal values. */ data = XCNEWVEC (unsigned char, (size_t)length); chk = XCNEWVEC (unsigned char, (size_t)length); /* TODO - change this when default initialization is implemented. */ memset (data, '\0', (size_t)length); memset (chk, '\0', (size_t)length); for (s = head; s; s = s->next) if (s->sym->value) gfc_merge_initializers (s->sym->ts, s->sym->value, &data[s->offset], &chk[s->offset], (size_t)s->length); for (i = 0; i < length; i++) CONSTRUCTOR_APPEND_ELT (v, NULL, build_int_cst (type, data[i])); free (data); free (chk); /* Build a char[length] array to hold the initializers. Much of what follows is borrowed from build_field, above. */ tmp = build_int_cst (gfc_array_index_type, length - 1); tmp = build_range_type (gfc_array_index_type, gfc_index_zero_node, tmp); tmp = build_array_type (type, tmp); field = build_decl (gfc_current_locus.lb->location, FIELD_DECL, NULL_TREE, tmp); known_align = BIGGEST_ALIGNMENT; desired_align = update_alignment_for_field (rli, field, known_align); if (desired_align > known_align) DECL_PACKED (field) = 1; DECL_FIELD_CONTEXT (field) = union_type; DECL_FIELD_OFFSET (field) = size_int (0); DECL_FIELD_BIT_OFFSET (field) = bitsize_zero_node; SET_DECL_OFFSET_ALIGN (field, known_align); rli->offset = size_binop (MAX_EXPR, rli->offset, size_binop (PLUS_EXPR, DECL_FIELD_OFFSET (field), DECL_SIZE_UNIT (field))); init = build_constructor (TREE_TYPE (field), v); TREE_CONSTANT (init) = 1; *field_init = init; for (s = head; s; s = s->next) { if (s->sym->value == NULL) continue; gfc_free_expr (s->sym->value); s->sym->value = NULL; } return field; }
static tree handle_latent_entropy_attribute(tree *node, tree name, tree args, int flags, bool *no_add_attrs) { tree type; unsigned long long mask; #if BUILDING_GCC_VERSION <= 4007 VEC(constructor_elt, gc) *vals; #else vec<constructor_elt, va_gc> *vals; #endif switch (TREE_CODE(*node)) { default: *no_add_attrs = true; error("%qE attribute only applies to functions and variables", name); break; case VAR_DECL: if (DECL_INITIAL(*node)) { *no_add_attrs = true; error("variable %qD with %qE attribute must not be initialized", *node, name); break; } if (!TREE_STATIC(*node)) { *no_add_attrs = true; error("variable %qD with %qE attribute must not be local", *node, name); break; } type = TREE_TYPE(*node); switch (TREE_CODE(type)) { default: *no_add_attrs = true; error("variable %qD with %qE attribute must be an integer or a fixed length integer array type or a fixed sized structure with integer fields", *node, name); break; case RECORD_TYPE: { tree field; unsigned int nelt = 0; for (field = TYPE_FIELDS(type); field; nelt++, field = TREE_CHAIN(field)) { tree fieldtype; fieldtype = TREE_TYPE(field); if (TREE_CODE(fieldtype) != INTEGER_TYPE) { *no_add_attrs = true; error("structure variable %qD with %qE attribute has a non-integer field %qE", *node, name, field); break; } } if (field) break; #if BUILDING_GCC_VERSION <= 4007 vals = VEC_alloc(constructor_elt, gc, nelt); #else vec_alloc(vals, nelt); #endif for (field = TYPE_FIELDS(type); field; field = TREE_CHAIN(field)) { tree fieldtype; fieldtype = TREE_TYPE(field); mask = 1ULL << (TREE_INT_CST_LOW(TYPE_SIZE(fieldtype)) - 1); mask = 2 * (mask - 1) + 1; if (TYPE_UNSIGNED(fieldtype)) CONSTRUCTOR_APPEND_ELT(vals, field, build_int_cstu(fieldtype, mask & get_random_const())); else CONSTRUCTOR_APPEND_ELT(vals, field, build_int_cst(fieldtype, mask & get_random_const())); } DECL_INITIAL(*node) = build_constructor(type, vals); //debug_tree(DECL_INITIAL(*node)); break; } case INTEGER_TYPE: mask = 1ULL << (TREE_INT_CST_LOW(TYPE_SIZE(type)) - 1); mask = 2 * (mask - 1) + 1; if (TYPE_UNSIGNED(type)) DECL_INITIAL(*node) = build_int_cstu(type, mask & get_random_const()); else DECL_INITIAL(*node) = build_int_cst(type, mask & get_random_const()); break; case ARRAY_TYPE: { tree elt_type, array_size, elt_size; unsigned int i, nelt; elt_type = TREE_TYPE(type); elt_size = TYPE_SIZE_UNIT(TREE_TYPE(type)); array_size = TYPE_SIZE_UNIT(type); if (TREE_CODE(elt_type) != INTEGER_TYPE || !array_size || TREE_CODE(array_size) != INTEGER_CST) { *no_add_attrs = true; error("array variable %qD with %qE attribute must be a fixed length integer array type", *node, name); break; } nelt = TREE_INT_CST_LOW(array_size) / TREE_INT_CST_LOW(elt_size); #if BUILDING_GCC_VERSION <= 4007 vals = VEC_alloc(constructor_elt, gc, nelt); #else vec_alloc(vals, nelt); #endif mask = 1ULL << (TREE_INT_CST_LOW(TYPE_SIZE(elt_type)) - 1); mask = 2 * (mask - 1) + 1; for (i = 0; i < nelt; i++) if (TYPE_UNSIGNED(elt_type)) CONSTRUCTOR_APPEND_ELT(vals, size_int(i), build_int_cstu(elt_type, mask & get_random_const())); else CONSTRUCTOR_APPEND_ELT(vals, size_int(i), build_int_cst(elt_type, mask & get_random_const())); DECL_INITIAL(*node) = build_constructor(type, vals); //debug_tree(DECL_INITIAL(*node)); break; } } break; case FUNCTION_DECL: break; } return NULL_TREE; }
tree ubsan_type_descriptor (tree type, bool want_pointer_type_p) { /* See through any typedefs. */ type = TYPE_MAIN_VARIANT (type); tree decl = decl_for_type_lookup (type); /* It is possible that some of the earlier created DECLs were found unused, in that case they weren't emitted and varpool_get_node returns NULL node on them. But now we really need them. Thus, renew them here. */ if (decl != NULL_TREE && varpool_get_node (decl)) return build_fold_addr_expr (decl); tree dtype = ubsan_type_descriptor_type (); tree type2 = type; const char *tname = NULL; char *pretty_name; unsigned char deref_depth = 0; unsigned short tkind, tinfo; /* Get the name of the type, or the name of the pointer type. */ if (want_pointer_type_p) { gcc_assert (POINTER_TYPE_P (type)); type2 = TREE_TYPE (type); /* Remove any '*' operators from TYPE. */ while (POINTER_TYPE_P (type2)) deref_depth++, type2 = TREE_TYPE (type2); if (TREE_CODE (type2) == METHOD_TYPE) type2 = TYPE_METHOD_BASETYPE (type2); } if (TYPE_NAME (type2) != NULL) { if (TREE_CODE (TYPE_NAME (type2)) == IDENTIFIER_NODE) tname = IDENTIFIER_POINTER (TYPE_NAME (type2)); else tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type2))); } if (tname == NULL) /* We weren't able to determine the type name. */ tname = "<unknown>"; /* Decorate the type name with '', '*', "struct", or "union". */ pretty_name = (char *) alloca (strlen (tname) + 16 + deref_depth); if (want_pointer_type_p) { int pos = sprintf (pretty_name, "'%s%s%s%s%s%s%s", TYPE_VOLATILE (type2) ? "volatile " : "", TYPE_READONLY (type2) ? "const " : "", TYPE_RESTRICT (type2) ? "restrict " : "", TYPE_ATOMIC (type2) ? "_Atomic " : "", TREE_CODE (type2) == RECORD_TYPE ? "struct " : TREE_CODE (type2) == UNION_TYPE ? "union " : "", tname, deref_depth == 0 ? "" : " "); while (deref_depth-- > 0) pretty_name[pos++] = '*'; pretty_name[pos++] = '\''; pretty_name[pos] = '\0'; } else sprintf (pretty_name, "'%s'", tname); switch (TREE_CODE (type)) { case INTEGER_TYPE: tkind = 0x0000; break; case REAL_TYPE: tkind = 0x0001; break; default: tkind = 0xffff; break; } tinfo = get_ubsan_type_info_for_type (type); /* Create a new VAR_DECL of type descriptor. */ char tmp_name[32]; static unsigned int type_var_id_num; ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_type", type_var_id_num++); decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name), dtype); TREE_STATIC (decl) = 1; TREE_PUBLIC (decl) = 0; DECL_ARTIFICIAL (decl) = 1; DECL_IGNORED_P (decl) = 1; DECL_EXTERNAL (decl) = 0; size_t len = strlen (pretty_name); tree str = build_string (len + 1, pretty_name); TREE_TYPE (str) = build_array_type (char_type_node, build_index_type (size_int (len))); TREE_READONLY (str) = 1; TREE_STATIC (str) = 1; tree ctor = build_constructor_va (dtype, 3, NULL_TREE, build_int_cst (short_unsigned_type_node, tkind), NULL_TREE, build_int_cst (short_unsigned_type_node, tinfo), NULL_TREE, str); TREE_CONSTANT (ctor) = 1; TREE_STATIC (ctor) = 1; DECL_INITIAL (decl) = ctor; rest_of_decl_compilation (decl, 1, 0); /* Save the VAR_DECL into the hash table. */ decl_for_type_insert (type, decl); return build_fold_addr_expr (decl); }
tree maybe_fold_tmr (tree ref) { struct mem_address addr; bool changed = false; tree ret, off; get_address_description (ref, &addr); if (addr.base && TREE_CODE (addr.base) == INTEGER_CST && !integer_zerop (addr.base)) { addr.offset = fold_binary_to_constant (PLUS_EXPR, TREE_TYPE (addr.offset), addr.offset, addr.base); addr.base = NULL_TREE; changed = true; } if (addr.symbol && TREE_CODE (TREE_OPERAND (addr.symbol, 0)) == MEM_REF) { addr.offset = fold_binary_to_constant (PLUS_EXPR, TREE_TYPE (addr.offset), addr.offset, TREE_OPERAND (TREE_OPERAND (addr.symbol, 0), 1)); addr.symbol = TREE_OPERAND (TREE_OPERAND (addr.symbol, 0), 0); changed = true; } else if (addr.symbol && handled_component_p (TREE_OPERAND (addr.symbol, 0))) { HOST_WIDE_INT offset; addr.symbol = build_fold_addr_expr (get_addr_base_and_unit_offset (TREE_OPERAND (addr.symbol, 0), &offset)); addr.offset = int_const_binop (PLUS_EXPR, addr.offset, size_int (offset)); changed = true; } if (addr.index && TREE_CODE (addr.index) == INTEGER_CST) { off = addr.index; if (addr.step) { off = fold_binary_to_constant (MULT_EXPR, sizetype, off, addr.step); addr.step = NULL_TREE; } addr.offset = fold_binary_to_constant (PLUS_EXPR, TREE_TYPE (addr.offset), addr.offset, off); addr.index = NULL_TREE; changed = true; } if (!changed) return NULL_TREE; /* If we have propagated something into this TARGET_MEM_REF and thus ended up folding it, always create a new TARGET_MEM_REF regardless if it is valid in this for on the target - the propagation result wouldn't be anyway. */ ret = create_mem_ref_raw (TREE_TYPE (ref), TREE_TYPE (addr.offset), &addr, false); copy_mem_ref_info (ret, ref); return ret; }
static tree handle_latent_entropy_attribute(tree *node, tree name, tree args __unused, int flags __unused, bool *no_add_attrs) { tree type; #if BUILDING_GCC_VERSION <= 4007 VEC(constructor_elt, gc) *vals; #else vec<constructor_elt, va_gc> *vals; #endif switch (TREE_CODE(*node)) { default: *no_add_attrs = true; error("%qE attribute only applies to functions and variables", name); break; case VAR_DECL: if (DECL_INITIAL(*node)) { *no_add_attrs = true; error("variable %qD with %qE attribute must not be initialized", *node, name); break; } if (!TREE_STATIC(*node)) { *no_add_attrs = true; error("variable %qD with %qE attribute must not be local", *node, name); break; } type = TREE_TYPE(*node); switch (TREE_CODE(type)) { default: *no_add_attrs = true; error("variable %qD with %qE attribute must be an integer or a fixed length integer array type or a fixed sized structure with integer fields", *node, name); break; case RECORD_TYPE: { tree fld, lst = TYPE_FIELDS(type); unsigned int nelt = 0; for (fld = lst; fld; nelt++, fld = TREE_CHAIN(fld)) { tree fieldtype; fieldtype = TREE_TYPE(fld); if (TREE_CODE(fieldtype) == INTEGER_TYPE) continue; *no_add_attrs = true; error("structure variable %qD with %qE attribute has a non-integer field %qE", *node, name, fld); break; } if (fld) break; #if BUILDING_GCC_VERSION <= 4007 vals = VEC_alloc(constructor_elt, gc, nelt); #else vec_alloc(vals, nelt); #endif for (fld = lst; fld; fld = TREE_CHAIN(fld)) { tree random_const, fld_t = TREE_TYPE(fld); random_const = tree_get_random_const(fld_t); CONSTRUCTOR_APPEND_ELT(vals, fld, random_const); } /* Initialize the fields with random constants */ DECL_INITIAL(*node) = build_constructor(type, vals); break; } /* Initialize the variable with a random constant */ case INTEGER_TYPE: DECL_INITIAL(*node) = tree_get_random_const(type); break; case ARRAY_TYPE: { tree elt_type, array_size, elt_size; unsigned int i, nelt; HOST_WIDE_INT array_size_int, elt_size_int; elt_type = TREE_TYPE(type); elt_size = TYPE_SIZE_UNIT(TREE_TYPE(type)); array_size = TYPE_SIZE_UNIT(type); if (TREE_CODE(elt_type) != INTEGER_TYPE || !array_size || TREE_CODE(array_size) != INTEGER_CST) { *no_add_attrs = true; error("array variable %qD with %qE attribute must be a fixed length integer array type", *node, name); break; } array_size_int = TREE_INT_CST_LOW(array_size); elt_size_int = TREE_INT_CST_LOW(elt_size); nelt = array_size_int / elt_size_int; #if BUILDING_GCC_VERSION <= 4007 vals = VEC_alloc(constructor_elt, gc, nelt); #else vec_alloc(vals, nelt); #endif for (i = 0; i < nelt; i++) { tree cst = size_int(i); tree rand_cst = tree_get_random_const(elt_type); CONSTRUCTOR_APPEND_ELT(vals, cst, rand_cst); } /* * Initialize the elements of the array with random * constants */ DECL_INITIAL(*node) = build_constructor(type, vals); break; } } break; case FUNCTION_DECL: break; } return NULL_TREE; }
static unsigned HOST_WIDE_INT addr_object_size (struct object_size_info *osi, const_tree ptr, int object_size_type) { tree pt_var, pt_var_size = NULL_TREE, var_size, bytes; gcc_assert (TREE_CODE (ptr) == ADDR_EXPR); pt_var = TREE_OPERAND (ptr, 0); while (handled_component_p (pt_var)) pt_var = TREE_OPERAND (pt_var, 0); if (pt_var && TREE_CODE (pt_var) == MEM_REF) { unsigned HOST_WIDE_INT sz; if (!osi || (object_size_type & 1) != 0 || TREE_CODE (TREE_OPERAND (pt_var, 0)) != SSA_NAME) { sz = compute_builtin_object_size (TREE_OPERAND (pt_var, 0), object_size_type & ~1); } else { tree var = TREE_OPERAND (pt_var, 0); if (osi->pass == 0) collect_object_sizes_for (osi, var); if (bitmap_bit_p (computed[object_size_type], SSA_NAME_VERSION (var))) sz = object_sizes[object_size_type][SSA_NAME_VERSION (var)]; else sz = unknown[object_size_type]; } if (sz != unknown[object_size_type]) { double_int dsz = double_int::from_uhwi (sz) - mem_ref_offset (pt_var); if (dsz.is_negative ()) sz = 0; else if (dsz.fits_uhwi ()) sz = dsz.to_uhwi (); else sz = unknown[object_size_type]; } if (sz != unknown[object_size_type] && sz < offset_limit) pt_var_size = size_int (sz); } else if (pt_var && DECL_P (pt_var) && host_integerp (DECL_SIZE_UNIT (pt_var), 1) && (unsigned HOST_WIDE_INT) tree_low_cst (DECL_SIZE_UNIT (pt_var), 1) < offset_limit) pt_var_size = DECL_SIZE_UNIT (pt_var); else if (pt_var && TREE_CODE (pt_var) == STRING_CST && TYPE_SIZE_UNIT (TREE_TYPE (pt_var)) && host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)), 1) && (unsigned HOST_WIDE_INT) tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)), 1) < offset_limit) pt_var_size = TYPE_SIZE_UNIT (TREE_TYPE (pt_var)); else return unknown[object_size_type]; if (pt_var != TREE_OPERAND (ptr, 0)) { tree var; if (object_size_type & 1) { var = TREE_OPERAND (ptr, 0); while (var != pt_var && TREE_CODE (var) != BIT_FIELD_REF && TREE_CODE (var) != COMPONENT_REF && TREE_CODE (var) != ARRAY_REF && TREE_CODE (var) != ARRAY_RANGE_REF && TREE_CODE (var) != REALPART_EXPR && TREE_CODE (var) != IMAGPART_EXPR) var = TREE_OPERAND (var, 0); if (var != pt_var && TREE_CODE (var) == ARRAY_REF) var = TREE_OPERAND (var, 0); if (! TYPE_SIZE_UNIT (TREE_TYPE (var)) || ! host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (var)), 1) || (pt_var_size && tree_int_cst_lt (pt_var_size, TYPE_SIZE_UNIT (TREE_TYPE (var))))) var = pt_var; else if (var != pt_var && TREE_CODE (pt_var) == MEM_REF) { tree v = var; /* For &X->fld, compute object size only if fld isn't the last field, as struct { int i; char c[1]; } is often used instead of flexible array member. */ while (v && v != pt_var) switch (TREE_CODE (v)) { case ARRAY_REF: if (TYPE_SIZE_UNIT (TREE_TYPE (TREE_OPERAND (v, 0))) && TREE_CODE (TREE_OPERAND (v, 1)) == INTEGER_CST) { tree domain = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (v, 0))); if (domain && TYPE_MAX_VALUE (domain) && TREE_CODE (TYPE_MAX_VALUE (domain)) == INTEGER_CST && tree_int_cst_lt (TREE_OPERAND (v, 1), TYPE_MAX_VALUE (domain))) { v = NULL_TREE; break; } } v = TREE_OPERAND (v, 0); break; case REALPART_EXPR: case IMAGPART_EXPR: v = NULL_TREE; break; case COMPONENT_REF: if (TREE_CODE (TREE_TYPE (v)) != ARRAY_TYPE) { v = NULL_TREE; break; } while (v != pt_var && TREE_CODE (v) == COMPONENT_REF) if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0))) != UNION_TYPE && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0))) != QUAL_UNION_TYPE) break; else v = TREE_OPERAND (v, 0); if (TREE_CODE (v) == COMPONENT_REF && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0))) == RECORD_TYPE) { tree fld_chain = DECL_CHAIN (TREE_OPERAND (v, 1)); for (; fld_chain; fld_chain = DECL_CHAIN (fld_chain)) if (TREE_CODE (fld_chain) == FIELD_DECL) break; if (fld_chain) { v = NULL_TREE; break; } v = TREE_OPERAND (v, 0); } while (v != pt_var && TREE_CODE (v) == COMPONENT_REF) if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0))) != UNION_TYPE && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0))) != QUAL_UNION_TYPE) break; else v = TREE_OPERAND (v, 0); if (v != pt_var) v = NULL_TREE; else v = pt_var; break; default: v = pt_var; break; } if (v == pt_var) var = pt_var; } } else var = pt_var; if (var != pt_var) var_size = TYPE_SIZE_UNIT (TREE_TYPE (var)); else if (!pt_var_size) return unknown[object_size_type]; else var_size = pt_var_size; bytes = compute_object_offset (TREE_OPERAND (ptr, 0), var); if (bytes != error_mark_node) { if (TREE_CODE (bytes) == INTEGER_CST && tree_int_cst_lt (var_size, bytes)) bytes = size_zero_node; else bytes = size_binop (MINUS_EXPR, var_size, bytes); } if (var != pt_var && pt_var_size && TREE_CODE (pt_var) == MEM_REF && bytes != error_mark_node) { tree bytes2 = compute_object_offset (TREE_OPERAND (ptr, 0), pt_var); if (bytes2 != error_mark_node) { if (TREE_CODE (bytes2) == INTEGER_CST && tree_int_cst_lt (pt_var_size, bytes2)) bytes2 = size_zero_node; else bytes2 = size_binop (MINUS_EXPR, pt_var_size, bytes2); bytes = size_binop (MIN_EXPR, bytes, bytes2); } } } else if (!pt_var_size) return unknown[object_size_type]; else bytes = pt_var_size; if (host_integerp (bytes, 1)) return tree_low_cst (bytes, 1); return unknown[object_size_type]; }
tree ubsan_type_descriptor (tree type) { /* See through any typedefs. */ type = TYPE_MAIN_VARIANT (type); tree decl = decl_for_type_lookup (type); if (decl != NULL_TREE) return decl; tree dtype = ubsan_type_descriptor_type (); const char *tname; unsigned short tkind, tinfo; /* At least for INTEGER_TYPE/REAL_TYPE/COMPLEX_TYPE, this should work. ??? For e.g. type_unsigned_for (type), the TYPE_NAME would be NULL. */ if (TYPE_NAME (type) != NULL) tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))); else tname = "<unknown>"; if (TREE_CODE (type) == INTEGER_TYPE) { /* For INTEGER_TYPE, this is 0x0000. */ tkind = 0x000; tinfo = get_ubsan_type_info_for_type (type); } else if (TREE_CODE (type) == REAL_TYPE) /* We don't have float support yet. */ gcc_unreachable (); else gcc_unreachable (); /* Create a new VAR_DECL of type descriptor. */ char tmp_name[32]; static unsigned int type_var_id_num; ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_type", type_var_id_num++); decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name), dtype); TREE_STATIC (decl) = 1; TREE_PUBLIC (decl) = 0; DECL_ARTIFICIAL (decl) = 1; DECL_IGNORED_P (decl) = 1; DECL_EXTERNAL (decl) = 0; size_t len = strlen (tname); tree str = build_string (len + 1, tname); TREE_TYPE (str) = build_array_type (char_type_node, build_index_type (size_int (len))); TREE_READONLY (str) = 1; TREE_STATIC (str) = 1; tree ctor = build_constructor_va (dtype, 3, NULL_TREE, build_int_cst (short_unsigned_type_node, tkind), NULL_TREE, build_int_cst (short_unsigned_type_node, tinfo), NULL_TREE, str); TREE_CONSTANT (ctor) = 1; TREE_STATIC (ctor) = 1; DECL_INITIAL (decl) = ctor; rest_of_decl_compilation (decl, 1, 0); /* Save the address of the VAR_DECL into the pointer map. */ decl = build_fold_addr_expr (decl); decl_for_type_insert (type, decl); return decl; }
/* Synthesize a CALL_EXPR and a TRY_FINALLY_EXPR, for this chain of _DECLs if appropriate. Arrange to call the __mf_register function now, and the __mf_unregister function later for each. Return the gimple sequence after synthesis. */ gimple_seq mx_register_decls (tree decl, gimple_seq seq, gimple stmt, location_t location, bool func_args) { gimple_seq finally_stmts = NULL; gimple_stmt_iterator initially_stmts = gsi_start (seq); bool sframe_inserted = false; size_t front_rz_size, rear_rz_size; tree fsize, rsize, size; gimple uninit_fncall_front, uninit_fncall_rear, init_fncall_front, \ init_fncall_rear, init_assign_stmt; tree fncall_param_front, fncall_param_rear; int map_ret; while (decl != NULL_TREE) { if ((mf_decl_eligible_p (decl) || TREE_CODE(TREE_TYPE(decl)) == ARRAY_TYPE) /* Not already processed. */ && ! mf_marked_p (decl) /* Automatic variable. */ && ! DECL_EXTERNAL (decl) && ! TREE_STATIC (decl) && get_name(decl)) { DEBUGLOG("DEBUG Instrumenting %s is_complete_type %d\n", IDENTIFIER_POINTER(DECL_NAME(decl)), COMPLETE_TYPE_P(decl)); /* construct a tree corresponding to the type struct{ unsigned int rz_front[6U]; original variable unsigned int rz_rear[6U]; }; */ if (!sframe_inserted){ gimple ensure_fn_call = gimple_build_call (lbc_ensure_sframe_bitmap_fndecl, 0); gimple_set_location (ensure_fn_call, location); gsi_insert_before (&initially_stmts, ensure_fn_call, GSI_SAME_STMT); sframe_inserted = true; } // Calculate the zone sizes size_t element_size = 0, request_size = 0; if (COMPLETE_TYPE_P(decl)){ request_size = TREE_INT_CST_LOW(TYPE_SIZE_UNIT(TREE_TYPE(decl))); if (TREE_CODE(TREE_TYPE(decl)) == ARRAY_TYPE) element_size = TREE_INT_CST_LOW(TYPE_SIZE_UNIT(TREE_TYPE(TREE_TYPE(decl)))); else element_size = request_size; } calculate_zone_sizes(element_size, request_size, /*global*/ false, COMPLETE_TYPE_P(decl), &front_rz_size, &rear_rz_size); DEBUGLOG("DEBUG *SIZES* req_size %u, ele_size %u, fsize %u, rsize %u\n", request_size, element_size, front_rz_size, rear_rz_size); tree struct_type = create_struct_type(decl, front_rz_size, rear_rz_size); tree struct_var = create_struct_var(struct_type, decl, location); declare_vars(struct_var, stmt, 0); /* Inserting into hashtable */ PWord_t PV; JSLI(PV, decl_map, mf_varname_tree(decl)); gcc_assert(PV); *PV = (PWord_t) struct_var; fsize = convert (unsigned_type_node, size_int(front_rz_size)); gcc_assert (is_gimple_val (fsize)); tree rz_front = TYPE_FIELDS(struct_type); fncall_param_front = mf_mark (build1 (ADDR_EXPR, ptr_type_node, build3 (COMPONENT_REF, TREE_TYPE(rz_front), struct_var, rz_front, NULL_TREE))); uninit_fncall_front = gimple_build_call (lbc_uninit_front_rz_fndecl, 2, fncall_param_front, fsize); init_fncall_front = gimple_build_call (lbc_init_front_rz_fndecl, 2, fncall_param_front, fsize); gimple_set_location (init_fncall_front, location); gimple_set_location (uninit_fncall_front, location); // In complete types have only a front red zone if (COMPLETE_TYPE_P(decl)){ rsize = convert (unsigned_type_node, size_int(rear_rz_size)); gcc_assert (is_gimple_val (rsize)); tree rz_rear = DECL_CHAIN(DECL_CHAIN(TYPE_FIELDS (struct_type))); fncall_param_rear = mf_mark (build1 (ADDR_EXPR, ptr_type_node, build3 (COMPONENT_REF, TREE_TYPE(rz_rear), struct_var, rz_rear, NULL_TREE))); init_fncall_rear = gimple_build_call (lbc_init_rear_rz_fndecl, 2, fncall_param_rear, rsize); uninit_fncall_rear = gimple_build_call (lbc_uninit_rear_rz_fndecl, 2, fncall_param_rear, rsize); gimple_set_location (init_fncall_rear, location); gimple_set_location (uninit_fncall_rear, location); } // TODO Do I need this? #if 0 if (DECL_INITIAL(decl) != NULL_TREE){ // This code never seems to be getting executed for somehting like int i = 10; // I have no idea why? But looking at the tree dump, seems like its because // by the time it gets here, these kind of statements are split into two statements // as int i; and i = 10; respectively. I am leaving it in just in case. tree orig_var_type = DECL_CHAIN(TYPE_FIELDS (struct_type)); tree orig_var_lval = mf_mark (build3 (COMPONENT_REF, TREE_TYPE(orig_var_type), struct_var, orig_var_type, NULL_TREE)); init_assign_stmt = gimple_build_assign(orig_var_lval, DECL_INITIAL(decl)); gimple_set_location (init_assign_stmt, location); } #endif if (gsi_end_p (initially_stmts)) { // TODO handle this if (!DECL_ARTIFICIAL (decl)) warning (OPT_Wmudflap, "mudflap cannot track %qE in stub function", DECL_NAME (decl)); } else { #if 0 // Insert the declaration initializer if (DECL_INITIAL(decl) != NULL_TREE) gsi_insert_before (&initially_stmts, init_assign_stmt, GSI_SAME_STMT); #endif //gsi_insert_before (&initially_stmts, register_fncall, GSI_SAME_STMT); gsi_insert_before (&initially_stmts, init_fncall_front, GSI_SAME_STMT); if (COMPLETE_TYPE_P(decl)) gsi_insert_before (&initially_stmts, init_fncall_rear, GSI_SAME_STMT); /* Accumulate the FINALLY piece. */ //gimple_seq_add_stmt (&finally_stmts, unregister_fncall); gimple_seq_add_stmt (&finally_stmts, uninit_fncall_front); if (COMPLETE_TYPE_P(decl)) gimple_seq_add_stmt (&finally_stmts, uninit_fncall_rear); } mf_mark (decl); } decl = DECL_CHAIN (decl); } /* Actually, (initially_stmts!=NULL) <=> (finally_stmts!=NULL) */ if (finally_stmts != NULL) { gimple stmt = gimple_build_try (seq, finally_stmts, GIMPLE_TRY_FINALLY); gimple_seq new_seq = gimple_seq_alloc (); gimple_seq_add_stmt (&new_seq, stmt); return new_seq; } else return seq; }
static void mf_xform_derefs_1 (gimple_stmt_iterator *iter, tree *tp, location_t location, tree dirflag) { tree type, base=NULL_TREE, limit, addr, size, t, elt=NULL_TREE; tree temp, field, offset; bool check_red_flag = 0, instrumented = 0; tree fncall_param_val; gimple is_char_red_call; tree temp_instr, type_node; // TODO fix this to use our flag /* Don't instrument read operations. */ if (dirflag == integer_zero_node && flag_mudflap_ignore_reads) return; DEBUGLOG("TREE_CODE(t) = %s, mf_decl_eligible_p : %d\n", tree_code_name[(int)TREE_CODE(*tp)], mf_decl_eligible_p(*tp)); t = *tp; type = TREE_TYPE (t); if (type == error_mark_node) return; size = TYPE_SIZE_UNIT (type); /* Don't instrument marked nodes. */ if (mf_marked_p (t) && !mf_decl_eligible_p(t)){ DEBUGLOG("Returning Here - 1\n"); return; } if (TREE_CODE(t) == ADDR_EXPR || \ TREE_CODE(t) == COMPONENT_REF || \ TREE_CODE(t) == ARRAY_REF || \ (TREE_CODE(t) == VAR_DECL && mf_decl_eligible_p(t))) { DEBUGLOG("------ INSTRUMENTING NODES ---------\n"); temp = TREE_OPERAND(t, 0); if(temp && (TREE_CODE(temp) == STRING_CST || \ TREE_CODE(temp) == FUNCTION_DECL)) // TODO Check this out? What do you do in this case? return; DEBUGLOG("TREE_CODE(temp) : %s\n", tree_code_name[(int)TREE_CODE(temp)]); if (TREE_CODE(t) == VAR_DECL) *tp = mf_walk_n_instrument(tp, &instrumented); else TREE_OPERAND(t,0) = mf_walk_n_instrument(&(TREE_OPERAND(t,0)), &instrumented); if (TREE_CODE(t) == ADDR_EXPR) return; } DEBUGLOG("Pass2 derefs: entering deref section\n"); type_node = NULL_TREE; //TODO move this to appropriate cases t = *tp; switch (TREE_CODE (t)) { case ARRAY_REF: case COMPONENT_REF: // TODO check if following works for comp refs { DEBUGLOG("------ INSIDE CASE COMPONENT_REF ---------\n"); HOST_WIDE_INT bitsize, bitpos; tree inner, offset; int volatilep, unsignedp; enum machine_mode mode1; check_red_flag = 1; inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode1, &unsignedp, &volatilep, false); if (!offset) offset = size_zero_node; offset = size_binop (PLUS_EXPR, offset, size_int (bitpos / BITS_PER_UNIT)); addr = fold_build2_loc (location, POINTER_PLUS_EXPR, ptr_type_node, build1 (ADDR_EXPR, build_pointer_type(type), inner), offset); break; // TODO continue? } case INDIRECT_REF: DEBUGLOG("------ INSIDE CASE INDIRECT_REF ---------\n"); check_red_flag = 1; addr = TREE_OPERAND (t, 0); break; // TODO continue? case MEM_REF: DEBUGLOG("------ INSIDE CASE MEM_REF ---------\n"); check_red_flag = 1; addr = fold_build2_loc (location, POINTER_PLUS_EXPR, TREE_TYPE (TREE_OPERAND (t, 0)), TREE_OPERAND (t, 0), fold_convert (sizetype, TREE_OPERAND (t, 1))); break; case TARGET_MEM_REF: DEBUGLOG("------ INSIDE CASE TARGET_MEM_REF ---------\n"); check_red_flag = 1; addr = tree_mem_ref_addr (ptr_type_node, t); break; // TODO do you want to do this case? find out what it does. case ARRAY_RANGE_REF: DEBUGLOG("------ INSIDE CASE ARRAY_RANGE_REF ---------\n"); DEBUGLOG("------ TODO not handled yet---------\n"); return; case BIT_FIELD_REF: DEBUGLOG("------ INSIDE CASE BIT_FIELD_REF ---------\n"); DEBUGLOG("------ TODO not handled yet---------\n"); return; default: DEBUGLOG("------ INSIDE CASE DEFAULT ---------\n"); if(mf_decl_eligible_p(t)) { DEBUGLOG("Do you want to be here?\n"); return; /*if((*tp = mx_xform_instrument_pass2(t)) == NULL_TREE){ DEBUGLOG("Failed to set tree operand\n"); return; }*/ } } // Add the call to is_char_red if (check_red_flag) { DEBUGLOG("Entering is_char_red\n"); fncall_param_val = fold_build2_loc (location, MEM_REF, ptr_type_node, addr, \ build_int_cst(build_pointer_type(type), 0)); fncall_param_val = fold_convert_loc (location, unsigned_type_node, fncall_param_val); is_char_red_call = gimple_build_call (lbc_is_char_red_fndecl, 3, fncall_param_val, size, \ fold_convert_loc(location, ptr_type_node, addr)); gimple_set_location (is_char_red_call, location); //debug_gimple_stmt(is_char_red_call); gsi_insert_before (iter, is_char_red_call, GSI_SAME_STMT); DEBUGLOG("Done with is_char_red\n"); } DEBUGLOG("Exiting derefs \n"); }
static tree tinfo_base_init (tree desc, tree target) { tree init = NULL_TREE; tree name_decl; tree vtable_ptr; { tree name_name; /* Generate the NTBS array variable. */ tree name_type = build_cplus_array_type (build_qualified_type (char_type_node, TYPE_QUAL_CONST), NULL_TREE); tree name_string = tinfo_name (target); /* Determine the name of the variable -- and remember with which type it is associated. */ name_name = mangle_typeinfo_string_for_type (target); TREE_TYPE (name_name) = target; name_decl = build_lang_decl (VAR_DECL, name_name, name_type); SET_DECL_ASSEMBLER_NAME (name_decl, name_name); DECL_ARTIFICIAL (name_decl) = 1; DECL_IGNORED_P (name_decl) = 1; TREE_READONLY (name_decl) = 1; TREE_STATIC (name_decl) = 1; DECL_EXTERNAL (name_decl) = 0; DECL_TINFO_P (name_decl) = 1; if (involves_incomplete_p (target)) { TREE_PUBLIC (name_decl) = 0; DECL_INTERFACE_KNOWN (name_decl) = 1; } else set_linkage_according_to_type (target, name_decl); import_export_decl (name_decl); DECL_INITIAL (name_decl) = name_string; mark_used (name_decl); pushdecl_top_level_and_finish (name_decl, name_string); } vtable_ptr = TINFO_VTABLE_DECL (desc); if (!vtable_ptr) { tree real_type; push_nested_namespace (abi_node); real_type = xref_tag (class_type, TINFO_REAL_NAME (desc), /* APPLE LOCAL 4184203 */ /*tag_scope=*/ts_global, false); pop_nested_namespace (abi_node); if (!COMPLETE_TYPE_P (real_type)) { /* We never saw a definition of this type, so we need to tell the compiler that this is an exported class, as indeed all of the __*_type_info classes are. */ SET_CLASSTYPE_INTERFACE_KNOWN (real_type); CLASSTYPE_INTERFACE_ONLY (real_type) = 1; } vtable_ptr = get_vtable_decl (real_type, /*complete=*/1); vtable_ptr = build_unary_op (ADDR_EXPR, vtable_ptr, 0); /* We need to point into the middle of the vtable. */ vtable_ptr = build2 (PLUS_EXPR, TREE_TYPE (vtable_ptr), vtable_ptr, size_binop (MULT_EXPR, size_int (2 * TARGET_VTABLE_DATA_ENTRY_DISTANCE), TYPE_SIZE_UNIT (vtable_entry_type))); TINFO_VTABLE_DECL (desc) = vtable_ptr; } init = tree_cons (NULL_TREE, vtable_ptr, init); init = tree_cons (NULL_TREE, decay_conversion (name_decl), init); init = build_constructor (NULL_TREE, nreverse (init)); TREE_CONSTANT (init) = 1; TREE_INVARIANT (init) = 1; TREE_STATIC (init) = 1; init = tree_cons (NULL_TREE, init, NULL_TREE); return init; }
static tree get_pseudo_ti_desc (tree type) { switch (TREE_CODE (type)) { case OFFSET_TYPE: return ptm_desc_type_node; case POINTER_TYPE: return ptr_desc_type_node; case ENUMERAL_TYPE: return enum_desc_type_node; case FUNCTION_TYPE: return func_desc_type_node; case ARRAY_TYPE: return ary_desc_type_node; case UNION_TYPE: case RECORD_TYPE: if (TYPE_PTRMEMFUNC_P (type)) return ptm_desc_type_node; else if (!COMPLETE_TYPE_P (type)) { if (!at_eof) cxx_incomplete_type_error (NULL_TREE, type); return class_desc_type_node; } else if (!BINFO_N_BASE_BINFOS (TYPE_BINFO (type))) return class_desc_type_node; else { tree binfo = TYPE_BINFO (type); VEC (tree) *base_accesses = BINFO_BASE_ACCESSES (binfo); tree base_binfo = BINFO_BASE_BINFO (binfo, 0); int num_bases = BINFO_N_BASE_BINFOS (binfo); if (num_bases == 1 && VEC_index (tree, base_accesses, 0) == access_public_node && !BINFO_VIRTUAL_P (base_binfo) && integer_zerop (BINFO_OFFSET (base_binfo))) /* single non-virtual public. */ return si_class_desc_type_node; else { tree var_desc; tree array_domain, base_array; if (TREE_VEC_LENGTH (vmi_class_desc_type_node) <= num_bases) { int ix; tree extend = make_tree_vec (num_bases + 5); for (ix = TREE_VEC_LENGTH (vmi_class_desc_type_node); ix--;) TREE_VEC_ELT (extend, ix) = TREE_VEC_ELT (vmi_class_desc_type_node, ix); vmi_class_desc_type_node = extend; } var_desc = TREE_VEC_ELT (vmi_class_desc_type_node, num_bases); if (var_desc) return var_desc; /* Create the array of __base_class_type_info entries. G++ 3.2 allocated an array that had one too many entries, and then filled that extra entries with zeros. */ if (abi_version_at_least (2)) array_domain = build_index_type (size_int (num_bases - 1)); else array_domain = build_index_type (size_int (num_bases)); base_array = build_array_type (base_desc_type_node, array_domain); push_nested_namespace (abi_node); var_desc = create_pseudo_type_info ("__vmi_class_type_info", num_bases, build_decl (FIELD_DECL, NULL_TREE, integer_type_node), build_decl (FIELD_DECL, NULL_TREE, integer_type_node), build_decl (FIELD_DECL, NULL_TREE, base_array), NULL); pop_nested_namespace (abi_node); TREE_VEC_ELT (vmi_class_desc_type_node, num_bases) = var_desc; return var_desc; } } default: return bltn_desc_type_node; } }
tree ubsan_type_descriptor (tree type, enum ubsan_print_style pstyle) { /* See through any typedefs. */ type = TYPE_MAIN_VARIANT (type); tree decl = decl_for_type_lookup (type); /* It is possible that some of the earlier created DECLs were found unused, in that case they weren't emitted and varpool_get_node returns NULL node on them. But now we really need them. Thus, renew them here. */ if (decl != NULL_TREE && varpool_get_node (decl)) return build_fold_addr_expr (decl); tree dtype = ubsan_type_descriptor_type (); tree type2 = type; const char *tname = NULL; char *pretty_name; unsigned char deref_depth = 0; unsigned short tkind, tinfo; /* Get the name of the type, or the name of the pointer type. */ if (pstyle == UBSAN_PRINT_POINTER) { gcc_assert (POINTER_TYPE_P (type)); type2 = TREE_TYPE (type); /* Remove any '*' operators from TYPE. */ while (POINTER_TYPE_P (type2)) deref_depth++, type2 = TREE_TYPE (type2); if (TREE_CODE (type2) == METHOD_TYPE) type2 = TYPE_METHOD_BASETYPE (type2); } /* If an array, get its type. */ type2 = strip_array_types (type2); if (pstyle == UBSAN_PRINT_ARRAY) { while (POINTER_TYPE_P (type2)) deref_depth++, type2 = TREE_TYPE (type2); } if (TYPE_NAME (type2) != NULL) { if (TREE_CODE (TYPE_NAME (type2)) == IDENTIFIER_NODE) tname = IDENTIFIER_POINTER (TYPE_NAME (type2)); else if (DECL_NAME (TYPE_NAME (type2)) != NULL) tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type2))); } if (tname == NULL) /* We weren't able to determine the type name. */ tname = "<unknown>"; /* Decorate the type name with '', '*', "struct", or "union". */ pretty_name = (char *) alloca (strlen (tname) + 16 + deref_depth); if (pstyle == UBSAN_PRINT_POINTER) { int pos = sprintf (pretty_name, "'%s%s%s%s%s%s%s", TYPE_VOLATILE (type2) ? "volatile " : "", TYPE_READONLY (type2) ? "const " : "", TYPE_RESTRICT (type2) ? "restrict " : "", TYPE_ATOMIC (type2) ? "_Atomic " : "", TREE_CODE (type2) == RECORD_TYPE ? "struct " : TREE_CODE (type2) == UNION_TYPE ? "union " : "", tname, deref_depth == 0 ? "" : " "); while (deref_depth-- > 0) pretty_name[pos++] = '*'; pretty_name[pos++] = '\''; pretty_name[pos] = '\0'; } else if (pstyle == UBSAN_PRINT_ARRAY) { /* Pretty print the array dimensions. */ gcc_assert (TREE_CODE (type) == ARRAY_TYPE); tree t = type; int pos = sprintf (pretty_name, "'%s ", tname); while (deref_depth-- > 0) pretty_name[pos++] = '*'; while (TREE_CODE (t) == ARRAY_TYPE) { pretty_name[pos++] = '['; tree dom = TYPE_DOMAIN (t); if (dom && TREE_CODE (TYPE_MAX_VALUE (dom)) == INTEGER_CST) pos += sprintf (&pretty_name[pos], HOST_WIDE_INT_PRINT_DEC, tree_to_shwi (TYPE_MAX_VALUE (dom)) + 1); else /* ??? We can't determine the variable name; print VLA unspec. */ pretty_name[pos++] = '*'; pretty_name[pos++] = ']'; t = TREE_TYPE (t); } pretty_name[pos++] = '\''; pretty_name[pos] = '\0'; /* Save the tree with stripped types. */ type = t; } else sprintf (pretty_name, "'%s'", tname); switch (TREE_CODE (type)) { case BOOLEAN_TYPE: case ENUMERAL_TYPE: case INTEGER_TYPE: tkind = 0x0000; break; case REAL_TYPE: /* FIXME: libubsan right now only supports float, double and long double type formats. */ if (TYPE_MODE (type) == TYPE_MODE (float_type_node) || TYPE_MODE (type) == TYPE_MODE (double_type_node) || TYPE_MODE (type) == TYPE_MODE (long_double_type_node)) tkind = 0x0001; else tkind = 0xffff; break; default: tkind = 0xffff; break; } tinfo = get_ubsan_type_info_for_type (type); /* Create a new VAR_DECL of type descriptor. */ char tmp_name[32]; static unsigned int type_var_id_num; ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_type", type_var_id_num++); decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name), dtype); TREE_STATIC (decl) = 1; TREE_PUBLIC (decl) = 0; DECL_ARTIFICIAL (decl) = 1; DECL_IGNORED_P (decl) = 1; DECL_EXTERNAL (decl) = 0; size_t len = strlen (pretty_name); tree str = build_string (len + 1, pretty_name); TREE_TYPE (str) = build_array_type (char_type_node, build_index_type (size_int (len))); TREE_READONLY (str) = 1; TREE_STATIC (str) = 1; tree ctor = build_constructor_va (dtype, 3, NULL_TREE, build_int_cst (short_unsigned_type_node, tkind), NULL_TREE, build_int_cst (short_unsigned_type_node, tinfo), NULL_TREE, str); TREE_CONSTANT (ctor) = 1; TREE_STATIC (ctor) = 1; DECL_INITIAL (decl) = ctor; varpool_finalize_decl (decl); /* Save the VAR_DECL into the hash table. */ decl_for_type_insert (type, decl); return build_fold_addr_expr (decl); }