| // 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); |