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);
u = *(u32int*)buf;
}
if(ptrace(type, pid, addr+i, &u) < 0)
if(ptrace(type, pid, addr+i, u) < 0)
goto ptraceerr;
}
}
@ -501,192 +501,3 @@ proctextfile(int pid)
}
Bterm(b);
#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
*/
int
attachargs(int argc, char **argv, int omode)
attachargs(int argc, char **argv, int omode, int verbose)
{
int i;
Fhdr *hdr;
char *s;
char *s, *t;
symhdr = nil;
corhdr = nil;
@ -56,9 +56,9 @@ attachargs(int argc, char **argv, int omode)
fprint(2, "crackhdr %s: %r\n", argv[i]);
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){
fprint(2, "core cmd: %s\n", hdr->cmd);
if(corpid){
fprint(2, "already have corpid %d; ignoring core %s\n", corpid, argv[i]);
uncrackhdr(hdr);
@ -90,10 +90,21 @@ attachargs(int argc, char **argv, int omode)
symfil = s;
}
}
if(corhdr){ /* try from core */
if(corhdr->txtfil != nil){
fprint(2, "core %s: text %s\n", corfil, corhdr->txtfil);
symfil = corhdr->txtfil;
if(corhdr && corhdr->cmdline){ /* try from core */
/*
* prog gives only the basename of the command,
* 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){
@ -124,10 +135,10 @@ attachargs(int argc, char **argv, int omode)
if(corpid)
attachproc(corpid);
if(corhdr)
attachcore(corhdr);
attachdynamic(verbose);
return 0;
}
@ -167,7 +178,7 @@ int
attachcore(Fhdr *hdr)
{
unattach();
if(corhdr == nil)
if(hdr == nil)
return 0;
if(mapfile(hdr, 0, cormap, &correg) < 0){
fprint(2, "attachcore %s: %r\n", hdr->filename);
@ -180,10 +191,12 @@ attachcore(Fhdr *hdr)
}
int
attachdynamic(void)
attachdynamic(int verbose)
{
extern void elfdl386mapdl(void);
elfdl386mapdl();
extern void elfdl386mapdl(int);
if(mach && mach->type == M386 && symhdr && symhdr->elf)
elfdl386mapdl(verbose);
return 0;
}

View file

@ -2,6 +2,7 @@
#include <libc.h>
#include <bio.h>
#include <mach.h>
#include "elf.h"
static struct
{
@ -50,9 +51,18 @@ crackhdr(char *name, int mode)
void
uncrackhdr(Fhdr *hdr)
{
close(hdr->fd);
_delhdr(hdr);
free(hdr->cmd);
int i;
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);
}
@ -71,6 +81,8 @@ mapfile(Fhdr *fp, ulong base, Map *map, Regs **regs)
werrstr("cannot load map for this file type");
return -1;
}
if(regs)
*regs = nil;
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"
static int mapelf(Fhdr *fp, ulong base, Map *map, Regs**);
static int mapcoreregs(Fhdr *fp, Map *map, Regs**);
static char *getcorecmd(Fhdr *fp);
static int unpacknote(Elf *elf, uchar *a, uchar *ea, ElfNote *note, uchar **pa);
static struct
{
@ -40,28 +39,24 @@ static struct
{
uint mtype;
uint atype;
int (*coreregs)(Elf*, ElfNote*, uchar**);
int (*corecmd)(Elf*, ElfNote*, char**);
void (*elfcore)(Fhdr*, Elf*, ElfNote*);
} ctab[] =
{ /* Font Tab 4 */
M386, ALINUX,
coreregslinux386,
corecmdlinux386,
M386, ANONE,
coreregslinux386, /* [sic] */
corecmdlinux386, /* [sic] */
M386, AFREEBSD,
coreregsfreebsd386,
corecmdfreebsd386,
M386, ALINUX, elfcorelinux386,
M386, ANONE, elfcorelinux386, /* [sic] */
/* M386, AFREEBSD, elfcorefreebsd386, */
};
int
crackelf(int fd, Fhdr *fp)
{
int i, havetext, havedata;
uchar *a, *sa, *ea;
int i, havetext, havedata, n;
Elf *elf;
ElfNote note;
ElfProg *p;
ElfSect *s1, *s2;
void (*elfcore)(Fhdr*, Elf*, ElfNote*);
if((elf = elfinit(fd)) == nil)
return -1;
@ -133,16 +128,37 @@ crackelf(int fd, Fhdr *fp)
fp->map = mapelf;
if(fp->ftype == FCORE){
elfcore = nil;
for(i=0; i<nelem(ctab); i++){
if(ctab[i].atype != fp->atype
|| ctab[i].mtype != fp->mtype)
continue;
elf->coreregs = ctab[i].coreregs;
elf->corecmd = ctab[i].corecmd;
elfcore = ctab[i].elfcore;
break;
}
if((fp->cmd = getcorecmd(fp)) == nil)
fprint(2, "warning: reading core command: %r");
if(elfcore)
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;
}
@ -258,10 +274,8 @@ mapelf(Fhdr *fp, ulong base, Map *map, Regs **regs)
}
}
if(fp->ftype == FCORE){
if(mapcoreregs(fp, map, regs) < 0)
fprint(2, "warning: reading core regs: %r");
}
if(fp->nthread && regs)
*regs = coreregs(fp, fp->thread[0].id);
return 0;
}
@ -286,126 +300,3 @@ unpacknote(Elf *elf, uchar *a, uchar *ea, ElfNote *note, uchar **pa)
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 elfmap(Elf*, ElfSect*);
int coreregslinux386(Elf*, ElfNote*, uchar**);
int coreregsfreebsd386(Elf*, ElfNote*, uchar**);
int corecmdlinux386(Elf*, ElfNote*, char**);
int corecmdfreebsd386(Elf*, ElfNote*, char**);
void elfdl386mapdl(void);
struct Fhdr;
void elfcorelinux386(struct Fhdr*, Elf*, ElfNote*);
void elfdl386mapdl(int);

View file

@ -34,6 +34,10 @@ struct Status
UregLinux386 reg;
u32int fpvalid;
};
enum
{
StatusSize = sizeof(Status),
};
struct Psinfo
{
@ -51,6 +55,10 @@ struct Psinfo
char fname[16];
char psargs[80];
};
enum
{
PsinfoSize = sizeof(Psinfo),
};
int
coreregslinux386(Elf *elf, ElfNote *note, uchar **up)
@ -65,8 +73,9 @@ coreregslinux386(Elf *elf, ElfNote *note, uchar **up)
}
s = (Status*)note->desc;
l = &s->reg;
if((u = _linux2ureg386(l)) == nil)
if((u = malloc(sizeof *u)) == nil)
return -1;
linux2ureg386(l, u);
*up = (uchar*)u;
return sizeof(Ureg);
}
@ -93,3 +102,101 @@ corecmdlinux386(Elf *elf, ElfNote *note, char **pp)
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
elfdl386mapdl(void)
elfdl386mapdl(int verbose)
{
int i;
Fhdr *hdr;
u32int linkdebug, linkmap, name, addr;
char buf[1024];
print("elfdl386mapdl\n");
if((linkdebug = dyninfo(symhdr, DT_DEBUG)) == 0){
fprint(2, "no dt_debug section\n");
return;
@ -109,25 +108,27 @@ print("elfdl386mapdl\n");
|| get4(cormap, linkmap+12, &linkmap) < 0)
break;
if(name
&& getstr(cormap, name, buf, sizeof buf) >= 0
&& buf[0]
&& access(buf, AEXIST) >= 0){
if((hdr = crackhdr(buf, OREAD)) == nil)
fprint(2, "crackhdr %s: %r\n", buf);
else{
fprint(2, "%s: %s %s %s\n", buf, hdr->aname, hdr->mname, hdr->fname);
hdr->base = addr;
if(mapfile(hdr, addr, symmap, nil) < 0)
fprint(2, "mapfile %s: %r\n", buf);
if(corhdr){
unmapfile(corhdr, cormap);
mapfile(hdr, addr, cormap, nil);
}
if(symopen(hdr) < 0)
fprint(2, "syminit %s: %\r", buf);
}
}
if(name == 0 || getstr(cormap, name, buf, sizeof buf) < 0 || buf[0] == 0)
continue;
if((hdr = crackhdr(buf, OREAD)) == nil){
fprint(2, "crackhdr %s: %r\n", buf);
continue;
}
hdr->base = addr;
if(verbose)
fprint(2, "%s: %s %s %s\n", buf, hdr->aname, hdr->mname, hdr->fname);
if(mapfile(hdr, addr, symmap, nil) < 0)
fprint(2, "mapping %s: %r\n", buf);
if(corhdr){
/*
* Need to map the text file under the core file.
*/
unmapfile(corhdr, cormap);
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;
if(i < 0)
break;
if(sp && strcmp(sp->name, "main") == 0)
break;
if(sp){
if(strcmp(sp->name, "main") == 0
|| strcmp(sp->name, "procscheduler") == 0
|| strcmp(sp->name, "threadstart") == 0)
break;
}
pc = nextpc;
memmove(cur, next, mach->nwindreg*sizeof(cur[0]));
}

View file

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

View file

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

View file

@ -6,6 +6,103 @@
#include <libc.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[] =
{
[TD_OK] "no error",
@ -47,3 +144,146 @@ terr(int 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{
for(p=fhdrlist; p && p->next!=h; p=p->next)
;
if(p)
if(p){
p->next = h->next;
if(p->next == nil)
last = p;
if(p->next == nil)
last = p;
}
}
h->next = nil;
}

View file

@ -1,18 +1,11 @@
#include <u.h>
#include <libc.h>
#include <mach.h>
#include <elf.h>
#include "ureg386.h"
Ureg*
_linux2ureg386(UregLinux386 *l)
void
linux2ureg386(UregLinux386 *l, Ureg *u)
{
Ureg *u;
u = malloc(sizeof(Ureg));
if(u == nil)
return nil;
u->di = l->edi;
u->si = l->esi;
u->bp = l->ebp;
@ -32,5 +25,27 @@ _linux2ureg386(UregLinux386 *l)
u->flags = l->eflags;
u->sp = l->esp;
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;
struct UregLinux386
{
ulong ebx;
ulong ecx;
ulong edx;
ulong esi;
ulong edi;
ulong ebp;
ulong eax;
ulong xds;
ulong xes;
ulong xfs;
ulong xgs;
ulong origeax;
ulong eip;
ulong xcs;
ulong eflags;
ulong esp;
ulong xss;
u32int ebx;
u32int ecx;
u32int edx;
u32int esi;
u32int edi;
u32int ebp;
u32int eax;
u32int xds;
u32int xes;
u32int xfs;
u32int xgs;
u32int origeax;
u32int eip;
u32int xcs;
u32int eflags;
u32int esp;
u32int xss;
};
Ureg *_linux2ureg386(UregLinux386*);
void linux2ureg386(UregLinux386*, Ureg*);
void ureg2linux386(Ureg*, UregLinux386*);