|
From: Jeremy F. <je...@go...> - 2005-02-01 22:53:31
|
CVS commit by fitzhardinge:
Final step - remove the baseBlock and all its uses. Also optimises
the dispatch loop, and the handling of the dispatch counter (there's
no need to set %ebp to INNER_COUNTERZERO in every basic block).
A coregrind/x86/gen_offsets.c 1.1 [no copyright GENERATED FILE]
M +1 -1 cachegrind/x86/cg_arch.c 1.5
M +23 -58 coregrind/core.h 1.75
M +4 -2 coregrind/core_asm.h 1.6
M +1 -1 coregrind/toolfuncs.def 1.10
M +1 -11 coregrind/vg_errcontext.c 1.66
M +16 -16 coregrind/vg_execontext.c 1.25
M +72 -104 coregrind/vg_from_ucode.c 1.88
M +2 -66 coregrind/vg_main.c 1.242
M +2 -1 coregrind/vg_memory.c 1.88
M +23 -101 coregrind/vg_scheduler.c 1.217
M +3 -19 coregrind/vg_signals.c 1.117
M +1 -4 coregrind/vg_symtab2.c 1.100
M +1 -1 coregrind/vg_syscalls.c 1.240
M +1 -1 coregrind/vg_translate.c 1.98
M +17 -19 coregrind/vg_transtab.c 1.39
M +18 -3 coregrind/x86/Makefile.am 1.22
M +33 -82 coregrind/x86/core_arch.h 1.20
M +4 -3 coregrind/x86/core_arch_asm.h 1.3
M +45 -69 coregrind/x86/dispatch.S 1.4
M +6 -19 coregrind/x86/helpers.S 1.4
M +0 -33 coregrind/x86/signal.c 1.12
M +48 -362 coregrind/x86/state.c 1.16
M +9 -8 coregrind/x86-linux/ldt.c 1.8
M +9 -10 coregrind/x86-linux/syscall.S 1.5
M +3 -8 coregrind/x86-linux/syscalls.c 1.20
M +0 -2 helgrind/hg_main.c 1.94
M +16 -30 include/tool.h.base 1.22
M +0 -1 include/tool_asm.h 1.3
M +2 -60 include/x86/tool_arch.h 1.6
M +3 -54 memcheck/mc_main.c 1.58
--- valgrind/cachegrind/x86/cg_arch.c #1.4:1.5
@@ -249,5 +249,5 @@ static
Int get_caches_from_CPUID(cache_t* I1c, cache_t* D1c, cache_t* L2c)
{
- Int level, res, ret;
+ Int level, ret;
Char vendor_id[13];
--- valgrind/coregrind/core.h #1.74:1.75
@@ -643,4 +643,9 @@ struct _ThreadState {
VgSchedReturnCode exitreason;
+ /* Architecture-specific thread state
+ Leave early in the structure to make offsets small
+ */
+ arch_thread_t arch;
+
/* This thread's blocked-signals mask. Semantics is that for a
signal to be delivered to this thread, the signal must not be
@@ -692,7 +697,4 @@ struct _ThreadState {
vki_stack_t altstack;
- /* Architecture-specific thread state */
- arch_thread_t arch;
-
/* OS-specific thread state */
os_thread_t os_state;
@@ -724,12 +726,4 @@ extern void VG_(kill_thread)(ThreadId ti
extern Bool VG_(is_valid_tid) ( ThreadId tid );
-/* Determine if 'tid' is that of the current running thread (Nb: returns
- False if no thread is currently running. */
-extern Bool VG_(is_VCPU_thread)(ThreadId tid);
-
-/* Returns the ThreadId (if any) who's state is currently in the
- BaseBlock. */
-extern ThreadId VG_(get_VCPU_tid) ( void );
-
/* Get the ThreadState for a particular tid */
extern ThreadState *VG_(get_ThreadState)(ThreadId tid);
@@ -784,5 +778,5 @@ extern VgSchedReturnCode VG_(scheduler)
extern void VG_(shutdown_actions)(ThreadId tid);
-extern void VG_(scheduler_init) ( void );
+extern void VG_(scheduler_init) ( Addr init_eip, Addr init_esp );
extern void VG_(pp_sched_status) ( void );
@@ -791,16 +785,4 @@ extern void VG_(pp_sched_status) ( void
extern void VG_(resume_scheduler) ( ThreadId tid );
-/* Copy the state of a thread from VG_(baseBlock), presumably after it
- has been descheduled. For sanity-check purposes, fill the vacated
- VG_(baseBlock) with garbage so as to make the system more likely to
- fail quickly if we erroneously continue to poke around inside
- VG_(baseBlock) without first doing a load_thread_state().
-*/
-void VG_(save_thread_state) ( ThreadId tid );
-
-/* Copy the saved state of a thread into VG_(baseBlock), ready for it
- to be run. */
-void VG_(load_thread_state) ( ThreadId tid );
-
/* If true, a fault is Valgrind-internal (ie, a bug) */
extern Bool VG_(my_fault);
@@ -1183,8 +1165,4 @@ extern UInt VG_(unchained_jumps_done); /
extern void VG_(print_scheduler_stats) ( void );
-extern Int VG_(alloc_BaB)( Int ); // Allocate slots in baseBlock
-extern void VG_(align_BaB)( UInt ); // Align baseBlock offset
-extern Int VG_(alloc_BaB_1_set)( Addr ); // Allocate & init baseBlock slot
-
/* ---------------------------------------------------------------------
Exports of vg_memory.c
@@ -1644,4 +1622,17 @@ GEN_SYSCALL_WRAPPER(sys_gettid); // * L
------------------------------------------------------------------ */
+/* An entry in TC. Payload always is always padded out to a word-aligned
+ quantity so that these structs are always word-aligned. */
+typedef
+ struct {
+ /* 32-bit or 64-bit offsets */
+ /* +0 or 0 */ Addr orig_addr;
+ /* +4 or 8 */ UShort orig_size;
+ /* +6 or 10 */ UShort trans_size;
+ /* +8 or 12 */ UShort jump_sites[VG_MAX_JUMPS];
+ /* +VG_CODE_OFFSET */ UChar payload[0];
+ }
+ TCEntry;
+
/* The fast-cache for tt-lookup. */
extern Addr VG_(tt_fast)[VG_TT_FAST_SIZE];
@@ -1677,5 +1668,5 @@ extern void VG_(sigreturn)(void);
/* Run a thread for a (very short) while, until some event happens
which means we need to defer to the scheduler. */
-extern UInt VG_(run_innerloop) ( void );
+extern UInt VG_(run_innerloop) ( ThreadState *tst );
/* The patching routing called when a BB wants to chain itself to
@@ -1707,29 +1698,8 @@ __attribute__ ((noreturn))
extern void VG_(missing_tool_func) ( const Char* fn );
-/* ---------------------------------------------------------------------
- The baseBlock -- arch-neutral bits
- ------------------------------------------------------------------ */
-
-#define INVALID_OFFSET (-1)
-
-/* An array of words. In generated code, %ebp always points to the
- start of this array. Useful stuff, like the simulated CPU state,
- and the addresses of helper functions, can then be found by
- indexing off %ebp. The following declares variables which, at
- startup time, are given values denoting offsets into baseBlock.
- These offsets are in *words* from the start of baseBlock. */
-
-#define VG_BASEBLOCK_WORDS 400
-
-extern UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
-
// ---------------------------------------------------------------------
// Architecture-specific things defined in eg. x86/*.c
// ---------------------------------------------------------------------
-// For setting up the baseBlock
-extern void VGA_(init_low_baseBlock) ( Addr client_ip, Addr sp_at_startup );
-extern void VGA_(init_high_baseBlock) ( Addr client_ip, Addr sp_at_startup );
-
// Register state moving
extern void VGA_(load_state) ( arch_thread_t*, ThreadId tid );
@@ -1737,6 +1707,6 @@ extern void VGA_(save_state) ( arch_thre
// Thread stuff
+extern void VGA_(init_thread) ( ThreadId tid, Addr init_eip, Addr init_esp );
extern void VGA_(clear_thread) ( arch_thread_t* );
-extern void VGA_(init_thread) ( arch_thread_t* );
extern void VGA_(cleanup_thread) ( arch_thread_t* );
extern void VGA_(setup_child) ( arch_thread_t*, arch_thread_t* );
@@ -1772,5 +1742,4 @@ extern Bool VGA_(client_request)(ThreadI
// Symtab stuff
-extern UInt* VGA_(reg_addr_from_BB) ( Int reg );
extern UInt* VGA_(reg_addr_from_tst) ( Int reg, arch_thread_t* );
@@ -1779,15 +1748,11 @@ extern Bool VGA_(setup_pointercheck) ( v
// For attaching the debugger
-extern Int VGA_(ptrace_setregs_from_BB) ( Int pid );
extern Int VGA_(ptrace_setregs_from_tst) ( Int pid, arch_thread_t* arch );
// Making coredumps
-extern void VGA_(fill_elfregs_from_BB) ( struct vki_user_regs_struct* regs );
extern void VGA_(fill_elfregs_from_tst) ( struct vki_user_regs_struct* regs,
const arch_thread_t* arch );
-extern void VGA_(fill_elffpregs_from_BB) ( vki_elf_fpregset_t* fpu );
extern void VGA_(fill_elffpregs_from_tst) ( vki_elf_fpregset_t* fpu,
const arch_thread_t* arch );
-extern void VGA_(fill_elffpxregs_from_BB) ( vki_elf_fpxregset_t* xfpu );
extern void VGA_(fill_elffpxregs_from_tst) ( vki_elf_fpxregset_t* xfpu,
const arch_thread_t* arch );
@@ -1849,5 +1814,5 @@ extern const Addr vga_sys_before, vga_sy
right thing.
*/
-extern void VGA_(client_syscall)(Int syscallno, arch_thread_t *regs,
+extern void VGA_(client_syscall)(Int syscallno, ThreadState *tst,
const vki_sigset_t *syscall_mask);
--- valgrind/coregrind/core_asm.h #1.5:1.6
@@ -40,6 +40,6 @@
/* Magic values that %ebp might be set to when returning to the
dispatcher. The only other legitimate value is to point to the
- start of VG_(baseBlock). These also are return values from
- VG_(run_innerloop) to the scheduler.
+ start of the thread's ThreadState. These also are return values
+ from VG_(run_innerloop) to the scheduler.
EBP means %ebp can legitimately have this value when a basic block
@@ -55,4 +55,6 @@
#define VG_TRC_FAULT_SIGNAL 37 /* TRC only; got sigsegv/sigbus */
+#define VG_MAX_TRC 128 /* Highest possible TRC value */
+
/* Constants for the fast translation lookup cache. */
#define VG_TT_FAST_BITS 15
--- valgrind/coregrind/toolfuncs.def #1.9:1.10
@@ -235,5 +235,5 @@
## Use VG_(set_shadow_archreg)() to set the eight general purpose regs,
## and use VG_(set_shadow_eflags)() to set eflags.
-void, post_regs_write_init, void
+void, post_regs_write_init, ThreadId tid
## Use VG_(set_thread_shadow_archreg)() to set the shadow regs for these
--- valgrind/coregrind/vg_execontext.c #1.24:1.25
@@ -313,10 +313,4 @@ void get_needed_regs(ThreadId tid, Addr*
Addr* stack_highest_word)
{
- if (VG_(is_VCPU_thread)(tid)) {
- /* thread currently in baseblock */
- *ip = VG_(baseBlock)[VGOFF_INSTR_PTR];
- *fp = VG_(baseBlock)[VGOFF_FRAME_PTR];
- *sp = VG_(baseBlock)[VGOFF_STACK_PTR];
- } else {
/* thread in thread table */
ThreadState* tst = & VG_(threads)[ tid ];
@@ -324,5 +318,5 @@ void get_needed_regs(ThreadId tid, Addr*
*fp = ARCH_FRAME_PTR(tst->arch);
*sp = ARCH_STACK_PTR(tst->arch);
- }
+
*stack_highest_word = VG_(threads)[tid].stack_highest_word;
@@ -377,7 +371,4 @@ Addr VG_(get_EIP) ( ThreadId tid )
Addr ret;
- if (VG_(is_running_thread)(tid))
- ret = VG_(baseBlock)[VGOFF_INSTR_PTR];
- else
ret = ARCH_INSTR_PTR(VG_(threads)[ tid ].arch);
@@ -385,4 +376,13 @@ Addr VG_(get_EIP) ( ThreadId tid )
}
+Addr VG_(get_thread_stack_pointer) ( ThreadId tid )
+{
+ Addr ret;
+
+ ret = ARCH_STACK_PTR(VG_(threads)[ tid ].arch);
+
+ return ret;
+}
+
/*--------------------------------------------------------------------*/
/*--- end ---*/
--- valgrind/coregrind/vg_from_ucode.c #1.87:1.88
@@ -31,5 +31,5 @@
#include "core.h"
-
+#include <stddef.h> /* for offsetof */
/*------------------------------------------------------------*/
@@ -44,4 +44,7 @@
/*------------------------------------------------------------*/
+//#define TSTOFF(REG) (offsetof(ThreadState, arch) + offsetof(arch_thread_t, REG))
+#define TSTOFF(REG) (offsetof(ThreadState, arch.REG))
+
/*
The emit_* routines constitute the lowest level of instruction
@@ -72,5 +75,5 @@ static Int relocsz; /* size of reloc
static enum _eflags_state {
- UPD_Simd, /* baseblock copy is up to date */
+ UPD_Simd, /* ThreadState copy is up to date */
UPD_Real, /* CPU copy is up to date */
UPD_Both, /* both are current */
@@ -270,5 +273,5 @@ static __inline__ void boundscheck()
static void emit_get_eflags ( void )
{
- Int off = 4 * VGOFF_(m_eflags);
+ Int off = TSTOFF(m_eflags);
vg_assert(off >= 0 && off < 128);
@@ -286,5 +289,5 @@ static void emit_get_eflags ( void )
static void emit_put_eflags ( void )
{
- Int off = 4 * VGOFF_(m_eflags);
+ Int off = TSTOFF(m_eflags);
vg_assert(off >= 0 && off < 128);
@@ -1425,5 +1428,5 @@ void VG_( emit_movzwl_regmem_reg ) ( Boo
static void emit_get_sse_state ( void )
{
- Int off = 4 * VGOFF_(m_ssestate);
+ Int off = TSTOFF(m_sse);
if (VG_(have_ssestate)) {
VG_(new_emit)(False, FlagsEmpty, FlagsEmpty);
@@ -1445,5 +1448,5 @@ static void emit_get_sse_state ( void )
static void emit_put_sse_state ( void )
{
- Int off = 4 * VGOFF_(m_ssestate);
+ Int off = TSTOFF(m_sse);
if (VG_(have_ssestate)) {
VG_(new_emit)(False, FlagsEmpty, FlagsEmpty);
@@ -2473,6 +2476,6 @@ void emit_three_regs_or_lits_args_setup
}
-/* Synthesise a call to a C function `fn' (which must be registered in
- baseBlock) doing all the reg saving and arg handling work.
+/* Synthesise a call to a C function `fn' doing all the reg saving and
+ arg handling work.
WARNING: a UInstr should *not* be translated with synth_ccall followed
@@ -2640,5 +2643,5 @@ static void synth_jmp_lit ( Addr addr, J
if (VG_(clo_chain_bb) && (jmpkind == JmpBoring || jmpkind == JmpCall)) {
- synth_mov_reg_offregmem(4, R_EAX, 4*VGOFF_(m_eip), R_EBP); /* update EIP */
+ synth_mov_reg_offregmem(4, R_EAX, TSTOFF(m_eip), R_EBP); /* update EIP */
emit_call_patchme();
} else {
@@ -2694,5 +2697,5 @@ static void synth_jcond_lit ( Condcode c
VG_(emit_movv_offregmem_reg)
- ( 4, VGOFF_(m_eflags) * 4, R_EBP, R_EAX );
+ ( 4, TSTOFF(m_eflags), R_EBP, R_EAX );
/* eax == %EFLAGS */
@@ -2726,5 +2729,5 @@ static void synth_jcond_lit ( Condcode c
VG_(emit_movv_offregmem_reg)
- ( 4, VGOFF_(m_eflags) * 4, R_EBP, R_EAX );
+ ( 4, TSTOFF(m_eflags), R_EBP, R_EAX );
/* eax == %EFLAGS */
@@ -2773,9 +2776,9 @@ static void synth_jcond_lit ( Condcode c
VG_(emitB) ( 0xF6 ); /* Grp3 */
VG_(emit_amode_offregmem_reg)(
- VGOFF_(m_eflags) * 4, R_EBP, 0 /* subcode for TEST */);
+ TSTOFF(m_eflags), R_EBP, 0 /* subcode for TEST */);
VG_(emitB) (mask);
if (dis)
VG_(printf)("\n\t\ttestb $0x%x, %d(%%ebp)\n",
- mask, VGOFF_(m_eflags) * 4);
+ mask, TSTOFF(m_eflags));
} else {
/* all cond codes are in lower 16 bits */
@@ -2785,9 +2788,9 @@ static void synth_jcond_lit ( Condcode c
VG_(emitB) ( 0xF7 );
VG_(emit_amode_offregmem_reg)(
- VGOFF_(m_eflags) * 4, R_EBP, 0 /* subcode for TEST */);
+ TSTOFF(m_eflags), R_EBP, 0 /* subcode for TEST */);
VG_(emitW) (mask);
if (dis)
VG_(printf)("\n\t\ttestl $0x%x, %d(%%ebp)\n",
- mask, VGOFF_(m_eflags) * 4);
+ mask, TSTOFF(m_eflags));
}
@@ -3352,5 +3355,5 @@ static void synth_cmovl_reg_reg ( Condco
/*----------------------------------------------------*/
-/* Return the byte offset from %ebp (ie, into baseBlock)
+/* Return the byte offset from %ebp (ie, into ThreadState)
for the specified ArchReg or SpillNo. */
static Int spillOrArchOffset ( Int size, Tag tag, UInt value )
@@ -3359,24 +3362,24 @@ static Int spillOrArchOffset ( Int size,
vg_assert(size == 4);
vg_assert(value >= 0 && value < VG_MAX_SPILLSLOTS);
- return 4 * (value + VGOFF_(spillslots));
+ return TSTOFF(spillslots[value]);
}
if (tag == ArchReg) {
switch (value) {
- case R_EAX: return 4 * VGOFF_(m_eax);
- case R_ECX: return 4 * VGOFF_(m_ecx);
- case R_EDX: return 4 * VGOFF_(m_edx);
- case R_EBX: return 4 * VGOFF_(m_ebx);
+ case R_EAX: return TSTOFF(m_eax);
+ case R_ECX: return TSTOFF(m_ecx);
+ case R_EDX: return TSTOFF(m_edx);
+ case R_EBX: return TSTOFF(m_ebx);
case R_ESP:
- if (size == 1) return 4 * VGOFF_(m_eax) + 1;
- else return 4 * VGOFF_(m_esp);
+ if (size == 1) return TSTOFF(m_eax) + 1;
+ else return TSTOFF(m_esp);
case R_EBP:
- if (size == 1) return 4 * VGOFF_(m_ecx) + 1;
- else return 4 * VGOFF_(m_ebp);
+ if (size == 1) return TSTOFF(m_ecx) + 1;
+ else return TSTOFF(m_ebp);
case R_ESI:
- if (size == 1) return 4 * VGOFF_(m_edx) + 1;
- else return 4 * VGOFF_(m_esi);
+ if (size == 1) return TSTOFF(m_edx) + 1;
+ else return TSTOFF(m_esi);
case R_EDI:
- if (size == 1) return 4 * VGOFF_(m_ebx) + 1;
- else return 4 * VGOFF_(m_edi);
+ if (size == 1) return TSTOFF(m_ebx) + 1;
+ else return TSTOFF(m_edi);
}
}
@@ -3386,5 +3389,5 @@ static Int spillOrArchOffset ( Int size,
static Int eflagsOffset ( void )
{
- return 4 * VGOFF_(m_eflags);
+ return TSTOFF(m_eflags);
}
@@ -3392,29 +3395,14 @@ static Int segRegOffset ( UInt archregs
{
switch (archregs) {
- case R_CS: return 4 * VGOFF_(m_cs);
- case R_SS: return 4 * VGOFF_(m_ss);
- case R_DS: return 4 * VGOFF_(m_ds);
- case R_ES: return 4 * VGOFF_(m_es);
- case R_FS: return 4 * VGOFF_(m_fs);
- case R_GS: return 4 * VGOFF_(m_gs);
+ case R_CS: return TSTOFF(m_cs);
+ case R_SS: return TSTOFF(m_ss);
+ case R_DS: return TSTOFF(m_ds);
+ case R_ES: return TSTOFF(m_es);
+ case R_FS: return TSTOFF(m_fs);
+ case R_GS: return TSTOFF(m_gs);
default: VG_(core_panic)("segRegOffset");
}
}
-UInt VG_(get_archreg) ( UInt arch )
-{
- switch (arch) {
- case R_EAX: return VG_(baseBlock)[ VGOFF_(m_eax) ];
- case R_ECX: return VG_(baseBlock)[ VGOFF_(m_ecx) ];
- case R_EDX: return VG_(baseBlock)[ VGOFF_(m_edx) ];
- case R_EBX: return VG_(baseBlock)[ VGOFF_(m_ebx) ];
- case R_ESP: return VG_(baseBlock)[ VGOFF_(m_esp) ];
- case R_EBP: return VG_(baseBlock)[ VGOFF_(m_ebp) ];
- case R_ESI: return VG_(baseBlock)[ VGOFF_(m_esi) ];
- case R_EDI: return VG_(baseBlock)[ VGOFF_(m_edi) ];
- default: VG_(core_panic)( "get_archreg");
- }
-}
-
UInt VG_(get_thread_archreg) ( ThreadId tid, UInt arch )
{
@@ -3437,46 +3425,49 @@ UInt VG_(get_thread_archreg) ( ThreadId
}
-/* Return the baseBlock index for the specified shadow register */
-static Int shadow_reg_index ( Int arch )
+/* Return a pointer to the specified shadow register */
+static UInt *shadow_reg_ptr ( ThreadState *tst, Int arch )
{
switch (arch) {
- case R_EAX: return VGOFF_(sh_eax);
- case R_ECX: return VGOFF_(sh_ecx);
- case R_EDX: return VGOFF_(sh_edx);
- case R_EBX: return VGOFF_(sh_ebx);
- case R_ESP: return VGOFF_(sh_esp);
- case R_EBP: return VGOFF_(sh_ebp);
- case R_ESI: return VGOFF_(sh_esi);
- case R_EDI: return VGOFF_(sh_edi);
- default: VG_(core_panic)( "shadow_reg_index");
+ case R_EAX: return &tst->arch.sh_eax;
+ case R_ECX: return &tst->arch.sh_ecx;
+ case R_EDX: return &tst->arch.sh_edx;
+ case R_EBX: return &tst->arch.sh_ebx;
+ case R_ESP: return &tst->arch.sh_esp;
+ case R_EBP: return &tst->arch.sh_ebp;
+ case R_ESI: return &tst->arch.sh_esi;
+ case R_EDI: return &tst->arch.sh_edi;
+ default: VG_(core_panic)( "shadow_reg_ptr");
}
}
-/* Return the byte offset from %ebp (ie, into baseBlock)
+/* Return the byte offset from %ebp (ie, into ThreadState)
for the specified shadow register */
Int VG_(shadow_reg_offset) ( Int arch )
{
- return 4 * shadow_reg_index ( arch );
+ /* This has the effect of offsetof() */
+ return (Int)shadow_reg_ptr ( 0, arch );
}
Int VG_(shadow_flags_offset) ( void )
{
- return 4 * VGOFF_(sh_eflags);
+ return TSTOFF(sh_eflags);
}
/* Accessing shadow arch. registers */
-UInt VG_(get_shadow_archreg) ( UInt archreg )
+UInt VG_(get_shadow_archreg) ( ThreadState *tst, UInt archreg )
{
- return VG_(baseBlock)[ shadow_reg_index(archreg) ];
+ return *shadow_reg_ptr(tst, archreg);
}
-void VG_(set_shadow_archreg) ( UInt archreg, UInt val )
+void VG_(set_shadow_archreg) ( ThreadState *tst, UInt archreg, UInt val )
{
- VG_(baseBlock)[ shadow_reg_index(archreg) ] = val;
+ *shadow_reg_ptr(tst, archreg) = val;
}
-void VG_(set_shadow_eflags) ( UInt val )
+void VG_(set_thread_shadow_eflags) ( ThreadId tid, UInt val )
{
- VG_(baseBlock)[ VGOFF_(sh_eflags) ] = val;
+ ThreadState* tst = VG_(get_ThreadState)(tid);
+
+ tst->arch.sh_eflags = val;
}
@@ -3488,15 +3479,5 @@ UInt VG_(get_thread_shadow_archreg) ( Th
tst = & VG_(threads)[tid];
- switch (archreg) {
- case R_EAX: return tst->arch.sh_eax;
- case R_ECX: return tst->arch.sh_ecx;
- case R_EDX: return tst->arch.sh_edx;
- case R_EBX: return tst->arch.sh_ebx;
- case R_ESP: return tst->arch.sh_esp;
- case R_EBP: return tst->arch.sh_ebp;
- case R_ESI: return tst->arch.sh_esi;
- case R_EDI: return tst->arch.sh_edi;
- default: VG_(core_panic)( "get_thread_shadow_archreg");
- }
+ return VG_(get_shadow_archreg)(tst, archreg);
}
@@ -3508,20 +3489,10 @@ void VG_(set_thread_shadow_archreg) ( Th
tst = & VG_(threads)[tid];
- switch (archreg) {
- case R_EAX: tst->arch.sh_eax = val; break;
- case R_ECX: tst->arch.sh_ecx = val; break;
- case R_EDX: tst->arch.sh_edx = val; break;
- case R_EBX: tst->arch.sh_ebx = val; break;
- case R_ESP: tst->arch.sh_esp = val; break;
- case R_EBP: tst->arch.sh_ebp = val; break;
- case R_ESI: tst->arch.sh_esi = val; break;
- case R_EDI: tst->arch.sh_edi = val; break;
- default: VG_(core_panic)( "set_thread_shadow_archreg");
- }
+ VG_(set_shadow_archreg) ( tst, archreg, val );
}
-Addr VG_(shadow_archreg_address) ( UInt archreg )
+Addr VG_(shadow_archreg_address) ( ThreadId tid, UInt archreg )
{
- return (Addr) & VG_(baseBlock)[ shadow_reg_index(archreg) ];
+ return (Addr) shadow_reg_ptr(VG_(get_ThreadState)(tid), archreg);
}
@@ -3608,9 +3579,9 @@ static void emitUInstr ( UCodeBlock* cb,
/* We have to update all 32 bits of the value. */
VG_(emit_movv_lit_offregmem)(
- 4, *curr_eip, 4*VGOFF_(m_eip), R_EBP);
+ 4, *curr_eip, TSTOFF(m_eip), R_EBP);
} else {
/* Cool! we only need to update lowest 8 bits */
VG_(emit_movb_lit_offregmem)(
- *curr_eip & 0xFF, 4*VGOFF_(m_eip)+0, R_EBP);
+ *curr_eip & 0xFF, TSTOFF(m_eip)+0, R_EBP);
}
@@ -3719,5 +3690,5 @@ static void emitUInstr ( UCodeBlock* cb,
/* get D in u->val1 (== 1 or -1) */
- synth_mov_offregmem_reg (u->size, 4*VGOFF_(m_dflag), R_EBP, u->val1);
+ synth_mov_offregmem_reg (u->size, TSTOFF(m_dflag), R_EBP, u->val1);
/* u->val1 &= EFlagD (== 0 or EFlagD) */
@@ -3728,8 +3699,4 @@ static void emitUInstr ( UCodeBlock* cb,
eflagsOffset(), R_EBP);
- /* EFLAGS &= ~EFlagD (make sure there's no surprises) */
- synth_nonshiftop_lit_offregmem(False, AND, u->size, ~EFlagD,
- eflagsOffset(), R_EBP);
-
/* u->val1 |= EFLAGS (EFLAGS & EflagD == 0) */
synth_nonshiftop_offregmem_reg(False, OR, u->size,
@@ -3763,5 +3730,5 @@ static void emitUInstr ( UCodeBlock* cb,
/* save D */
- synth_mov_reg_offregmem(u->size, u->val1, 4*VGOFF_(m_dflag), R_EBP);
+ synth_mov_reg_offregmem(u->size, u->val1, TSTOFF(m_dflag), R_EBP);
/* EFLAGS &= ~EFlagD */
@@ -4473,6 +4440,7 @@ UChar* VG_(emit_code) ( UCodeBlock* cb,
VG_(printf)("\n\t\tsubl $1, (%p)\n", &VG_(dispatch_ctr));
+ /* Don't bother setting EBP; the dispatch loop can work it out for
+ itself by looking at dispatch_ctr. */
VG_(emit_jcondshort_target)(False, CondNZ, &tgt, JP_TAKEN);
- VG_(emit_movv_lit_reg) ( 4, VG_TRC_INNER_COUNTERZERO, R_EBP );
emit_ret();
VG_(target_forward)(&tgt);
--- valgrind/coregrind/vg_main.c #1.241:1.242
@@ -223,7 +223,4 @@ static void print_all_stats ( void )
static Int ptrace_setregs(Int pid, ThreadId tid)
{
- if (VG_(is_VCPU_thread)( tid ))
- return VGA_(ptrace_setregs_from_BB)(pid);
- else
return VGA_(ptrace_setregs_from_tst)(pid, &VG_(threads)[tid].arch);
}
@@ -336,9 +333,4 @@ void VG_(unimplemented) ( Char* msg )
}
-Addr VG_(get_stack_pointer) ( void )
-{
- return VG_(baseBlock)[VGOFF_STACK_PTR];
-}
-
/* Debugging thing .. can be called from assembly with OYNK macro. */
void VG_(oynk) ( Int n )
@@ -2119,42 +2111,4 @@ static void setup_file_descriptors(void)
-/*====================================================================*/
-/*=== baseBlock: definition + setup ===*/
-/*====================================================================*/
-
-/* This is the actual defn of baseblock. */
-UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
-
-/* Words. */
-static Int baB_off = 0;
-
-
-/* Returns the offset, in words. */
-Int VG_(alloc_BaB) ( Int words )
-{
- Int off = baB_off;
- baB_off += words;
- if (baB_off >= VG_BASEBLOCK_WORDS)
- VG_(core_panic)( "VG_(alloc_BaB): baseBlock is too small");
-
- return off;
-}
-
-/* Align offset, in *bytes* */
-void VG_(align_BaB) ( UInt align )
-{
- vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
- baB_off += (align-1);
- baB_off &= ~(align-1);
-}
-
-/* Allocate 1 word in baseBlock and set it to the given value. */
-Int VG_(alloc_BaB_1_set) ( Addr a )
-{
- Int off = VG_(alloc_BaB)(1);
- VG_(baseBlock)[off] = (UInt)a;
- return off;
-}
-
Bool VG_(need_to_handle_SP_assignment)(void)
{
@@ -2174,13 +2128,4 @@ Bool VG_(need_to_handle_SP_assignment)(v
}
-// The low/high split is for x86, so that the more common helpers can be
-// in the first 128 bytes of the start, which allows the use of a more
-// compact addressing mode.
-static void init_baseBlock ( Addr client_eip, Addr sp_at_startup )
-{
- VGA_(init_low_baseBlock)(client_eip, sp_at_startup);
- VGA_(init_high_baseBlock)(client_eip, sp_at_startup);
-}
-
/*====================================================================*/
/*=== Initialise program data/text, etc. ===*/
@@ -2647,12 +2592,4 @@ int main(int argc, char **argv, char **e
//--------------------------------------------------------------
- // Set up baseBlock
- // p: {pre,post}_clo_init() [for tool helper registration]
- // load_client() [for 'client_eip']
- // setup_client_stack() [for 'sp_at_startup']
- //--------------------------------------------------------------
- init_baseBlock(client_eip, sp_at_startup);
-
- //--------------------------------------------------------------
// Search for file descriptors that are inherited from our parent
// p: process_cmd_line_options [for VG_(clo_track_fds)]
@@ -2663,8 +2600,7 @@ int main(int argc, char **argv, char **e
//--------------------------------------------------------------
// Initialise the scheduler
- // p: init_baseBlock() [baseBlock regs copied into VG_(threads)[1]]
// p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
//--------------------------------------------------------------
- VG_(scheduler_init)();
+ VG_(scheduler_init)(client_eip, sp_at_startup);
//--------------------------------------------------------------
--- valgrind/coregrind/vg_memory.c #1.87:1.88
@@ -738,5 +738,6 @@ REGPARM(1)
void VG_(unknown_SP_update)(Addr new_SP)
{
- Addr old_SP = VG_(get_archreg)(R_STACK_PTR);
+ ThreadState *tst = &VG_(threads)[VG_(get_running_tid)()];
+ Addr old_SP = ARCH_STACK_PTR(tst->arch);
Word delta = (Word)new_SP - (Word)old_SP;
--- valgrind/coregrind/vg_scheduler.c #1.216:1.217
@@ -76,12 +76,4 @@ ThreadState VG_(threads)[VG_N_THREADS];
Bool VG_(my_fault) = True;
-/* The tid of the thread currently in VG_(baseBlock). */
-static ThreadId vg_tid_currently_in_baseBlock = VG_INVALID_THREADID;
-
-/* The tid either currently in baseBlock, or was in baseBlock before
- was saved it out; this is only updated when a new thread is loaded
- into the baseBlock */
-static ThreadId vg_tid_last_in_baseBlock = VG_INVALID_THREADID;
-
/* Forwards */
static void do_client_request ( ThreadId tid );
@@ -134,6 +126,5 @@ Bool is_valid_or_empty_tid ( ThreadId ti
/* For constructing error messages only: try and identify a thread
whose stack satisfies the predicate p, or return VG_INVALID_THREADID
- if none do. A small complication is dealing with any currently
- VG_(baseBlock)-resident thread.
+ if none do.
*/
ThreadId VG_(first_matching_thread_stack)
@@ -141,22 +132,9 @@ ThreadId VG_(first_matching_thread_stack
void* d )
{
- ThreadId tid, tid_to_skip;
-
- tid_to_skip = VG_INVALID_THREADID;
-
- /* First check to see if there's a currently-loaded thread in
- VG_(baseBlock). */
- if (vg_tid_currently_in_baseBlock != VG_INVALID_THREADID) {
- tid = vg_tid_currently_in_baseBlock;
- if ( p ( VG_(baseBlock)[VGOFF_STACK_PTR],
- VG_(threads)[tid].stack_highest_word, d ) )
- return tid;
- else
- tid_to_skip = tid;
- }
+ ThreadId tid;
for (tid = 1; tid < VG_N_THREADS; tid++) {
if (VG_(threads)[tid].status == VgTs_Empty) continue;
- if (tid == tid_to_skip) continue;
+
if ( p ( ARCH_STACK_PTR(VG_(threads)[tid].arch),
VG_(threads)[tid].stack_highest_word, d ) )
@@ -243,30 +221,4 @@ ThreadState *VG_(get_ThreadState)(Thread
}
-/* This, specifically, means that tid's register state is in the
- BaseBlock */
-Bool VG_(is_VCPU_thread)(ThreadId tid)
-{
- ThreadId curr = VG_(get_VCPU_tid)();
- return (curr == tid && VG_INVALID_THREADID != tid);
-}
-
-/* Return the tid of the thread who's context is in the BaseBlock (if
- any) */
-ThreadId VG_(get_VCPU_tid) ( void )
-{
- if (!VG_(is_valid_tid)(vg_tid_currently_in_baseBlock))
- return VG_INVALID_THREADID;
- return vg_tid_currently_in_baseBlock;
-}
-
-ThreadId VG_(get_current_or_recent_tid) ( void )
-{
- vg_assert(vg_tid_currently_in_baseBlock == vg_tid_last_in_baseBlock ||
- vg_tid_currently_in_baseBlock == VG_INVALID_THREADID);
- vg_assert(VG_(is_valid_tid)(vg_tid_last_in_baseBlock));
-
- return vg_tid_last_in_baseBlock;
-}
-
/* Given an LWP id (ie, real kernel thread id), find the corresponding
ThreadId */
@@ -308,4 +260,9 @@ void VG_(set_running)(ThreadId tid)
}
+ThreadId VG_(get_running_tid)(void)
+{
+ return running_tid;
+}
+
Bool VG_(is_running_thread)(ThreadId tid)
{
@@ -449,31 +406,4 @@ void VG_(vg_yield)(void)
}
-/* Copy the state of a thread from VG_(baseBlock), presumably after it
- has been descheduled. For sanity-check purposes, fill the vacated
- VG_(baseBlock) with garbage so as to make the system more likely to
- fail quickly if we erroneously continue to poke around inside
- VG_(baseBlock) without first doing a load_thread_state().
-*/
-void VG_(save_thread_state) ( ThreadId tid )
-{
- vg_assert(vg_tid_currently_in_baseBlock != VG_INVALID_THREADID);
-
- VGA_(save_state)(&VG_(threads)[tid].arch, tid);
-
- vg_tid_currently_in_baseBlock = VG_INVALID_THREADID;
-}
-
-/* Copy the saved state of a thread into VG_(baseBlock), ready for it
- to be run. */
-void VG_(load_thread_state) ( ThreadId tid )
-{
- vg_assert(vg_tid_currently_in_baseBlock == VG_INVALID_THREADID);
-
- VGA_(load_state)(&VG_(threads)[tid].arch, tid);
-
- vg_tid_currently_in_baseBlock = tid;
- vg_tid_last_in_baseBlock = tid;
-}
-
void VG_(resume_scheduler)(ThreadId tid)
@@ -513,4 +443,7 @@ UInt run_thread_for_a_while ( ThreadId t
volatile UInt trc = 0;
Bool jumped;
+ ThreadState *tst = VG_(get_ThreadState)(tid);
+ Addr EIP = tst->arch.m_eip;
+ Addr nextEIP;
vg_assert(VG_(is_valid_tid)(tid));
@@ -519,5 +452,4 @@ UInt run_thread_for_a_while ( ThreadId t
VGP_PUSHCC(VgpRun);
- VG_(load_thread_state) ( tid );
/* there should be no undealt-with signals */
@@ -529,5 +461,10 @@ UInt run_thread_for_a_while ( ThreadId t
VG_(my_fault) = False;
- SCHEDSETJMP(tid, jumped, trc = VG_(run_innerloop)());
+ SCHEDSETJMP(tid, jumped, trc = VG_(run_innerloop)(tst));
+
+ nextEIP = tst->arch.m_eip;
+ if (nextEIP >= VG_(client_end))
+ VG_(printf)("trc=%d jump to %p from %p\n",
+ trc, nextEIP, EIP);
VG_(my_fault) = True;
@@ -541,11 +478,4 @@ UInt run_thread_for_a_while ( ThreadId t
}
- /* If we were delivered a signal, then the ThreadState registers
- may already be up to date. */
- if (VG_(is_VCPU_thread)(tid))
- VG_(save_thread_state) ( tid );
-
- vg_assert(VG_(get_VCPU_tid)() == VG_INVALID_THREADID);
-
VGP_POPCC(VgpRun);
return trc;
@@ -614,8 +544,8 @@ static void sched_fork_cleanup(ThreadId
/* Initialise the scheduler. Create a single "main" thread ready to
- run, with special ThreadId of one. This is called at startup; the
- caller takes care to park the client's state in VG_(baseBlock).
+ run, with special ThreadId of one. This is called at startup, and is
+ passed the initial state for the first thread.
*/
-void VG_(scheduler_init) ( void )
+void VG_(scheduler_init) ( Addr client_eip, Addr sp_at_startup )
{
Int i;
@@ -641,10 +571,5 @@ void VG_(scheduler_init) ( void )
VG_(master_tid) = tid_main;
- /* Copy VG_(baseBlock) state to tid_main's slot. */
- vg_tid_currently_in_baseBlock = tid_main;
- vg_tid_last_in_baseBlock = tid_main;
-
- VGA_(init_thread)(&VG_(threads)[tid_main].arch);
- VG_(save_thread_state) ( tid_main );
+ VGA_(init_thread)(tid_main, client_eip, sp_at_startup);
/* Initial thread's stack is the original process stack */
@@ -653,7 +578,4 @@ void VG_(scheduler_init) ( void )
VG_(threads)[tid_main].stack_size = VG_(client_rlimit_stack).rlim_cur;
- /* So now ... */
- vg_assert(vg_tid_currently_in_baseBlock == VG_INVALID_THREADID);
-
VG_(atfork)(NULL, NULL, sched_fork_cleanup);
}
@@ -907,7 +829,7 @@ void VG_(set_return_from_syscall_shadow)
}
-UInt VG_(get_exit_status_shadow) ( void )
+UInt VG_(get_exit_status_shadow) ( ThreadId tid )
{
- return VG_(get_shadow_archreg)(R_SYSCALL_ARG1);
+ return VG_(get_thread_shadow_archreg)(tid, R_SYSCALL_ARG1);
}
--- valgrind/coregrind/vg_signals.c #1.116:1.117
@@ -1059,16 +1059,9 @@ static void fill_prstatus(const ThreadSt
vg_assert(sizeof(*regs) == sizeof(prs->pr_reg));
- if (VG_(is_VCPU_thread)(tst->tid)) {
- VGA_(fill_elfregs_from_BB)(regs);
- } else {
VGA_(fill_elfregs_from_tst)(regs, &tst->arch);
- }
}
static void fill_fpu(const ThreadState *tst, vki_elf_fpregset_t *fpu)
{
- if (VG_(is_running_thread)(tst->tid))
- VGA_(fill_elffpregs_from_BB)(fpu);
- else
VGA_(fill_elffpregs_from_tst)(fpu, &tst->arch);
}
@@ -1076,7 +1069,4 @@ static void fill_fpu(const ThreadState *
static void fill_xfpu(const ThreadState *tst, vki_elf_fpxregset_t *xfpu)
{
- if (VG_(is_running_thread)(tst->tid))
- VGA_(fill_elffpxregs_from_BB)(xfpu);
- else
VGA_(fill_elffpxregs_from_tst)(xfpu, &tst->arch);
}
@@ -1488,8 +1478,4 @@ void VG_(deliver_signal) ( ThreadId tid,
vg_assert(VG_(is_valid_tid)(tid));
- /* Before we muck with the thread's state, we need to work out where it is. */
- if (VG_(is_VCPU_thread)(tid))
- VG_(save_thread_state)(tid);
-
vg_push_signal_frame ( tid, info );
@@ -1726,7 +1712,5 @@ void vg_sync_signalhandler ( Int sigNo,
if (info->si_signo == VKI_SIGSEGV) {
Addr fault = (Addr)info->_sifields._sigfault._addr;
- Addr esp = VG_(is_running_thread)(tid)
- ? VG_(baseBlock)[VGOFF_STACK_PTR]
- : ARCH_STACK_PTR(VG_(threads)[tid].arch);
+ Addr esp = ARCH_STACK_PTR(VG_(threads)[tid].arch);
if (VG_(clo_trace_signals)) {
--- valgrind/coregrind/vg_symtab2.c #1.99:1.100
@@ -2013,7 +2013,4 @@ static UInt *regaddr(ThreadId tid, Int r
UInt *ret = 0;
- if (VG_(is_VCPU_thread)(tid))
- ret = VGA_(reg_addr_from_BB)(regno);
- else
ret = VGA_(reg_addr_from_tst)(regno, &VG_(threads)[tid].arch);
--- valgrind/coregrind/vg_syscalls.c #1.239:1.240
@@ -6038,5 +6038,5 @@ void VG_(client_syscall) ( ThreadId tid
VG_(set_sleeping)(tid, VgTs_WaitSys);
- VGA_(client_syscall)(syscallno, &tst->arch, &mask);
+ VGA_(client_syscall)(syscallno, tst, &mask);
/* VGA_(client_syscall) may not return if the syscall was
interrupted by a signal. In that case, flow of control
--- valgrind/coregrind/vg_transtab.c #1.38:1.39
@@ -64,17 +64,4 @@ static /* const */ Int vg_tc_sector_szB
#define IS_ALIGNED(a) (((a) & (CODE_ALIGNMENT-1)) == 0)
-/* An entry in TC. Payload always is always padded out to a word-aligned
- quantity so that these structs are always word-aligned. */
-typedef
- struct {
- /* 32-bit or 64-bit offsets */
- /* +0 or 0 */ Addr orig_addr;
- /* +4 or 8 */ UShort orig_size;
- /* +6 or 10 */ UShort trans_size;
- /* +8 or 12 */ UShort jump_sites[VG_MAX_JUMPS];
- /* +VG_CODE_OFFSET */ UChar payload[0];
- }
- TCEntry;
-
/* An entry in TT. */
typedef
@@ -563,4 +550,6 @@ void VG_(add_to_trans_tab) ( Addr orig_a
Int i, nBytes, trans_size_aligned;
TCEntry* tce;
+ UShort prev;
+
/*
VG_(printf)("add_to_trans_tab(%d) %x %d %x %d\n",
@@ -569,8 +558,4 @@ void VG_(add_to_trans_tab) ( Addr orig_a
*/
- if (VG_(clo_trace_codegen) & 1)
- VG_(message)(Vg_DebugMsg, "add_to_trans_tab: inserting code for %p intro transtab at %p\n",
- orig_addr, trans_addr);
-
vg_assert(offsetof(TCEntry, payload) == VG_CODE_OFFSET);
@@ -597,7 +582,20 @@ void VG_(add_to_trans_tab) ( Addr orig_a
}
+ if (VG_(clo_trace_codegen) & 1)
+ VG_(message)(Vg_DebugMsg, "add_to_trans_tab: inserting code for %p into transtab at %p\n",
+ orig_addr, tce->payload);
+
/* relocate absolute jumps */
- for(i = 0; i < cb->nrelocs; i++)
- VG_(reloc_abs_jump)(&tce->payload[cb->relocs[i]]);
+ prev = 0;
+ for(i = 0; i < cb->nrelocs; i++) {
+ UShort off = cb->relocs[i];
+
+ vg_assert(off < trans_size);
+ vg_assert(i == 0 || off > prev);
+
+ VG_(reloc_abs_jump)(&tce->payload[off]);
+
+ prev = off;
+ }
add_tt_entry(tce);
--- valgrind/coregrind/vg_errcontext.c #1.65:1.66
@@ -293,15 +293,5 @@ Bool VG_(is_action_requested) ( Char* ac
-/* I've gone all object-oriented... initialisation depends on where the
- error comes from:
-
- - If from generated code (tst == NULL), the %EIP/%EBP values that we
- need in order to attach GDB are picked up out of VG_(baseBlock) rather
- than from the thread table (vg_threads in vg_scheduler.c).
-
- - If not from generated code but in response to requests passed back to
- the scheduler (tst != NULL), we pick up %EIP/%EBP values from the
- stored thread state, not from VG_(baseBlock).
-*/
+/* Construct an error */
static __inline__
void construct_error ( Error* err, ThreadId tid, ErrorKind ekind, Addr a,
--- valgrind/coregrind/vg_translate.c #1.97:1.98
@@ -292,5 +292,5 @@ Bool VG_(any_flag_use) ( UInstr* u )
register number. This effectively defines the order in which real
registers are allocated. %ebp is excluded since it is permanently
- reserved for pointing at VG_(baseBlock).
+ reserved for pointing at the thread's ThreadState.
Important! This function must correspond with the value of
--- valgrind/coregrind/x86-linux/ldt.c #1.7:1.8
@@ -178,8 +178,12 @@ unsigned int wine_ldt_get_limit( const V
Addr VG_(do_useseg) ( UInt seg_selector, Addr virtual_addr )
{
+ ThreadId tid = VG_(get_running_tid)();
+ ThreadState *tst = &VG_(threads)[tid];
UInt table;
Addr base;
UInt limit;
+ vg_assert(tid != VG_INVALID_THREADID);
+
if (0)
VG_(printf)("do_useseg: seg_selector = %p, vaddr = %p\n",
@@ -191,8 +195,5 @@ Addr VG_(do_useseg) ( UInt seg_selector,
privilege). This forms the bottom 2 bits of the selector. */
if ((seg_selector & 3) != 3) {
- ThreadId tid = VG_(get_VCPU_tid)();
- vg_assert(tid != VG_INVALID_THREADID);
-
- //VG_(printf)("synth fault EIP=%p\n", VG_(baseBlock)[VGOFF_(m_eip)]);
+ //VG_(printf)("synth fault EIP=%p\n", tst->arch.m_eip);
VG_(synth_fault)(tid);
VG_(resume_scheduler)(tid);
@@ -212,6 +213,6 @@ Addr VG_(do_useseg) ( UInt seg_selector,
/* Come up with a suitable GDT entry. We look at the thread's TLS
- array, which is pointed to by a VG_(baseBlock) entry. */
- the_tls = (VgLdtEntry*)VG_(baseBlock)[VGOFF_(tls_ptr)];
+ array, which is pointed to by a ThreadState.arch entry. */
+ the_tls = tst->arch.tls;
base = (Addr)wine_ldt_get_base ( &the_tls[seg_selector-VKI_GDT_ENTRY_TLS_MIN] );
limit = (UInt)wine_ldt_get_limit ( &the_tls[seg_selector-VKI_GDT_ENTRY_TLS_MIN] );
@@ -222,9 +223,9 @@ Addr VG_(do_useseg) ( UInt seg_selector,
/* Come up with a suitable LDT entry. We look at the thread's LDT,
- which is pointed to by a VG_(baseBlock) entry. If null, we will
+ which is pointed to by a ThreadState.arch entry. If null, we will
use an implied zero-entry -- although this usually implies the
program is in deep trouble, since it is using LDT entries which
it probably hasn't set up. */
- the_ldt = (VgLdtEntry*)VG_(baseBlock)[VGOFF_(ldt)];
+ the_ldt = tst->arch.ldt;
if (the_ldt == NULL) {
base = 0;
--- valgrind/coregrind/x86-linux/syscall.S #1.4:1.5
@@ -150,5 +150,5 @@
Int VGA_(_client_syscall)(Int syscallno, // 0
- arch_thread_t *regs, // 4
+ ThreadState *tst, // 4
const vki_sigset_t *sysmask, // 8
vki_sigset_t *postmask, // 12
@@ -183,13 +183,12 @@
js 5f /* sigprocmask failed */
- movl 4+FSZ(%esp), %eax /* eax == arch_thread_t * */
+ movl 4+FSZ(%esp), %eax /* eax == ThreadState * */
- /* the offsets below are defined by the layout of arch_thread_t */
- movl 4(%eax), %ebx
- movl 8(%eax), %ecx
- movl 12(%eax), %edx
- movl 16(%eax), %esi
- movl 20(%eax), %edi
- movl 24(%eax), %ebp
+ movl VGOFF_ebx(%eax), %ebx
+ movl VGOFF_ecx(%eax), %ecx
+ movl VGOFF_edx(%eax), %edx
+ movl VGOFF_esi(%eax), %esi
+ movl VGOFF_edi(%eax), %edi
+ movl VGOFF_ebp(%eax), %ebp
movl 0+FSZ(%esp), %eax /* use syscallno argument rather than thread EAX */
@@ -200,5 +199,5 @@
committed to EAX. */
movl 4+FSZ(%esp), %ebx
- movl %eax, 0(%ebx) /* save back to EAX */
+ movl %eax, VGOFF_eax(%ebx) /* save back to EAX */
4: /* Re-block signals. If eip is in [4,5), then the syscall is complete and
--- valgrind/coregrind/x86-linux/syscalls.c #1.19:1.20
@@ -148,14 +148,14 @@ void VGA_(interrupted_syscall)(ThreadId
}
-extern void VGA_(_client_syscall)(Int syscallno, arch_thread_t *regs,
+extern void VGA_(_client_syscall)(Int syscallno, ThreadState *tst,
const vki_sigset_t *syscall_mask,
const vki_sigset_t *restore_mask,
Int nsigwords);
-void VGA_(client_syscall)(Int syscallno, arch_thread_t *regs,
+void VGA_(client_syscall)(Int syscallno, ThreadState *tst,
const vki_sigset_t *syscall_mask)
{
vki_sigset_t saved;
- VGA_(_client_syscall)(syscallno, regs, syscall_mask, &saved, _VKI_NSIG_WORDS * sizeof(UWord));
+ VGA_(_client_syscall)(syscallno, tst, syscall_mask, &saved, _VKI_NSIG_WORDS * sizeof(UWord));
}
@@ -314,11 +314,6 @@ static Int do_clone(ThreadId ptid,
If the clone call specifies a NULL esp for the new thread, then
it actually gets a copy of the parent's esp.
-
- Copy the parent's CPU state into the child's, in a roundabout
- way (via baseBlock). (Why?)
*/
- VGA_(load_state)(&ptst->arch, ptid);
VGA_(setup_child)( &ctst->arch, &ptst->arch );
- VGA_(save_state)(&ctst->arch, ctid);
PLATFORM_SET_SYSCALL_RESULT(ctst->arch, 0);
--- valgrind/coregrind/x86/Makefile.am #1.21:1.22
@@ -7,4 +7,5 @@
core_arch.h \
core_arch_asm.h \
+ core_arch_asm_offsets.h \
x86_private.h \
x86_private_asm.h
@@ -14,8 +15,9 @@
EXTRA_DIST = \
jmp_with_stack.c \
- libpthread.c
+ libpthread.c \
+ gen_offsets.c core_arch_asm_offsets.h
-BUILT_SOURCES = stage2.lds
-CLEANFILES = stage2.lds
+BUILT_SOURCES = stage2.lds core_arch_asm_offsets.h
+CLEANFILES = stage2.lds core_arch_asm_offsets.h
libarch_a_SOURCES = \
@@ -27,4 +29,13 @@
state.c
+# gcc should be able to autogen dependencies for these too, but
+# automake doesn't seem to know how
+cpuid.$(OBJEXT) helpers.$(OBJEXT) dispatch.$(OBJEXT): \
+ $(srcdir)/core_arch_asm.h core_arch_asm_offsets.h
+
+gen_offsets_SOURCES = gen_offsets.c
+
+noinst_PROGRAMS = gen_offsets
+
# Extract ld's default linker script and hack it to our needs
stage2.lds: Makefile
@@ -33,2 +44,6 @@
-e '/^=====\+$$/d' \
-e 's/0x08048000/kickstart_base/g' > $@ || rm -f $@
+
+# offsets
+core_arch_asm_offsets.h: gen_offsets
+ ./gen_offsets > $@ || rm -f $@
--- valgrind/coregrind/x86/core_arch.h #1.19:1.20
@@ -48,5 +48,5 @@
#define ARCH_CLREQ_RET(regs) ((regs).m_edx)
-// Accessors for the baseBlock
+// Accessors for the ThreadState
#define R_CLREQ_RET R_EDX
#define R_PTHREQ_RET R_EDX
@@ -72,57 +72,4 @@
-/* -----------------------------------------------------
- Read-write parts of baseBlock.
- -------------------------------------------------- */
-
-/* State of the simulated CPU. */
-extern Int VGOFF_(m_eax);
-extern Int VGOFF_(m_ecx);
-extern Int VGOFF_(m_edx);
-extern Int VGOFF_(m_ebx);
-extern Int VGOFF_(m_esp);
-extern Int VGOFF_(m_ebp);
-extern Int VGOFF_(m_esi);
-extern Int VGOFF_(m_edi);
-extern Int VGOFF_(m_eflags);
-extern Int VGOFF_(m_ssestate);
-extern Int VGOFF_(m_eip);
-
-extern Int VGOFF_(m_dflag); /* D flag is handled specially */
-
-extern Int VGOFF_(m_cs);
-extern Int VGOFF_(m_ss);
-extern Int VGOFF_(m_ds);
-extern Int VGOFF_(m_es);
-extern Int VGOFF_(m_fs);
-extern Int VGOFF_(m_gs);
-
-/* Reg-alloc spill area (VG_MAX_SPILLSLOTS words long). */
-extern Int VGOFF_(spillslots);
-
-/* Records the valid bits for the 8 integer regs & flags reg. */
-extern Int VGOFF_(sh_eax);
-extern Int VGOFF_(sh_ecx);
-extern Int VGOFF_(sh_edx);
-extern Int VGOFF_(sh_ebx);
-extern Int VGOFF_(sh_esp);
-extern Int VGOFF_(sh_ebp);
-extern Int VGOFF_(sh_esi);
-extern Int VGOFF_(sh_edi);
-extern Int VGOFF_(sh_eflags);
-
-/* -----------------------------------------------------
- Read-only parts of baseBlock.
- -------------------------------------------------- */
-
-/* This thread's LDT pointer. */
-extern Int VGOFF_(ldt);
-
-/* This thread's TLS pointer. */
-extern Int VGOFF_(tls_ptr);
-
-/* Nb: Most helper offsets are in include/tool.h, for use by tools */
-
-
/* ---------------------------------------------------------------------
Elf stuff
@@ -225,6 +172,18 @@ typedef struct _LDT_ENTRY {
/* ---------------------------------------------------------------------
- Constants pertaining to the simulated CPU state, VG_(baseBlock),
- which need to go here to avoid ugly circularities.
+ Miscellaneous constants
+ ------------------------------------------------------------------ */
+
+// Total number of spill slots available for register allocation.
+#define VG_MAX_SPILLSLOTS 24
+
+// Valgrind's stack size, in words.
+#define VG_STACK_SIZE_W 16384
+
+// Base address of client address space.
+#define CLIENT_BASE 0x00000000ul
+
+/* ---------------------------------------------------------------------
+ Constants pertaining to the simulated CPU state.
------------------------------------------------------------------ */
@@ -283,6 +242,5 @@ typedef struct {
Although the segment registers are 16 bits long, storage
- management here and in VG_(baseBlock) is
- simplified if we pretend they are 32 bits.
+ management here is simplified if we pretend they are 32 bits.
NOTE: the x86-linux/syscall.S requires this structure to start with m_eax-m_ebp
@@ -297,4 +255,5 @@ typedef struct {
UInt m_esp;
UInt m_eflags;
+ UInt m_dflag;
UInt m_eip;
@@ -306,4 +265,15 @@ typedef struct {
UInt m_gs;
+ /* Put shadow state near real state */
+ UInt sh_eax;
+ UInt sh_ebx;
+ UInt sh_ecx;
+ UInt sh_edx;
+ UInt sh_esi;
+ UInt sh_edi;
+ UInt sh_ebp;
+ UInt sh_esp;
+ UInt sh_eflags;
+
/* Pointer to this thread's Local (Segment) Descriptor Table.
Starts out as NULL, indicating there is no table, and we hope to
@@ -319,4 +288,9 @@ typedef struct {
VgLdtEntry tls[VKI_GDT_ENTRY_TLS_ENTRIES];
+ /* Spill slots - don't really need to be part of per-thread state,
+ since they're never live across context-switches, but it's
+ convenient for now. TODO: move onto thread stack. */
+ Word spillslots[VG_MAX_SPILLSLOTS];
+
/* The SSE/FPU state. This array does not (necessarily) have the
required 16-byte alignment required to get stuff in/out by
@@ -328,14 +302,4 @@ typedef struct {
struct i387_fxsave_struct fxsave;
} m_sse;
-
- UInt sh_eax;
- UInt sh_ebx;
- UInt sh_ecx;
- UInt sh_edx;
- UInt sh_esi;
- UInt sh_edi;
- UInt sh_ebp;
- UInt sh_esp;
- UInt sh_eflags;
}
arch_thread_t;
@@ -356,17 +320,4 @@ struct arch_thread_aux {
void VGA_(signal_return)(ThreadId tid, Bool isRT);
-/* ---------------------------------------------------------------------
- Miscellaneous constants
- ------------------------------------------------------------------ */
-
-// Total number of spill slots available for register allocation.
-#define VG_MAX_SPILLSLOTS 24
-
-// Valgrind's stack size, in words.
-#define VG_STACK_SIZE_W 16384
-
-// Base address of client address space.
-#define CLIENT_BASE 0x00000000ul
-
#endif // __X86_CORE_ARCH_H
--- valgrind/coregrind/x86/core_arch_asm.h #1.2:1.3
@@ -31,4 +31,8 @@
#define __X86_CORE_ARCH_ASM_H
+#ifndef _GEN_OFFSETS
+#include "core_arch_asm_offsets.h"
+#endif /* _GEN_OFFSETS */
+
/* size of call instruction put into generated code at jump sites */
#define VG_PATCHME_CALLSZ 5
@@ -40,7 +44,4 @@
#define VG_MAX_JUMPS 2
-/* Offset of code in a TCEntry */
-#define VG_CODE_OFFSET (8 + VG_MAX_JUMPS * 2)
-
/* Debugging hack for assembly code ... sigh. */
#if 0
--- valgrind/coregrind/x86/dispatch.S #1.3:1.4
@@ -57,11 +57,15 @@
movl VG_(tt_fast)(,reg,4), reg; \
cmpl %eax, (reg); \
- jnz fail
+ jne fail; \
+ addl $VG_CODE_OFFSET, reg
/* The C world needs a way to get started simulating. So we provide
- a function void vg_run_innerloop ( void ), which starts running
+ a function void vg_run_innerloop (), which starts running
from vg_m_eip, and exits when the counter reaches zero. This loop
- can also exit if vg_oursignalhandler() catches a non-resumable
- signal, for example SIGSEGV. It then longjmp()s back past here.
+ can also exit if it catches a synchronous signal, for example SIGSEGV.
+ It then longjmp()s back past here.
+
+ Prototype:
+ UInt VG_(run_innerloop)(ThreadState *tst);
*/
@@ -71,27 +75,24 @@
/* ----- entry point to VG_(run_innerloop) ----- */
+#define FSZ (5*4 + 4) /* 5 pushes + retaddr */
pushl %ebx
pushl %esi
pushl %edi
pushl %ebp
+ pushl %fs /* always save %fs */
/* check to see if we're doing pointer checking */
- movb VG_(clo_pointercheck), %al
- testb %al,%al
+ cmpb $0, VG_(clo_pointercheck)
jz 1f
- pushl %fs /* save %fs */
mov $(VG_POINTERCHECK_SEGIDX << 3) + 7, %eax /* load new %fs */
movw %ax,%fs
-1:
- /* Set up the baseBlock pointer */
- movl $VG_(baseBlock), %ebp
+ /* Set up the ThreadState pointer */
+1: movl FSZ(%esp), %ebp
/* fetch m_eip into %eax */
- movl VGOFF_(m_eip), %esi
- movl (%ebp, %esi, 4), %eax
+ movl VGOFF_eip(%ebp), %eax
-dispatch_main:
/* Jump here to do a new dispatch.
%eax holds destination (original) address.
@@ -99,5 +100,5 @@
requested to the address in %eax.
- If ebp == & VG_(baseBlock), just jump next to %eax.
+ If ebp == tst, just jump next to %eax.
If ebp == VG_EBP_JMP_SYSCALL, do a system call before
@@ -109,71 +110,45 @@
If %ebp has any other value, we panic.
*/
- /*cmpl $VG_(baseBlock), %ebp*/
- /*jnz dispatch_exceptional*/
- /* fall into main loop */
+ /* try a fast lookup in the translation cache */
+2: TT_LOOKUP(%ebx, fast_lookup_failed)
+
+ /* Found a match. Call the tce.payload field */
+ incl VG_(unchained_jumps_done) /* update stats */
+
+ /* call generated code */
+ call *%ebx
-dispatch_boring:
- /* save the jump address at VG_(baseBlock)[VGOFF_(m_eip)] */
- movl VGOFF_(m_eip), %esi
- movl %eax, (%ebp, %esi, 4)
+ movl FSZ(%esp), %ebx /* ebx==ThreadState */
+ /* save the jump address at tst->arch.m_eip */
+ movl %eax, VGOFF_eip(%ebx)
+
/* Are we out of timeslice? If yes, defer to scheduler. */
cmpl $0, VG_(dispatch_ctr)
jz counter_is_zero
- /* try a fast lookup in the translation cache */
- TT_LOOKUP(%ebx, fast_lookup_failed)
- /* Found a match. Call the tce.payload field (+VG_CODE_OFFSET) */
- addl $VG_CODE_OFFSET, %ebx
- incl VG_(unchained_jumps_done) /* update stats */
- call *%ebx
-
- cmpl $VG_(baseBlock), %ebp
- jz dispatch_boring
+ cmpl %ebx, %ebp
+ jz 2b /* thread still current ; keep going */
- jmp dispatch_exceptional
+ movl %ebp, %eax /* return exceptional dispatch */
+3: popl %fs
+ popl %ebp
+ popl %edi
+ popl %esi
+ popl %ebx
+ ret
fast_lookup_failed:
/* %EIP is up to date here since dispatch_boring dominates */
movl $VG_TRC_INNER_FASTMISS, %eax
- jmp run_innerloop_exit
+ jmp 3b
counter_is_zero:
/* %EIP is up to date here since dispatch_boring dominates */
movl $VG_TRC_INNER_COUNTERZERO, %eax
- jmp run_innerloop_exit
+ jmp 3b
-run_innerloop_exit:
- movb VG_(clo_pointercheck), %bl
- testb %bl,%bl
- jz 1f
-
- /* restore %fs */
- popl %fs
-
-1: popl %ebp
- popl %edi
- popl %esi
- popl %ebx
- ret
-
-
-
-/* Other ways of getting out of the inner loop. Placed out-of-line to
- make it look cleaner.
-*/
-dispatch_exceptional:
- /* this is jumped to only, not fallen-through from above */
- cmpl $VG_TRC_INNER_COUNTERZERO, %ebp
- jz counter_is_zero
-
- /* save %eax in %EIP and defer to sched */
- movl VGOFF_(m_eip), %esi
- movl %eax, VG_(baseBlock)(,%esi, 4)
- movl %ebp, %eax
- jmp run_innerloop_exit
-
/*
@@ -201,11 +176,12 @@
TT_LOOKUP(%ebx, 1f)
+ /* ebx = target eip */
+
/* Patch call instruction at callsite into a chained jmp */
- popl %eax /* eax = just after (VG_PATCHME_CALLSZ byte) call */
- addl $VG_CODE_OFFSET, %ebx /* ebx = target eip */
- subl %eax, %ebx /* ebx = delta */
- movb $0xE9, -(VG_PATCHME_CALLSZ-0)(%eax) /* 0xe9 = jmp */
- movl %ebx, -(VG_PATCHME_CALLSZ-1)(%eax) /* store delta */
- addl %eax, %ebx
+ popl %ecx /* ecx = just after (VG_PATCHME_CALLSZ byte) call */
+ subl %ecx, %ebx /* ebx = delta */
+ movb $0xE9, -(VG_PATCHME_CALLSZ-0)(%ecx) /* 0xe9 = jmp */
+ movl %ebx, -(VG_PATCHME_CALLSZ-1)(%ecx) /* store delta */
+ addl %ecx, %ebx
incl VG_(bb_enchain_count) /* update stats */
jmp *%ebx /* jmp to dest */
--- valgrind/coregrind/x86/helpers.S #1.3:1.4
@@ -241,20 +241,18 @@
VG_(helper_fstsw_AX):
pushl %eax
- pushl %esi
- movl VGOFF_(m_ssestate), %esi
pushfl
cmpb $0, VG_(have_ssestate)
jz aa1nosse
- fxrstor (%ebp, %esi, 4)
+ fxrstor VGOFF_sse(%ebp)
jmp aa1merge
aa1nosse:
- frstor (%ebp, %esi, 4)
+ frstor VGOFF_sse(%ebp)
aa1merge:
popfl
fstsw %ax
- popl %esi
movw %ax, 8(%esp)
+
popl %eax
ret
@@ -487,6 +485,5 @@
pushl %eax
- movl VGOFF_(m_dflag), %eax
- movl (%ebp, %eax, 4), %eax
+ movl VGOFF_dflag(%ebp), %eax
movl %eax, 8(%esp)
@@ -497,20 +494,10 @@
.global VG_(helper_CLD)
VG_(helper_CLD):
- pushl %eax
-
- movl VGOFF_(m_dflag), %eax
- movl $1, (%ebp, %eax, 4)
-
- popl %eax
+ movl $1, VGOFF_dflag(%ebp)
ret
.global VG_(helper_STD)
VG_(helper_STD):
- pushl %eax
-
- movl VGOFF_(m_dflag), %eax
- movl $-1, (%ebp, %eax, 4)
-
- popl %eax
+ movl $-1, VGOFF_dflag(%ebp)
ret
--- valgrind/coregrind/x86/signal.c #1.11:1.12
@@ -639,27 +639,4 @@ void VGA_(signal_return)(ThreadId tid, B
/*------------------------------------------------------------*/
-void VGA_(fill_elfregs_from_BB)(struct vki_user_regs_struct* regs)
-{
- regs->eflags = VG_(baseBlock)[VGOFF_(m_eflags)];
- regs->esp = VG_(baseBlock)[VGOFF_(m_esp)];
- regs->eip = VG_(baseBlock)[VGOFF_(m_eip)];
-
- regs->ebx = VG_(baseBlock)[VGOFF_(m_ebx)];
- regs->ecx = VG_(baseBlock)[VGOFF_(m_ecx)];
- regs->edx = VG_(baseBlock)[VGOFF_(m_edx)];
- regs->esi = VG_(baseBlock)[VGOFF_(m_esi)];
- regs->edi = VG_(baseBlock)[VGOFF_(m_edi)];
- regs->ebp = VG_(baseBlock)[VGOFF_(m_ebp)];
- regs->eax = VG_(baseBlock)[VGOFF_(m_eax)];
-
- regs->cs = VG_(baseBlock)[VGOFF_(m_cs)];
- regs->ds = VG_(baseBlock)[VGOFF_(m_ds)];
- regs->ss = VG_(baseBlock)[VGOFF_(m_ss)];
- regs->es = VG_(baseBlock)[VGOFF_(m_es)];
- regs->fs = VG_(baseBlock)[VGOFF_(m_fs)];
- regs->gs = VG_(baseBlock)[VGOFF_(m_gs)];
-}
-
-
void VGA_(fill_elfregs_from_tst)(struct vki_user_regs_struct* regs,
const arch_thread_t* arch)
@@ -703,9 +680,4 @@ static void fill_fpu(vki_elf_fpregset_t
}
-void VGA_(fill_elffpregs_from_BB)( vki_elf_fpregset_t* fpu )
-{
- fill_fpu(fpu, (const Char *)&VG_(baseBlock)[VGOFF_(m_ssestate)]);
-}
-
void VGA_(fill_elffpregs_from_tst)( vki_elf_fpregset_t*...
[truncated message content] |