xpcom/analysis/stack.js

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 require({ after_gcc_pass: "cfg" });
michael@0 6
michael@0 7 include("gcc_util.js");
michael@0 8 include("unstable/lazy_types.js");
michael@0 9
michael@0 10 function process_type(c)
michael@0 11 {
michael@0 12 if ((c.kind == 'class' || c.kind == 'struct') &&
michael@0 13 !c.isIncomplete)
michael@0 14 isStack(c);
michael@0 15 }
michael@0 16
michael@0 17 /**
michael@0 18 * A BlameChain records a chain of one or more location/message pairs. It
michael@0 19 * can be used to issue a complex error message such as:
michael@0 20 * location: error: Allocated class Foo on the heap
michael@0 21 * locationofFoo: class Foo inherits from class Bar
michael@0 22 * locationofBar: in class Bar
michael@0 23 * locationofBarMem: Member Bar::mFoo
michael@0 24 * locationofBaz: class Baz is annotated NS_STACK
michael@0 25 */
michael@0 26 function BlameChain(loc, message, prev)
michael@0 27 {
michael@0 28 this.loc = loc;
michael@0 29 this.message = message;
michael@0 30 this.prev = prev;
michael@0 31 }
michael@0 32
michael@0 33 BlameChain.prototype.toString = function()
michael@0 34 {
michael@0 35 let loc = this.loc;
michael@0 36 if (loc === undefined)
michael@0 37 loc = "<unknown location>";
michael@0 38
michael@0 39 let str = '%s: %s'.format(loc.toString(), this.message);
michael@0 40 if (this.prev)
michael@0 41 str += "\n%s".format(this.prev);
michael@0 42 return str;
michael@0 43 };
michael@0 44
michael@0 45 function isStack(c)
michael@0 46 {
michael@0 47 function calculate()
michael@0 48 {
michael@0 49 if (hasAttribute(c, 'NS_stack'))
michael@0 50 return new BlameChain(c.loc, '%s %s is annotated NS_STACK_CLASS'.format(c.kind, c.name));
michael@0 51
michael@0 52 for each (let base in c.bases) {
michael@0 53 let r = isStack(base.type);
michael@0 54 if (r != null)
michael@0 55 return new BlameChain(c.loc, '%s %s is a base of %s %s'.format(base.type.kind, base.type.name, c.kind, c.name), r);
michael@0 56 }
michael@0 57
michael@0 58 for each (let member in c.members) {
michael@0 59 if (member.isFunction)
michael@0 60 continue;
michael@0 61
michael@0 62 if (hasAttribute(member, 'NS_okonheap'))
michael@0 63 continue;
michael@0 64
michael@0 65 let type = member.type;
michael@0 66 while (true) {
michael@0 67 if (type === undefined)
michael@0 68 break;
michael@0 69
michael@0 70 if (type.isArray) {
michael@0 71 type = type.type;
michael@0 72 continue;
michael@0 73 }
michael@0 74
michael@0 75 if (type.typedef) {
michael@0 76 if (hasAttribute(type, 'NS_stack'))
michael@0 77 return true;
michael@0 78
michael@0 79 type = type.typedef;
michael@0 80 continue;
michael@0 81 }
michael@0 82 break;
michael@0 83 }
michael@0 84
michael@0 85 if (type === undefined) {
michael@0 86 warning("incomplete type for member " + member + ".", member.loc);
michael@0 87 continue;
michael@0 88 }
michael@0 89
michael@0 90 if (type.isPointer || type.isReference)
michael@0 91 continue;
michael@0 92
michael@0 93 if (!type.kind || (type.kind != 'class' && type.kind != 'struct'))
michael@0 94 continue;
michael@0 95
michael@0 96 let r = isStack(type);
michael@0 97 if (r != null)
michael@0 98 return new BlameChain(c.loc, 'In class %s'.format(c.name),
michael@0 99 new BlameChain(member.loc, 'Member %s'.format(member.name), r));
michael@0 100 }
michael@0 101 return null;
michael@0 102 }
michael@0 103
michael@0 104 if (!c.hasOwnProperty('isStack'))
michael@0 105 c.isStack = calculate();
michael@0 106
michael@0 107 return c.isStack;
michael@0 108 }
michael@0 109
michael@0 110 function process_tree(fn)
michael@0 111 {
michael@0 112 if (hasAttribute(dehydra_convert(fn), 'NS_suppress_stackcheck'))
michael@0 113 return;
michael@0 114
michael@0 115 let cfg = function_decl_cfg(fn);
michael@0 116
michael@0 117 for (let bb in cfg_bb_iterator(cfg)) {
michael@0 118 let it = bb_isn_iterator(bb);
michael@0 119 for (let isn in it) {
michael@0 120 if (isn.tree_code() != GIMPLE_CALL)
michael@0 121 continue;
michael@0 122
michael@0 123 let name = gimple_call_function_name(isn);
michael@0 124 if (name != "operator new" && name != "operator new []")
michael@0 125 continue;
michael@0 126
michael@0 127 // ignore placement new
michael@0 128 // TODO? ensure 2nd arg is local stack variable
michael@0 129 if (gimple_call_num_args(isn) == 2 &&
michael@0 130 TREE_TYPE(gimple_call_arg(isn, 1)).tree_code() == POINTER_TYPE)
michael@0 131 continue;
michael@0 132
michael@0 133 let newLhs = gimple_call_lhs(isn);
michael@0 134 if (!newLhs)
michael@0 135 error("Non assigning call to operator new", location_of(isn));
michael@0 136
michael@0 137 // if isn is the last of its block there are other problems...
michael@0 138 assign = it.next();
michael@0 139
michael@0 140 // Calls to |new| are always followed by an assignment, casting the void ptr to which
michael@0 141 // |new| was assigned, to a ptr variable of the same type as the allocated object.
michael@0 142 // Exception: explicit calls to |::operator new (size_t)|, which can be ignored.
michael@0 143 if (assign.tree_code() != GIMPLE_ASSIGN)
michael@0 144 continue;
michael@0 145
michael@0 146 let assignRhs = gimple_op(assign, 1);
michael@0 147 if (newLhs != assignRhs)
michael@0 148 continue;
michael@0 149
michael@0 150 let assignLhs = gimple_op(assign, 0);
michael@0 151 let type = TREE_TYPE(TREE_TYPE(assignLhs));
michael@0 152 let dehydraType = dehydra_convert(type);
michael@0 153
michael@0 154 let r = isStack(dehydraType);
michael@0 155 if (r)
michael@0 156 warning("constructed object of type '%s' not on the stack: %s".format(dehydraType.name, r), location_of(isn));
michael@0 157 }
michael@0 158 }
michael@0 159 }

mercurial