merge
This commit is contained in:
commit
9b194f23b2
5
lib/theo
5
lib/theo
|
@ -905,3 +905,8 @@ No.
|
||||||
No.
|
No.
|
||||||
Not going to explain further.
|
Not going to explain further.
|
||||||
Get your shit together
|
Get your shit together
|
||||||
|
oh my, the moral outrage
|
||||||
|
Let it go, and consider leaving for good.
|
||||||
|
Do you have evidence?
|
||||||
|
Diffs are welcome.
|
||||||
|
Please don't do that.
|
||||||
|
|
|
@ -5248,3 +5248,4 @@ I've been looking into running Plan 9 in JSLinux -- Skip Tavakkolian
|
||||||
i have been looking for an excuse to install 9front.
|
i have been looking for an excuse to install 9front.
|
||||||
I'm beginning to wonder if anyone is left that isn't part of 9front? -- Steve Stallion
|
I'm beginning to wonder if anyone is left that isn't part of 9front? -- Steve Stallion
|
||||||
Having a public mailing list is an invitation for discussion amongst likeminded individuals, not elitist fuckery. -- Steve Stallion, talking about 9fans
|
Having a public mailing list is an invitation for discussion amongst likeminded individuals, not elitist fuckery. -- Steve Stallion, talking about 9fans
|
||||||
|
[9fans] ..... UNSUBSCRIBE_HELP NEEDED
|
||||||
|
|
|
@ -41,6 +41,8 @@ struct DTName {
|
||||||
/*
|
/*
|
||||||
we assign all pairs (probe,action-group) (called an enabling or DTEnab) a unique ID called EPID.
|
we assign all pairs (probe,action-group) (called an enabling or DTEnab) a unique ID called EPID.
|
||||||
we could also use probe IDs and action group IDs but using a single 32-bit ID for both is more flexible/efficient.
|
we could also use probe IDs and action group IDs but using a single 32-bit ID for both is more flexible/efficient.
|
||||||
|
|
||||||
|
epid == -1 indicates a fault record (see below)
|
||||||
*/
|
*/
|
||||||
struct DTEnab {
|
struct DTEnab {
|
||||||
u32int epid;
|
u32int epid;
|
||||||
|
@ -235,6 +237,10 @@ struct DTTrigInfo {
|
||||||
DTChan *ch;
|
DTChan *ch;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* fault records are used to note when a probe had to be aborted (e.g. because of a page fault) */
|
||||||
|
enum {
|
||||||
|
DTFILL = 1, /* illegal address */
|
||||||
|
};
|
||||||
|
|
||||||
void dtinit(int);
|
void dtinit(int);
|
||||||
void dtsync(void);
|
void dtsync(void);
|
||||||
|
@ -269,6 +275,7 @@ int dtcread(DTChan *, void *, int);
|
||||||
int dtcaggread(DTChan *, void *, int);
|
int dtcaggread(DTChan *, void *, int);
|
||||||
void dtcreset(DTChan *);
|
void dtcreset(DTChan *);
|
||||||
void dtcrun(DTChan *, int);
|
void dtcrun(DTChan *, int);
|
||||||
|
int dtcfault(DTTrigInfo *, int, char *, ...);
|
||||||
|
|
||||||
/* aggbuf functions */
|
/* aggbuf functions */
|
||||||
int dtaunpackid(DTAgg *);
|
int dtaunpackid(DTAgg *);
|
||||||
|
|
|
@ -511,6 +511,17 @@ TEXT _wrmsrinst(SB), $0
|
||||||
MOVL BP, AX /* BP set to -1 if traped */
|
MOVL BP, AX /* BP set to -1 if traped */
|
||||||
RET
|
RET
|
||||||
|
|
||||||
|
/* fault-proof memcpy */
|
||||||
|
TEXT peek(SB), $0
|
||||||
|
MOVL src+0(FP), SI
|
||||||
|
MOVL dst+4(FP), DI
|
||||||
|
MOVL cnt+8(FP), CX
|
||||||
|
CLD
|
||||||
|
TEXT _peekinst(SB), $0
|
||||||
|
REP; MOVSB
|
||||||
|
MOVL CX, AX
|
||||||
|
RET
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Try to determine the CPU type which requires fiddling with EFLAGS.
|
* Try to determine the CPU type which requires fiddling with EFLAGS.
|
||||||
* If the Id bit can be toggled then the CPUID instruction can be used
|
* If the Id bit can be toggled then the CPUID instruction can be used
|
||||||
|
|
|
@ -67,6 +67,7 @@ LIB=\
|
||||||
/$objtype/lib/libmp.a\
|
/$objtype/lib/libmp.a\
|
||||||
/$objtype/lib/libfis.a\
|
/$objtype/lib/libfis.a\
|
||||||
/$objtype/lib/libaml.a\
|
/$objtype/lib/libaml.a\
|
||||||
|
/$objtype/lib/libdtracy.a\
|
||||||
|
|
||||||
ETHER=`{echo devether.c ether*.c | sed 's/\.c/.'$O'/g'}
|
ETHER=`{echo devether.c ether*.c | sed 's/\.c/.'$O'/g'}
|
||||||
AUDIO=`{echo devaudio.c audio*.c | sed 's/\.c/.'$O'/g'}
|
AUDIO=`{echo devaudio.c audio*.c | sed 's/\.c/.'$O'/g'}
|
||||||
|
|
|
@ -18,6 +18,7 @@ dev
|
||||||
cap
|
cap
|
||||||
kprof
|
kprof
|
||||||
fs
|
fs
|
||||||
|
dtracy
|
||||||
|
|
||||||
ether netif
|
ether netif
|
||||||
bridge netif log
|
bridge netif log
|
||||||
|
@ -138,6 +139,9 @@ misc
|
||||||
vgavesa
|
vgavesa
|
||||||
vgavmware +cur
|
vgavmware +cur
|
||||||
|
|
||||||
|
dtracysys
|
||||||
|
dtracytimer
|
||||||
|
|
||||||
ip
|
ip
|
||||||
tcp
|
tcp
|
||||||
udp
|
udp
|
||||||
|
|
|
@ -450,6 +450,7 @@ trap(Ureg* ureg)
|
||||||
extern void _forkretiret(void);
|
extern void _forkretiret(void);
|
||||||
extern void _rdmsrinst(void);
|
extern void _rdmsrinst(void);
|
||||||
extern void _wrmsrinst(void);
|
extern void _wrmsrinst(void);
|
||||||
|
extern void _peekinst(void);
|
||||||
|
|
||||||
extern void load_fs(ulong);
|
extern void load_fs(ulong);
|
||||||
extern void load_gs(ulong);
|
extern void load_gs(ulong);
|
||||||
|
@ -478,6 +479,11 @@ trap(Ureg* ureg)
|
||||||
ureg->pc += 2;
|
ureg->pc += 2;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
} else if(pc == _peekinst){
|
||||||
|
if(vno == VectorGPF){
|
||||||
|
ureg->pc += 2;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -712,6 +718,13 @@ fault386(Ureg* ureg, void*)
|
||||||
if(!user){
|
if(!user){
|
||||||
if(vmapsync(addr))
|
if(vmapsync(addr))
|
||||||
return;
|
return;
|
||||||
|
{
|
||||||
|
extern void _peekinst(void);
|
||||||
|
if((void(*)(void))ureg->pc == _peekinst){
|
||||||
|
ureg->pc += 2;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
if(addr >= USTKTOP)
|
if(addr >= USTKTOP)
|
||||||
panic("kernel fault: bad address pc=0x%.8lux addr=0x%.8lux", ureg->pc, addr);
|
panic("kernel fault: bad address pc=0x%.8lux addr=0x%.8lux", ureg->pc, addr);
|
||||||
if(up == nil)
|
if(up == nil)
|
||||||
|
|
|
@ -449,6 +449,18 @@ TEXT _wrmsrinst(SB), $0
|
||||||
MOVQ BP, AX /* BP set to -1 if traped */
|
MOVQ BP, AX /* BP set to -1 if traped */
|
||||||
RET
|
RET
|
||||||
|
|
||||||
|
/* fault-proof memcpy */
|
||||||
|
TEXT peek(SB), 1, $-4
|
||||||
|
MOVQ RARG, SI
|
||||||
|
MOVQ dst+8(FP), DI
|
||||||
|
MOVL cnt+16(FP), CX
|
||||||
|
CLD
|
||||||
|
TEXT _peekinst(SB), $0
|
||||||
|
REP; MOVSB
|
||||||
|
MOVL CX, AX
|
||||||
|
RET
|
||||||
|
|
||||||
|
|
||||||
TEXT invlpg(SB), 1, $-4
|
TEXT invlpg(SB), 1, $-4
|
||||||
INVLPG (RARG)
|
INVLPG (RARG)
|
||||||
RET
|
RET
|
||||||
|
|
|
@ -65,6 +65,7 @@ LIB=\
|
||||||
/$objtype/lib/libc.a\
|
/$objtype/lib/libc.a\
|
||||||
/$objtype/lib/libfis.a\
|
/$objtype/lib/libfis.a\
|
||||||
/$objtype/lib/libaml.a\
|
/$objtype/lib/libaml.a\
|
||||||
|
/$objtype/lib/libdtracy.a\
|
||||||
|
|
||||||
ETHER=`{cd ../pc; echo devether.c ether*.c | sed 's/\.c/.'$O'/g'}
|
ETHER=`{cd ../pc; echo devether.c ether*.c | sed 's/\.c/.'$O'/g'}
|
||||||
AUDIO=`{cd ../pc; echo devaudio.c audio*.c | sed 's/\.c/.'$O'/g'}
|
AUDIO=`{cd ../pc; echo devaudio.c audio*.c | sed 's/\.c/.'$O'/g'}
|
||||||
|
|
|
@ -41,6 +41,7 @@ dev
|
||||||
|
|
||||||
segment
|
segment
|
||||||
vmx
|
vmx
|
||||||
|
dtracy
|
||||||
|
|
||||||
link
|
link
|
||||||
# devpccard
|
# devpccard
|
||||||
|
@ -136,6 +137,9 @@ misc
|
||||||
vgavesa
|
vgavesa
|
||||||
# vgavmware +cur
|
# vgavmware +cur
|
||||||
|
|
||||||
|
dtracysys
|
||||||
|
dtracytimer
|
||||||
|
|
||||||
ip
|
ip
|
||||||
tcp
|
tcp
|
||||||
udp
|
udp
|
||||||
|
|
|
@ -440,6 +440,7 @@ trap(Ureg *ureg)
|
||||||
|
|
||||||
extern void _rdmsrinst(void);
|
extern void _rdmsrinst(void);
|
||||||
extern void _wrmsrinst(void);
|
extern void _wrmsrinst(void);
|
||||||
|
extern void _peekinst(void);
|
||||||
|
|
||||||
pc = (void*)ureg->pc;
|
pc = (void*)ureg->pc;
|
||||||
if(pc == _rdmsrinst || pc == _wrmsrinst){
|
if(pc == _rdmsrinst || pc == _wrmsrinst){
|
||||||
|
@ -448,6 +449,11 @@ trap(Ureg *ureg)
|
||||||
ureg->pc += 2;
|
ureg->pc += 2;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
} else if(pc == _peekinst){
|
||||||
|
if(vno == VectorGPF){
|
||||||
|
ureg->pc += 2;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -672,6 +678,14 @@ faultamd64(Ureg* ureg, void*)
|
||||||
read = !(ureg->error & 2);
|
read = !(ureg->error & 2);
|
||||||
user = userureg(ureg);
|
user = userureg(ureg);
|
||||||
if(!user){
|
if(!user){
|
||||||
|
{
|
||||||
|
extern void _peekinst(void);
|
||||||
|
|
||||||
|
if((void(*)(void))ureg->pc == _peekinst){
|
||||||
|
ureg->pc += 2;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
if(addr >= USTKTOP)
|
if(addr >= USTKTOP)
|
||||||
panic("kernel fault: bad address pc=%#p addr=%#p", ureg->pc, addr);
|
panic("kernel fault: bad address pc=%#p addr=%#p", ureg->pc, addr);
|
||||||
if(up == nil)
|
if(up == nil)
|
||||||
|
|
|
@ -125,9 +125,13 @@ dtkfree(DTKChan *p)
|
||||||
dtktab[idx] = nil;
|
dtktab[idx] = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int dtracyen;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dtracyinit(void)
|
dtracyinit(void)
|
||||||
{
|
{
|
||||||
|
dtracyen = getconf("*dtracy") != nil;
|
||||||
|
if(!dtracyen) return;
|
||||||
machlocks = smalloc(sizeof(Lock) * conf.nmach);
|
machlocks = smalloc(sizeof(Lock) * conf.nmach);
|
||||||
dtinit(conf.nmach);
|
dtinit(conf.nmach);
|
||||||
}
|
}
|
||||||
|
@ -135,6 +139,8 @@ dtracyinit(void)
|
||||||
static Chan*
|
static Chan*
|
||||||
dtracyattach(char *spec)
|
dtracyattach(char *spec)
|
||||||
{
|
{
|
||||||
|
if(!dtracyen)
|
||||||
|
error("*dtracy= not set");
|
||||||
return devattach(L'Δ', spec);
|
return devattach(L'Δ', spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -512,67 +518,16 @@ dtgetvar(int v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int peek(char *, char *, int);
|
||||||
|
|
||||||
int
|
int
|
||||||
dtpeek(uvlong addr, void *buf, int len)
|
dtpeek(uvlong addr, void *buf, int len)
|
||||||
{
|
{
|
||||||
if((uintptr)addr != addr || up == nil || !okaddr((uintptr) addr, len, 0)) return -1;
|
uintptr a;
|
||||||
memmove(buf, (void *) addr, len);
|
|
||||||
return 0;
|
a = addr;
|
||||||
|
if(len == 0) return 0;
|
||||||
|
if(a != addr || a > -(uintptr)len || len < 0) return -1;
|
||||||
|
if(up == nil || up->privatemem || a >= KZERO) return -1;
|
||||||
|
return peek((void *)a, buf, len) > 0 ? -1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DTProbe *timerprobe;
|
|
||||||
|
|
||||||
static void
|
|
||||||
dtracytimer(void *)
|
|
||||||
{
|
|
||||||
DTTrigInfo info;
|
|
||||||
|
|
||||||
memset(&info, 0, sizeof(info));
|
|
||||||
for(;;){
|
|
||||||
tsleep(&up->sleep, return0, nil, 1000);
|
|
||||||
dtptrigger(timerprobe, m->machno, &info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
timerprovide(DTProvider *prov, DTName)
|
|
||||||
{
|
|
||||||
static int provided;
|
|
||||||
|
|
||||||
if(provided) return;
|
|
||||||
provided = 1;
|
|
||||||
timerprobe = dtpnew((DTName){"timer", "", "1s"}, prov, nil);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
timerenable(DTProbe *)
|
|
||||||
{
|
|
||||||
static int gotkproc;
|
|
||||||
|
|
||||||
if(!gotkproc){
|
|
||||||
kproc("dtracytimer", dtracytimer, nil);
|
|
||||||
gotkproc=1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
timerdisable(DTProbe *)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
DTProvider dtracyprov_timer = {
|
|
||||||
.name = "timer",
|
|
||||||
.provide = timerprovide,
|
|
||||||
.enable = timerenable,
|
|
||||||
.disable = timerdisable,
|
|
||||||
};
|
|
||||||
|
|
||||||
extern DTProvider dtracyprov_sys;
|
|
||||||
|
|
||||||
DTProvider *dtproviders[] = {
|
|
||||||
&dtracyprov_timer,
|
|
||||||
&dtracyprov_sys,
|
|
||||||
nil,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
|
@ -260,7 +260,7 @@ sysdisable(DTProbe *p)
|
||||||
z = systab[i], systab[i] = wraptab[i], wraptab[i] = z;
|
z = systab[i], systab[i] = wraptab[i], wraptab[i] = z;
|
||||||
}
|
}
|
||||||
|
|
||||||
DTProvider dtracyprov_sys = {
|
DTProvider dtracysysprov = {
|
||||||
.name = "sys",
|
.name = "sys",
|
||||||
.provide = sysprovide,
|
.provide = sysprovide,
|
||||||
.enable = sysenable,
|
.enable = sysenable,
|
||||||
|
|
56
sys/src/9/port/dtracytimer.c
Normal file
56
sys/src/9/port/dtracytimer.c
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
#include "u.h"
|
||||||
|
#include "../port/lib.h"
|
||||||
|
#include "mem.h"
|
||||||
|
#include "dat.h"
|
||||||
|
#include "fns.h"
|
||||||
|
#include "../port/error.h"
|
||||||
|
|
||||||
|
#include <dtracy.h>
|
||||||
|
|
||||||
|
static DTProbe *timerprobe;
|
||||||
|
|
||||||
|
static void
|
||||||
|
dtracytimer(void *)
|
||||||
|
{
|
||||||
|
DTTrigInfo info;
|
||||||
|
|
||||||
|
memset(&info, 0, sizeof(info));
|
||||||
|
for(;;){
|
||||||
|
tsleep(&up->sleep, return0, nil, 1000);
|
||||||
|
dtptrigger(timerprobe, m->machno, &info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
timerprovide(DTProvider *prov, DTName)
|
||||||
|
{
|
||||||
|
static int provided;
|
||||||
|
|
||||||
|
if(provided) return;
|
||||||
|
provided = 1;
|
||||||
|
timerprobe = dtpnew((DTName){"timer", "", "1s"}, prov, nil);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
timerenable(DTProbe *)
|
||||||
|
{
|
||||||
|
static int gotkproc;
|
||||||
|
|
||||||
|
if(!gotkproc){
|
||||||
|
kproc("dtracytimer", dtracytimer, nil);
|
||||||
|
gotkproc=1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
timerdisable(DTProbe *)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
DTProvider dtracytimerprov = {
|
||||||
|
.name = "timer",
|
||||||
|
.provide = timerprovide,
|
||||||
|
.enable = timerenable,
|
||||||
|
.disable = timerdisable,
|
||||||
|
};
|
|
@ -58,7 +58,8 @@ collect && section == "misc"{
|
||||||
if($i ~ "[+=]cur")
|
if($i ~ "[+=]cur")
|
||||||
vgacur[nvgacur++] = $1;
|
vgacur[nvgacur++] = $1;
|
||||||
}
|
}
|
||||||
}
|
}else if($1 ~ "^dtracy.*")
|
||||||
|
dtracyprov[ndtracyprov++] = $1;
|
||||||
}
|
}
|
||||||
|
|
||||||
collect && section == "port"{
|
collect && section == "port"{
|
||||||
|
@ -191,6 +192,16 @@ END{
|
||||||
printf "\n";
|
printf "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(ndtracyprov){
|
||||||
|
printf "#include <dtracy.h>\n";
|
||||||
|
for(i = 0; i < ndtracyprov; i++)
|
||||||
|
printf "extern DTProvider %sprov;\n", dtracyprov[i]
|
||||||
|
printf "DTProvider *dtproviders[] = {\n"
|
||||||
|
for(i = 0; i < ndtracyprov; i++)
|
||||||
|
printf "\t&%sprov,\n", dtracyprov[i]
|
||||||
|
printf "\tnil,\n};\n\n"
|
||||||
|
}
|
||||||
|
|
||||||
printf "char* conffile = \"%s/%s\";\n", pwd, ARGV[1];
|
printf "char* conffile = \"%s/%s\";\n", pwd, ARGV[1];
|
||||||
printf "ulong kerndate = KERNDATE;\n";
|
printf "ulong kerndate = KERNDATE;\n";
|
||||||
|
|
||||||
|
|
|
@ -462,6 +462,34 @@ parseclause(Clause *cl, uchar *p, uchar *e, Enab *en, Biobuf *bp)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uchar *
|
||||||
|
parsefault(uchar *p0, uchar *e)
|
||||||
|
{
|
||||||
|
uchar *p;
|
||||||
|
u32int epid;
|
||||||
|
u8int type, dummy;
|
||||||
|
u16int n;
|
||||||
|
Enab *en;
|
||||||
|
|
||||||
|
p = unpack(p0, e, "csci", &type, &n, &dummy, &epid);
|
||||||
|
if(p == nil) return nil;
|
||||||
|
en = epidlookup(epid);
|
||||||
|
switch(type){
|
||||||
|
case DTFILL: {
|
||||||
|
u32int pid;
|
||||||
|
u64int addr;
|
||||||
|
|
||||||
|
p = unpack(p, e, "iv", &pid, &addr);
|
||||||
|
if(p == nil) return nil;
|
||||||
|
fprint(2, "dtracy: illegal access: probe=%s, pid=%d, addr=%#llx\n", en != nil ? en->probe : nil, pid, addr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
fprint(2, "dtracy: unknown fault type %#.2ux\n", type);
|
||||||
|
}
|
||||||
|
return p0 + n - 12;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
parsebuf(uchar *p, int n, Biobuf *bp)
|
parsebuf(uchar *p, int n, Biobuf *bp)
|
||||||
{
|
{
|
||||||
|
@ -474,6 +502,11 @@ parsebuf(uchar *p, int n, Biobuf *bp)
|
||||||
while(p < e){
|
while(p < e){
|
||||||
p = unpack(p, e, "iv", &epid, &ts);
|
p = unpack(p, e, "iv", &epid, &ts);
|
||||||
if(p == nil) goto err;
|
if(p == nil) goto err;
|
||||||
|
if(epid == (u32int)-1){
|
||||||
|
p = parsefault(p, e);
|
||||||
|
if(p == nil) goto err;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
en = epidlookup(epid);
|
en = epidlookup(epid);
|
||||||
if(en == nil) goto err;
|
if(en == nil) goto err;
|
||||||
if(parseclause(en->cl, p - 12, p + en->reclen - 12, en, bp) < 0) return -1;
|
if(parseclause(en->cl, p - 12, p + en->reclen - 12, en, bp) < 0) return -1;
|
||||||
|
|
|
@ -1414,4 +1414,6 @@ threadmain(int argc, char **argv)
|
||||||
passwdparse(gidtab, readfile(gidfile));
|
passwdparse(gidtab, readfile(gidfile));
|
||||||
|
|
||||||
threadpostmountsrv(&sshfssrv, svc, mtpt, MCREATE | mflag);
|
threadpostmountsrv(&sshfssrv, svc, mtpt, MCREATE | mflag);
|
||||||
|
|
||||||
|
exits(nil);
|
||||||
}
|
}
|
||||||
|
|
|
@ -230,6 +230,55 @@ dtpeekstr(uvlong addr, u8int *v, int len)
|
||||||
#define PUT4(c) *bp++ = c; *bp++ = c >> 8; *bp++ = c >> 16; *bp++ = c >> 24;
|
#define PUT4(c) *bp++ = c; *bp++ = c >> 8; *bp++ = c >> 16; *bp++ = c >> 24;
|
||||||
#define PUT8(c) PUT4(c); PUT4(c>>32);
|
#define PUT8(c) PUT4(c); PUT4(c>>32);
|
||||||
|
|
||||||
|
int
|
||||||
|
dtcfault(DTTrigInfo *info, int type, char *fmt, ...)
|
||||||
|
{
|
||||||
|
DTBuf *b;
|
||||||
|
va_list va;
|
||||||
|
int n;
|
||||||
|
char *s;
|
||||||
|
u8int *bp;
|
||||||
|
u32int l;
|
||||||
|
uvlong q;
|
||||||
|
|
||||||
|
b = info->ch->wrbufs[info->machno];
|
||||||
|
n = 20;
|
||||||
|
va_start(va, fmt);
|
||||||
|
for(s = fmt; *s != 0; s++)
|
||||||
|
switch(*s){
|
||||||
|
case 'i': n += 4; break;
|
||||||
|
case 'p': n += 8; break;
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
va_end(va);
|
||||||
|
if(b->wr + n > DTBUFSZ)
|
||||||
|
return -1;
|
||||||
|
bp = &b->data[b->wr];
|
||||||
|
PUT4(-1);
|
||||||
|
PUT8(info->ts);
|
||||||
|
PUT1(type);
|
||||||
|
PUT2(n);
|
||||||
|
PUT1(0);
|
||||||
|
PUT4(info->epid);
|
||||||
|
va_start(va, fmt);
|
||||||
|
for(s = fmt; *s != 0; s++)
|
||||||
|
switch(*s){
|
||||||
|
case 'i':
|
||||||
|
l = va_arg(va, int);
|
||||||
|
PUT4(l);
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
q = (uintptr) va_arg(va, void *);
|
||||||
|
PUT8(q);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
va_end(va);
|
||||||
|
assert(bp - b->data - b->wr == n);
|
||||||
|
b->wr = bp - b->data;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
dtgexec(DTActGr *g, DTTrigInfo *info)
|
dtgexec(DTActGr *g, DTTrigInfo *info)
|
||||||
{
|
{
|
||||||
|
@ -265,8 +314,8 @@ dtgexec(DTActGr *g, DTTrigInfo *info)
|
||||||
break;
|
break;
|
||||||
case ACTTRACESTR:
|
case ACTTRACESTR:
|
||||||
if(dtpeekstr(v, bp, g->acts[i].size) < 0){
|
if(dtpeekstr(v, bp, g->acts[i].size) < 0){
|
||||||
snprint(info->ch->errstr, sizeof(info->ch->errstr), "fault @ %#llux", v);
|
dtcfault(info, DTFILL, "ip", dtgetvar(DTV_PID), v);
|
||||||
return -1;
|
return 0;
|
||||||
}
|
}
|
||||||
bp += g->acts[i].size;
|
bp += g->acts[i].size;
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue