Start working through proper handling of pthreads when

debugging Linux core dumps.  Pthreads for active processes
is still not supported, nor are other systems.
This commit is contained in:
rsc 2005-01-23 22:33:04 +00:00
parent a0e8d02d09
commit dd944ec72a
14 changed files with 528 additions and 415 deletions

View file

@ -168,7 +168,7 @@ ptracerw(int type, int xtype, int isr, int pid, ulong addr, void *v, uint n)
memmove(buf, (char*)v+i, n-i); memmove(buf, (char*)v+i, n-i);
u = *(u32int*)buf; u = *(u32int*)buf;
} }
if(ptrace(type, pid, addr+i, &u) < 0) if(ptrace(type, pid, addr+i, u) < 0)
goto ptraceerr; goto ptraceerr;
} }
} }
@ -501,192 +501,3 @@ proctextfile(int pid)
} }
Bterm(b); Bterm(b);
#endif #endif
/*
* bottom-end functions for libthread_db to call
*/
enum
{
PS_OK,
PS_ERR,
PS_BADPID,
PS_BADLWPID,
PS_BADADDR,
PS_NOSYM,
PS_NOFPREGS,
};
pid_t
ps_getpid(struct ps_prochandle *ph)
{
return ph->pid;
}
int
ps_pstop(const struct ps_prochandle *ph)
{
return PS_ERR;
}
int
ps_pcontinue(const struct ps_prochandle *ph)
{
return PS_ERR;
}
int
ps_lstop(const struct ps_prochandle *ph)
{
return PS_ERR;
}
int
ps_lcontinue(const struct ps_prochandle *ph)
{
return PS_ERR;
}
/* read/write data or text memory */
int
ps_pdread(struct ps_prochandle *ph, psaddr_t addr, void *v, size_t sz)
{
//print("read %d %p %d\n", ph->pid, addr, sz);
if(ptracerw(PTRACE_PEEKDATA, 0, 1, ph->pid, (ulong)addr, v, sz) < 0)
return PS_ERR;
//print(" => 0x%lux\n", *(ulong*)v);
return PS_OK;
}
int
ps_pdwrite(struct ps_prochandle *ph, psaddr_t addr, void *v, size_t sz)
{
//print("write %d %p\n", ph->pid, addr);
if(ptracerw(PTRACE_POKEDATA, PTRACE_PEEKDATA, 0, ph->pid, (ulong)addr, v, sz) < 0)
return PS_ERR;
return PS_OK;
}
int
ps_ptread(struct ps_prochandle *ph, psaddr_t addr, void *v, size_t sz)
{
//print("read %d %p\n", ph->pid, addr);
if(ptracerw(PTRACE_PEEKTEXT, 0, 1, ph->pid, (ulong)addr, v, sz) < 0)
return PS_ERR;
return PS_OK;
}
int
ps_ptwrite(struct ps_prochandle *ph, psaddr_t addr, void *v, size_t sz)
{
//print("write %d %p\n", ph->pid, addr);
if(ptracerw(PTRACE_POKETEXT, PTRACE_PEEKTEXT, 0, ph->pid, (ulong)addr, v, sz) < 0)
return PS_ERR;
return PS_OK;
}
int
ps_lgetregs(struct ps_prochandle *ph, lwpid_t lwp, prgregset_t regs)
{
if(lwp == 0){
memset(regs, 0xfe, sizeof(regs[0])*nelem(linuxregs));
return PS_OK;
}
//print("getregs %d %p (%d)\n", lwp, regs, sizeof(regs[0])*nelem(linuxregs));
if(ptraceattach(lwp) < 0){
fprint(2, "ptrace attach: %r\n");
return PS_ERR;
}
if(ptracerw(PTRACE_PEEKUSER, 0, 1, lwp, 0, regs, sizeof(regs[0])*nelem(linuxregs)) < 0){
fprint(2, "ptrace: %r\n");
return PS_ERR;
}
return PS_OK;
}
int
ps_lsetregs(struct ps_prochandle *ph, lwpid_t lwp, prgregset_t regs)
{
print("setregs %d\n", lwp);
if(ptracerw(PTRACE_POKEUSER, PTRACE_PEEKUSER, 1, lwp, 0, regs, sizeof(regs[0])*nelem(linuxregs)) < 0)
return PS_ERR;
return PS_OK;
}
int
ps_lgetfpregs(struct ps_prochandle *ph, lwpid_t lwp, prfpregset_t *fpregs)
{
if(ptracerw(PTRACE_PEEKUSER, 0, 1, lwp, 18*4, fpregs, sizeof *fpregs) < 0)
return PS_ERR;
return PS_OK;
}
int
ps_lsetfpregs(struct ps_prochandle *ph, lwpid_t lwp, prfpregset_t *fpregs)
{
if(ptracerw(PTRACE_POKEUSER, PTRACE_PEEKUSER, 1, lwp, 18*4, fpregs, sizeof *fpregs) < 0)
return PS_ERR;
return PS_OK;
}
/* Fetch the special per-thread address associated with the given LWP.
This call is only used on a few platforms (most use a normal register).
The meaning of the `int' parameter is machine-dependent. */
int
ps_get_thread_area(struct ps_prochandle *ph, lwpid_t lwp, int xxx, psaddr_t *addr)
{
return PS_NOSYM;
}
/* Look up the named symbol in the named DSO in the symbol tables
associated with the process being debugged, filling in *SYM_ADDR
with the corresponding run-time address. */
int
ps_pglobal_lookup(struct ps_prochandle *ph, char *object_name, char *sym_name, psaddr_t *sym_addr)
{
Fhdr *fp;
ulong addr;
if((fp = findhdr(object_name)) == nil){
print("lookup %d %s %s => no such hdr\n", ph->pid, object_name, sym_name);
return PS_NOSYM;
}
if(elfsymlookup(fp->elf, sym_name, &addr) < 0){
print("lookup %d %s %s => name not found\n", ph->pid, object_name, sym_name);
return PS_NOSYM;
}
print("lookup %d %s %s => 0x%lux\n", ph->pid, object_name, sym_name, addr);
*sym_addr = (void*)(addr+fp->base);
return PS_OK;
}
Ureg*
_linux2ureg386(UregLinux386 *l)
{
Ureg *u;
u = malloc(sizeof(Ureg));
if(u == nil)
return nil;
u->di = l->edi;
u->si = l->esi;
u->bp = l->ebp;
u->nsp = l->esp;
u->bx = l->ebx;
u->dx = l->edx;
u->cx = l->ecx;
u->ax = l->eax;
u->gs = l->xgs;
u->fs = l->xfs;
u->es = l->xes;
u->ds = l->xds;
u->trap = ~0; // l->trapno;
u->ecode = ~0; // l->err;
u->pc = l->eip;
u->cs = l->xcs;
u->flags = l->eflags;
u->sp = l->esp;
u->ss = l->xss;
return u;
}

View file

@ -26,11 +26,11 @@ alldigs(char *s)
* attach to arguments in argc, argv * attach to arguments in argc, argv
*/ */
int int
attachargs(int argc, char **argv, int omode) attachargs(int argc, char **argv, int omode, int verbose)
{ {
int i; int i;
Fhdr *hdr; Fhdr *hdr;
char *s; char *s, *t;
symhdr = nil; symhdr = nil;
corhdr = nil; corhdr = nil;
@ -56,9 +56,9 @@ attachargs(int argc, char **argv, int omode)
fprint(2, "crackhdr %s: %r\n", argv[i]); fprint(2, "crackhdr %s: %r\n", argv[i]);
continue; continue;
} }
fprint(2, "%s: %s %s %s\n", argv[i], hdr->aname, hdr->mname, hdr->fname); if(verbose)
fprint(2, "%s: %s %s %s\n", argv[i], hdr->aname, hdr->mname, hdr->fname);
if(hdr->ftype == FCORE){ if(hdr->ftype == FCORE){
fprint(2, "core cmd: %s\n", hdr->cmd);
if(corpid){ if(corpid){
fprint(2, "already have corpid %d; ignoring core %s\n", corpid, argv[i]); fprint(2, "already have corpid %d; ignoring core %s\n", corpid, argv[i]);
uncrackhdr(hdr); uncrackhdr(hdr);
@ -90,10 +90,21 @@ attachargs(int argc, char **argv, int omode)
symfil = s; symfil = s;
} }
} }
if(corhdr){ /* try from core */ if(corhdr && corhdr->cmdline){ /* try from core */
if(corhdr->txtfil != nil){ /*
fprint(2, "core %s: text %s\n", corfil, corhdr->txtfil); * prog gives only the basename of the command,
symfil = corhdr->txtfil; * so try the command line for a path.
*/
if((s = strdup(corhdr->cmdline)) != nil){
t = strchr(s, ' ');
if(t)
*t = 0;
if((t = searchpath(s)) != nil){
if(verbose)
fprint(2, "core: text %s\n", t);
symfil = t;
}
free(s);
} }
} }
if((symhdr = crackhdr(symfil, omode)) == nil){ if((symhdr = crackhdr(symfil, omode)) == nil){
@ -124,10 +135,10 @@ attachargs(int argc, char **argv, int omode)
if(corpid) if(corpid)
attachproc(corpid); attachproc(corpid);
if(corhdr) if(corhdr)
attachcore(corhdr); attachcore(corhdr);
attachdynamic(verbose);
return 0; return 0;
} }
@ -167,7 +178,7 @@ int
attachcore(Fhdr *hdr) attachcore(Fhdr *hdr)
{ {
unattach(); unattach();
if(corhdr == nil) if(hdr == nil)
return 0; return 0;
if(mapfile(hdr, 0, cormap, &correg) < 0){ if(mapfile(hdr, 0, cormap, &correg) < 0){
fprint(2, "attachcore %s: %r\n", hdr->filename); fprint(2, "attachcore %s: %r\n", hdr->filename);
@ -180,10 +191,12 @@ attachcore(Fhdr *hdr)
} }
int int
attachdynamic(void) attachdynamic(int verbose)
{ {
extern void elfdl386mapdl(void); extern void elfdl386mapdl(int);
elfdl386mapdl();
if(mach && mach->type == M386 && symhdr && symhdr->elf)
elfdl386mapdl(verbose);
return 0; return 0;
} }

View file

@ -2,6 +2,7 @@
#include <libc.h> #include <libc.h>
#include <bio.h> #include <bio.h>
#include <mach.h> #include <mach.h>
#include "elf.h"
static struct static struct
{ {
@ -50,9 +51,18 @@ crackhdr(char *name, int mode)
void void
uncrackhdr(Fhdr *hdr) uncrackhdr(Fhdr *hdr)
{ {
close(hdr->fd); int i;
_delhdr(hdr);
free(hdr->cmd); symclose(hdr);
if(hdr->elf)
elfclose(hdr->elf);
if(hdr->fd >= 0)
close(hdr->fd);
free(hdr->cmdline);
free(hdr->prog);
for(i=0; i<hdr->nthread; i++)
free(hdr->thread[i].ureg);
free(hdr->thread);
free(hdr); free(hdr);
} }
@ -71,6 +81,8 @@ mapfile(Fhdr *fp, ulong base, Map *map, Regs **regs)
werrstr("cannot load map for this file type"); werrstr("cannot load map for this file type");
return -1; return -1;
} }
if(regs)
*regs = nil;
return fp->map(fp, base, map, regs); return fp->map(fp, base, map, regs);
} }
@ -90,3 +102,23 @@ unmapfile(Fhdr *fp, Map *map)
} }
} }
} }
Regs*
coreregs(Fhdr *fp, uint id)
{
UregRegs *r;
int i;
for(i=0; i<fp->nthread; i++){
if(fp->thread[i].id == id){
if((r = mallocz(sizeof *r, 1)) == nil)
return nil;
r->r.rw = _uregrw;
r->ureg = fp->thread[i].ureg;
return &r->r;
}
}
werrstr("thread not found");
return nil;
}

View file

@ -5,8 +5,7 @@
#include "dwarf.h" #include "dwarf.h"
static int mapelf(Fhdr *fp, ulong base, Map *map, Regs**); static int mapelf(Fhdr *fp, ulong base, Map *map, Regs**);
static int mapcoreregs(Fhdr *fp, Map *map, Regs**); static int unpacknote(Elf *elf, uchar *a, uchar *ea, ElfNote *note, uchar **pa);
static char *getcorecmd(Fhdr *fp);
static struct static struct
{ {
@ -40,28 +39,24 @@ static struct
{ {
uint mtype; uint mtype;
uint atype; uint atype;
int (*coreregs)(Elf*, ElfNote*, uchar**); void (*elfcore)(Fhdr*, Elf*, ElfNote*);
int (*corecmd)(Elf*, ElfNote*, char**);
} ctab[] = } ctab[] =
{ /* Font Tab 4 */ { /* Font Tab 4 */
M386, ALINUX, M386, ALINUX, elfcorelinux386,
coreregslinux386, M386, ANONE, elfcorelinux386, /* [sic] */
corecmdlinux386, /* M386, AFREEBSD, elfcorefreebsd386, */
M386, ANONE,
coreregslinux386, /* [sic] */
corecmdlinux386, /* [sic] */
M386, AFREEBSD,
coreregsfreebsd386,
corecmdfreebsd386,
}; };
int int
crackelf(int fd, Fhdr *fp) crackelf(int fd, Fhdr *fp)
{ {
int i, havetext, havedata; uchar *a, *sa, *ea;
int i, havetext, havedata, n;
Elf *elf; Elf *elf;
ElfNote note;
ElfProg *p; ElfProg *p;
ElfSect *s1, *s2; ElfSect *s1, *s2;
void (*elfcore)(Fhdr*, Elf*, ElfNote*);
if((elf = elfinit(fd)) == nil) if((elf = elfinit(fd)) == nil)
return -1; return -1;
@ -133,16 +128,37 @@ crackelf(int fd, Fhdr *fp)
fp->map = mapelf; fp->map = mapelf;
if(fp->ftype == FCORE){ if(fp->ftype == FCORE){
elfcore = nil;
for(i=0; i<nelem(ctab); i++){ for(i=0; i<nelem(ctab); i++){
if(ctab[i].atype != fp->atype if(ctab[i].atype != fp->atype
|| ctab[i].mtype != fp->mtype) || ctab[i].mtype != fp->mtype)
continue; continue;
elf->coreregs = ctab[i].coreregs; elfcore = ctab[i].elfcore;
elf->corecmd = ctab[i].corecmd;
break; break;
} }
if((fp->cmd = getcorecmd(fp)) == nil) if(elfcore)
fprint(2, "warning: reading core command: %r"); for(i=0; i<elf->nprog; i++){
p = &elf->prog[i];
if(p->type != ElfProgNote)
continue;
n = p->filesz;
a = malloc(n);
if(a == nil)
goto err;
if(seek(fp->fd, p->offset, 0) < 0 || readn(fp->fd, a, n) != n){
free(a);
continue;
}
sa = a;
ea = a+n;
while(a < ea){
note.offset = (a-sa) + p->offset;
if(unpacknote(elf, a, ea, &note, &a) < 0)
break;
elfcore(fp, elf, &note);
}
free(sa);
}
return 0; return 0;
} }
@ -258,10 +274,8 @@ mapelf(Fhdr *fp, ulong base, Map *map, Regs **regs)
} }
} }
if(fp->ftype == FCORE){ if(fp->nthread && regs)
if(mapcoreregs(fp, map, regs) < 0) *regs = coreregs(fp, fp->thread[0].id);
fprint(2, "warning: reading core regs: %r");
}
return 0; return 0;
} }
@ -286,126 +300,3 @@ unpacknote(Elf *elf, uchar *a, uchar *ea, ElfNote *note, uchar **pa)
return 0; return 0;
} }
static int
mapcoreregs(Fhdr *fp, Map *map, Regs **rp)
{
int i;
uchar *a, *sa, *ea, *uregs;
uint n;
ElfNote note;
ElfProg *p;
Elf *elf;
UregRegs *r;
elf = fp->elf;
if(elf->coreregs == 0){
werrstr("cannot parse %s %s cores", fp->mname, fp->aname);
return -1;
}
for(i=0; i<elf->nprog; i++){
p = &elf->prog[i];
if(p->type != ElfProgNote)
continue;
n = p->filesz;
a = malloc(n);
if(a == nil)
return -1;
if(seek(fp->fd, p->offset, 0) < 0 || readn(fp->fd, a, n) != n){
free(a);
continue;
}
sa = a;
ea = a+n;
while(a < ea){
note.offset = (a-sa) + p->offset;
if(unpacknote(elf, a, ea, &note, &a) < 0)
break;
switch(note.type){
case ElfNotePrStatus:
if((n = (*elf->coreregs)(elf, &note, &uregs)) < 0){
free(sa);
return -1;
}
free(sa);
if((r = mallocz(sizeof(*r), 1)) == nil){
free(uregs);
return -1;
}
r->r.rw = _uregrw;
r->ureg = uregs;
*rp = &r->r;
return 0;
case ElfNotePrFpreg:
case ElfNotePrPsinfo:
case ElfNotePrTaskstruct:
case ElfNotePrAuxv:
case ElfNotePrXfpreg:
break;
}
// fprint(2, "0x%lux note %s/%lud %p\n", note.offset, note.name, note.type, note.desc);
}
free(sa);
}
fprint(2, "could not find registers in core file\n");
return -1;
}
static char*
getcorecmd(Fhdr *fp)
{
int i;
uchar *a, *sa, *ea;
char *cmd;
uint n;
ElfNote note;
ElfProg *p;
Elf *elf;
elf = fp->elf;
if(elf->corecmd == 0){
werrstr("cannot parse %s %s cores", fp->mname, fp->aname);
return nil;
}
for(i=0; i<elf->nprog; i++){
p = &elf->prog[i];
if(p->type != ElfProgNote)
continue;
n = p->filesz;
a = malloc(n);
if(a == nil)
return nil;
if(seek(fp->fd, p->offset, 0) < 0 || readn(fp->fd, a, n) != n){
free(a);
continue;
}
sa = a;
ea = a+n;
while(a < ea){
note.offset = (a-sa) + p->offset;
if(unpacknote(elf, a, ea, &note, &a) < 0)
break;
switch(note.type){
case ElfNotePrPsinfo:
if((n = elf->corecmd(elf, &note, &cmd)) < 0){
free(sa);
return nil;
}
free(sa);
return cmd;
case ElfNotePrStatus:
case ElfNotePrFpreg:
case ElfNotePrTaskstruct:
case ElfNotePrAuxv:
case ElfNotePrXfpreg:
break;
}
// fprint(2, "0x%lux note %s/%lud %p\n", note.offset, note.name, note.type, note.desc);
}
free(sa);
}
fprint(2, "could not find registers in core file\n");
return nil;
}

View file

@ -232,8 +232,6 @@ int elfsym(Elf*, int, ElfSym*);
int elfsymlookup(Elf*, char*, ulong*); int elfsymlookup(Elf*, char*, ulong*);
int elfmap(Elf*, ElfSect*); int elfmap(Elf*, ElfSect*);
int coreregslinux386(Elf*, ElfNote*, uchar**); struct Fhdr;
int coreregsfreebsd386(Elf*, ElfNote*, uchar**); void elfcorelinux386(struct Fhdr*, Elf*, ElfNote*);
int corecmdlinux386(Elf*, ElfNote*, char**); void elfdl386mapdl(int);
int corecmdfreebsd386(Elf*, ElfNote*, char**);
void elfdl386mapdl(void);

View file

@ -34,6 +34,10 @@ struct Status
UregLinux386 reg; UregLinux386 reg;
u32int fpvalid; u32int fpvalid;
}; };
enum
{
StatusSize = sizeof(Status),
};
struct Psinfo struct Psinfo
{ {
@ -51,6 +55,10 @@ struct Psinfo
char fname[16]; char fname[16];
char psargs[80]; char psargs[80];
}; };
enum
{
PsinfoSize = sizeof(Psinfo),
};
int int
coreregslinux386(Elf *elf, ElfNote *note, uchar **up) coreregslinux386(Elf *elf, ElfNote *note, uchar **up)
@ -65,8 +73,9 @@ coreregslinux386(Elf *elf, ElfNote *note, uchar **up)
} }
s = (Status*)note->desc; s = (Status*)note->desc;
l = &s->reg; l = &s->reg;
if((u = _linux2ureg386(l)) == nil) if((u = malloc(sizeof *u)) == nil)
return -1; return -1;
linux2ureg386(l, u);
*up = (uchar*)u; *up = (uchar*)u;
return sizeof(Ureg); return sizeof(Ureg);
} }
@ -93,3 +102,101 @@ corecmdlinux386(Elf *elf, ElfNote *note, char **pp)
return 0; return 0;
} }
#define dprint if(0)print
void
elfcorelinux386(Fhdr *fp, Elf *elf, ElfNote *note)
{
int i;
Psinfo *ps;
Status *st;
Mach *m;
Ureg *u;
m = fp->mach;
dprint("%s ", note->name);
switch(note->type){
case ElfNotePrPsinfo:
ps = (Psinfo*)note->desc;
dprint("note info\n");
dprint("state=%d sname=%d zomb=%d nice=%d\n",
ps->state, ps->sname, ps->zomb, ps->nice);
dprint("flag=0x%ux uid=%ud gid=%ud pid=%ud ppid=%ud pgrp=%ud sid=%ud\n",
(uint)m->swap4(ps->flag),
(uint)m->swap2(ps->uid),
(uint)m->swap2(ps->gid),
(uint)m->swap4(ps->pid),
(uint)m->swap4(ps->ppid),
(uint)m->swap4(ps->pgrp),
(uint)m->swap4(ps->sid));
dprint("fname=%s psargs=%s\n", ps->fname, ps->psargs);
fp->pid = m->swap4(ps->pid);
if((fp->prog = strdup(ps->fname)) == nil)
fprint(2, "warning: out of memory saving core program name\n");
if((fp->cmdline = strdup(ps->psargs)) == nil)
fprint(2, "warning: out of memory saving core command line\n");
break;
case ElfNotePrTaskstruct:
dprint("note taskstruct\n");
break;
case ElfNotePrAuxv:
dprint("note auxv\n");
break;
case ElfNotePrStatus:
dprint("note status\n");
if(note->descsz < StatusSize){
dprint("too small\n");
break;
}
st = (Status*)note->desc;
dprint("sig=%ud code=%ud errno=%ud cursig=%ud sigpend=0x%ux sighold=0x%ux\n",
(uint)m->swap4(st->signo),
(uint)m->swap4(st->code),
(uint)m->swap4(st->errno),
(uint)m->swap4(st->cursig),
(uint)m->swap4(st->sigpend),
(uint)m->swap4(st->sighold));
dprint("pid=%ud ppid=%ud pgrp=%ud sid=%ud\n",
(uint)m->swap4(st->pid),
(uint)m->swap4(st->ppid),
(uint)m->swap4(st->pgrp),
(uint)m->swap4(st->sid));
dprint("utime=%ud.%06ud stime=%ud.%06ud cutime=%ud.%06ud cstime=%ud.%06ud\n",
(uint)m->swap4(st->utime[0]),
(uint)m->swap4(st->utime[1]),
(uint)m->swap4(st->stime[0]),
(uint)m->swap4(st->stime[1]),
(uint)m->swap4(st->cutime[0]),
(uint)m->swap4(st->cutime[1]),
(uint)m->swap4(st->cstime[0]),
(uint)m->swap4(st->cstime[1]));
dprint("fpvalid=%ud\n",
(uint)m->swap4(st->fpvalid));
if((fp->thread = realloc(fp->thread, (1+fp->nthread)*sizeof(fp->thread[0]))) == nil){
fprint(2, "warning: out of memory saving thread info\n");
return;
}
i = fp->nthread;
fp->thread[i].id = m->swap4(st->pid);
u = malloc(sizeof *u);
if(u == nil){
fprint(2, "warning: out of memory saving thread info\n");
return;
}
fp->thread[i].ureg = u;
linux2ureg386(&st->reg, u);
fp->nthread++;
break;
case ElfNotePrFpreg:
dprint("note fpreg\n");
/* XXX maybe record floating-point registers eventually */
break;
case ElfNotePrXfpreg:
dprint("note xfpreg\n");
/* XXX maybe record floating-point registers eventually */
break;
default:
dprint("note %d\n", note->type);
}
}

View file

@ -86,14 +86,13 @@ dyninfo(Fhdr *hdr, int x)
} }
void void
elfdl386mapdl(void) elfdl386mapdl(int verbose)
{ {
int i; int i;
Fhdr *hdr; Fhdr *hdr;
u32int linkdebug, linkmap, name, addr; u32int linkdebug, linkmap, name, addr;
char buf[1024]; char buf[1024];
print("elfdl386mapdl\n");
if((linkdebug = dyninfo(symhdr, DT_DEBUG)) == 0){ if((linkdebug = dyninfo(symhdr, DT_DEBUG)) == 0){
fprint(2, "no dt_debug section\n"); fprint(2, "no dt_debug section\n");
return; return;
@ -109,25 +108,27 @@ print("elfdl386mapdl\n");
|| get4(cormap, linkmap+12, &linkmap) < 0) || get4(cormap, linkmap+12, &linkmap) < 0)
break; break;
if(name if(name == 0 || getstr(cormap, name, buf, sizeof buf) < 0 || buf[0] == 0)
&& getstr(cormap, name, buf, sizeof buf) >= 0 continue;
&& buf[0] if((hdr = crackhdr(buf, OREAD)) == nil){
&& access(buf, AEXIST) >= 0){ fprint(2, "crackhdr %s: %r\n", buf);
if((hdr = crackhdr(buf, OREAD)) == nil) continue;
fprint(2, "crackhdr %s: %r\n", buf); }
else{ hdr->base = addr;
fprint(2, "%s: %s %s %s\n", buf, hdr->aname, hdr->mname, hdr->fname); if(verbose)
hdr->base = addr; fprint(2, "%s: %s %s %s\n", buf, hdr->aname, hdr->mname, hdr->fname);
if(mapfile(hdr, addr, symmap, nil) < 0) if(mapfile(hdr, addr, symmap, nil) < 0)
fprint(2, "mapfile %s: %r\n", buf); fprint(2, "mapping %s: %r\n", buf);
if(corhdr){ if(corhdr){
unmapfile(corhdr, cormap); /*
mapfile(hdr, addr, cormap, nil); * Need to map the text file under the core file.
} */
if(symopen(hdr) < 0) unmapfile(corhdr, cormap);
fprint(2, "syminit %s: %\r", buf); mapfile(hdr, addr, cormap, nil);
} mapfile(corhdr, 0, cormap, nil);
} }
if(symopen(hdr) < 0)
fprint(2, "syminit %s: %r\n", buf);
} }
} }

View file

@ -87,8 +87,12 @@ stacktrace(Map *map, Regs *regs, Tracer trace)
break; break;
if(i < 0) if(i < 0)
break; break;
if(sp && strcmp(sp->name, "main") == 0) if(sp){
break; if(strcmp(sp->name, "main") == 0
|| strcmp(sp->name, "procscheduler") == 0
|| strcmp(sp->name, "threadstart") == 0)
break;
}
pc = nextpc; pc = nextpc;
memmove(cur, next, mach->nwindreg*sizeof(cur[0])); memmove(cur, next, mach->nwindreg*sizeof(cur[0]));
} }

View file

@ -31,7 +31,7 @@ addseg(Map *map, Seg seg)
{ {
Seg *ss; Seg *ss;
if(map == 0){ if(map == nil){
werrstr("invalid map"); werrstr("invalid map");
return -1; return -1;
} }
@ -57,7 +57,7 @@ findseg(Map *map, char *name, char *file)
{ {
int i; int i;
if(map == 0) if(map == nil)
return -1; return -1;
for(i=0; i<map->nseg; i++){ for(i=0; i<map->nseg; i++){
if(name && (!map->seg[i].name || strcmp(map->seg[i].name, name) != 0)) if(name && (!map->seg[i].name || strcmp(map->seg[i].name, name) != 0))

View file

@ -43,7 +43,7 @@ OFILES=\
symstabs.$O\ symstabs.$O\
ureg386.$O\ ureg386.$O\
HFILES=mach.h HFILES=$PLAN9/include/mach.h
<$PLAN9/src/mksyslib <$PLAN9/src/mksyslib
CFLAGS=$CFLAGS -I. CFLAGS=$CFLAGS -I.

View file

@ -6,6 +6,103 @@
#include <libc.h> #include <libc.h>
#include <mach.h> #include <mach.h>
typedef struct Ptprog Ptprog;
struct Pprog
{
Pthread *t;
uint nt;
};
typedef struct Pthread Pthread;
struct Pthread
{
td_thrhandle_t handle;
};
void
pthreadattach(int pid)
{
}
void pthreadattach()
set up mapping
Regs *pthreadregs()
int npthread();
static int td_get_allthreads(td_thragent_t*, td_thrhandle_t**);
static int terr(int);
Regs*
threadregs()
{
}
typedef struct AllThread AllThread;
struct AllThread
{
td_thrhandle_t *a;
int n;
int err;
};
static int
thritercb(const td_thrhandle_t *th, void *cb)
{
td_thrhandle_t **p;
AllThread *a;
int n;
a = cb;
if((a->n&(a->n-1)) == 0){
if(a->n == 0)
n = 1;
else
n = a->n<<1;
if((p = realloc(a->a, n*sizeof a->a[0])) == 0){
a->err = -1;
return -1; /* stop iteration */
}
a->a = p;
}
a->a[a->n++] = *th;
return 0;
}
int
td_get_allthreads(td_thragent_t *ta, td_thrhandle_t **pall)
{
int e;
AllThread a;
a.a = nil;
a.n = 0;
a.err = 0;
if((e = td_ta_thr_iter(ta, thritercb, &a,
TD_THR_ANY_STATE,
TD_THR_LOWEST_PRIORITY,
TD_SIGNO_MASK,
TD_THR_ANY_USER_FLAGS)) != TD_OK){
werrstr("%s", terr(e));
return -1;
}
if(a.err){
free(a.a);
return -1;
}
*pall = a.a;
return a.n;
}
static char *tderrstr[] = static char *tderrstr[] =
{ {
[TD_OK] "no error", [TD_OK] "no error",
@ -47,3 +144,146 @@ terr(int e)
return tderrstr[e]; return tderrstr[e];
} }
/*
* bottom-end functions for libthread_db to call
*/
enum
{
PS_OK,
PS_ERR,
PS_BADPID,
PS_BADLWPID,
PS_BADADDR,
PS_NOSYM,
PS_NOFPREGS,
};
pid_t
ps_getpid(struct ps_prochandle *ph)
{
return ph->pid;
}
int
ps_pstop(const struct ps_prochandle *ph)
{
return PS_ERR;
}
int
ps_pcontinue(const struct ps_prochandle *ph)
{
return PS_ERR;
}
int
ps_lstop(const struct ps_prochandle *ph)
{
return PS_ERR;
}
int
ps_lcontinue(const struct ps_prochandle *ph)
{
return PS_ERR;
}
/* read/write data or text memory */
int
ps_pdread(struct ps_prochandle *ph, psaddr_t addr, void *v, size_t sz)
{
if(get1(ph->map, addr, v, sz) < 0)
return PS_ERR;
return PS_OK;
}
int
ps_pdwrite(struct ps_prochandle *ph, psaddr_t addr, void *v, size_t sz)
{
if(put1(ph->map, addr, v, sz) < 0)
return PS_ERR;
return PS_OK;
}
int
ps_ptread(struct ps_prochandle *ph, psaddr_t addr, void *v, size_t sz)
{
return ps_pdread(ph, addr, v, sz);
}
int
ps_ptwrite(struct ps_prochandle *ph, psaddr_t addr, void *v, size_t sz)
{
return ps_pdwrite(ph, addr, v, sz);
}
int
ps_lgetregs(struct ps_prochandle *ph, lwpid_t lwp, prgregset_t regs)
{
int i;
USED(ph);
if(corhdr == nil)
return sys_ps_lgetregs(ph, lwp, regs);
for(i=0; i<corhdr->nthread; i++){
if(corhdr->thread[i].id == lwp){
ureg2prgregset(corhdr->thread[i].ureg, regs);
return PS_OK;
}
}
return PS_ERR;
}
int
ps_lsetregs(struct ps_prochandle *ph, lwpid_t lwp, prgregset_t regs)
{
if(corhdr == nil)
return sys_ps_lsetregs(ph, lwp, regs);
return PS_ERR;
}
int
ps_lgetfpregs(struct ps_prochandle *ph, lwpid_t lwp, prfpregset_t *fpregs)
{
if(corhdr == nil)
return sys_ps_lgetfpregs(ph, lwp, fpregs);
/* BUG - Look in core dump. */
return PS_ERR:
}
int
ps_lsetfpregs(struct ps_prochandle *ph, lwpid_t lwp, prfpregset_t *fpregs)
{
if(corhdr == nil)
return sys_ps_lsetfpregs(ph, lwp, fpregs);
return PS_ERR;
}
/* Fetch the special per-thread address associated with the given LWP.
This call is only used on a few platforms (most use a normal register).
The meaning of the `int' parameter is machine-dependent. */
int
ps_get_thread_area(struct ps_prochandle *ph, lwpid_t lwp, int xxx, psaddr_t *addr)
{
return sys_ps_get_thread_area(ph, lwp, xxx, addr);
}
int
ps_pglobal_lookup(struct ps_prochandle *ph, char *object_name, char *sym_name, psaddr_t *sym_addr)
{
Fhdr *fp;
ulong addr;
if((fp = findhdr(object_name)) == nil){
print("libmach pthread: lookup %d %s %s => no such hdr\n", ph->pid, object_name, sym_name);
return PS_NOSYM;
}
if(elfsymlookup(fp->elf, sym_name, &addr) < 0){
print("libmach pthread: lookup %d %s %s => name not found\n", ph->pid, object_name, sym_name);
return PS_NOSYM;
}
/* print("libmach pthread: lookup %d %s %s => 0x%lux\n", ph->pid, object_name, sym_name, addr); */
*sym_addr = (void*)(addr+fp->base);
return PS_OK;
}

View file

@ -42,10 +42,11 @@ _delhdr(Fhdr *h)
else{ else{
for(p=fhdrlist; p && p->next!=h; p=p->next) for(p=fhdrlist; p && p->next!=h; p=p->next)
; ;
if(p) if(p){
p->next = h->next; p->next = h->next;
if(p->next == nil) if(p->next == nil)
last = p; last = p;
}
} }
h->next = nil; h->next = nil;
} }

View file

@ -1,18 +1,11 @@
#include <u.h> #include <u.h>
#include <libc.h> #include <libc.h>
#include <mach.h> #include <mach.h>
#include <elf.h>
#include "ureg386.h" #include "ureg386.h"
void
Ureg* linux2ureg386(UregLinux386 *l, Ureg *u)
_linux2ureg386(UregLinux386 *l)
{ {
Ureg *u;
u = malloc(sizeof(Ureg));
if(u == nil)
return nil;
u->di = l->edi; u->di = l->edi;
u->si = l->esi; u->si = l->esi;
u->bp = l->ebp; u->bp = l->ebp;
@ -32,5 +25,27 @@ _linux2ureg386(UregLinux386 *l)
u->flags = l->eflags; u->flags = l->eflags;
u->sp = l->esp; u->sp = l->esp;
u->ss = l->xss; u->ss = l->xss;
return u;
} }
void
ureg2linux386(Ureg *u, UregLinux386 *l)
{
l->edi = u->di;
l->esi = u->si;
l->ebp = u->bp;
l->esp = u->nsp;
l->ebx = u->bx;
l->edx = u->dx;
l->ecx = u->cx;
l->eax = u->ax;
l->xgs = u->gs;
l->xfs = u->fs;
l->xes = u->es;
l->xds = u->ds;
l->eip = u->pc;
l->xcs = u->cs;
l->eflags = u->flags;
l->esp = u->sp;
l->xss = u->ss;
}

View file

@ -25,24 +25,24 @@ struct Ureg
typedef struct UregLinux386 UregLinux386; typedef struct UregLinux386 UregLinux386;
struct UregLinux386 struct UregLinux386
{ {
ulong ebx; u32int ebx;
ulong ecx; u32int ecx;
ulong edx; u32int edx;
ulong esi; u32int esi;
ulong edi; u32int edi;
ulong ebp; u32int ebp;
ulong eax; u32int eax;
ulong xds; u32int xds;
ulong xes; u32int xes;
ulong xfs; u32int xfs;
ulong xgs; u32int xgs;
ulong origeax; u32int origeax;
ulong eip; u32int eip;
ulong xcs; u32int xcs;
ulong eflags; u32int eflags;
ulong esp; u32int esp;
ulong xss; u32int xss;
}; };
Ureg *_linux2ureg386(UregLinux386*); void linux2ureg386(UregLinux386*, Ureg*);
void ureg2linux386(Ureg*, UregLinux386*);