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:
parent
a0e8d02d09
commit
dd944ec72a
14 changed files with 528 additions and 415 deletions
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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, ¬e, &a) < 0)
|
||||||
|
break;
|
||||||
|
elfcore(fp, elf, ¬e);
|
||||||
|
}
|
||||||
|
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, ¬e, &a) < 0)
|
|
||||||
break;
|
|
||||||
switch(note.type){
|
|
||||||
case ElfNotePrStatus:
|
|
||||||
if((n = (*elf->coreregs)(elf, ¬e, &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, ¬e, &a) < 0)
|
|
||||||
break;
|
|
||||||
switch(note.type){
|
|
||||||
case ElfNotePrPsinfo:
|
|
||||||
if((n = elf->corecmd(elf, ¬e, &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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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]));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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))
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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*);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue