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)
downloadplan9port-dd944ec72a26d0b380ba2af5f6c00310f2f1651e.tar.gz
plan9port-dd944ec72a26d0b380ba2af5f6c00310f2f1651e.tar.bz2
plan9port-dd944ec72a26d0b380ba2af5f6c00310f2f1651e.zip
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*);