зеркало из https://github.com/mozilla/gecko-dev.git
Static rooting analysis updates for browser. No bug. r=NPOTB
--HG-- extra : rebase_source : f7e8f1f3039c6ebaa3dabea2a7c181a880d1792b
This commit is contained in:
Родитель
6f73405058
Коммит
304e360031
|
@ -16,24 +16,27 @@ if (typeof arguments[0] != 'string' || typeof arguments[1] != 'string')
|
|||
|
||||
var gcFunctionsFile = arguments[0];
|
||||
var gcTypesFile = arguments[1];
|
||||
var start = arguments[2]|0;
|
||||
var end = arguments[3]|0;
|
||||
var tmpfile = arguments[4];
|
||||
if (!start)
|
||||
start = 1;
|
||||
if (!tmpfile)
|
||||
tmpfile = "tmp.txt";
|
||||
var batch = arguments[2]|0;
|
||||
var numBatches = (arguments[3]|0) || 1;
|
||||
var tmpfile = arguments[4] || "tmp.txt";
|
||||
|
||||
var gcFunctions = {};
|
||||
var suppressedFunctions = {};
|
||||
var gcFunctionsText = snarf(gcFunctionsFile).split('\n');
|
||||
for (var line of gcFunctionsText) {
|
||||
if (match = /GC Function: (.*)/.exec(line))
|
||||
gcFunctions[match[1]] = true;
|
||||
if (match = /Suppressed Function: (.*)/.exec(line))
|
||||
suppressedFunctions[match[1]] = true;
|
||||
assert(!system("grep 'GC Function' " + gcFunctionsFile + " > tmp.txt"));
|
||||
var text = snarf("tmp.txt").split('\n');
|
||||
assert(text.pop().length == 0);
|
||||
for (var line of text) {
|
||||
match = /GC Function: (.*)/.exec(line);
|
||||
gcFunctions[match[1]] = true;
|
||||
}
|
||||
gcFunctionsText = null;
|
||||
assert(!system("grep 'Suppressed Function' " + arguments[0] + " > tmp.txt"));
|
||||
text = snarf("tmp.txt").split('\n');
|
||||
assert(text.pop().length == 0);
|
||||
for (var line of text) {
|
||||
match = /Suppressed Function: (.*)/.exec(line);
|
||||
suppressedFunctions[match[1]] = true;
|
||||
}
|
||||
text = null;
|
||||
|
||||
var match;
|
||||
var gcThings = {};
|
||||
|
@ -477,7 +480,7 @@ function processBodies()
|
|||
}
|
||||
}
|
||||
|
||||
if (start == 1)
|
||||
if (batch == 1)
|
||||
print("Time: " + new Date);
|
||||
|
||||
var xdb = xdbLibrary();
|
||||
|
@ -486,8 +489,10 @@ xdb.open("src_body.xdb");
|
|||
var minStream = xdb.min_data_stream()|0;
|
||||
var maxStream = xdb.max_data_stream()|0;
|
||||
|
||||
start += minStream - 1;
|
||||
end += minStream - 1;
|
||||
var N = (maxStream - minStream) + 1;
|
||||
var each = Math.floor(N/numBatches);
|
||||
var start = minStream + each * (batch - 1);
|
||||
var end = Math.min(minStream + each * batch - 1, maxStream);
|
||||
|
||||
// Find the source tree
|
||||
for (let nameIndex = minStream; nameIndex <= maxStream; nameIndex++) {
|
||||
|
|
|
@ -11,6 +11,10 @@ function indirectCallCannotGC(caller, name)
|
|||
if (/CallDestroyScriptHook/.test(caller))
|
||||
return true;
|
||||
|
||||
// hooks called deep inside utility libraries.
|
||||
if (name == "_malloc_message")
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -20,7 +24,9 @@ var ignoreClasses = [
|
|||
"JSStringFinalizer",
|
||||
"SprintfStateStr",
|
||||
"JSLocaleCallbacks",
|
||||
"JSC::ExecutableAllocator"
|
||||
"JSC::ExecutableAllocator",
|
||||
"_MD_IOVector",
|
||||
"PRIOMethods"
|
||||
];
|
||||
|
||||
function fieldCallCannotGC(csu, field)
|
||||
|
@ -67,8 +73,19 @@ function ignoreEdgeUse(edge, variable)
|
|||
return false;
|
||||
}
|
||||
|
||||
var ignoreFunctions = [
|
||||
"ptio.c:pt_MapError",
|
||||
"PR_ExplodeTime",
|
||||
"PR_ErrorInstallTable"
|
||||
];
|
||||
|
||||
function ignoreGCFunction(fun)
|
||||
{
|
||||
for (var i = 0; i < ignoreFunctions.length; i++) {
|
||||
if (fun == ignoreFunctions[i])
|
||||
return true;
|
||||
}
|
||||
|
||||
// XXX modify refillFreeList<NoGC> to not need data flow analysis to understand it cannot GC.
|
||||
if (/refillFreeList/.test(fun) && /\(js::AllowGC\)0u/.test(fun))
|
||||
return true;
|
||||
|
|
|
@ -75,6 +75,9 @@ function memo(name)
|
|||
return memoized[name];
|
||||
}
|
||||
|
||||
var seenCallees = null;
|
||||
var seenSuppressedCallees = null;
|
||||
|
||||
function processBody(caller, body)
|
||||
{
|
||||
if (!('PEdge' in body))
|
||||
|
@ -83,29 +86,43 @@ function processBody(caller, body)
|
|||
if (edge.Kind != "Call")
|
||||
continue;
|
||||
var callee = edge.Exp[0];
|
||||
var suppressText = (edge.Index[0] in body.suppressed) ? "SUPPRESS_GC " : "";
|
||||
var suppressText = "";
|
||||
var seen = seenCallees;
|
||||
if (edge.Index[0] in body.suppressed) {
|
||||
suppressText = "SUPPRESS_GC ";
|
||||
seen = seenSuppressedCallees;
|
||||
}
|
||||
var prologue = suppressText + memo(caller) + " ";
|
||||
if (callee.Kind == "Var") {
|
||||
assert(callee.Variable.Kind == "Func");
|
||||
var name = callee.Variable.Name[0];
|
||||
print("D " + prologue + memo(name));
|
||||
if (!(name in seen)) {
|
||||
print("D " + prologue + memo(name));
|
||||
seen[name] = true;
|
||||
}
|
||||
var otherName = otherDestructorName(name);
|
||||
if (otherName)
|
||||
if (otherName && !(otherName in seen)) {
|
||||
print("D " + prologue + memo(otherName));
|
||||
seen[otherName] = true;
|
||||
}
|
||||
} else {
|
||||
assert(callee.Kind == "Drf");
|
||||
if (callee.Exp[0].Kind == "Fld") {
|
||||
var field = callee.Exp[0].Field;
|
||||
if ("FieldInstanceFunction" in field) {
|
||||
var fieldName = field.Name[0];
|
||||
var csuName = field.FieldCSU.Type.Name;
|
||||
if ("FieldInstanceFunction" in field && csuName != "nsISupports") {
|
||||
// virtual function call.
|
||||
var functions = findVirtualFunctions(field.FieldCSU.Type.Name, field.Name[0]);
|
||||
for (var name of functions)
|
||||
print("D " + prologue + memo(name));
|
||||
} else {
|
||||
var functions = findVirtualFunctions(csuName, fieldName);
|
||||
for (var name of functions) {
|
||||
if (!(name in seen)) {
|
||||
print("D " + prologue + memo(name));
|
||||
seen[name] = true;
|
||||
}
|
||||
}
|
||||
} else if (csuName != "nsISupports" || fieldName == "QueryInterface") {
|
||||
// indirect call through a field.
|
||||
print("F " + prologue +
|
||||
"CLASS " + field.FieldCSU.Type.Name +
|
||||
" FIELD " + field.Name[0]);
|
||||
print("F " + prologue + "CLASS " + csuName + " FIELD " + fieldName);
|
||||
}
|
||||
} else if (callee.Exp[0].Kind == "Var") {
|
||||
// indirect call through a variable.
|
||||
|
@ -150,6 +167,10 @@ for (var nameIndex = minStream; nameIndex <= maxStream; nameIndex++) {
|
|||
body.suppressed = [];
|
||||
for (var body of functionBodies)
|
||||
computeSuppressedPoints(body);
|
||||
|
||||
seenCallees = {};
|
||||
seenSuppressedCallees = {};
|
||||
|
||||
for (var body of functionBodies)
|
||||
processBody(name.readString(), body);
|
||||
|
||||
|
|
|
@ -4,13 +4,8 @@ set -e
|
|||
|
||||
JOBS="$1"
|
||||
|
||||
N=$($SIXGILL/bin/xdbkeys src_body.xdb | wc -l)
|
||||
EACH=$(( $N / $JOBS ))
|
||||
START=1
|
||||
for j in $(seq $JOBS); do
|
||||
END=$(( $START + $EACH ))
|
||||
env PATH=$PATH:$SIXGILL/bin XDB=$SIXGILL/bin/xdb.so $JS $ANALYZE gcFunctions.txt gcTypes.txt $START $END tmp.$j > rootingHazards.$j &
|
||||
START=$END
|
||||
env PATH=$PATH:$SIXGILL/bin XDB=$SIXGILL/bin/xdb.so $JS $ANALYZE gcFunctions.txt gcTypes.txt $j $JOBS tmp.$j > rootingHazards.$j &
|
||||
done
|
||||
|
||||
wait
|
||||
|
|
Загрузка…
Ссылка в новой задаче