Subversion Repositories planix.SVN

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

// portable acid for all architectures

defn pfl(addr)
{
        print(pcfile(addr), ":", pcline(addr), "\n");
}

defn
notestk(addr)
{
        local pc, sp;
        complex Ureg addr;

        pc = addr.pc\X;
        sp = addr.sp\X;

        print("Note pc:", pc, " sp:", sp, " ", fmt(pc, 'a'), " ");
        pfl(pc);
        _stk(pc, sp, linkreg(addr), 1);
}

defn
notelstk(addr)
{
        local pc, sp;
        complex Ureg addr;

        pc = addr.pc\X;
        sp = addr.sp\X;

        print("Note pc:", pc, " sp:", sp, " ", fmt(pc, 'a'), " ");
        pfl(pc);
        _stk(pc, sp, linkreg(addr), 1);
}

defn labstk(l)                          // trace from a label
{
        _stk(*(l+4), *l, linkreg(0), 0);
}

defn params(param)
{
        while param do {
                sym = head param;
                print(sym[0], "=", itoa(sym[1], "%ux"));
                param = tail param;
                if param then
                        print (",");
        }       
}

stkprefix = "";
stkignore = {};
stkend = 0;

defn locals(l)
{
        local sym;

        while l do {
                sym = head l;
                print(stkprefix, "\t", sym[0], "=", itoa(sym[1], "%ux"), "\n");
                l = tail l;
        }       
}

defn _stkign(file)
{
        s = stkignore;
        while s do {
                if regexp(head s, file) then
                        return 1;
                s = tail s;
        }
        return 0;
}

// print a stack trace
//
// in a run of leading frames in files matched by regexps in stkignore,
// only print the last one.
defn _stk(pc, sp, link, dolocals)
{
        local stk, ign, last, lastpc;

        stk = strace(pc, sp, link);
        if stkignore then
                ign = 1;
        else
                ign = 0;
        last = stk;
        lastpc = pc;
        while stk do {
                if ign then {
                        if !_stkign(pcfile(pc)) then {
                                ign = 0;
                                stk = last;
                                pc = lastpc;
                        }
                }
                frame = head stk;
                if !ign then {
                        print(stkprefix, fmt(frame[0], 'a'), "(");
                        params(frame[2]);
                        print(")+", itoa(pc-frame[0], "%ux"), " ");
                        pfl(pc);
                        if dolocals then
                                locals(frame[3]);
                }
                last = stk;
                lastpc = pc;
                stk = tail stk;
                pc = frame[1];
        }
        print(stkprefix, fmt(pc, 'a'), " ");
        pfl(pc);
}

defn findsrc(file)
{
        local lst, src;

        if file[0] == '/' then {
                src = file(file);
                if src != {} then {
                        srcfiles = append srcfiles, file;
                        srctext = append srctext, src;
                        return src;
                }
                return {};
        }

        lst = srcpath;
        while head lst do {
                src = file(head lst+file);
                if src != {} then {
                        srcfiles = append srcfiles, file;
                        srctext = append srctext, src;
                        return src;
                }
                lst = tail lst;
        }
}

defn line(addr)
{
        local src, file;

        file = pcfile(addr);
        src = match(file, srcfiles);

        if src >= 0 then
                src = srctext[src];
        else
                src = findsrc(file);

        if src == {} then {
                print("no source for ", file, "\n");
                return {};
        }
        line = pcline(addr)-1;
        print(file, ":", src[line], "\n");
}

defn addsrcdir(dir)
{
        dir = dir+"/";

        if match(dir, srcpath) >= 0 then {
                print("already in srcpath\n");
                return {};
        }

        srcpath = {dir}+srcpath;
}

defn source()
{
        local l;

        l = srcpath;
        while l do {
                print(head l, "\n");
                l = tail l;
        }
        l = srcfiles;

        while l do {
                print("\t", head l, "\n");
                l = tail l;
        }
}

defn Bsrc(addr)
{
        local lst;

        lst = srcpath;
        file = pcfile(addr);
        if file[0] == '/' && access(file) then {
                rc("B "+file+":"+itoa(pcline(addr)));
                return {};
        }
        while head lst do {
                name = head lst+file;
                if access(name) then {
                        rc("B "+name+":"+itoa(pcline(addr)));
                        return {};
                }
                lst = tail lst;
        }
        print("no source for ", file, "\n");
}

defn srcline(addr)
{
        local text, cline, line, file, src;
        file = pcfile(addr);
        src = match(file,srcfiles);
        if (src>=0) then
                src = srctext[src];
        else
                src = findsrc(file);
        if (src=={}) then
        {
                return "(no source)";
        }
        return src[pcline(addr)-1];
}

defn src(addr)
{
        local src, file, line, cline, text;

        file = pcfile(addr);
        src = match(file, srcfiles);

        if src >= 0 then
                src = srctext[src];
        else
                src = findsrc(file);

        if src == {} then {
                print("no source for ", file, "\n");
                return {};
        }

        cline = pcline(addr)-1;
        print(file, ":", cline+1, "\n");
        line = cline-5;
        loop 0,10 do {
                if line >= 0 then {
                        text = src[line];
                        if text == {} then
                                return {};
                        if line == cline then
                                print(">");
                        else
                                print(" ");
                        print(line+1, "\t", text, "\n");
                }
                line = line+1;
        }       
}

defn step()                                     // single step the process
{
        local lst, lpl, addr, bput;

        bput = 0;
        if match(*PC, bplist) >= 0 then {       // Sitting on a breakpoint
                bput = fmt(*PC, bpfmt);
                *bput = @bput;
        }

        lst = follow(*PC);

        lpl = lst;
        while lpl do {                          // place break points
                *(head lpl) = bpinst;
                lpl = tail lpl;
        }

        startstop(pid);                         // do the step

        while lst do {                          // remove the breakpoints
                addr = fmt(head lst, bpfmt);
                *addr = @addr;
                lst = tail lst;
        }
        if bput != 0 then
                *bput = bpinst;
}

defn bpset(addr)                                // set a breakpoint
{
        if status(pid) != "Stopped" then {
                print("Waiting...\n");
                stop(pid);
        }
        if match(addr, bplist) >= 0 then
                print("breakpoint already set at ", fmt(addr, 'a'), "\n");
        else {
                *fmt(addr, bpfmt) = bpinst;
                bplist = append bplist, addr;
        }
}

defn bptab()                                    // print a table of breakpoints
{
        local lst, addr;

        lst = bplist;
        while lst do {
                addr = head lst;
                print("\t", fmt(addr, 'X'), " ", fmt(addr, 'a'), "  ", fmt(addr, 'i'), "\n");
                lst = tail lst;
        }
}

defn bpdel(addr)                                // delete a breakpoint
{
        local n, pc, nbplist;

        n = match(addr, bplist);
        if n < 0  then {
                print("no breakpoint at ", fmt(addr, 'a'), "\n");
                return {};
        }

        addr = fmt(addr, bpfmt);
        *addr = @addr;

        nbplist = {};                           // delete from list
        while bplist do {
                pc = head bplist;
                if pc != addr then
                        nbplist = append nbplist, pc;
                bplist = tail bplist;
        }
        bplist = nbplist;                       // delete from memory
}

defn cont()                                     // continue execution
{
        local addr;

        addr = fmt(*PC, bpfmt);
        if match(addr, bplist) >= 0 then {      // Sitting on a breakpoint
                *addr = @addr;
                step();                         // Step over
                *addr = bpinst;
        }
        startstop(pid);                         // Run
}

defn stopped(pid)               // called from acid when a process changes state
{
        pstop(pid);             // stub so this is easy to replace
}

defn procs()                    // print status of processes
{
        local c, lst, cpid;

        cpid = pid;
        lst = proclist;
        while lst do {
                np = head lst;
                setproc(np);
                if np == cpid then
                        c = '>';
                else
                        c = ' ';
                print(fmt(c, 'c'), np, ": ", status(np), " at ", fmt(*PC, 'a'), " setproc(", np, ")\n");
                lst = tail lst;
        }
        pid = cpid;
        if pid != 0 then
                setproc(pid);
}

_asmlines = 30;

defn asm(addr)
{
        local bound;

        bound = fnbound(addr);

        addr = fmt(addr, 'i');
        loop 1,_asmlines do {
                print(fmt(addr, 'a'), " ", fmt(addr, 'X'));
                print("\t", @addr++, "\n");
                if bound != {} && addr > bound[1] then {
                        lasmaddr = addr;
                        return {};
                }
        }
        lasmaddr = addr;
}

defn casm()
{
        asm(lasmaddr);
}

defn win()
{
        local npid, estr;

        bplist = {};
        notes = {};

        estr = "/sys/lib/acid/window '0 0 600 400' "+textfile;
        if progargs != "" then
                estr = estr+" "+progargs;

        npid = rc(estr);
        npid = atoi(npid);
        if npid == 0 then
                error("win failed to create process");

        setproc(npid);
        stopped(npid);
}

defn win2()
{
        local npid, estr;

        bplist = {};
        notes = {};

        estr = "/sys/lib/acid/transcript '0 0 600 400' '100 100 700 500' "+textfile;
        if progargs != "" then
                estr = estr+" "+progargs;

        npid = rc(estr);
        npid = atoi(npid);
        if npid == 0 then
                error("win failed to create process");

        setproc(npid);
        stopped(npid);
}

defn new()
{
        bplist = {};
        newproc(progargs);
        // Dont miss the delay slot calls
        bpset(follow(main)[0]);
        cont();
        bpdel(*PC);
}

defn stmnt()                    // step one statement
{
        local line;

        line = pcline(*PC);
        while 1 do {
                step();
                if line != pcline(*PC) then {
                        src(*PC);
                        return {};
                }
        }
}

defn func()                     // step until we leave the current function
{
        local bound, end, start, pc;

        bound = fnbound(*PC);
        if bound == {} then {
                print("cannot locate text symbol\n");
                return {};
        }

        pc = *PC;
        start = bound[0];
        end = bound[1];
        while pc >= start && pc < end do {
                step();
                pc = *PC;
        }
}

defn next()
{
        local sp, bound;

        sp = *SP;
        bound = fnbound(*PC);
        stmnt();
        pc = *PC;
        if pc >= bound[0] && pc < bound[1] then
                return {};

        while (pc < bound[0] || pc > bound[1]) && sp >= *SP do {
                step();
                pc = *PC;
        }
        src(*PC);
}

defn dump(addr, n, fmt)
{
        // see definition of dump in acid manual: it does n+1 iterations
        loop 0, n do {
                print(fmt(addr, 'X'), ": ");
                addr = mem(addr, fmt);
        }
}

defn mem(addr, fmt)
{

        local i, c, n;

        i = 0;
        while fmt[i] != 0 do {
                c = fmt[i];
                n = 0;
                while '0' <= fmt[i] && fmt[i] <= '9' do {
                        n = 10*n + fmt[i]-'0';
                        i = i+1;
                }
                if n <= 0 then n = 1;
                addr = fmt(addr, fmt[i]);
                while n > 0 do {
                        print(*addr++, " ");
                        n = n-1;
                }
                i = i+1;
        }
        print("\n");
        return addr;
}

defn symbols(pattern)
{
        local l, s;

        l = symbols;
        while l do {
                s = head l;
                if regexp(pattern, s[0]) then
                        print(s[0], "\t", s[1], "\t", s[2], "\n");
                l = tail l;
        }
}

defn spsrch(len)
{
        local addr, a, s, e;

        addr = *SP;
        s = origin & 0x7fffffff;
        e = etext & 0x7fffffff;
        loop 1, len do {
                a = *addr++;
                c = a & 0x7fffffff;
                if c > s && c < e then {
                        print("src(", a, ")\n");
                        pfl(a);
                }                       
        }
}

progargs="";
print("/sys/lib/acid/port");