|  | // 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" then | 
|  | return *AX; | 
|  | if objtype=="mips" then | 
|  | return *R1; | 
|  | if objtype=="power" || objtype=="alpha" 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(acidfile); |