Subversion Repositories planix.SVN

Rev

Blame | Last modification | View Log | RSS feed

// 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("/sys/lib/acid/trump");