aboutsummaryrefslogtreecommitdiff
path: root/src/libmach
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2005-01-23 22:33:04 +0000
committerrsc <devnull@localhost>2005-01-23 22:33:04 +0000
commitdd944ec72a26d0b380ba2af5f6c00310f2f1651e (patch)
tree2f40332ca2fcf189d347cf4f577cf613af21108f /src/libmach
parenta0e8d02d093e01fdadf8a16bc86fe18b0c4e82c3 (diff)
Start working through proper handling of pthreads when
debugging Linux core dumps. Pthreads for active processes is still not supported, nor are other systems.
Diffstat (limited to 'src/libmach')
-rw-r--r--src/libmach/Linux.c191
-rw-r--r--src/libmach/cmdline.c39
-rw-r--r--src/libmach/crack.c38
-rw-r--r--src/libmach/crackelf.c181
-rw-r--r--src/libmach/elf.h8
-rw-r--r--src/libmach/elfcorelinux386.c109
-rw-r--r--src/libmach/elfdl386.c43
-rw-r--r--src/libmach/frame.c8
-rw-r--r--src/libmach/map.c4
-rw-r--r--src/libmach/mkfile2
-rw-r--r--src/libmach/pthread.c240
-rw-r--r--src/libmach/sym.c7
-rw-r--r--src/libmach/ureg386.c35
-rw-r--r--src/libmach/ureg386.h38
14 files changed, 528 insertions, 415 deletions
diff --git a/src/libmach/Linux.c b/src/libmach/Linux.c
index 9127434f..ff727409 100644
--- a/src/libmach/Linux.c
+++ b/src/libmach/Linux.c
@@ -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;
-}
diff --git a/src/libmach/cmdline.c b/src/libmach/cmdline.c
index 4da38d9e..568bc017 100644
--- a/src/libmach/cmdline.c
+++ b/src/libmach/cmdline.c
@@ -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;
}
diff --git a/src/libmach/crack.c b/src/libmach/crack.c
index ffc3b06c..c186456a 100644
--- a/src/libmach/crack.c
+++ b/src/libmach/crack.c
@@ -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;
+}
+
diff --git a/src/libmach/crackelf.c b/src/libmach/crackelf.c
index 682d9a72..e80d9ec3 100644
--- a/src/libmach/crackelf.c
+++ b/src/libmach/crackelf.c
@@ -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;
-}
-
diff --git a/src/libmach/elf.h b/src/libmach/elf.h
index 6b65cfc8..f5245099 100644
--- a/src/libmach/elf.h
+++ b/src/libmach/elf.h
@@ -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);
diff --git a/src/libmach/elfcorelinux386.c b/src/libmach/elfcorelinux386.c
index 9e8d0aa9..4c4aabc4 100644
--- a/src/libmach/elfcorelinux386.c
+++ b/src/libmach/elfcorelinux386.c
@@ -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);
+ }
+}
+
diff --git a/src/libmach/elfdl386.c b/src/libmach/elfdl386.c
index a2439158..5386f1b6 100644
--- a/src/libmach/elfdl386.c
+++ b/src/libmach/elfdl386.c
@@ -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);
}
}
diff --git a/src/libmach/frame.c b/src/libmach/frame.c
index 035c6a52..7d03f3b4 100644
--- a/src/libmach/frame.c
+++ b/src/libmach/frame.c
@@ -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]));
}
diff --git a/src/libmach/map.c b/src/libmach/map.c
index bfb5f722..b20bd873 100644
--- a/src/libmach/map.c
+++ b/src/libmach/map.c
@@ -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))
diff --git a/src/libmach/mkfile b/src/libmach/mkfile
index 53d1af99..a6d6507e 100644
--- a/src/libmach/mkfile
+++ b/src/libmach/mkfile
@@ -43,7 +43,7 @@ OFILES=\
symstabs.$O\
ureg386.$O\
-HFILES=mach.h
+HFILES=$PLAN9/include/mach.h
<$PLAN9/src/mksyslib
CFLAGS=$CFLAGS -I.
diff --git a/src/libmach/pthread.c b/src/libmach/pthread.c
index 46eca4f2..8a2b60a9 100644
--- a/src/libmach/pthread.c
+++ b/src/libmach/pthread.c
@@ -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;
+}
+
diff --git a/src/libmach/sym.c b/src/libmach/sym.c
index b5d3eacf..3b5c5ec4 100644
--- a/src/libmach/sym.c
+++ b/src/libmach/sym.c
@@ -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;
}
diff --git a/src/libmach/ureg386.c b/src/libmach/ureg386.c
index 09ef095d..76945030 100644
--- a/src/libmach/ureg386.c
+++ b/src/libmach/ureg386.c
@@ -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;
+}
+
diff --git a/src/libmach/ureg386.h b/src/libmach/ureg386.h
index f5f9a474..9c4853d6 100644
--- a/src/libmach/ureg386.h
+++ b/src/libmach/ureg386.h
@@ -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*);