plan9fox/sys/lib/acid/trump
2016-05-04 16:11:48 +02:00

171 lines
3.1 KiB
Text

// trace user malloc pool - trace malloc, realloc, and free calls
// if trumpsbrk is set, we trace sbrkalloc and sbrkmerge too.
_stoprunning = 0;
trumphexaddrs = 0;
trumpsbrk = 0;
defn stopped(pid) {
local l;
local pc;
pc = *PC;
if notes then {
if (notes[0]!="sys: breakpoint") then
{
print(pid,": ",reason(*TRAP),"\t");
print(fmt(pc,97),"\t",fmt(pc,105),"\n");
print("Notes pending:\n");
l = notes;
while l do
{
print("\t",head l,"\n");
l = tail l;
}
_stoprunning = 1;
}
}
}
defn printstack() {
local frame, stk, pcs, lst, x;
pcs = {*PC};
stk = strace(*PC,*SP,0);
while stk do {
pcs = append pcs, stk[0][1];
stk = tail stk;
}
print(" #");
lst = pcs;
while lst do {
if trumphexaddrs != 0 then
x = lst[0]\X;
else
x = lst[0]\a;
print(" src(", x, ");");
lst = tail lst;
}
print("\n");
}
defn setuptrump() {
mallocPC = malloc;
malloczPC = mallocz;
freePC = free;
reallocPC = realloc;
sbrkallocPC = sbrkalloc;
sbrkmergePC = sbrkmerge;
// linker might fill delay slot with first instruction
if objtype == "mips" then {
mallocPC = mallocPC+4;
malloczPC = malloczPC+4;
freePC = freePC+4;
reallocPC = reallocPC+4;
sbrkallocPC = sbrkallocPC+4;
sbrkmergePC = sbrkmergePC+4;
}
bpset(mallocPC);
bpset(malloczPC);
bpset(freePC);
bpset(reallocPC);
if trumpsbrk then {
bpset(sbrkallocPC);
bpset(sbrkmergePC);
}
}
defn cleantrump() {
stop(pid);
bpdel(mallocPC);
bpdel(malloczPC);
bpdel(freePC);
bpdel(reallocPC);
bpdel(sbrkallocPC);
bpdel(sbrkmergePC);
}
defn trumpflush() {
stop(pid); // already stopped, but flushes output
}
defn new() {
bplist = {};
newproc(progargs);
bpset(follow(main)[0]);
cont();
bpdel(*PC);
// clear the hang bit, which is left set by newproc, so programs we fork/exec don't hang
printto("/proc/"+itoa(pid)+"/ctl", "nohang");
}
defn trumpfninfo() {
local arg0, arg1, stk, retpc, params;
stk = strace(*PC, *SP, 0);
retpc = stk[0][1];
params = stk[0][2];
arg0 = params[0][1];
arg1 = 0;
if tail params != {} then
arg1 = params[1][1];
return {arg0, arg1, retpc};
}
defn trumpretval() {
if objtype=="386" || objtype=="amd64" then
return *AX;
if objtype=="mips" then
return *R1;
if objtype=="power" || objtype=="arm" then
return *R0;
}
defn trump() {
local arg0, arg1, pc, ret, x;
stop(pid);
_stoprunning = 0;
setuptrump();
while !_stoprunning do {
cont();
if notes[0]!="sys: breakpoint" then {
cleantrump();
return {};
}
pc = *PC;
x = trumpfninfo();
arg0 = x[0];
if pc == reallocPC || pc == sbrkmergePC then
arg1 = x[1];
bpset(x[2]);
cont();
bpdel(x[2]);
ret = trumpretval();
if pc == mallocPC then
print(ret\X, " malloc ", arg0\D);
if pc == malloczPC then
print(ret\X, " mallocz ", arg0\D);
if pc == freePC then
print(arg0\X, " free");
if pc == reallocPC then
print(ret\X, " realloc ", arg0\X, " ", arg1\D);
if pc == sbrkallocPC then
print(ret\X, " sbrkalloc ", arg0\D);
if pc == sbrkmergePC then
print("sbrkmerge ", arg0\X, " ", arg1\X, " = ", ret\D);
printstack();
trumpflush();
}
}
defn untrump() {
cleantrump();
start(pid);
}
print("/sys/lib/acid/trump");