mirror of
https://github.com/Zenithsiz/ftmemsim-valgrind.git
synced 2026-02-04 02:18:37 +00:00
implement a couple more instructions. I've mailed this patch to Julian
and Nick but got no reply. I guess they're okay with it. I tested them quite a lot so it should be fine. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1834
This commit is contained in:
parent
3545e98607
commit
eaf2fd38cd
16
NEWS
16
NEWS
@ -1,3 +1,19 @@
|
||||
Snapshot 2003XXXX (XX XXXX 2003)
|
||||
|
||||
- Implemented more opcodes:
|
||||
- push %es
|
||||
- push %ds
|
||||
- pop %es
|
||||
- pop %ds
|
||||
- movntq
|
||||
- sfence
|
||||
- pshufw
|
||||
- pavgb
|
||||
- ucomiss
|
||||
- enter
|
||||
|
||||
- Memcheck: Implemented handling of more SSE(2) constructs
|
||||
|
||||
|
||||
Snapshot 20030725 (25 July 2003)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
|
||||
/* -*- c-basic-offset: 3 -*- */
|
||||
/*--------------------------------------------------------------------*/
|
||||
/*--- The JITter: translate x86 code to ucode. ---*/
|
||||
/*--- vg_to_ucode.c ---*/
|
||||
@ -104,7 +104,7 @@ static Char* nameGrp8 ( Int opc_aux )
|
||||
return grp8_names[opc_aux];
|
||||
}
|
||||
|
||||
Char* VG_(name_of_int_reg) ( Int size, Int reg )
|
||||
const Char* VG_(name_of_int_reg) ( Int size, Int reg )
|
||||
{
|
||||
static Char* ireg32_names[8]
|
||||
= { "%eax", "%ecx", "%edx", "%ebx",
|
||||
@ -125,7 +125,7 @@ Char* VG_(name_of_int_reg) ( Int size, Int reg )
|
||||
return NULL; /*notreached*/
|
||||
}
|
||||
|
||||
Char* VG_(name_of_seg_reg) ( Int sreg )
|
||||
const Char* VG_(name_of_seg_reg) ( Int sreg )
|
||||
{
|
||||
switch (sreg) {
|
||||
case R_ES: return "%es";
|
||||
@ -138,23 +138,23 @@ Char* VG_(name_of_seg_reg) ( Int sreg )
|
||||
}
|
||||
}
|
||||
|
||||
Char* VG_(name_of_mmx_reg) ( Int mmxreg )
|
||||
const Char* VG_(name_of_mmx_reg) ( Int mmxreg )
|
||||
{
|
||||
static Char* mmx_names[8]
|
||||
static const Char* mmx_names[8]
|
||||
= { "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7" };
|
||||
if (mmxreg < 0 || mmxreg > 7) VG_(core_panic)("name_of_mmx_reg");
|
||||
return mmx_names[mmxreg];
|
||||
}
|
||||
|
||||
Char* VG_(name_of_xmm_reg) ( Int xmmreg )
|
||||
const Char* VG_(name_of_xmm_reg) ( Int xmmreg )
|
||||
{
|
||||
static Char* xmm_names[8]
|
||||
static const Char* xmm_names[8]
|
||||
= { "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7" };
|
||||
if (xmmreg < 0 || xmmreg > 7) VG_(core_panic)("name_of_xmm_reg");
|
||||
return xmm_names[xmmreg];
|
||||
}
|
||||
|
||||
Char* VG_(name_of_mmx_gran) ( UChar gran )
|
||||
const Char* VG_(name_of_mmx_gran) ( UChar gran )
|
||||
{
|
||||
switch (gran) {
|
||||
case 0: return "b";
|
||||
@ -165,7 +165,7 @@ Char* VG_(name_of_mmx_gran) ( UChar gran )
|
||||
}
|
||||
}
|
||||
|
||||
Char VG_(name_of_int_size) ( Int size )
|
||||
const Char VG_(name_of_int_size) ( Int size )
|
||||
{
|
||||
switch (size) {
|
||||
case 4: return 'l';
|
||||
@ -3698,6 +3698,19 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd )
|
||||
goto decode_success;
|
||||
}
|
||||
|
||||
/* SFENCE -- flush all pending store operations to memory */
|
||||
if (insn[0] == 0x0F && insn[1] == 0xAE
|
||||
&& (gregOfRM(insn[2]) == 7)) {
|
||||
vg_assert(sz == 4);
|
||||
eip += 3;
|
||||
uInstr2(cb, SSE3, 0, /* ignore sz for internal ops */
|
||||
Lit16, (((UShort)0x0F) << 8) | (UShort)0xAE,
|
||||
Lit16, (UShort)insn[2] );
|
||||
if (dis)
|
||||
VG_(printf)("sfence\n");
|
||||
goto decode_success;
|
||||
}
|
||||
|
||||
/* CVTTSD2SI (0xF2,0x0F,0x2C) -- convert a double-precision float
|
||||
value in memory or xmm reg to int and put it in an ireg.
|
||||
Truncate. */
|
||||
@ -3838,6 +3851,15 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd )
|
||||
goto decode_success;
|
||||
}
|
||||
|
||||
/* PSHUFW */
|
||||
if (sz == 4
|
||||
&& insn[0] == 0x0F && insn[1] == 0x70) {
|
||||
eip = dis_SSE2_reg_or_mem_Imm8 ( cb, sorb, eip+2, 16,
|
||||
"pshufw",
|
||||
insn[0], insn[1] );
|
||||
goto decode_success;
|
||||
}
|
||||
|
||||
/* SHUFPS */
|
||||
if (insn[0] == 0x0F && insn[1] == 0xC6) {
|
||||
vg_assert(sz == 4);
|
||||
@ -4075,7 +4097,15 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd )
|
||||
0x66, insn[0], insn[1] );
|
||||
goto decode_success;
|
||||
}
|
||||
|
||||
/* 0xE0: PAVGB(src)xmmreg-or-mem, (dst)xmmreg, size 4 */
|
||||
if (sz == 4
|
||||
&& insn[0] == 0x0F
|
||||
&& insn[1] == 0xE0 ) {
|
||||
eip = dis_SSE2_reg_or_mem ( cb, sorb, eip+2, 16, "pavg{b,w}",
|
||||
insn[0], insn[1] );
|
||||
goto decode_success;
|
||||
}
|
||||
|
||||
/* 0x60: PUNPCKLBW (src)xmmreg-or-mem, (dst)xmmreg */
|
||||
/* 0x61: PUNPCKLWD (src)xmmreg-or-mem, (dst)xmmreg */
|
||||
/* 0x62: PUNPCKLDQ (src)xmmreg-or-mem, (dst)xmmreg */
|
||||
@ -4280,10 +4310,11 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd )
|
||||
goto decode_success;
|
||||
}
|
||||
|
||||
/* COMISS (src)xmmreg-or-mem, (dst)xmmreg */
|
||||
/* (U)COMISS (src)xmmreg-or-mem, (dst)xmmreg */
|
||||
if (sz == 4
|
||||
&& insn[0] == 0x0F && insn[1] == 0x2F) {
|
||||
eip = dis_SSE2_reg_or_mem ( cb, sorb, eip+2, 4, "comiss",
|
||||
&& insn[0] == 0x0F
|
||||
&& ( insn[1] == 0x2E || insn[ 1 ] == 0x2F )) {
|
||||
eip = dis_SSE2_reg_or_mem ( cb, sorb, eip+2, 4, "{u}comiss",
|
||||
insn[0], insn[1] );
|
||||
vg_assert(LAST_UINSTR(cb).opcode == SSE2a_MemRd
|
||||
|| LAST_UINSTR(cb).opcode == SSE3);
|
||||
@ -4558,6 +4589,29 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd )
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xC8: /* ENTER */
|
||||
d32 = getUDisp16(eip); eip += 2;
|
||||
abyte = getUChar(eip); eip++;
|
||||
|
||||
vg_assert(sz == 4);
|
||||
vg_assert(abyte == 0);
|
||||
|
||||
t1 = newTemp(cb); t2 = newTemp(cb);
|
||||
uInstr2(cb, GET, sz, ArchReg, R_EBP, TempReg, t1);
|
||||
uInstr2(cb, GET, 4, ArchReg, R_ESP, TempReg, t2);
|
||||
uInstr2(cb, SUB, 4, Literal, 0, TempReg, t2);
|
||||
uLiteral(cb, sz);
|
||||
uInstr2(cb, PUT, 4, TempReg, t2, ArchReg, R_ESP);
|
||||
uInstr2(cb, STORE, 4, TempReg, t1, TempReg, t2);
|
||||
uInstr2(cb, PUT, 4, TempReg, t2, ArchReg, R_EBP);
|
||||
if (d32) {
|
||||
uInstr2(cb, SUB, 4, Literal, 0, TempReg, t2);
|
||||
uLiteral(cb, d32);
|
||||
uInstr2(cb, PUT, 4, TempReg, t2, ArchReg, R_ESP);
|
||||
}
|
||||
if (dis) VG_(printf)("enter 0x%x, 0x%x", d32, abyte);
|
||||
break;
|
||||
|
||||
case 0xC9: /* LEAVE */
|
||||
t1 = newTemp(cb); t2 = newTemp(cb);
|
||||
uInstr2(cb, GET, 4, ArchReg, R_EBP, TempReg, t1);
|
||||
@ -5236,6 +5290,28 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd )
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x1F: /* POP %DS */
|
||||
case 0x07: /* POP %ES */
|
||||
{
|
||||
Int sreg = INVALID_TEMPREG;
|
||||
vg_assert(sz == 4);
|
||||
switch(opc) {
|
||||
case 0x1F: sreg = R_DS; break;
|
||||
case 0x07: sreg = R_ES; break;
|
||||
}
|
||||
|
||||
t1 = newTemp(cb); t2 = newTemp(cb);
|
||||
uInstr2(cb, GET, 4, ArchReg, R_ESP, TempReg, t2);
|
||||
uInstr2(cb, LOAD, 2, TempReg, t2, TempReg, t1);
|
||||
uInstr2(cb, ADD, 4, Literal, 0, TempReg, t2);
|
||||
uLiteral(cb, sz);
|
||||
uInstr2(cb, PUT, 4, TempReg, t2, ArchReg, R_ESP);
|
||||
uInstr2(cb, PUTSEG, 2, TempReg, t1, ArchRegS, sreg);
|
||||
if (dis)
|
||||
VG_(printf)("pop %s\n", VG_(name_of_seg_reg)(sreg));
|
||||
break;
|
||||
}
|
||||
|
||||
/* ------------------------ PUSH ----------------------- */
|
||||
|
||||
case 0x50: /* PUSH eAX */
|
||||
@ -5340,6 +5416,28 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd )
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x06: /* PUSH %ES */
|
||||
case 0x1E: /* PUSH %DS */
|
||||
{
|
||||
Int sreg = INVALID_TEMPREG;
|
||||
switch(opc) {
|
||||
case 0x06: sreg = R_ES; break;
|
||||
case 0x1E: sreg = R_DS; break;
|
||||
}
|
||||
|
||||
vg_assert(sz == 4);
|
||||
t1 = newTemp(cb); t2 = newTemp(cb);
|
||||
uInstr2(cb, GETSEG, 2, ArchRegS, sreg, TempReg, t1);
|
||||
uInstr2(cb, GET, 4, ArchReg, R_ESP, TempReg, t2);
|
||||
uInstr2(cb, SUB, 4, Literal, 0, TempReg, t2);
|
||||
uLiteral(cb, 4);
|
||||
uInstr2(cb, PUT, 4, TempReg, t2, ArchReg, R_ESP);
|
||||
uInstr2(cb, STORE, 2, TempReg, t1, TempReg, t2);
|
||||
if(dis)
|
||||
VG_(printf)("push %s\n", VG_(name_of_seg_reg)(sreg));
|
||||
break;
|
||||
}
|
||||
|
||||
/* ------------------------ SCAS et al ----------------- */
|
||||
|
||||
case 0xA4: /* MOVSb, no REP prefix */
|
||||
@ -6099,6 +6197,7 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd )
|
||||
break;
|
||||
|
||||
case 0x7F: /* MOVQ (src)mmxreg, (dst)mmxreg-or-mem */
|
||||
case 0xE7: /* MOVNTQ (src)mmxreg, (dst)mmxreg-or-mem */
|
||||
vg_assert(sz == 4);
|
||||
modrm = getUChar(eip);
|
||||
if (epartIsReg(modrm)) {
|
||||
@ -6113,7 +6212,7 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd )
|
||||
(((UShort)(opc)) << 8) | ((UShort)modrm),
|
||||
TempReg, tmpa);
|
||||
if (dis)
|
||||
VG_(printf)("movq %s, %s\n",
|
||||
VG_(printf)("mov(nt)q %s, %s\n",
|
||||
nameMMXReg(gregOfRM(modrm)),
|
||||
dis_buf);
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
This file is part of Valgrind, an extensible x86 protected-mode
|
||||
emulator for monitoring program execution on x86-Unixes.
|
||||
|
||||
Copyright (C) 2000-2003 Julian Seward
|
||||
Copyright (C) 2000-2003 Julian Seward
|
||||
jseward@acm.org
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
@ -42,7 +42,7 @@
|
||||
/*=== Build options and table sizes. ===*/
|
||||
/*====================================================================*/
|
||||
|
||||
/* You should be able to change these options or sizes, recompile, and
|
||||
/* You should be able to change these options or sizes, recompile, and
|
||||
still have a working system. */
|
||||
|
||||
/* The maximum number of pthreads that we support. This is
|
||||
@ -58,7 +58,7 @@
|
||||
|
||||
/* Total number of integer registers available for allocation -- all of
|
||||
them except %esp, %ebp. %ebp permanently points at VG_(baseBlock).
|
||||
|
||||
|
||||
If you increase this you'll have to also change at least these:
|
||||
- VG_(rank_to_realreg)()
|
||||
- VG_(realreg_to_rank)()
|
||||
@ -68,7 +68,7 @@
|
||||
|
||||
You can decrease it, and performance will drop because more spills will
|
||||
occur. If you decrease it too much, everything will fall over.
|
||||
|
||||
|
||||
Do not change this unless you really know what you are doing! */
|
||||
#define VG_MAX_REALREGS 6
|
||||
|
||||
@ -276,26 +276,26 @@ extern Bool VG_(within_m_state_static_OR_threads)(Addr a);
|
||||
#define VG_INVALID_THREADID ((ThreadId)(0))
|
||||
|
||||
/* ThreadIds are simply indices into the VG_(threads)[] array. */
|
||||
typedef
|
||||
UInt
|
||||
typedef
|
||||
UInt
|
||||
ThreadId;
|
||||
|
||||
/* When looking for the current ThreadId, this is the safe option and
|
||||
probably the one you want.
|
||||
|
||||
|
||||
Details: Use this one from non-generated code, eg. from functions called
|
||||
on events like 'new_mem_heap'. In such a case, the "current" thread is
|
||||
temporarily suspended as Valgrind's dispatcher is running. This function
|
||||
is also suitable to be called from generated code (ie. from UCode, or a C
|
||||
function called directly from UCode).
|
||||
|
||||
|
||||
If you use VG_(get_current_tid)() from non-generated code, it will return
|
||||
0 signifying the invalid thread, which is probably not what you want. */
|
||||
extern ThreadId VG_(get_current_or_recent_tid) ( void );
|
||||
|
||||
/* When looking for the current ThreadId, only use this one if you know what
|
||||
you are doing.
|
||||
|
||||
|
||||
Details: Use this one from generated code, eg. from C functions called
|
||||
from UCode. (VG_(get_current_or_recent_tid)() is also suitable in that
|
||||
case.) If you use this function from non-generated code, it will return
|
||||
@ -328,12 +328,12 @@ extern ThreadId VG_(first_matching_thread_stack)
|
||||
*
|
||||
* Note that they all output to the file descriptor given by the
|
||||
* --logfile-fd=N argument, which defaults to 2 (stderr). Hence no
|
||||
* need for VG_(fprintf)().
|
||||
* need for VG_(fprintf)().
|
||||
*/
|
||||
extern UInt VG_(printf) ( const char *format, ... );
|
||||
/* too noisy ... __attribute__ ((format (printf, 1, 2))) ; */
|
||||
extern UInt VG_(sprintf) ( Char* buf, Char *format, ... );
|
||||
extern UInt VG_(vprintf) ( void(*send)(Char),
|
||||
extern UInt VG_(vprintf) ( void(*send)(Char),
|
||||
const Char *format, va_list vargs );
|
||||
|
||||
extern Int VG_(rename) ( Char* old_name, Char* new_name );
|
||||
@ -397,7 +397,7 @@ extern Int VG_(memcmp) ( const void* s1, const void* s2, Int n );
|
||||
extern Int VG_(strcmp_ws) ( const Char* s1, const Char* s2 );
|
||||
extern Int VG_(strncmp_ws) ( const Char* s1, const Char* s2, Int nmax );
|
||||
|
||||
/* Like strncpy(), but if 'src' is longer than 'ndest' inserts a '\0' as the
|
||||
/* Like strncpy(), but if 'src' is longer than 'ndest' inserts a '\0' as the
|
||||
last character. */
|
||||
extern void VG_(strncpy_safely) ( Char* dest, const Char* src, Int ndest );
|
||||
|
||||
@ -441,13 +441,13 @@ extern Char* VG_(getcwd) ( Char* buf, Int size );
|
||||
__PRETTY_FUNCTION__), 0)))
|
||||
|
||||
__attribute__ ((__noreturn__))
|
||||
extern void VG_(skin_assert_fail) ( const Char* expr, const Char* file,
|
||||
extern void VG_(skin_assert_fail) ( const Char* expr, const Char* file,
|
||||
Int line, const Char* fn );
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* system/mman.h */
|
||||
extern void* VG_(mmap)( void* start, UInt length,
|
||||
extern void* VG_(mmap)( void* start, UInt length,
|
||||
UInt prot, UInt flags, UInt fd, UInt offset );
|
||||
extern Int VG_(munmap)( void* start, Int length );
|
||||
|
||||
@ -456,8 +456,8 @@ extern void* VG_(get_memory_from_mmap) ( Int nBytes, Char* who );
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* signal.h.
|
||||
|
||||
/* signal.h.
|
||||
|
||||
Note that these use the vk_ (kernel) structure
|
||||
definitions, which are different in places from those that glibc
|
||||
defines -- hence the 'k' prefix. Since we're operating right at the
|
||||
@ -478,10 +478,10 @@ extern void VG_(ksigaddset_from_set) ( vki_ksigset_t* dst, vki_ksigset_t* src );
|
||||
extern void VG_(ksigdelset_from_set) ( vki_ksigset_t* dst, vki_ksigset_t* src );
|
||||
|
||||
/* --- Mess with the kernel's sig state --- */
|
||||
extern Int VG_(ksigprocmask) ( Int how, const vki_ksigset_t* set,
|
||||
extern Int VG_(ksigprocmask) ( Int how, const vki_ksigset_t* set,
|
||||
vki_ksigset_t* oldset );
|
||||
extern Int VG_(ksigaction) ( Int signum,
|
||||
const vki_ksigaction* act,
|
||||
extern Int VG_(ksigaction) ( Int signum,
|
||||
const vki_ksigaction* act,
|
||||
vki_ksigaction* oldact );
|
||||
|
||||
extern Int VG_(ksignal) ( Int signum, void (*sighandler)(Int) );
|
||||
@ -538,7 +538,7 @@ typedef
|
||||
WIDEN, /* Signed or unsigned widening */
|
||||
|
||||
/* Conditional or unconditional jump */
|
||||
JMP,
|
||||
JMP,
|
||||
|
||||
/* FPU ops */
|
||||
FPU, /* Doesn't touch memory */
|
||||
@ -564,7 +564,7 @@ typedef
|
||||
/* 2 bytes, reads/writes mem. Insns of the form
|
||||
bbbbbbbb:mod mmxreg r/m.
|
||||
Held in val1[15:0], and mod and rm are to be replaced
|
||||
at codegen time by a reference to the Temp/RealReg holding
|
||||
at codegen time by a reference to the Temp/RealReg holding
|
||||
the address. Arg2 holds this Temp/Real Reg.
|
||||
Transfer is always at size 8.
|
||||
*/
|
||||
@ -696,9 +696,9 @@ typedef
|
||||
#if 0
|
||||
/* 5 bytes, reads/writes mem. Insns of the form
|
||||
bbbbbbbb:bbbbbbbb:bbbbbbbb:mod mmxreg r/m:bbbbbbbb
|
||||
Held in val1[15:0], val2[15:0], lit32[7:0].
|
||||
mod and rm are to be replaced at codegen time by a reference
|
||||
to the Temp/RealReg holding the address. Arg3 holds this
|
||||
Held in val1[15:0], val2[15:0], lit32[7:0].
|
||||
mod and rm are to be replaced at codegen time by a reference
|
||||
to the Temp/RealReg holding the address. Arg3 holds this
|
||||
Temp/Real Reg. Transfer is always at size 16. */
|
||||
SSE3a1_MemRd,
|
||||
SSE3a1_MemWr,
|
||||
@ -732,7 +732,7 @@ typedef
|
||||
|
||||
Seven possibilities: 'arg[123]' show where args go, 'ret' shows
|
||||
where return value goes (if present).
|
||||
|
||||
|
||||
CCALL(-, -, - ) void f(void)
|
||||
CCALL(arg1, -, - ) void f(UInt arg1)
|
||||
CCALL(arg1, arg2, - ) void f(UInt arg1, UInt arg2)
|
||||
@ -745,8 +745,8 @@ typedef
|
||||
/* This opcode makes it easy for skins that extend UCode to do this to
|
||||
avoid opcode overlap:
|
||||
|
||||
enum { EU_OP1 = DUMMY_FINAL_UOPCODE + 1, ... }
|
||||
|
||||
enum { EU_OP1 = DUMMY_FINAL_UOPCODE + 1, ... }
|
||||
|
||||
WARNING: Do not add new opcodes after this one! They can be added
|
||||
before, though. */
|
||||
DUMMY_FINAL_UOPCODE
|
||||
@ -774,7 +774,7 @@ typedef
|
||||
CondLE = 14, /* less or equal */
|
||||
CondNLE = 15, /* not less or equal */
|
||||
CondAlways = 16 /* Jump always */
|
||||
}
|
||||
}
|
||||
Condcode;
|
||||
|
||||
|
||||
@ -793,7 +793,7 @@ typedef
|
||||
/* Flags. User-level code can only read/write O(verflow), S(ign),
|
||||
Z(ero), A(ux-carry), C(arry), P(arity), and may also write
|
||||
D(irection). That's a total of 7 flags. A FlagSet is a bitset,
|
||||
thusly:
|
||||
thusly:
|
||||
76543210
|
||||
DOSZACP
|
||||
and bit 7 must always be zero since it is unused.
|
||||
@ -882,7 +882,7 @@ typedef
|
||||
Bool signed_widen:1; /* signed or unsigned WIDEN ? */
|
||||
JmpKind jmpkind:3; /* additional properties of unconditional JMP */
|
||||
|
||||
/* Additional properties for UInstrs that call C functions:
|
||||
/* Additional properties for UInstrs that call C functions:
|
||||
- CCALL
|
||||
- PUT (when %ESP is the target)
|
||||
- possibly skin-specific UInstrs
|
||||
@ -897,12 +897,12 @@ typedef
|
||||
to use this information requires converting between register ranks
|
||||
and the Intel register numbers, using VG_(realreg_to_rank)()
|
||||
and/or VG_(rank_to_realreg)() */
|
||||
RRegSet regs_live_after:VG_MAX_REALREGS;
|
||||
RRegSet regs_live_after:VG_MAX_REALREGS;
|
||||
}
|
||||
UInstr;
|
||||
|
||||
|
||||
typedef
|
||||
typedef
|
||||
struct _UCodeBlock
|
||||
UCodeBlock;
|
||||
|
||||
@ -911,7 +911,7 @@ extern Int VG_(get_num_temps) (UCodeBlock* cb);
|
||||
|
||||
extern UInstr* VG_(get_instr) (UCodeBlock* cb, Int i);
|
||||
extern UInstr* VG_(get_last_instr) (UCodeBlock* cb);
|
||||
|
||||
|
||||
|
||||
/*====================================================================*/
|
||||
/*=== Instrumenting UCode ===*/
|
||||
@ -965,7 +965,7 @@ extern void VG_(new_UInstr3) ( UCodeBlock* cb, Opcode opcode, Int sz,
|
||||
Tag tag2, UInt val2,
|
||||
Tag tag3, UInt val3 );
|
||||
|
||||
/* Set read/write/undefined flags. Undefined flags are treaten as written,
|
||||
/* Set read/write/undefined flags. Undefined flags are treaten as written,
|
||||
but it's worth keeping them logically distinct. */
|
||||
extern void VG_(set_flag_fields) ( UCodeBlock* cb, FlagSet fr, FlagSet fw,
|
||||
FlagSet fu);
|
||||
@ -1016,7 +1016,7 @@ extern UCodeBlock* VG_(setup_UCodeBlock) ( UCodeBlock* cb );
|
||||
extern void VG_(free_UCodeBlock) ( UCodeBlock* cb );
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* UCode pretty/ugly printing. Probably only useful to call from a skin
|
||||
/* UCode pretty/ugly printing. Probably only useful to call from a skin
|
||||
if VG_(needs).extended_UCode == True. */
|
||||
|
||||
/* When True, all generated code is/should be printed. */
|
||||
@ -1029,7 +1029,7 @@ extern void VG_(pp_UInstr_regs) ( Int instrNo, UInstr* u );
|
||||
extern void VG_(up_UInstr) ( Int instrNo, UInstr* u );
|
||||
extern Char* VG_(name_UOpcode) ( Bool upper, Opcode opc );
|
||||
extern Char* VG_(name_UCondcode) ( Condcode cond );
|
||||
extern void VG_(pp_UOperand) ( UInstr* u, Int operandNo,
|
||||
extern void VG_(pp_UOperand) ( UInstr* u, Int operandNo,
|
||||
Int sz, Bool parens );
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
@ -1123,11 +1123,11 @@ extern Int VGOFF_(helper_DAA);
|
||||
#define R_GS 5
|
||||
|
||||
/* For pretty printing x86 code */
|
||||
extern Char* VG_(name_of_mmx_gran) ( UChar gran );
|
||||
extern Char* VG_(name_of_mmx_reg) ( Int mmxreg );
|
||||
extern Char* VG_(name_of_seg_reg) ( Int sreg );
|
||||
extern Char* VG_(name_of_int_reg) ( Int size, Int reg );
|
||||
extern Char VG_(name_of_int_size) ( Int size );
|
||||
extern const Char* VG_(name_of_mmx_gran) ( UChar gran );
|
||||
extern const Char* VG_(name_of_mmx_reg) ( Int mmxreg );
|
||||
extern const Char* VG_(name_of_seg_reg) ( Int sreg );
|
||||
extern const Char* VG_(name_of_int_reg) ( Int size, Int reg );
|
||||
extern const Char VG_(name_of_int_size) ( Int size );
|
||||
|
||||
/* Shorter macros for convenience */
|
||||
#define nameIReg VG_(name_of_int_reg)
|
||||
@ -1157,7 +1157,7 @@ extern Int VG_(realreg_to_rank) ( Int realreg );
|
||||
extern Int VG_(rank_to_realreg) ( Int rank );
|
||||
|
||||
/* Call a subroutine. Does no argument passing, stack manipulations, etc. */
|
||||
extern void VG_(synth_call) ( Bool ensure_shortform, Int word_offset,
|
||||
extern void VG_(synth_call) ( Bool ensure_shortform, Int word_offset,
|
||||
Bool upd_cc, FlagSet use_flags, FlagSet set_flags );
|
||||
|
||||
/* For calling C functions -- saves caller save regs, pushes args, calls,
|
||||
@ -1169,7 +1169,7 @@ extern void VG_(synth_call) ( Bool ensure_shortform, Int word_offset,
|
||||
by some other x86 assembly code; this will invalidate the results of
|
||||
vg_realreg_liveness_analysis() and everything will fall over. */
|
||||
extern void VG_(synth_ccall) ( Addr fn, Int argc, Int regparms_n, UInt argv[],
|
||||
Tag tagv[], Int ret_reg,
|
||||
Tag tagv[], Int ret_reg,
|
||||
RRegSet regs_live_before,
|
||||
RRegSet regs_live_after );
|
||||
|
||||
@ -1233,17 +1233,17 @@ extern void VG_(emit_jcondshort_target)( Bool simd_cc, Condcode cond, Int *tgt )
|
||||
|
||||
/* Generic resolution type used in a few different ways, such as deciding
|
||||
how closely to compare two errors for equality. */
|
||||
typedef
|
||||
enum { Vg_LowRes, Vg_MedRes, Vg_HighRes }
|
||||
typedef
|
||||
enum { Vg_LowRes, Vg_MedRes, Vg_HighRes }
|
||||
VgRes;
|
||||
|
||||
typedef
|
||||
struct _ExeContext
|
||||
ExeContext;
|
||||
|
||||
/* Compare two ExeContexts. Number of callers considered depends on `res':
|
||||
Vg_LowRes: 2
|
||||
Vg_MedRes: 4
|
||||
/* Compare two ExeContexts. Number of callers considered depends on `res':
|
||||
Vg_LowRes: 2
|
||||
Vg_MedRes: 4
|
||||
Vg_HighRes: all */
|
||||
extern Bool VG_(eq_ExeContext) ( VgRes res,
|
||||
ExeContext* e1, ExeContext* e2 );
|
||||
@ -1255,10 +1255,10 @@ extern void VG_(pp_ExeContext) ( ExeContext* );
|
||||
ExeContexts to see if we already have it, and if not, allocate a
|
||||
new one. Either way, return a pointer to the context. Context size
|
||||
controlled by --num-callers option.
|
||||
|
||||
|
||||
If called from generated code, use VG_(get_current_tid)() to get the
|
||||
current ThreadId. If called from non-generated code, the current
|
||||
ThreadId should be passed in by the core.
|
||||
ThreadId should be passed in by the core.
|
||||
*/
|
||||
extern ExeContext* VG_(get_ExeContext) ( ThreadId tid );
|
||||
|
||||
@ -1269,7 +1269,7 @@ extern Addr VG_(get_EIP_from_ExeContext) ( ExeContext* e, UInt n );
|
||||
|
||||
/* Just grab the client's EIP, as a much smaller and cheaper
|
||||
indication of where they are. Use is basically same as for
|
||||
VG_(get_ExeContext)() above.
|
||||
VG_(get_ExeContext)() above.
|
||||
*/
|
||||
extern Addr VG_(get_EIP)( ThreadId tid );
|
||||
|
||||
@ -1289,9 +1289,9 @@ extern void VG_(mini_stack_dump) ( Addr eips[], UInt n_eips );
|
||||
/*====================================================================*/
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Suppressions describe errors which we want to suppress, ie, not
|
||||
/* Suppressions describe errors which we want to suppress, ie, not
|
||||
show the user, usually because it is caused by a problem in a library
|
||||
which we can't fix, replace or work around. Suppressions are read from
|
||||
which we can't fix, replace or work around. Suppressions are read from
|
||||
a file at startup time. This gives flexibility so that new
|
||||
suppressions can be added to the file as and when needed.
|
||||
*/
|
||||
@ -1351,23 +1351,23 @@ void* VG_(get_error_extra) ( Error* err );
|
||||
|
||||
/* Call this when an error occurs. It will be recorded if it hasn't been
|
||||
seen before. If it has, the existing error record will have its count
|
||||
incremented.
|
||||
|
||||
incremented.
|
||||
|
||||
'tid' can be found as for VG_(get_ExeContext)(). The `extra' field can
|
||||
be stack-allocated; it will be copied by the core if needed (but it
|
||||
won't be copied if it's NULL).
|
||||
|
||||
If no 'a', 's' or 'extra' of interest needs to be recorded, just use
|
||||
NULL for them. */
|
||||
extern void VG_(maybe_record_error) ( ThreadId tid, ErrorKind ekind,
|
||||
extern void VG_(maybe_record_error) ( ThreadId tid, ErrorKind ekind,
|
||||
Addr a, Char* s, void* extra );
|
||||
|
||||
/* Similar to VG_(maybe_record_error)(), except this one doesn't record the
|
||||
error -- useful for errors that can only happen once. The errors can be
|
||||
suppressed, though. Return value is True if it was suppressed.
|
||||
`print_error' dictates whether to print the error, which is a bit of a
|
||||
`print_error' dictates whether to print the error, which is a bit of a
|
||||
hack that's useful sometimes if you just want to know if the error would
|
||||
be suppressed without possibly printing it. `count_error' dictates
|
||||
be suppressed without possibly printing it. `count_error' dictates
|
||||
whether to add the error in the error total count (another mild hack). */
|
||||
extern Bool VG_(unique_error) ( ThreadId tid, ErrorKind ekind,
|
||||
Addr a, Char* s, void* extra,
|
||||
@ -1375,7 +1375,7 @@ extern Bool VG_(unique_error) ( ThreadId tid, ErrorKind ekind,
|
||||
Bool allow_GDB_attach, Bool count_error );
|
||||
|
||||
/* Gets a non-blank, non-comment line of at most nBuf chars from fd.
|
||||
Skips leading spaces on the line. Returns True if EOF was hit instead.
|
||||
Skips leading spaces on the line. Returns True if EOF was hit instead.
|
||||
Useful for reading in extra skin-specific suppression lines. */
|
||||
extern Bool VG_(get_line) ( Int fd, Char* buf, Int nBuf );
|
||||
|
||||
@ -1393,12 +1393,12 @@ extern Bool VG_(get_line) ( Int fd, Char* buf, Int nBuf );
|
||||
extern Bool VG_(get_filename) ( Addr a, Char* filename, Int n_filename );
|
||||
extern Bool VG_(get_fnname) ( Addr a, Char* fnname, Int n_fnname );
|
||||
extern Bool VG_(get_linenum) ( Addr a, UInt* linenum );
|
||||
extern Bool VG_(get_fnname_w_offset)
|
||||
extern Bool VG_(get_fnname_w_offset)
|
||||
( Addr a, Char* fnname, Int n_fnname );
|
||||
|
||||
/* This one is more efficient if getting both filename and line number,
|
||||
because the two lookups are done together. */
|
||||
extern Bool VG_(get_filename_linenum)
|
||||
extern Bool VG_(get_filename_linenum)
|
||||
( Addr a, Char* filename, Int n_filename,
|
||||
UInt* linenum );
|
||||
|
||||
@ -1476,7 +1476,7 @@ extern VgHashTable VG_(HT_construct) ( void );
|
||||
/* Add a node to the table. */
|
||||
extern void VG_(HT_add_node) ( VgHashTable t, VgHashNode* node );
|
||||
|
||||
/* Looks up a node in the hash table. Also returns the address of the
|
||||
/* Looks up a node in the hash table. Also returns the address of the
|
||||
previous node's `next' pointer which allows it to be removed from the
|
||||
list later without having to look it up again. */
|
||||
extern VgHashNode* VG_(HT_get_node) ( VgHashTable t, UInt key,
|
||||
@ -1484,7 +1484,7 @@ extern VgHashNode* VG_(HT_get_node) ( VgHashTable t, UInt key,
|
||||
|
||||
/* Allocates a sorted array of pointers to all the shadow chunks of malloc'd
|
||||
blocks. */
|
||||
extern VgHashNode** VG_(HT_to_sorted_array) ( VgHashTable t,
|
||||
extern VgHashNode** VG_(HT_to_sorted_array) ( VgHashTable t,
|
||||
/*OUT*/ UInt* n_shadows );
|
||||
|
||||
/* Returns first node that matches predicate `p', or NULL if none do.
|
||||
@ -1510,7 +1510,7 @@ extern void VG_(HT_destruct) ( VgHashTable t );
|
||||
/* This one lets you override the shadow of the return value register for a
|
||||
syscall. Call it from SK_(post_syscall)() (not SK_(pre_syscall)()!) to
|
||||
override the default shadow register value. */
|
||||
extern void VG_(set_return_from_syscall_shadow) ( ThreadId tid,
|
||||
extern void VG_(set_return_from_syscall_shadow) ( ThreadId tid,
|
||||
UInt ret_shadow );
|
||||
|
||||
/* This can be called from SK_(fini)() to find the shadow of the argument
|
||||
@ -1527,21 +1527,21 @@ extern UInt VG_(get_exit_status_shadow) ( void );
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* General stuff, for replacing any functions */
|
||||
|
||||
/* Is the client running on the simulated CPU or the real one?
|
||||
/* Is the client running on the simulated CPU or the real one?
|
||||
|
||||
Nb: If it is, and you want to call a function to be run on the real CPU,
|
||||
use one of the VALGRIND_NON_SIMD_CALL[123] macros in valgrind.h to call it.
|
||||
|
||||
Nb: don't forget the function parentheses when using this in a
|
||||
Nb: don't forget the function parentheses when using this in a
|
||||
condition... write this:
|
||||
|
||||
if (VG_(is_running_on_simd_CPU)()) { ... } // calls function
|
||||
|
||||
not this:
|
||||
|
||||
|
||||
if (VG_(is_running_on_simd_CPU)) { ... } // address of var!
|
||||
*/
|
||||
extern Bool VG_(is_running_on_simd_CPU) ( void );
|
||||
extern Bool VG_(is_running_on_simd_CPU) ( void );
|
||||
|
||||
|
||||
/*====================================================================*/
|
||||
@ -1554,9 +1554,9 @@ extern Bool VG_(is_running_on_simd_CPU) ( void );
|
||||
|
||||
/* Arena size for valgrind's own malloc(); default value is 0, but can
|
||||
be overridden by skin -- but must be done so *statically*, eg:
|
||||
|
||||
|
||||
Int VG_(vg_malloc_redzone_szB) = 4;
|
||||
|
||||
|
||||
It can't be done from a function like SK_(pre_clo_init)(). So it can't,
|
||||
for example, be controlled with a command line option, unfortunately. */
|
||||
extern UInt VG_(vg_malloc_redzone_szB);
|
||||
@ -1574,14 +1574,14 @@ extern void SK_(__builtin_vec_delete) ( void* p );
|
||||
extern void* SK_(realloc) ( void* p, Int size );
|
||||
|
||||
/* Can be called from SK_(malloc) et al to do the actual alloc/freeing. */
|
||||
extern void* VG_(cli_malloc) ( UInt align, Int nbytes );
|
||||
extern void* VG_(cli_malloc) ( UInt align, Int nbytes );
|
||||
extern void VG_(cli_free) ( void* p );
|
||||
|
||||
/* Check if an address is within a range, allowing for redzones at edges */
|
||||
extern Bool VG_(addr_is_in_block)( Addr a, Addr start, UInt size );
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Some options that can be used by a skin if malloc() et al are replaced.
|
||||
/* Some options that can be used by a skin if malloc() et al are replaced.
|
||||
The skin should call the functions in the appropriate places to give
|
||||
control over these aspects of Valgrind's version of malloc(). */
|
||||
|
||||
@ -1623,7 +1623,7 @@ extern void VG_(details_copyright_author) ( Char* copyright_author );
|
||||
|
||||
/* Average size of a translation, in bytes, so that the translation
|
||||
storage machinery can allocate memory appropriately. Not critical,
|
||||
setting is optional. */
|
||||
setting is optional. */
|
||||
extern void VG_(details_avg_translation_sizeB) ( UInt size );
|
||||
|
||||
/* String printed if an `sk_assert' assertion fails or VG_(skin_panic)
|
||||
@ -1643,7 +1643,7 @@ extern void VG_(needs_libc_freeres) ( void );
|
||||
- pthread API errors (many; eg. unlocking a non-locked mutex)
|
||||
- invalid file descriptors to blocking syscalls read() and write()
|
||||
- bad signal numbers passed to sigaction()
|
||||
- attempt to install signal handler for SIGKILL or SIGSTOP */
|
||||
- attempt to install signal handler for SIGKILL or SIGSTOP */
|
||||
extern void VG_(needs_core_errors) ( void );
|
||||
|
||||
/* Booleans that indicate extra operations are defined; if these are True,
|
||||
@ -1687,7 +1687,7 @@ extern void VG_(needs_data_syms) ( void );
|
||||
|
||||
/* Part of the core from which this call was made. Useful for determining
|
||||
what kind of error message should be emitted. */
|
||||
typedef
|
||||
typedef
|
||||
enum { Vg_CorePThread, Vg_CoreSignal, Vg_CoreSysCall, Vg_CoreTranslate }
|
||||
CorePart;
|
||||
|
||||
@ -1695,8 +1695,8 @@ typedef
|
||||
|
||||
/* Events happening in core to track. To be notified, pass a callback
|
||||
function to the appropriate function. To ignore an event, don't do
|
||||
anything (default is for events to be ignored).
|
||||
|
||||
anything (default is for events to be ignored).
|
||||
|
||||
Note that most events aren't passed a ThreadId. To find out the ThreadId
|
||||
of the affected thread, use VG_(get_current_or_recent_tid)(). For the
|
||||
ones passed a ThreadId, use that instead, since
|
||||
@ -1709,7 +1709,7 @@ typedef
|
||||
malloc() et al. See above how to do this.) */
|
||||
|
||||
/* These ones occur at startup, upon some signals, and upon some syscalls */
|
||||
EV VG_(track_new_mem_startup) ( void (*f)(Addr a, UInt len,
|
||||
EV VG_(track_new_mem_startup) ( void (*f)(Addr a, UInt len,
|
||||
Bool rr, Bool ww, Bool xx) );
|
||||
EV VG_(track_new_mem_stack_signal) ( void (*f)(Addr a, UInt len) );
|
||||
EV VG_(track_new_mem_brk) ( void (*f)(Addr a, UInt len) );
|
||||
@ -1726,12 +1726,12 @@ EV VG_(track_die_mem_munmap) ( void (*f)(Addr a, UInt len) );
|
||||
|
||||
/* These ones are called when %esp changes. A skin could track these itself
|
||||
(except for ban_mem_stack) but it's much easier to use the core's help.
|
||||
|
||||
|
||||
The specialised ones are called in preference to the general one, if they
|
||||
are defined. These functions are called a lot if they are used, so
|
||||
specialising can optimise things significantly. If any of the
|
||||
specialised cases are defined, the general case must be defined too.
|
||||
|
||||
specialised cases are defined, the general case must be defined too.
|
||||
|
||||
Nb: they must all use the __attribute__((regparm(n))) attribute. */
|
||||
EV VG_(track_new_mem_stack_4) ( void (*f)(Addr new_ESP) );
|
||||
EV VG_(track_new_mem_stack_8) ( void (*f)(Addr new_ESP) );
|
||||
@ -1759,7 +1759,7 @@ EV VG_(track_pre_mem_write) ( void (*f)(CorePart part, ThreadId tid,
|
||||
Char* s, Addr a, UInt size) );
|
||||
/* Not implemented yet -- have to add in lots of places, which is a
|
||||
pain. Won't bother unless/until there's a need. */
|
||||
/* EV VG_(track_post_mem_read) ( void (*f)(ThreadId tid, Char* s,
|
||||
/* EV VG_(track_post_mem_read) ( void (*f)(ThreadId tid, Char* s,
|
||||
Addr a, UInt size) ); */
|
||||
EV VG_(track_post_mem_write) ( void (*f)(Addr a, UInt size) );
|
||||
|
||||
@ -1770,11 +1770,11 @@ EV VG_(track_post_mem_write) ( void (*f)(Addr a, UInt size) );
|
||||
|
||||
/* Use VG_(set_shadow_archreg)() to set the eight general purpose regs,
|
||||
and use VG_(set_shadow_eflags)() to set eflags. */
|
||||
EV VG_(track_post_regs_write_init) ( void (*f)() );
|
||||
EV VG_(track_post_regs_write_init) ( void (*f)() );
|
||||
|
||||
/* Use VG_(set_thread_shadow_archreg)() to set the shadow regs for these
|
||||
/* Use VG_(set_thread_shadow_archreg)() to set the shadow regs for these
|
||||
events. */
|
||||
EV VG_(track_post_reg_write_syscall_return)
|
||||
EV VG_(track_post_reg_write_syscall_return)
|
||||
( void (*f)(ThreadId tid, UInt reg) );
|
||||
EV VG_(track_post_reg_write_deliver_signal)
|
||||
( void (*f)(ThreadId tid, UInt reg) );
|
||||
@ -1801,20 +1801,20 @@ EV VG_(track_post_thread_create)( void (*f)(ThreadId tid, ThreadId child) );
|
||||
about to resume. */
|
||||
EV VG_(track_post_thread_join) ( void (*f)(ThreadId joiner, ThreadId joinee) );
|
||||
|
||||
|
||||
|
||||
/* Mutex events (not exhaustive) */
|
||||
|
||||
/* Called before a thread can block while waiting for a mutex (called
|
||||
regardless of whether the thread will block or not). */
|
||||
EV VG_(track_pre_mutex_lock) ( void (*f)(ThreadId tid,
|
||||
EV VG_(track_pre_mutex_lock) ( void (*f)(ThreadId tid,
|
||||
void* /*pthread_mutex_t* */ mutex) );
|
||||
/* Called once the thread actually holds the mutex (always paired with
|
||||
pre_mutex_lock). */
|
||||
EV VG_(track_post_mutex_lock) ( void (*f)(ThreadId tid,
|
||||
EV VG_(track_post_mutex_lock) ( void (*f)(ThreadId tid,
|
||||
void* /*pthread_mutex_t* */ mutex) );
|
||||
/* Called after a thread has released a mutex (no need for a corresponding
|
||||
pre_mutex_unlock, because unlocking can't block). */
|
||||
EV VG_(track_post_mutex_unlock) ( void (*f)(ThreadId tid,
|
||||
EV VG_(track_post_mutex_unlock) ( void (*f)(ThreadId tid,
|
||||
void* /*pthread_mutex_t* */ mutex) );
|
||||
|
||||
|
||||
@ -1852,7 +1852,7 @@ EV VG_(track_post_deliver_signal) ( void (*f)(ThreadId tid, Int sigNum ) );
|
||||
/* Initialise skin. Must do the following:
|
||||
- initialise the `details' struct, via the VG_(details_*)() functions
|
||||
- register any helpers called by generated code
|
||||
|
||||
|
||||
May do the following:
|
||||
- initialise the `needs' struct to indicate certain requirements, via
|
||||
the VG_(needs_*)() functions
|
||||
@ -1915,7 +1915,7 @@ extern Bool SK_(recognised_suppression) ( Char* name, Supp* su );
|
||||
|
||||
/* Read any extra info for this suppression kind. Most likely for filling
|
||||
in the `extra' and `string' parts (with VG_(set_supp_{extra,string})())
|
||||
of a suppression if necessary. Should return False if a syntax error
|
||||
of a suppression if necessary. Should return False if a syntax error
|
||||
occurred, True otherwise. */
|
||||
extern Bool SK_(read_extra_suppression_info) ( Int fd, Char* buf, Int nBuf,
|
||||
Supp* su );
|
||||
@ -2014,8 +2014,8 @@ extern void SK_(pp_XUInstr) ( UInstr* u );
|
||||
/* VG_(needs).syscall_wrapper */
|
||||
|
||||
/* If either of the pre_ functions malloc() something to return, the
|
||||
* corresponding post_ function had better free() it!
|
||||
*/
|
||||
* corresponding post_ function had better free() it!
|
||||
*/
|
||||
extern void* SK_( pre_syscall) ( ThreadId tid, UInt syscallno,
|
||||
Bool is_blocking );
|
||||
extern void SK_(post_syscall) ( ThreadId tid, UInt syscallno,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user