blob: 06c18804f36216ad07efabee482e78249bb239a7 [file] [log] [blame]
/* -*- indent-tabs-mode: nil; js-indent-level: 4 -*- */
"use strict";
// gcc appends this to mangled function names for "not in charge"
// constructors/destructors.
var internalMarker = " *INTERNAL* ";
if (! Set.prototype.hasOwnProperty("update")) {
Object.defineProperty(Set.prototype, "update", {
value: function (collection) {
for (let elt of collection)
this.add(elt);
}
});
}
function assert(x, msg)
{
if (x)
return;
debugger;
if (msg)
throw "assertion failed: " + msg + "\n" + (Error().stack);
else
throw "assertion failed: " + (Error().stack);
}
function defined(x) {
return x !== undefined;
}
function xprint(x, padding)
{
if (!padding)
padding = "";
if (x instanceof Array) {
print(padding + "[");
for (var elem of x)
xprint(elem, padding + " ");
print(padding + "]");
} else if (x instanceof Object) {
print(padding + "{");
for (var prop in x) {
print(padding + " " + prop + ":");
xprint(x[prop], padding + " ");
}
print(padding + "}");
} else {
print(padding + x);
}
}
function sameBlockId(id0, id1)
{
if (id0.Kind != id1.Kind)
return false;
if (!sameVariable(id0.Variable, id1.Variable))
return false;
if (id0.Kind == "Loop" && id0.Loop != id1.Loop)
return false;
return true;
}
function sameVariable(var0, var1)
{
assert("Name" in var0 || var0.Kind == "This" || var0.Kind == "Return");
assert("Name" in var1 || var1.Kind == "This" || var1.Kind == "Return");
if ("Name" in var0)
return "Name" in var1 && var0.Name[0] == var1.Name[0];
return var0.Kind == var1.Kind;
}
function blockIdentifier(body)
{
if (body.BlockId.Kind == "Loop")
return body.BlockId.Loop;
assert(body.BlockId.Kind == "Function", "body.Kind should be Function, not " + body.BlockId.Kind);
return body.BlockId.Variable.Name[0];
}
function collectBodyEdges(body)
{
body.predecessors = [];
body.successors = [];
if (!("PEdge" in body))
return;
for (var edge of body.PEdge) {
var [ source, target ] = edge.Index;
if (!(target in body.predecessors))
body.predecessors[target] = [];
body.predecessors[target].push(edge);
if (!(source in body.successors))
body.successors[source] = [];
body.successors[source].push(edge);
}
}
function getPredecessors(body)
{
try {
if (!('predecessors' in body))
collectBodyEdges(body);
} catch (e) {
debugger;
printErr("body is " + body);
}
return body.predecessors;
}
function getSuccessors(body)
{
if (!('successors' in body))
collectBodyEdges(body);
return body.successors;
}
// Split apart a function from sixgill into its mangled and unmangled name. If
// no mangled name was given, use the unmangled name as its mangled name
function splitFunction(func)
{
var split = func.indexOf("$");
if (split != -1)
return [ func.substr(0, split), func.substr(split+1) ];
split = func.indexOf("|");
if (split != -1)
return [ func.substr(0, split), func.substr(split+1) ];
return [ func, func ];
}
function mangled(fullname)
{
var [ mangled, unmangled ] = splitFunction(fullname);
return mangled;
}
function readable(fullname)
{
var [ mangled, unmangled ] = splitFunction(fullname);
return unmangled;
}
function xdbLibrary()
{
var lib = ctypes.open(os.getenv('XDB'));
var api = {
open: lib.declare("xdb_open", ctypes.default_abi, ctypes.void_t, ctypes.char.ptr),
min_data_stream: lib.declare("xdb_min_data_stream", ctypes.default_abi, ctypes.int),
max_data_stream: lib.declare("xdb_max_data_stream", ctypes.default_abi, ctypes.int),
read_key: lib.declare("xdb_read_key", ctypes.default_abi, ctypes.char.ptr, ctypes.int),
read_entry: lib.declare("xdb_read_entry", ctypes.default_abi, ctypes.char.ptr, ctypes.char.ptr),
free_string: lib.declare("xdb_free", ctypes.default_abi, ctypes.void_t, ctypes.char.ptr)
};
try {
api.lookup_key = lib.declare("xdb_lookup_key", ctypes.default_abi, ctypes.int, ctypes.char.ptr);
} catch (e) {
// lookup_key is for development use only and is not strictly necessary.
}
return api;
}
function cLibrary()
{
var lib;
try {
lib = ctypes.open("libc.so.6");
} catch(e) {
lib = ctypes.open("libc.so");
}
return {
fopen: lib.declare("fopen", ctypes.default_abi, ctypes.void_t.ptr, ctypes.char.ptr, ctypes.char.ptr),
getline: lib.declare("getline", ctypes.default_abi, ctypes.ssize_t, ctypes.char.ptr.ptr, ctypes.size_t.ptr, ctypes.void_t.ptr),
fclose: lib.declare("fclose", ctypes.default_abi, ctypes.int, ctypes.void_t.ptr),
free: lib.declare("free", ctypes.default_abi, ctypes.void_t, ctypes.void_t.ptr),
};
}
function* readFileLines_gen(filename)
{
var libc = cLibrary();
var linebuf = ctypes.char.ptr();
var bufsize = ctypes.size_t(0);
var fp = libc.fopen(filename, "r");
if (fp.isNull())
throw "Unable to open '" + filename + "'"
while (libc.getline(linebuf.address(), bufsize.address(), fp) > 0)
yield linebuf.readString();
libc.fclose(fp);
libc.free(ctypes.void_t.ptr(linebuf));
}
function addToKeyedList(collection, key, entry)
{
if (!(key in collection))
collection[key] = [];
collection[key].push(entry);
}
function loadTypeInfo(filename)
{
var info = {};
for (var line of readFileLines_gen(filename)) {
line = line.replace(/\n/, "");
let [property, name] = line.split("$$");
addToKeyedList(info, property, name);
}
return info;
}