LOCAL void putct1(bigptr q, bigptr lp, bigptr cp, int *ip) { NODE *p; int i; struct bigblock *lp1, *cp1; if(q->tag==TEXPR && q->b_expr.opcode==OPCONCAT) { putct1(q->b_expr.leftp, lp, cp, ip); putct1(q->b_expr.rightp, lp, cp , ip); frexpr(q->vleng); ckfree(q); } else { i = (*ip)++; lp1 = cpexpr(lp); lp1->b_addr.memoffset = mkexpr(OPPLUS, lp1->b_addr.memoffset, MKICON(i*FSZLENG)); cp1 = cpexpr(cp); cp1->b_addr.memoffset = mkexpr(OPPLUS, cp1->b_addr.memoffset, MKICON(i*FSZADDR)); p = putassign( lp1, cpexpr(q->vleng) ); sendp2(p); p = putassign( cp1, addrof(putch1(q)) ); sendp2(p); } }
void goto_symext::symex_free(const expr2tc &expr) { const code_free2t &code = to_code_free2t(expr); // Trigger 'free'-mode dereference of this pointer. Should generate various // dereference failure callbacks. expr2tc tmp = code.operand; dereference(tmp, false, true); address_of2tc addrof(code.operand->type, tmp); pointer_offset2tc ptr_offs(pointer_type2(), addrof); equality2tc eq(ptr_offs, zero_ulong); claim(eq, "Operand of free must have zero pointer offset"); // Clear the alloc bit, and set the deallocated bit. guardt guard; type2tc sym_type = type2tc(new array_type2t(get_bool_type(), expr2tc(), true)); pointer_object2tc ptr_obj(pointer_type2(), code.operand); symbol2tc dealloc_sym(sym_type, deallocd_arr_name); index2tc dealloc_index_expr(get_bool_type(), dealloc_sym, ptr_obj); expr2tc truth = true_expr; symex_assign_rec(dealloc_index_expr, truth, guard); symbol2tc valid_sym(sym_type, valid_ptr_arr_name); index2tc valid_index_expr(get_bool_type(), valid_sym, ptr_obj); expr2tc falsity = false_expr; symex_assign_rec(valid_index_expr, falsity, guard); }
Tree calltree(Tree f, Type ty, Tree args, Symbol t3) { Tree p; if (args) f = tree(RIGHT, f->type, args, f); if (isstruct(ty)) assert(t3), p = tree(RIGHT, ty, tree(CALL+B, ty, f, addrof(idtree(t3))), idtree(t3)); else { Type rty = ty; if (isenum(ty)) rty = unqual(ty)->type; if (!isfloat(rty)) rty = promote(rty); p = tree(mkop(CALL, rty), rty, f, NULL); if (isptr(ty) || p->type->size > ty->size) p = cast(p, ty); } return p; }
Tree call(Tree f, Type fty, Coordinate src) { int n = 0; Tree args = NULL, r = NULL, e; Type *proto, rty = unqual(freturn(fty)); Symbol t3 = NULL; if (fty->u.f.oldstyle) proto = NULL; else proto = fty->u.f.proto; if (hascall(f)) r = f; if (isstruct(rty)) { t3 = temporary(AUTO, unqual(rty)); if (rty->size == 0) error("illegal use of incomplete type `%t'\n", rty); } if (t != ')') for (;;) { Tree q = pointer(expr1(0)); if (proto && *proto && *proto != voidtype) { Type aty; q = value(q); aty = assign(*proto, q); if (aty) q = cast(q, aty); else error("type error in argument %d to %s; found `%t' expected `%t'\n", n + 1, funcname(f), q->type, *proto); if ((isint(q->type) || isenum(q->type)) && q->type->size != inttype->size) q = cast(q, promote(q->type)); ++proto; } else { if (!fty->u.f.oldstyle && *proto == NULL) error("too many arguments to %s\n", funcname(f)); q = value(q); if (isarray(q->type) || q->type->size == 0) error("type error in argument %d to %s; `%t' is illegal\n", n + 1, funcname(f), q->type); else q = cast(q, promote(q->type)); } if (!IR->wants_argb && isstruct(q->type)) if (iscallb(q)) q = addrof(q); else { Symbol t1 = temporary(AUTO, unqual(q->type)); q = asgn(t1, q); q = tree(RIGHT, ptr(t1->type), root(q), lvalue(idtree(t1))); } if (q->type->size == 0) q->type = inttype; if (hascall(q)) r = r ? tree(RIGHT, voidtype, r, q) : q; args = tree(mkop(ARG, q->type), q->type, q, args); n++; if (Aflag >= 2 && n == 32) warning("more than 31 arguments in a call to %s\n", funcname(f)); if (t != ',') break; t = gettok(); } expect(')'); if (proto && *proto && *proto != voidtype) error("insufficient number of arguments to %s\n", funcname(f)); if (r) args = tree(RIGHT, voidtype, r, args); e = calltree(f, rty, args, t3); if (events.calls) apply(events.calls, &src, &e); return e; }
/* tracevalue - append format and argument to print the value of e */ static void tracevalue(Tree e, int lev) { Type ty = unqual(e->type); switch (ty->op) { case INT: if (ty == chartype || ty == signedchar) appendstr("'\\x%02x'"); else if (ty == longtype) appendstr("0x%ld"); else appendstr("0x%d"); break; case UNSIGNED: if (ty == chartype || ty == unsignedchar) appendstr("'\\x%02x'"); else if (ty == unsignedlong) appendstr("0x%lx"); else appendstr("0x%x"); break; case FLOAT: if (ty == longdouble) appendstr("%Lg"); else appendstr("%g"); break; case POINTER: if (unqual(ty->type) == chartype || unqual(ty->type) == signedchar || unqual(ty->type) == unsignedchar) { static Symbol null; if (null == NULL) null = mkstr("(null)"); tracevalue(cast(e, unsignedtype), lev + 1); appendstr(" \"%.30s\""); e = condtree(e, e, pointer(idtree(null->u.c.loc))); } else { appendstr("("); appendstr(typestring(ty, "")); appendstr(")0x%x"); } break; case STRUCT: { Field q; appendstr("("); appendstr(typestring(ty, "")); appendstr("){"); for (q = ty->u.sym->u.s.flist; q; q = q->link) { appendstr(q->name); appendstr("="); tracevalue(field(addrof(e), q->name), lev + 1); if (q->link) appendstr(","); } appendstr("}"); return; } case UNION: appendstr("("); appendstr(typestring(ty, "")); appendstr("){...}"); return; case ARRAY: if (lev && ty->type->size > 0) { int i; e = pointer(e); appendstr("{"); for (i = 0; i < ty->size/ty->type->size; i++) { Tree p = (*optree['+'])(ADD, e, consttree(i, inttype)); if (isptr(p->type) && isarray(p->type->type)) p = retype(p, p->type->type); else p = rvalue(p); if (i) appendstr(","); tracevalue(p, lev + 1); } appendstr("}"); } else appendstr(typestring(ty, "")); return; default: assert(0); } e = cast(e, promote(ty)); args = tree(mkop(ARG,e->type), e->type, e, args); }
void goto_symext::symex_realloc(const expr2tc &lhs, const sideeffect2t &code) { expr2tc src_ptr = code.operand; expr2tc realloc_size = code.size; internal_deref_items.clear(); dereference2tc deref(get_empty_type(), src_ptr); dereference(deref, dereferencet::INTERNAL); // src_ptr is now invalidated. // Free the given pointer. This just uses the pointer object from the pointer // variable that's the argument to realloc. It also leads to pointer validity // checking, and checks that the offset is zero. code_free2tc fr(code.operand); symex_free(fr); // We now have a list of things to work on. Recurse into them, build a result, // and then switch between those results afterwards. // Result list is the address of the reallocated piece of data, and the guard. std::list<std::pair<expr2tc, expr2tc>> result_list; for(auto &item : internal_deref_items) { expr2tc guard = item.guard; cur_state->rename_address(item.object); cur_state->guard.guard_expr(guard); target->renumber(guard, item.object, realloc_size, cur_state->source); type2tc new_ptr = type2tc(new pointer_type2t(item.object->type)); address_of2tc addrof(new_ptr, item.object); result_list.emplace_back(addrof, item.guard); // Bump the realloc-numbering of the object. This ensures that, after // renaming, the address_of we just generated compares differently to // previous address_of's before the realloc. unsigned int cur_num = 0; if(cur_state->realloc_map.find(item.object) != cur_state->realloc_map.end()) { cur_num = cur_state->realloc_map[item.object]; } cur_num++; std::map<expr2tc, unsigned>::value_type v(item.object, cur_num); cur_state->realloc_map.insert(v); } // Rebuild a gigantic if-then-else chain from the result list. expr2tc result; if(result_list.size() == 0) { // Nothing happened; there was nothing, or only null, to point at. // In this case, just return right now and leave the pointer free. The // symex_free that occurred above should trigger a dereference failure. return; } result = expr2tc(); for(auto const &it : result_list) { if(is_nil_expr(result)) result = it.first; else result = if2tc(result->type, it.second, it.first, result); } // Install pointer modelling data into the relevant arrays. pointer_object2tc ptr_obj(pointer_type2(), result); track_new_pointer(ptr_obj, type2tc(), realloc_size); symex_assign(code_assign2tc(lhs, result), true); }