![cinap_lenrek](/assets/img/avatar_default.png)
from the unicode-db patch readme: command() receives a char* that is assigned to lp, which is a Rune*, and lp is incremented later in readchar(), so each read consumed 4 bytes. The only time command() is called is in runpcs() with bkpt->comm, which is a char* built in subpcs through a char*, so the string stored in bkpt->comm was not a Rune string. A way to test the bug is: db program main:b argv/X :r
375 lines
5.8 KiB
C
375 lines
5.8 KiB
C
/*
|
|
*
|
|
* debugger
|
|
*
|
|
*/
|
|
#include "defs.h"
|
|
#include "fns.h"
|
|
|
|
extern int infile;
|
|
extern int outfile;
|
|
extern int maxpos;
|
|
|
|
/* general printing routines ($) */
|
|
|
|
char *Ipath = INCDIR;
|
|
static int tracetype;
|
|
static void printfp(Map*, int);
|
|
|
|
/*
|
|
* callback on stack trace
|
|
*/
|
|
static void
|
|
ptrace(Map *map, uvlong pc, uvlong sp, Symbol *sym)
|
|
{
|
|
char buf[512];
|
|
|
|
USED(map);
|
|
dprint("%s(", sym->name);
|
|
printparams(sym, sp);
|
|
dprint(") ");
|
|
printsource(sym->value);
|
|
dprint(" called from ");
|
|
symoff(buf, 512, pc, CTEXT);
|
|
dprint("%s ", buf);
|
|
printsource(pc);
|
|
dprint("\n");
|
|
if(tracetype == 'C')
|
|
printlocals(sym, sp);
|
|
}
|
|
|
|
void
|
|
printtrace(int modif)
|
|
{
|
|
int i;
|
|
uvlong pc, sp, link;
|
|
ulong w;
|
|
BKPT *bk;
|
|
Symbol s;
|
|
int stack;
|
|
char *fname;
|
|
char buf[512];
|
|
|
|
if (cntflg==0)
|
|
cntval = -1;
|
|
switch (modif) {
|
|
|
|
case '<':
|
|
if (cntval == 0) {
|
|
while (readchar() != EOR)
|
|
;
|
|
reread();
|
|
break;
|
|
}
|
|
if (rdc() == '<')
|
|
stack = 1;
|
|
else {
|
|
stack = 0;
|
|
reread();
|
|
}
|
|
fname = getfname();
|
|
redirin(stack, fname);
|
|
break;
|
|
|
|
case '>':
|
|
fname = getfname();
|
|
redirout(fname);
|
|
break;
|
|
|
|
case 'a':
|
|
attachprocess();
|
|
break;
|
|
|
|
case 'k':
|
|
kmsys();
|
|
break;
|
|
|
|
case 'q':
|
|
case 'Q':
|
|
done();
|
|
|
|
case 'w':
|
|
maxpos=(adrflg?adrval:MAXPOS);
|
|
break;
|
|
|
|
case 'S':
|
|
printsym();
|
|
break;
|
|
|
|
case 's':
|
|
maxoff=(adrflg?adrval:MAXOFF);
|
|
break;
|
|
|
|
case 'm':
|
|
printmap("? map", symmap);
|
|
printmap("/ map", cormap);
|
|
break;
|
|
|
|
case 0:
|
|
case '?':
|
|
if (pid)
|
|
dprint("pid = %d\n",pid);
|
|
else
|
|
prints("no process\n");
|
|
flushbuf();
|
|
|
|
case 'r':
|
|
case 'R':
|
|
printregs(modif);
|
|
return;
|
|
|
|
case 'f':
|
|
case 'F':
|
|
printfp(cormap, modif);
|
|
return;
|
|
|
|
case 'c':
|
|
case 'C':
|
|
tracetype = modif;
|
|
if (machdata->ctrace) {
|
|
if (adrflg) {
|
|
/*
|
|
* trace from jmpbuf for multi-threaded code.
|
|
* assume sp and pc are in adjacent locations
|
|
* and mach->szaddr in size.
|
|
*/
|
|
if (geta(cormap, adrval, &sp) < 0 ||
|
|
geta(cormap, adrval+mach->szaddr, &pc) < 0)
|
|
error("%r");
|
|
} else {
|
|
sp = rget(cormap, mach->sp);
|
|
pc = rget(cormap, mach->pc);
|
|
}
|
|
if(mach->link)
|
|
link = rget(cormap, mach->link);
|
|
else
|
|
link = 0;
|
|
if (machdata->ctrace(cormap, pc, sp, link, ptrace) <= 0)
|
|
error("no stack frame");
|
|
}
|
|
break;
|
|
|
|
/*print externals*/
|
|
case 'e':
|
|
for (i = 0; globalsym(&s, i); i++) {
|
|
if (get4(cormap, s.value, &w) > 0)
|
|
dprint("%s/%12t%#lux\n", s.name, w);
|
|
}
|
|
break;
|
|
|
|
/*print breakpoints*/
|
|
case 'b':
|
|
case 'B':
|
|
for (bk=bkpthead; bk; bk=bk->nxtbkpt)
|
|
if (bk->flag) {
|
|
symoff(buf, 512, (WORD)bk->loc, CTEXT);
|
|
dprint(buf);
|
|
if (bk->count != 1)
|
|
dprint(",%d", bk->count);
|
|
dprint(":%c %S", bk->flag == BKPTTMP ? 'B' : 'b', bk->comm);
|
|
}
|
|
break;
|
|
|
|
case 'M':
|
|
fname = getfname();
|
|
if (machbyname(fname) == 0)
|
|
dprint("unknown name\n");;
|
|
break;
|
|
default:
|
|
error("bad `$' command");
|
|
}
|
|
|
|
}
|
|
|
|
char *
|
|
getfname(void)
|
|
{
|
|
static char fname[ARB];
|
|
char *p;
|
|
|
|
if (rdc() == EOR) {
|
|
reread();
|
|
return (0);
|
|
}
|
|
p = fname;
|
|
do {
|
|
*p++ = lastc;
|
|
if (p >= &fname[ARB-1])
|
|
error("filename too long");
|
|
} while (rdc() != EOR);
|
|
*p = 0;
|
|
reread();
|
|
return (fname);
|
|
}
|
|
|
|
static void
|
|
printfp(Map *map, int modif)
|
|
{
|
|
Reglist *rp;
|
|
int i;
|
|
int ret;
|
|
char buf[512];
|
|
|
|
for (i = 0, rp = mach->reglist; rp->rname; rp += ret) {
|
|
ret = 1;
|
|
if (!(rp->rflags&RFLT))
|
|
continue;
|
|
ret = fpformat(map, rp, buf, sizeof(buf), modif);
|
|
if (ret < 0) {
|
|
werrstr("Register %s: %r", rp->rname);
|
|
error("%r");
|
|
}
|
|
/* double column print */
|
|
if (i&0x01)
|
|
dprint("%40t%-8s%-12s\n", rp->rname, buf);
|
|
else
|
|
dprint("\t%-8s%-12s", rp->rname, buf);
|
|
i++;
|
|
}
|
|
}
|
|
|
|
void
|
|
redirin(int stack, char *file)
|
|
{
|
|
char *pfile;
|
|
|
|
if (file == 0) {
|
|
iclose(-1, 0);
|
|
return;
|
|
}
|
|
iclose(stack, 0);
|
|
if ((infile = open(file, 0)) < 0) {
|
|
pfile = smprint("%s/%s", Ipath, file);
|
|
infile = open(pfile, 0);
|
|
free(pfile);
|
|
if(infile < 0) {
|
|
infile = STDIN;
|
|
error("cannot open");
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
printmap(char *s, Map *map)
|
|
{
|
|
int i;
|
|
|
|
if (!map)
|
|
return;
|
|
if (map == symmap)
|
|
dprint("%s%12t`%s'\n", s, fsym < 0 ? "-" : symfil);
|
|
else if (map == cormap)
|
|
dprint("%s%12t`%s'\n", s, fcor < 0 ? "-" : corfil);
|
|
else
|
|
dprint("%s\n", s);
|
|
for (i = 0; i < map->nsegs; i++) {
|
|
if (map->seg[i].inuse)
|
|
dprint("%s%8t%-16#llux %-16#llux %-16#llux\n",
|
|
map->seg[i].name, map->seg[i].b,
|
|
map->seg[i].e, map->seg[i].f);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* dump the raw symbol table
|
|
*/
|
|
void
|
|
printsym(void)
|
|
{
|
|
int i;
|
|
Sym *sp;
|
|
|
|
for (i = 0; sp = getsym(i); i++) {
|
|
switch(sp->type) {
|
|
case 't':
|
|
case 'l':
|
|
dprint("%16#llux t %s\n", sp->value, sp->name);
|
|
break;
|
|
case 'T':
|
|
case 'L':
|
|
dprint("%16#llux T %s\n", sp->value, sp->name);
|
|
break;
|
|
case 'D':
|
|
case 'd':
|
|
case 'B':
|
|
case 'b':
|
|
case 'a':
|
|
case 'p':
|
|
case 'm':
|
|
dprint("%16#llux %c %s\n", sp->value, sp->type, sp->name);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
#define STRINGSZ 128
|
|
|
|
/*
|
|
* print the value of dot as file:line
|
|
*/
|
|
void
|
|
printsource(ADDR dot)
|
|
{
|
|
char str[STRINGSZ];
|
|
|
|
if (fileline(str, STRINGSZ, dot))
|
|
dprint("%s", str);
|
|
}
|
|
|
|
void
|
|
printpc(void)
|
|
{
|
|
char buf[512];
|
|
|
|
dot = rget(cormap, mach->pc);
|
|
if(dot){
|
|
printsource((long)dot);
|
|
printc(' ');
|
|
symoff(buf, sizeof(buf), (long)dot, CTEXT);
|
|
dprint("%s/", buf);
|
|
if (machdata->das(cormap, dot, 'i', buf, sizeof(buf)) < 0)
|
|
error("%r");
|
|
dprint("%16t%s\n", buf);
|
|
}
|
|
}
|
|
|
|
void
|
|
printlocals(Symbol *fn, ADDR fp)
|
|
{
|
|
int i;
|
|
ulong w;
|
|
Symbol s;
|
|
|
|
s = *fn;
|
|
for (i = 0; localsym(&s, i); i++) {
|
|
if (s.class != CAUTO)
|
|
continue;
|
|
if (get4(cormap, fp-s.value, &w) > 0)
|
|
dprint("%8t%s.%s/%10t%#lux\n", fn->name, s.name, w);
|
|
else
|
|
dprint("%8t%s.%s/%10t?\n", fn->name, s.name);
|
|
}
|
|
}
|
|
|
|
void
|
|
printparams(Symbol *fn, ADDR fp)
|
|
{
|
|
int i;
|
|
Symbol s;
|
|
ulong w;
|
|
int first = 0;
|
|
|
|
fp += mach->szaddr; /* skip saved pc */
|
|
s = *fn;
|
|
for (i = 0; localsym(&s, i); i++) {
|
|
if (s.class != CPARAM)
|
|
continue;
|
|
if (first++)
|
|
dprint(", ");
|
|
if (get4(cormap, fp+s.value, &w) > 0)
|
|
dprint("%s=%#lux", s.name, w);
|
|
}
|
|
}
|