You can subscribe to this list here.
| 2002 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
(122) |
Nov
(152) |
Dec
(69) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2003 |
Jan
(6) |
Feb
(25) |
Mar
(73) |
Apr
(82) |
May
(24) |
Jun
(25) |
Jul
(10) |
Aug
(11) |
Sep
(10) |
Oct
(54) |
Nov
(203) |
Dec
(182) |
| 2004 |
Jan
(307) |
Feb
(305) |
Mar
(430) |
Apr
(312) |
May
(187) |
Jun
(342) |
Jul
(487) |
Aug
(637) |
Sep
(336) |
Oct
(373) |
Nov
(441) |
Dec
(210) |
| 2005 |
Jan
(385) |
Feb
(480) |
Mar
(636) |
Apr
(544) |
May
(679) |
Jun
(625) |
Jul
(810) |
Aug
(838) |
Sep
(634) |
Oct
(521) |
Nov
(965) |
Dec
(543) |
| 2006 |
Jan
(494) |
Feb
(431) |
Mar
(546) |
Apr
(411) |
May
(406) |
Jun
(322) |
Jul
(256) |
Aug
(401) |
Sep
(345) |
Oct
(542) |
Nov
(308) |
Dec
(481) |
| 2007 |
Jan
(427) |
Feb
(326) |
Mar
(367) |
Apr
(255) |
May
(244) |
Jun
(204) |
Jul
(223) |
Aug
(231) |
Sep
(354) |
Oct
(374) |
Nov
(497) |
Dec
(362) |
| 2008 |
Jan
(322) |
Feb
(482) |
Mar
(658) |
Apr
(422) |
May
(476) |
Jun
(396) |
Jul
(455) |
Aug
(267) |
Sep
(280) |
Oct
(253) |
Nov
(232) |
Dec
(304) |
| 2009 |
Jan
(486) |
Feb
(470) |
Mar
(458) |
Apr
(423) |
May
(696) |
Jun
(461) |
Jul
(551) |
Aug
(575) |
Sep
(134) |
Oct
(110) |
Nov
(157) |
Dec
(102) |
| 2010 |
Jan
(226) |
Feb
(86) |
Mar
(147) |
Apr
(117) |
May
(107) |
Jun
(203) |
Jul
(193) |
Aug
(238) |
Sep
(300) |
Oct
(246) |
Nov
(23) |
Dec
(75) |
| 2011 |
Jan
(133) |
Feb
(195) |
Mar
(315) |
Apr
(200) |
May
(267) |
Jun
(293) |
Jul
(353) |
Aug
(237) |
Sep
(278) |
Oct
(611) |
Nov
(274) |
Dec
(260) |
| 2012 |
Jan
(303) |
Feb
(391) |
Mar
(417) |
Apr
(441) |
May
(488) |
Jun
(655) |
Jul
(590) |
Aug
(610) |
Sep
(526) |
Oct
(478) |
Nov
(359) |
Dec
(372) |
| 2013 |
Jan
(467) |
Feb
(226) |
Mar
(391) |
Apr
(281) |
May
(299) |
Jun
(252) |
Jul
(311) |
Aug
(352) |
Sep
(481) |
Oct
(571) |
Nov
(222) |
Dec
(231) |
| 2014 |
Jan
(185) |
Feb
(329) |
Mar
(245) |
Apr
(238) |
May
(281) |
Jun
(399) |
Jul
(382) |
Aug
(500) |
Sep
(579) |
Oct
(435) |
Nov
(487) |
Dec
(256) |
| 2015 |
Jan
(338) |
Feb
(357) |
Mar
(330) |
Apr
(294) |
May
(191) |
Jun
(108) |
Jul
(142) |
Aug
(261) |
Sep
(190) |
Oct
(54) |
Nov
(83) |
Dec
(22) |
| 2016 |
Jan
(49) |
Feb
(89) |
Mar
(33) |
Apr
(50) |
May
(27) |
Jun
(34) |
Jul
(53) |
Aug
(53) |
Sep
(98) |
Oct
(206) |
Nov
(93) |
Dec
(53) |
| 2017 |
Jan
(65) |
Feb
(82) |
Mar
(102) |
Apr
(86) |
May
(187) |
Jun
(67) |
Jul
(23) |
Aug
(93) |
Sep
(65) |
Oct
(45) |
Nov
(35) |
Dec
(17) |
| 2018 |
Jan
(26) |
Feb
(35) |
Mar
(38) |
Apr
(32) |
May
(8) |
Jun
(43) |
Jul
(27) |
Aug
(30) |
Sep
(43) |
Oct
(42) |
Nov
(38) |
Dec
(67) |
| 2019 |
Jan
(32) |
Feb
(37) |
Mar
(53) |
Apr
(64) |
May
(49) |
Jun
(18) |
Jul
(14) |
Aug
(53) |
Sep
(25) |
Oct
(30) |
Nov
(49) |
Dec
(31) |
| 2020 |
Jan
(87) |
Feb
(45) |
Mar
(37) |
Apr
(51) |
May
(99) |
Jun
(36) |
Jul
(11) |
Aug
(14) |
Sep
(20) |
Oct
(24) |
Nov
(40) |
Dec
(23) |
| 2021 |
Jan
(14) |
Feb
(53) |
Mar
(85) |
Apr
(15) |
May
(19) |
Jun
(3) |
Jul
(14) |
Aug
(1) |
Sep
(57) |
Oct
(73) |
Nov
(56) |
Dec
(22) |
| 2022 |
Jan
(3) |
Feb
(22) |
Mar
(6) |
Apr
(55) |
May
(46) |
Jun
(39) |
Jul
(15) |
Aug
(9) |
Sep
(11) |
Oct
(34) |
Nov
(20) |
Dec
(36) |
| 2023 |
Jan
(79) |
Feb
(41) |
Mar
(99) |
Apr
(169) |
May
(48) |
Jun
(16) |
Jul
(16) |
Aug
(57) |
Sep
(19) |
Oct
|
Nov
|
Dec
|
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
|
|
|
1
(15) |
2
(12) |
3
(11) |
4
(20) |
5
(6) |
|
6
(6) |
7
(7) |
8
(8) |
9
(17) |
10
(25) |
11
(27) |
12
(6) |
|
13
(28) |
14
(16) |
15
(20) |
16
(9) |
17
(26) |
18
(7) |
19
(25) |
|
20
(7) |
21
(18) |
22
(25) |
23
(15) |
24
(21) |
25
(32) |
26
(15) |
|
27
(23) |
28
(33) |
|
|
|
|
|
|
From: Nicholas N. <nj...@cs...> - 2005-02-01 23:45:55
|
On Tue, 1 Feb 2005, Jeremy Fitzhardinge wrote: > I also checked in some improvements to the handling of dispatch_ctr. It > is per-thread rather than global, and so is easily accessible as an > offset from %ebp. This reduces the per-basic block preamble from 15 > bytes to 7 (16->8 if you use --branchpred=yes). It also makes the > meaning of dispatch_ctr a bit more precise. It used to mean "switch > contexts after 50k BBs were run, regardless of which thread", now it > means "switch after this thread runs 50k BBs" - the difference probably > isn't significant at the moment. Hmm, nice :) N |
|
From: Jeremy F. <je...@go...> - 2005-02-01 23:06:40
|
I just checked in a series of patches which remove the baseBlock and all its uses. The main reason for this was to simplify the code (~1000 lines gone), and to simplify accessing the CPU state. There's now only one place to look for VCPU state - the thread's ThreadState. While generated code is running, %ebp points to the thread's entry in VG_(threads). I also checked in some improvements to the handling of dispatch_ctr. It is per-thread rather than global, and so is easily accessible as an offset from %ebp. This reduces the per-basic block preamble from 15 bytes to 7 (16->8 if you use --branchpred=yes). It also makes the meaning of dispatch_ctr a bit more precise. It used to mean "switch contexts after 50k BBs were run, regardless of which thread", now it means "switch after this thread runs 50k BBs" - the difference probably isn't significant at the moment. The result of these changes gave me pretty significant performance improvements; ~7% for a single threaded CPU-bound task (gcc's cc1 on vg_from_ucode.i). The cost of a context switch is much cheaper now, since there's no copying between baseBlock<->ThreadState, so programs which do lots of syscalls or client requests could be significantly faster. The Tool interface is mostly unchanged. VG_(get_VCPU_thread)() doesn't mean quite the same thing as before (it used to mean "thread who's state is in the baseBlock"; now it means "thread currently holding the run_sema"), but as far as I can tell it hasn't made a difference. The one change I had to make was add a ThreadId argument to post_regs_write_init, since there's no thread actually running at that point. J |
|
From: Jeremy F. <je...@go...> - 2005-02-01 22:53:33
|
CVS commit by fitzhardinge:
Make dispatch_ctr a piece of per-thread state. This allows a the BB
preamble to use %ebp-relative addressing to decrement it; combined
with the cleanups in remove-baseblock.patch, this halves the size of
the BB preamble from 16 to 8 bytes.
The other reason for doing this is that it makes the semantics of
dispatch_ctr well defined; previously it only made certain that no one
thread could hog the VCPU; now it defines how many BBs a thread can
run before it is preempted.
M +3 -6 core.h 1.76
M +7 -6 vg_from_ucode.c 1.89
M +91 -127 vg_scheduler.c 1.218
M +1 -1 x86/dispatch.S 1.5
M +3 -0 x86/gen_offsets.c 1.2
--- valgrind/coregrind/core.h #1.75:1.76
@@ -643,4 +643,7 @@ struct _ThreadState {
VgSchedReturnCode exitreason;
+ /* Basic blocks remaining before timeslice up */
+ UInt dispatch_ctr;
+
/* Architecture-specific thread state
Leave early in the structure to make offsets small
@@ -765,10 +768,4 @@ extern void VG_(set_sleeping) ( ThreadId
extern void VG_(vg_yield)(void);
-/* Give a hint to the scheduler that it may be a good time to find a
- new runnable thread. If prefer_sched != VG_INVALID_THREADID, then
- try to schedule that thread.
-*/
-extern void VG_(need_resched) ( ThreadId prefer_sched );
-
// The scheduler.
extern VgSchedReturnCode VG_(scheduler) ( ThreadId tid );
--- valgrind/coregrind/vg_from_ucode.c #1.88:1.89
@@ -4428,15 +4428,16 @@ UChar* VG_(emit_code) ( UCodeBlock* cb,
if (dis) VG_(printf)("Generated x86 code:\n");
- /* Generate subl $1, VG_(dispatch_ctr) and drop into dispatch if we hit
- zero. We have to do this regardless of whether we're t-chaining
- or not. (The ia32 optimisation guide recommends sub over dec.) */
+ /* Generate subl $1, dispatch_ctr(%ebp) and drop into dispatch if
+ we hit zero. We have to do this regardless of whether we're
+ t-chaining or not. (The ia32 optimisation guide recommends sub
+ over dec.) */
VG_(init_target)(&tgt);
VG_(new_emit)(False, FlagsEmpty, FlagsOSZAP);
- VG_(emitB) (0x83); /* subl */
- emit_amode_litmem_reg((Addr)&VG_(dispatch_ctr), 5);
+ VG_(emitB) (0x83); /* grp1 */
+ VG_(emit_amode_offregmem_reg)(offsetof(ThreadState, dispatch_ctr), R_EBP, mkGrp1opcode(SUB));
VG_(emitB) (0x01);
if (dis)
- VG_(printf)("\n\t\tsubl $1, (%p)\n", &VG_(dispatch_ctr));
+ VG_(printf)("\n\t\tsubl $1, %d(%%ebp)\n", offsetof(ThreadState, dispatch_ctr));
/* Don't bother setting EBP; the dispatch loop can work it out for
--- valgrind/coregrind/vg_scheduler.c #1.217:1.218
@@ -496,4 +496,6 @@ void mostly_clear_thread_record ( Thread
VG_(threads)[tid].status = VgTs_Zombie;
+ VG_(threads)[tid].dispatch_ctr = 0;
+
VG_(threads)[tid].syscallno = -1;
@@ -641,6 +643,4 @@ VgSchedReturnCode VG_(scheduler) ( Threa
{
UInt trc;
- UInt dispatch_ctr_SAVED;
- Int done_this_time;
ThreadState *tst = VG_(get_ThreadState)(tid);
@@ -653,4 +653,16 @@ VgSchedReturnCode VG_(scheduler) ( Threa
while(!VG_(is_exiting)(tid)) {
+ UInt remaining_bbs;
+
+ if (tst->dispatch_ctr == 0) {
+ /* Our slice is done, so yield the CPU to another thread. This
+ doesn't sleep between sleeping and running, since that would
+ take too much time. */
+ VG_(set_sleeping)(tid, VgTs_Yielding);
+ /* nothing */
+ VG_(set_running)(tid);
+ VG_TRACK( thread_run, tid );
+
+ /* OK, do some relatively expensive housekeeping stuff */
scheduler_sanity(tid);
VG_(sanity_check_general)(False);
@@ -663,24 +675,18 @@ VgSchedReturnCode VG_(scheduler) ( Threa
n_scheduling_events_MAJOR++;
- VG_TRACK( thread_run, tid );
-
/* Figure out how many bbs to ask vg_run_innerloop to do. Note
that it decrements the counter before testing it for zero, so
- that if VG_(dispatch_ctr) is set to N you get at most N-1
- iterations. Also this means that VG_(dispatch_ctr) must
+ that if tst->dispatch_ctr is set to N you get at most N-1
+ iterations. Also this means that tst->dispatch_ctr must
exceed zero before entering the innerloop. Also also, the
decrement is done before the bb is actually run, so you
always get at least one decrement even if nothing happens. */
- VG_(dispatch_ctr) = VG_SCHEDULING_QUANTUM + 1;
-
- /* ... and remember what we asked for. */
- dispatch_ctr_SAVED = VG_(dispatch_ctr);
+ tst->dispatch_ctr = VG_SCHEDULING_QUANTUM + 1;
/* paranoia ... */
vg_assert(tst->tid == tid);
vg_assert(tst->os_state.lwpid == VG_(gettid)());
+ }
- /* Actually run the thread for a timeslice. */
- while(!VG_(is_exiting)(tid) && VG_(dispatch_ctr) > 0) {
/* For stats purposes only. */
n_scheduling_events_MINOR++;
@@ -688,8 +694,12 @@ VgSchedReturnCode VG_(scheduler) ( Threa
if (0)
VG_(message)(Vg_DebugMsg, "thread %d: running for %d bbs",
- tid, VG_(dispatch_ctr) - 1 );
+ tid, tst->dispatch_ctr - 1 );
+
+ remaining_bbs = tst->dispatch_ctr;
trc = run_thread_for_a_while ( tid );
+ VG_(bbs_done) += remaining_bbs - tst->dispatch_ctr;
+
if (VG_(clo_trace_sched) && VG_(clo_verbosity) > 2) {
Char buf[50];
@@ -698,10 +708,7 @@ VgSchedReturnCode VG_(scheduler) ( Threa
}
- done_this_time = (Int)dispatch_ctr_SAVED - (Int)VG_(dispatch_ctr);
- VG_(bbs_done) += (ULong)done_this_time;
-
switch(trc) {
case VG_TRC_INNER_FASTMISS:
- vg_assert(VG_(dispatch_ctr) > 0);
+ vg_assert(tst->dispatch_ctr > 0);
handle_tt_miss(tid);
break;
@@ -718,10 +725,10 @@ VgSchedReturnCode VG_(scheduler) ( Threa
/* Explicit yield, because this thread is in a spin-lock
or something. Let another thread run ASAP. */
- VG_(dispatch_ctr) = 0;
+ tst->dispatch_ctr = 0;
break;
case VG_TRC_INNER_COUNTERZERO:
/* Timeslice is out. Let a new thread be scheduled. */
- vg_assert(VG_(dispatch_ctr) == 0);
+ vg_assert(tst->dispatch_ctr == 0);
break;
@@ -744,12 +751,4 @@ VgSchedReturnCode VG_(scheduler) ( Threa
}
- /* Our slice is done, so yield the CPU to another thread. This
- doesn't sleep between sleeping and running, since that would
- take too much time. */
- VG_(set_sleeping)(tid, VgTs_Yielding);
- /* nothing */
- VG_(set_running)(tid);
- }
-
vg_assert(VG_(is_exiting)(tid));
@@ -759,39 +758,4 @@ VgSchedReturnCode VG_(scheduler) ( Threa
}
-void VG_(need_resched) ( ThreadId prefer )
-{
- /* Tell the scheduler now might be a good time to find a new
- runnable thread, because something happened which woke a thread
- up.
-
- NB: This can be called unsynchronized from either a signal
- handler, or from another LWP (ie, real kernel thread).
-
- In principle this could simply be a matter of setting
- VG_(dispatch_ctr) to a small value (say, 2), which would make
- any running code come back to the scheduler fairly quickly.
-
- However, since the scheduler implements a strict round-robin
- policy with only one priority level, there are, by definition,
- no better threads to be running than the current thread anyway,
- so we may as well ignore this hint. For processes with a
- mixture of compute and I/O bound threads, this means the compute
- threads could introduce longish latencies before the I/O threads
- run. For programs with only I/O bound threads, need_resched
- won't have any effect anyway.
-
- OK, so I've added command-line switches to enable low-latency
- syscalls and signals. The prefer_sched variable is in effect
- the ID of a single thread which has higher priority than all the
- others. If set, the scheduler will prefer to schedule that
- thread over all others. Naturally, this could lead to
- starvation or other unfairness.
- */
-
- if (VG_(dispatch_ctr) > 10)
- VG_(dispatch_ctr) = 2;
-
- (void)prefer; /* kernel's doing the selection, so we can't use this */
-}
/*
--- valgrind/coregrind/x86/gen_offsets.c #1.1:1.2
@@ -13,4 +13,7 @@ int main(int argc, char **argv)
printf("#define VG_CODE_OFFSET %d\n", offsetof(TCEntry, payload));
+ printf("\n/* offset of dispatch_ctr in ThreadState */\n");
+ printf("#define VGOFF_DISPATCH_CTR %d\n", offsetof(ThreadState, dispatch_ctr));
+
/* register offsets into struct ThreadState */
printf("\n/* register offsets in ThreadState */\n");
--- valgrind/coregrind/x86/dispatch.S #1.4:1.5
@@ -126,5 +126,5 @@
/* Are we out of timeslice? If yes, defer to scheduler. */
- cmpl $0, VG_(dispatch_ctr)
+ cmpl $0, VGOFF_DISPATCH_CTR(%ebx)
jz counter_is_zero
|
|
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] |
|
From: Jeremy F. <je...@go...> - 2005-02-01 22:53:09
|
CVS commit by fitzhardinge:
Remove all helper entries in the baseblock. Converts all callers to
directly call the appropriate function. This eliminates all the
helper-registration stuff, and the requirement that helpers be
registered at all.
M +0 -9 addrcheck/ac_main.c 1.72
M +0 -5 cachegrind/cg_main.c 1.83
M +0 -4 coregrind/core.h 1.74
M +6 -40 coregrind/vg_from_ucode.c 1.87
M +0 -126 coregrind/vg_main.c 1.241
M +81 -58 coregrind/vg_to_ucode.c 1.153
M +1 -1 coregrind/vg_translate.c 1.97
M +50 -49 coregrind/x86/core_arch.h 1.19
M +0 -90 coregrind/x86/state.c 1.15
M +0 -13 helgrind/hg_main.c 1.93
M +2 -10 include/tool.h.base 1.21
M +0 -7 lackey/lk_main.c 1.26
M +4 -5 memcheck/mc_from_ucode.c 1.16
M +0 -16 memcheck/mc_main.c 1.57
--- valgrind/coregrind/core.h #1.73:1.74
@@ -301,6 +301,4 @@ extern Bool VG_(clo_run_libc_freeres);
/* Use the basic-block chaining optimisation? Default: YES */
extern Bool VG_(clo_chain_bb);
-/* Use direct jumps to helper functions? Default: YES */
-extern Bool VG_(clo_direct_helpers);
/* Generate branch-prediction hints? */
extern Bool VG_(clo_branchpred);
@@ -1689,6 +1687,4 @@ extern UChar VG_(patch_me)[];
------------------------------------------------------------------ */
-extern void VG_(helper_undefined_instruction);
-
/* Information about trampoline code (for signal return and syscalls) */
extern const Char VG_(trampoline_code_start);
--- valgrind/coregrind/vg_main.c #1.240:1.241
@@ -1500,5 +1500,4 @@ Bool VG_(clo_run_libc_freeres) = True;
Bool VG_(clo_track_fds) = False;
Bool VG_(clo_chain_bb) = True;
-Bool VG_(clo_direct_helpers) = True;
Bool VG_(clo_show_below_main) = False;
Bool VG_(clo_pointercheck) = True;
@@ -1559,5 +1558,4 @@ void usage ( Bool debug_help )
" --profile=no|yes profile? (tool must be built for it) [no]\n"
" --chain-bb=no|yes do basic-block chaining? [yes]\n"
-" --direct-helpers=yes|no call helpers directly? [yes]\n"
" --branchpred=yes|no generate branch prediction hints [no]\n"
" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
@@ -1717,5 +1715,4 @@ static void process_cmd_line_options( UI
else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
else VG_BOOL_CLO("--chain-bb", VG_(clo_chain_bb))
- else VG_BOOL_CLO("--direct-helpers", VG_(clo_direct_helpers))
else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
@@ -2126,23 +2123,4 @@ static void setup_file_descriptors(void)
/*====================================================================*/
-Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
-
-/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
- * increased too much, they won't really be compact any more... */
-#define MAX_COMPACT_HELPERS 8
-#define MAX_NONCOMPACT_HELPERS 50
-
-/* For storing tool-specific helpers, determined at runtime. The addr
- * and offset arrays together form a (addr, offset) map that allows a
- * helper's baseBlock offset to be computed from its address. It's done
- * like this so CCALLs can use the function address rather than having to
- * muck around with offsets. */
-static UInt VG_(n_compact_helpers) = 0;
-static UInt VG_(n_noncompact_helpers) = 0;
-static Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
-static Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
-static Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
-static Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
-
/* This is the actual defn of baseblock. */
UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
@@ -2179,41 +2157,4 @@ Int VG_(alloc_BaB_1_set) ( Addr a )
}
-/* Registers a function in compact_helper_addrs; compact_helper_offsets is
- filled in later. */
-void VG_(register_compact_helper)(Addr a)
-{
- if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
- VG_(printf)("Can only register %d compact helpers\n",
- MAX_COMPACT_HELPERS);
- VG_(core_panic)("Too many compact helpers registered");
- }
- VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
- VG_(n_compact_helpers)++;
-}
-
-/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
- * is filled in later.
- */
-void VG_(register_noncompact_helper)(Addr a)
-{
- if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
- VG_(printf)("Can only register %d non-compact helpers\n",
- MAX_NONCOMPACT_HELPERS);
- VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
- VG_(core_panic)("Too many non-compact helpers registered");
- }
- VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
- VG_(n_noncompact_helpers)++;
-}
-
-/* Allocate offsets in baseBlock for the tool helpers */
-static
-void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
-{
- UInt i;
- for (i = 0; i < n; i++)
- offsets[i] = VG_(alloc_BaB_1_set)( addrs[i] );
-}
-
Bool VG_(need_to_handle_SP_assignment)(void)
{
@@ -2239,74 +2180,7 @@ static void init_baseBlock ( Addr client
{
VGA_(init_low_baseBlock)(client_eip, sp_at_startup);
-
- /* Allocate slots for compact helpers */
- assign_helpers_in_baseBlock(VG_(n_compact_helpers),
- VG_(compact_helper_offsets),
- VG_(compact_helper_addrs));
-
VGA_(init_high_baseBlock)(client_eip, sp_at_startup);
-
-#define REG(kind, size) \
- if (VG_(defined_##kind##_mem_stack##size)()) \
- VG_(register_noncompact_helper)( \
- (Addr) VG_(tool_interface).track_##kind##_mem_stack##size );
- REG(new, _8);
- REG(new, _12);
- REG(new, _16);
- REG(new, _32);
- REG(new, );
- REG(die, _8);
- REG(die, _12);
- REG(die, _16);
- REG(die, _32);
- REG(die, );
-#undef REG
-
- if (VG_(need_to_handle_SP_assignment)())
- VG_(register_noncompact_helper)((Addr) VG_(unknown_SP_update));
-
- VGOFF_(helper_undefined_instruction)
- = VG_(alloc_BaB_1_set)( (Addr) & VG_(helper_undefined_instruction));
-
- /* Allocate slots for noncompact helpers */
- assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
- VG_(noncompact_helper_offsets),
- VG_(noncompact_helper_addrs));
}
-// Finds the baseBlock offset of a tool-specified helper.
-// Searches through compacts first, then non-compacts.
-Int VG_(helper_offset)(Addr a)
-{
- UInt i;
- Char buf[100];
-
- for (i = 0; i < VG_(n_compact_helpers); i++)
- if (VG_(compact_helper_addrs)[i] == a)
- return VG_(compact_helper_offsets)[i];
- for (i = 0; i < VG_(n_noncompact_helpers); i++)
- if (VG_(noncompact_helper_addrs)[i] == a)
- return VG_(noncompact_helper_offsets)[i];
-
- /* Shouldn't get here */
- VG_(get_fnname) ( a, buf, 100 );
-
- VG_(printf)(
- "\nCouldn't find offset of helper from its address (%p: %s).\n"
- "A helper function probably used hasn't been registered?\n\n", a, buf);
-
- VG_(printf)(" compact helpers: ");
- for (i = 0; i < VG_(n_compact_helpers); i++)
- VG_(printf)("%p ", VG_(compact_helper_addrs)[i]);
-
- VG_(printf)("\n non-compact helpers: ");
- for (i = 0; i < VG_(n_noncompact_helpers); i++)
- VG_(printf)("%p ", VG_(noncompact_helper_addrs)[i]);
-
- VG_(printf)("\n");
- VG_(skin_panic)("Unfound helper");
-}
-
-
/*====================================================================*/
/*=== Initialise program data/text, etc. ===*/
--- valgrind/coregrind/vg_from_ucode.c #1.86:1.87
@@ -1994,24 +1994,4 @@ void emit_call_abs(Bool simd_flags, Addr
}
-static
-void emit_call_star_EBP_off ( Bool simd_flags, Int byte_off,
- FlagSet use_flag, FlagSet set_flag )
-{
- /* Used for helpers which expect to see Simd flags in Real flags */
- VG_(new_emit)(simd_flags, use_flag, set_flag);
-
- if (byte_off < -128 || byte_off > 127) {
- VG_(emitB) ( 0xFF );
- VG_(emitB) ( 0x95 );
- VG_(emitL) ( byte_off );
- } else {
- VG_(emitB) ( 0xFF );
- VG_(emitB) ( 0x55 );
- VG_(emitB) ( byte_off );
- }
- if (dis)
- VG_(printf)( "\n\t\tcall * %d(%%ebp)\n", byte_off );
-}
-
#if 0
/* evidently unused */
@@ -2374,21 +2354,8 @@ static Condcode invertCondition ( Condco
/* Synthesise a call to a helper.
*/
-void VG_(synth_call) ( Bool ensure_shortform, Int word_offset,
- Bool simd_flags, FlagSet use_flags, FlagSet set_flags )
+void VG_(synth_call) ( Addr target, Bool simd_flags, FlagSet use_flags, FlagSet set_flags )
{
- vg_assert(word_offset >= 0);
- vg_assert(word_offset < VG_BASEBLOCK_WORDS);
- if (ensure_shortform) {
- vg_assert(word_offset < 32);
- }
- if (VG_(clo_direct_helpers)) {
/* Call the helper directly */
- Addr target = VG_(baseBlock)[word_offset];
emit_call_abs ( simd_flags, target, use_flags, set_flags );
- } else {
- /* Call the helper via the baseBlock: *baseBlock[offset], ie,
- call * (4 x offset)(%ebp). */
- emit_call_star_EBP_off ( simd_flags, 4 * word_offset, use_flags, set_flags );
- }
}
@@ -2603,5 +2570,5 @@ void VG_(synth_ccall) ( Addr fn, Int arg
/* Call the function - may trash all flags */
- VG_(synth_call) ( False, VG_(helper_offset) ( fn ), False,
+ VG_(synth_call) ( fn, False,
FlagsEmpty, FlagsOSZACP );
@@ -4008,5 +3975,5 @@ static void emitUInstr ( UCodeBlock* cb,
case CALLM:
- vg_assert(u->tag1 == Lit16);
+ vg_assert(u->tag1 == Literal);
vg_assert(u->tag2 == NoValue);
vg_assert(u->size == 0);
@@ -4018,6 +3985,5 @@ static void emitUInstr ( UCodeBlock* cb,
instruction (and therefore operates on Real flags and
registers) */
- VG_(synth_call) ( False, u->val1,
- True, u->flags_r, u->flags_w );
+ VG_(synth_call) ( u->lit32, True, u->flags_r, u->flags_w );
break;
--- valgrind/coregrind/vg_to_ucode.c #1.152:1.153
@@ -1352,17 +1352,17 @@ static
void codegen_div ( UCodeBlock* cb, Int sz, Int t, Bool signed_divide )
{
- Int helper;
+ const Char *helper;
Int ta = newTemp(cb);
Int td = newTemp(cb);
switch (sz) {
- case 4: helper = (signed_divide ? VGOFF_(helper_idiv_64_32)
- : VGOFF_(helper_div_64_32));
+ case 4: helper = (signed_divide ? VG_(helper_idiv_64_32)
+ : VG_(helper_div_64_32));
break;
- case 2: helper = (signed_divide ? VGOFF_(helper_idiv_32_16)
- : VGOFF_(helper_div_32_16));
+ case 2: helper = (signed_divide ? VG_(helper_idiv_32_16)
+ : VG_(helper_div_32_16));
break;
- case 1: helper = (signed_divide ? VGOFF_(helper_idiv_16_8)
- : VGOFF_(helper_div_16_8));
+ case 1: helper = (signed_divide ? VG_(helper_idiv_16_8)
+ : VG_(helper_div_16_8));
break;
default: VG_(core_panic)("codegen_div");
@@ -1375,5 +1375,6 @@ void codegen_div ( UCodeBlock* cb, Int s
uInstr2(cb, GET, sz, ArchReg, R_EDX, TempReg, td);
uInstr1(cb, PUSH, sz, TempReg, td);
- uInstr1(cb, CALLM, 0, Lit16, helper);
+ uInstr1(cb, CALLM, 0, Literal, 0);
+ uLiteral(cb, (Addr)helper);
uFlagsRWU(cb, FlagsEmpty, FlagsEmpty, FlagsOSZACP);
uInstr1(cb, POP, sz, TempReg, t);
@@ -1389,5 +1390,6 @@ void codegen_div ( UCodeBlock* cb, Int s
uLiteral(cb, 0);
uInstr1(cb, PUSH, 1, TempReg, td);
- uInstr1(cb, CALLM, 0, Lit16, helper);
+ uInstr1(cb, CALLM, 0, Literal, 0);
+ uLiteral(cb, (Addr)helper);
uFlagsRWU(cb, FlagsEmpty, FlagsEmpty, FlagsOSZACP);
uInstr1(cb, POP, 1, TempReg, t);
@@ -1686,13 +1688,13 @@ static void codegen_mul_A_D_Reg ( UCodeB
UChar modrm, Bool signed_multiply )
{
- Int helper = signed_multiply
+ const Char *helper = signed_multiply
?
- (sz==1 ? VGOFF_(helper_imul_8_16)
- : (sz==2 ? VGOFF_(helper_imul_16_32)
- : VGOFF_(helper_imul_32_64)))
+ (sz==1 ? VG_(helper_imul_8_16)
+ : (sz==2 ? VG_(helper_imul_16_32)
+ : VG_(helper_imul_32_64)))
:
- (sz==1 ? VGOFF_(helper_mul_8_16)
- : (sz==2 ? VGOFF_(helper_mul_16_32)
- : VGOFF_(helper_mul_32_64)));
+ (sz==1 ? VG_(helper_mul_8_16)
+ : (sz==2 ? VG_(helper_mul_16_32)
+ : VG_(helper_mul_32_64)));
Int t1 = newTemp(cb);
Int ta = newTemp(cb);
@@ -1702,5 +1704,6 @@ static void codegen_mul_A_D_Reg ( UCodeB
uInstr2(cb, GET, sz, ArchReg, R_EAX, TempReg, ta);
uInstr1(cb, PUSH, sz, TempReg, ta);
- uInstr1(cb, CALLM, 0, Lit16, helper);
+ uInstr1(cb, CALLM, 0, Literal, 0);
+ uLiteral(cb, (Addr)helper);
uFlagsRWU(cb, FlagsEmpty, FlagsOC, FlagsSZAP);
if (sz > 1) {
@@ -1727,13 +1730,13 @@ static void codegen_mul_A_D_Temp ( UCode
UChar* dis_buf )
{
- Int helper = signed_multiply
+ const Char *helper = signed_multiply
?
- (sz==1 ? VGOFF_(helper_imul_8_16)
- : (sz==2 ? VGOFF_(helper_imul_16_32)
- : VGOFF_(helper_imul_32_64)))
+ (sz==1 ? VG_(helper_imul_8_16)
+ : (sz==2 ? VG_(helper_imul_16_32)
+ : VG_(helper_imul_32_64)))
:
- (sz==1 ? VGOFF_(helper_mul_8_16)
- : (sz==2 ? VGOFF_(helper_mul_16_32)
- : VGOFF_(helper_mul_32_64)));
+ (sz==1 ? VG_(helper_mul_8_16)
+ : (sz==2 ? VG_(helper_mul_16_32)
+ : VG_(helper_mul_32_64)));
Int t1 = newTemp(cb);
uInstr0(cb, CALLM_S, 0);
@@ -1741,5 +1744,6 @@ static void codegen_mul_A_D_Temp ( UCode
uInstr2(cb, GET, sz, ArchReg, R_EAX, TempReg, t1);
uInstr1(cb, PUSH, sz, TempReg, t1);
- uInstr1(cb, CALLM, 0, Lit16, helper);
+ uInstr1(cb, CALLM, 0, Literal, 0);
+ uLiteral(cb, (Addr)helper);
uFlagsRWU(cb, FlagsEmpty, FlagsOC, FlagsSZAP);
if (sz > 1) {
@@ -2062,5 +2066,6 @@ void dis_string_op_increment(UCodeBlock*
uInstr1 (cb, PUSH, 4, TempReg, t_inc);
- uInstr1 (cb, CALLM, 0, Lit16, VGOFF_(helper_get_dirflag));
+ uInstr1 (cb, CALLM, 0, Literal, 0);
+ uLiteral (cb, (Addr)VG_(helper_get_dirflag));
uFlagsRWU(cb, FlagD, FlagsEmpty, FlagsEmpty);
@@ -2418,5 +2423,6 @@ Addr dis_fpu ( UCodeBlock* cb,
uLiteral(cb, 0);
uInstr1(cb, PUSH, 4, TempReg, t1);
- uInstr1(cb, CALLM, 0, Lit16, VGOFF_(helper_fstsw_AX) );
+ uInstr1(cb, CALLM, 0, Literal, 0);
+ uLiteral(cb, (Addr)VG_(helper_fstsw_AX) );
uFlagsRWU(cb, FlagsEmpty, FlagsEmpty, FlagsEmpty);
uInstr1(cb, POP, 2, TempReg, t1);
@@ -2603,5 +2609,6 @@ Addr dis_SHLRD_Gv_Ev ( UCodeBlock* cb,
/* amt_tag and amt_val denote either ArchReg(%CL) or a Literal.
And eip on entry points at the modrm byte. */
- Int t, t1, t2, ta, helper;
+ Int t, t1, t2, ta;
+ const Char *helper;
UInt pair;
UChar dis_buf[50];
@@ -2610,8 +2617,8 @@ Addr dis_SHLRD_Gv_Ev ( UCodeBlock* cb,
helper = left_shift
- ? (sz==4 ? VGOFF_(helper_shldl)
- : VGOFF_(helper_shldw))
- : (sz==4 ? VGOFF_(helper_shrdl)
- : VGOFF_(helper_shrdw));
+ ? (sz==4 ? VG_(helper_shldl)
+ : VG_(helper_shldw))
+ : (sz==4 ? VG_(helper_shrdl)
+ : VG_(helper_shrdw));
/* Get the amount to be shifted by onto the stack. */
@@ -2641,5 +2648,6 @@ Addr dis_SHLRD_Gv_Ev ( UCodeBlock* cb,
uInstr2(cb, GET, sz, ArchReg, eregOfRM(modrm), TempReg, t2);
uInstr1(cb, PUSH, sz, TempReg, t2);
- uInstr1(cb, CALLM, 0, Lit16, helper);
+ uInstr1(cb, CALLM, 0, Literal, 0);
+ uLiteral(cb, (Addr)helper);
uFlagsRWU(cb, FlagsEmpty, FlagsOSZACP, FlagsEmpty);
uInstr1(cb, POP, sz, TempReg, t);
@@ -2654,5 +2662,6 @@ Addr dis_SHLRD_Gv_Ev ( UCodeBlock* cb,
uInstr2(cb, LOAD, sz, TempReg, ta, TempReg, t2);
uInstr1(cb, PUSH, sz, TempReg, t2);
- uInstr1(cb, CALLM, 0, Lit16, helper);
+ uInstr1(cb, CALLM, 0, Literal, 0);
+ uLiteral(cb, (Addr)helper);
uFlagsRWU(cb, FlagsEmpty, FlagsOSZACP, FlagsEmpty);
uInstr1(cb, POP, sz, TempReg, t);
@@ -2827,5 +2836,6 @@ Addr dis_bs_E_G ( UCodeBlock* cb,
Int sz, Addr eip, Bool fwds )
{
- Int t, t1, ta, helper;
+ Int t, t1, ta;
+ const Char *helper;
UInt pair;
Char dis_buf[50];
@@ -2836,7 +2846,7 @@ Addr dis_bs_E_G ( UCodeBlock* cb,
if (fwds)
- helper = sz == 2 ? VGOFF_(helper_bsfw) : VGOFF_(helper_bsfl);
+ helper = sz == 2 ? VG_(helper_bsfw) : VG_(helper_bsfl);
else
- helper = sz == 2 ? VGOFF_(helper_bsrw) : VGOFF_(helper_bsrl);
+ helper = sz == 2 ? VG_(helper_bsrw) : VG_(helper_bsrl);
modrm = getUChar(eip);
@@ -2864,5 +2874,6 @@ Addr dis_bs_E_G ( UCodeBlock* cb,
uInstr1(cb, PUSH, sz, TempReg, t);
- uInstr1(cb, CALLM, 0, Lit16, helper);
+ uInstr1(cb, CALLM, 0, Literal, 0);
+ uLiteral(cb, (Addr)helper);
uFlagsRWU(cb, FlagsEmpty, FlagZ, FlagsOSACP);
uInstr1(cb, POP, sz, TempReg, t);
@@ -2913,5 +2924,6 @@ void codegen_SAHF ( UCodeBlock* cb )
uInstr0(cb, CALLM_S, 0);
uInstr1(cb, PUSH, 4, TempReg, t);
- uInstr1(cb, CALLM, 0, Lit16, VGOFF_(helper_SAHF));
+ uInstr1(cb, CALLM, 0, Literal, 0);
+ uLiteral(cb, (Addr)VG_(helper_SAHF));
uFlagsRWU(cb, FlagsEmpty, FlagsSZACP, FlagsEmpty);
uInstr1(cb, CLEAR, 0, Lit16, 4);
@@ -2929,5 +2941,6 @@ void codegen_LAHF ( UCodeBlock* cb )
uInstr0(cb, CALLM_S, 0);
uInstr1(cb, PUSH, 4, TempReg, t);
- uInstr1(cb, CALLM, 0, Lit16, VGOFF_(helper_LAHF));
+ uInstr1(cb, CALLM, 0, Literal, 0);
+ uLiteral(cb, (Addr)VG_(helper_LAHF));
uFlagsRWU(cb, FlagsSZACP, FlagsEmpty, FlagsEmpty);
uInstr1(cb, POP, 4, TempReg, t);
@@ -3043,5 +3056,6 @@ Addr dis_cmpxchg8b ( UCodeBlock* cb,
uInstr1(cb, PUSH, 4, TempReg, accl);
- uInstr1(cb, CALLM, 0, Lit16, VGOFF_(helper_cmpxchg8b));
+ uInstr1(cb, CALLM, 0, Literal, 0);
+ uLiteral(cb, (Addr)VG_(helper_cmpxchg8b));
uFlagsRWU(cb, FlagsEmpty, FlagZ, FlagsEmpty);
@@ -5366,6 +5380,6 @@ static Addr disInstr ( UCodeBlock* cb, A
uInstr0(cb, CALLM_S, 0);
uInstr1(cb, PUSH, 4, TempReg, t1);
- uInstr1(cb, CALLM, 0, Lit16,
- opc == 0x27 ? VGOFF_(helper_DAA) : VGOFF_(helper_DAS) );
+ uInstr1(cb, CALLM, 0, Literal, 0);
+ uLiteral(cb, (Addr)(opc == 0x27 ? VG_(helper_DAA) : VG_(helper_DAS)) );
uFlagsRWU(cb, FlagsAC, FlagsSZACP, FlagO);
uInstr1(cb, POP, 4, TempReg, t1);
@@ -5384,6 +5398,6 @@ static Addr disInstr ( UCodeBlock* cb, A
uInstr0(cb, CALLM_S, 0);
uInstr1(cb, PUSH, 4, TempReg, t1);
- uInstr1(cb, CALLM, 0, Lit16,
- opc == 0x37 ? VGOFF_(helper_AAA) : VGOFF_(helper_AAS) );
+ uInstr1(cb, CALLM, 0, Literal, 0);
+ uLiteral(cb, (Addr)(opc == 0x37 ? VG_(helper_AAA) : VG_(helper_AAS)) );
uFlagsRWU(cb, FlagA, FlagsAC, FlagsEmpty);
uInstr1(cb, POP, 4, TempReg, t1);
@@ -5404,6 +5418,6 @@ static Addr disInstr ( UCodeBlock* cb, A
uInstr0(cb, CALLM_S, 0);
uInstr1(cb, PUSH, 4, TempReg, t1);
- uInstr1(cb, CALLM, 0, Lit16,
- opc == 0xD4 ? VGOFF_(helper_AAM) : VGOFF_(helper_AAD) );
+ uInstr1(cb, CALLM, 0, Literal, 0);
+ uLiteral(cb, (Addr)(opc == 0xD4 ? VG_(helper_AAM) : VG_(helper_AAD)) );
uFlagsRWU(cb, FlagsEmpty, FlagsSZP, FlagsEmpty);
uInstr1(cb, POP, 4, TempReg, t1);
@@ -6191,5 +6205,6 @@ static Addr disInstr ( UCodeBlock* cb, A
case 0xFC: /* CLD */
uInstr0(cb, CALLM_S, 0);
- uInstr1(cb, CALLM, 0, Lit16, VGOFF_(helper_CLD));
+ uInstr1(cb, CALLM, 0, Literal, 0);
+ uLiteral(cb, (Addr)VG_(helper_CLD));
uFlagsRWU(cb, FlagsEmpty, FlagD, FlagsEmpty);
uInstr0(cb, CALLM_E, 0);
@@ -6199,5 +6214,6 @@ static Addr disInstr ( UCodeBlock* cb, A
case 0xFD: /* STD */
uInstr0(cb, CALLM_S, 0);
- uInstr1(cb, CALLM, 0, Lit16, VGOFF_(helper_STD));
+ uInstr1(cb, CALLM, 0, Literal, 0);
+ uLiteral(cb, (Addr)VG_(helper_STD));
uFlagsRWU(cb, FlagsEmpty, FlagD, FlagsEmpty);
uInstr0(cb, CALLM_E, 0);
@@ -6207,5 +6223,6 @@ static Addr disInstr ( UCodeBlock* cb, A
case 0xF8: /* CLC */
uInstr0(cb, CALLM_S, 0);
- uInstr1(cb, CALLM, 0, Lit16, VGOFF_(helper_CLC));
+ uInstr1(cb, CALLM, 0, Literal, 0);
+ uLiteral(cb, (Addr)VG_(helper_CLC));
uFlagsRWU(cb, FlagsEmpty, FlagC, FlagsOSZAP);
uInstr0(cb, CALLM_E, 0);
@@ -6215,5 +6232,6 @@ static Addr disInstr ( UCodeBlock* cb, A
case 0xF9: /* STC */
uInstr0(cb, CALLM_S, 0);
- uInstr1(cb, CALLM, 0, Lit16, VGOFF_(helper_STC));
+ uInstr1(cb, CALLM, 0, Literal, 0);
+ uLiteral(cb, (Addr)VG_(helper_STC));
uFlagsRWU(cb, FlagsEmpty, FlagC, FlagsOSZAP);
uInstr0(cb, CALLM_E, 0);
@@ -6223,5 +6241,6 @@ static Addr disInstr ( UCodeBlock* cb, A
case 0xF5: /* CMC */
uInstr0(cb, CALLM_S, 0);
- uInstr1(cb, CALLM, 0, Lit16, VGOFF_(helper_CMC));
+ uInstr1(cb, CALLM, 0, Literal, 0);
+ uLiteral(cb, (Addr)VG_(helper_CMC));
uFlagsRWU(cb, FlagC, FlagC, FlagsOSZAP);
uInstr0(cb, CALLM_E, 0);
@@ -6397,5 +6416,6 @@ static Addr disInstr ( UCodeBlock* cb, A
uInstr1(cb, PUSH, 4, TempReg, t2);
- uInstr1(cb, CALLM, 0, Lit16, VGOFF_(helper_IN));
+ uInstr1(cb, CALLM, 0, Literal, 0);
+ uLiteral(cb, (Addr)VG_(helper_IN));
uFlagsRWU(cb, FlagsEmpty, FlagsEmpty, FlagsEmpty);
uInstr1(cb, POP, 4, TempReg, t2);
@@ -6433,5 +6453,6 @@ static Addr disInstr ( UCodeBlock* cb, A
uInstr2(cb, GET, 4, ArchReg, R_EAX, TempReg, t3);
uInstr1(cb, PUSH, 4, TempReg, t3);
- uInstr1(cb, CALLM, 0, Lit16, VGOFF_(helper_OUT));
+ uInstr1(cb, CALLM, 0, Literal, 0);
+ uLiteral(cb, (Addr)VG_(helper_OUT));
uFlagsRWU(cb, FlagsEmpty, FlagsEmpty, FlagsEmpty);
uInstr1(cb, CLEAR, 0, Lit16, 12);
@@ -6661,5 +6682,6 @@ static Addr disInstr ( UCodeBlock* cb, A
uInstr1(cb, PUSH, 4, TempReg, t4);
- uInstr1(cb, CALLM, 0, Lit16, VGOFF_(helper_CPUID));
+ uInstr1(cb, CALLM, 0, Literal, 0);
+ uLiteral(cb, (Addr)VG_(helper_CPUID));
uFlagsRWU(cb, FlagsEmpty, FlagsEmpty, FlagsEmpty);
@@ -6757,5 +6779,6 @@ static Addr disInstr ( UCodeBlock* cb, A
uLiteral(cb, 0);
uInstr1(cb, PUSH, 4, TempReg, t2);
- uInstr1(cb, CALLM, 0, Lit16, VGOFF_(helper_RDTSC));
+ uInstr1(cb, CALLM, 0, Literal, 0);
+ uLiteral(cb, (Addr)VG_(helper_RDTSC));
uFlagsRWU(cb, FlagsEmpty, FlagsEmpty, FlagsEmpty);
uInstr1(cb, POP, 4, TempReg, t3);
@@ -7341,6 +7364,6 @@ static Addr disInstr ( UCodeBlock* cb, A
uInstr0(cb, CALLM_S, 0);
- uInstr1(cb, CALLM, 0, Lit16,
- VGOFF_(helper_undefined_instruction));
+ uInstr1(cb, CALLM, 0, Literal, 0);
+ uLiteral(cb, (Addr)VG_(helper_undefined_instruction));
uInstr0(cb, CALLM_E, 0);
--- valgrind/coregrind/vg_translate.c #1.96:1.97
@@ -569,5 +569,5 @@ static Bool is_sane_UInstr ( UInstr* u )
case WIDEN: return LIT0 && SZ42 && CC0 && TR1 && N2 && N3 && XWIDEN;
case JMP: return LITm && SZ0 && CCj && TRL1 && N2 && N3 && XJMP;
- case CALLM: return LIT0 && SZ0 /*any*/ && Ls1 && N2 && N3 && XOTHER;
+ case CALLM: return LIT1 && SZ0 /*any*/ && L1 && N2 && N3 && XOTHER;
case CALLM_S:
case CALLM_E:return LIT0 && SZ0 && CC0 && N1 && N2 && N3 && XOTHER;
--- valgrind/include/tool.h.base #1.20:1.21
@@ -1055,11 +1055,4 @@
-/* Used to register helper functions to be called from generated code. A
- limited number of compact helpers can be registered; the code generated
- to call them is slightly shorter -- so register the mostly frequently
- called helpers as compact. */
-extern void VG_(register_compact_helper) ( Addr a );
-extern void VG_(register_noncompact_helper) ( Addr a );
-
/* ------------------------------------------------------------------ */
@@ -1271,5 +1264,4 @@
/* Finding offsets */
-extern Int VG_(helper_offset) ( Addr a );
extern Int VG_(shadow_reg_offset) ( Int arch );
extern Int VG_(shadow_flags_offset) ( void );
@@ -1281,6 +1273,6 @@
/* Call a subroutine. Does no argument passing, stack manipulations, etc. */
-extern void VG_(synth_call) ( Bool ensure_shortform, Int word_offset,
- Bool upd_cc, FlagSet use_flags, FlagSet set_flags );
+extern void VG_(synth_call) ( Addr target, Bool upd_cc,
+ FlagSet use_flags, FlagSet set_flags );
/* For calling C functions -- saves caller save regs, pushes args, calls,
--- valgrind/coregrind/x86/state.c #1.14:1.15
@@ -70,45 +70,4 @@ Int VGOFF_(sh_edi) = INVALID_OFFSET;
Int VGOFF_(sh_eflags) = INVALID_OFFSET;
-Int VGOFF_(helper_idiv_64_32) = INVALID_OFFSET;
-Int VGOFF_(helper_div_64_32) = INVALID_OFFSET;
-Int VGOFF_(helper_idiv_32_16) = INVALID_OFFSET;
-Int VGOFF_(helper_div_32_16) = INVALID_OFFSET;
-Int VGOFF_(helper_idiv_16_8) = INVALID_OFFSET;
-Int VGOFF_(helper_div_16_8) = INVALID_OFFSET;
-Int VGOFF_(helper_imul_32_64) = INVALID_OFFSET;
-Int VGOFF_(helper_mul_32_64) = INVALID_OFFSET;
-Int VGOFF_(helper_imul_16_32) = INVALID_OFFSET;
-Int VGOFF_(helper_mul_16_32) = INVALID_OFFSET;
-Int VGOFF_(helper_imul_8_16) = INVALID_OFFSET;
-Int VGOFF_(helper_mul_8_16) = INVALID_OFFSET;
-Int VGOFF_(helper_CLD) = INVALID_OFFSET;
-Int VGOFF_(helper_STD) = INVALID_OFFSET;
-Int VGOFF_(helper_get_dirflag) = INVALID_OFFSET;
-Int VGOFF_(helper_CLC) = INVALID_OFFSET;
-Int VGOFF_(helper_STC) = INVALID_OFFSET;
-Int VGOFF_(helper_CMC) = INVALID_OFFSET;
-Int VGOFF_(helper_shldl) = INVALID_OFFSET;
-Int VGOFF_(helper_shldw) = INVALID_OFFSET;
-Int VGOFF_(helper_shrdl) = INVALID_OFFSET;
-Int VGOFF_(helper_shrdw) = INVALID_OFFSET;
-Int VGOFF_(helper_IN) = INVALID_OFFSET;
-Int VGOFF_(helper_OUT) = INVALID_OFFSET;
-Int VGOFF_(helper_RDTSC) = INVALID_OFFSET;
-Int VGOFF_(helper_CPUID) = INVALID_OFFSET;
-Int VGOFF_(helper_BSWAP) = INVALID_OFFSET;
-Int VGOFF_(helper_bsfw) = INVALID_OFFSET;
-Int VGOFF_(helper_bsfl) = INVALID_OFFSET;
-Int VGOFF_(helper_bsrw) = INVALID_OFFSET;
-Int VGOFF_(helper_bsrl) = INVALID_OFFSET;
-Int VGOFF_(helper_fstsw_AX) = INVALID_OFFSET;
-Int VGOFF_(helper_SAHF) = INVALID_OFFSET;
-Int VGOFF_(helper_LAHF) = INVALID_OFFSET;
-Int VGOFF_(helper_DAS) = INVALID_OFFSET;
-Int VGOFF_(helper_DAA) = INVALID_OFFSET;
-Int VGOFF_(helper_AAS) = INVALID_OFFSET;
-Int VGOFF_(helper_AAA) = INVALID_OFFSET;
-Int VGOFF_(helper_AAD) = INVALID_OFFSET;
-Int VGOFF_(helper_AAM) = INVALID_OFFSET;
-Int VGOFF_(helper_cmpxchg8b) = INVALID_OFFSET;
static Int extractDflag(UInt eflags)
@@ -161,13 +120,4 @@ void VGA_(init_low_baseBlock) ( Addr cli
/* 9,10,11 or 18,19,20... depends on number whether shadow regs are used
* and on compact helpers registered */
-
- /* Make these most-frequently-called specialised ones compact, if they
- are used. */
- if (VG_(defined_new_mem_stack_4)())
- VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_new_mem_stack_4);
-
- if (VG_(defined_die_mem_stack_4)())
- VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_die_mem_stack_4);
-
}
@@ -245,44 +195,4 @@ void VGA_(init_high_baseBlock)( Addr cli
asm ("movl %%ss, %0"
: "=m" (VG_(baseBlock)[VGOFF_(m_ss)]));
-
- VG_(register_noncompact_helper)( (Addr) & VG_(do_useseg) );
-
-# define HELPER(name) \
- VGOFF_(helper_##name) = VG_(alloc_BaB_1_set)( (Addr) & VG_(helper_##name))
-
- /* Helper functions. */
- HELPER(idiv_64_32); HELPER(div_64_32);
- HELPER(idiv_32_16); HELPER(div_32_16);
- HELPER(idiv_16_8); HELPER(div_16_8);
-
- HELPER(imul_32_64); HELPER(mul_32_64);
- HELPER(imul_16_32); HELPER(mul_16_32);
- HELPER(imul_8_16); HELPER(mul_8_16);
-
- HELPER(CLD); HELPER(STD);
- HELPER(get_dirflag);
-
- HELPER(CLC); HELPER(STC);
- HELPER(CMC);
-
- HELPER(shldl); HELPER(shldw);
- HELPER(shrdl); HELPER(shrdw);
-
- HELPER(RDTSC); HELPER(CPUID);
-
- HELPER(bsfw); HELPER(bsfl);
- HELPER(bsrw); HELPER(bsrl);
-
- HELPER(fstsw_AX);
- HELPER(SAHF); HELPER(LAHF);
- HELPER(DAS); HELPER(DAA);
- HELPER(AAS); HELPER(AAA);
- HELPER(AAD); HELPER(AAM);
- HELPER(IN); HELPER(OUT);
- HELPER(cmpxchg8b);
-
- HELPER(undefined_instruction);
-
-# undef HELPER
}
--- valgrind/coregrind/x86/core_arch.h #1.18:1.19
@@ -123,5 +123,4 @@ extern Int VGOFF_(tls_ptr);
/* Nb: Most helper offsets are in include/tool.h, for use by tools */
-extern Int VGOFF_(helper_undefined_instruction);
@@ -139,54 +138,56 @@ extern Int VGOFF_(helper_undefined_instr
------------------------------------------------------------------ */
+extern const Char VG_(helper_undefined_instruction)[];
+
/* Mul, div, etc, -- we don't codegen these directly. */
-extern void VG_(helper_idiv_64_32);
-extern void VG_(helper_div_64_32);
-extern void VG_(helper_idiv_32_16);
-extern void VG_(helper_div_32_16);
-extern void VG_(helper_idiv_16_8);
-extern void VG_(helper_div_16_8);
+extern const Char VG_(helper_idiv_64_32)[];
+extern const Char VG_(helper_div_64_32)[];
+extern const Char VG_(helper_idiv_32_16)[];
+extern const Char VG_(helper_div_32_16)[];
+extern const Char VG_(helper_idiv_16_8)[];
+extern const Char VG_(helper_div_16_8)[];
-extern void VG_(helper_imul_32_64);
-extern void VG_(helper_mul_32_64);
-extern void VG_(helper_imul_16_32);
-extern void VG_(helper_mul_16_32);
-extern void VG_(helper_imul_8_16);
-extern void VG_(helper_mul_8_16);
+extern const Char VG_(helper_imul_32_64)[];
+extern const Char VG_(helper_mul_32_64)[];
+extern const Char VG_(helper_imul_16_32)[];
+extern const Char VG_(helper_mul_16_32)[];
+extern const Char VG_(helper_imul_8_16)[];
+extern const Char VG_(helper_mul_8_16)[];
-extern void VG_(helper_CLD);
-extern void VG_(helper_STD);
-extern void VG_(helper_get_dirflag);
+extern const Char VG_(helper_CLD)[];
+extern const Char VG_(helper_STD)[];
+extern const Char VG_(helper_get_dirflag)[];
-extern void VG_(helper_CLC);
-extern void VG_(helper_STC);
-extern void VG_(helper_CMC);
+extern const Char VG_(helper_CLC)[];
+extern const Char VG_(helper_STC)[];
+extern const Char VG_(helper_CMC)[];
-extern void VG_(helper_shldl);
-extern void VG_(helper_shldw);
-extern void VG_(helper_shrdl);
-extern void VG_(helper_shrdw);
+extern const Char VG_(helper_shldl)[];
+extern const Char VG_(helper_shldw)[];
+extern const Char VG_(helper_shrdl)[];
+extern const Char VG_(helper_shrdw)[];
-extern void VG_(helper_IN);
-extern void VG_(helper_OUT);
+extern const Char VG_(helper_IN)[];
+extern const Char VG_(helper_OUT)[];
-extern void VG_(helper_RDTSC);
-extern void VG_(helper_CPUID);
+extern const Char VG_(helper_RDTSC)[];
+extern const Char VG_(helper_CPUID)[];
-extern void VG_(helper_bsfw);
-extern void VG_(helper_bsfl);
-extern void VG_(helper_bsrw);
-extern void VG_(helper_bsrl);
+extern const Char VG_(helper_bsfw)[];
+extern const Char VG_(helper_bsfl)[];
+extern const Char VG_(helper_bsrw)[];
+extern const Char VG_(helper_bsrl)[];
-extern void VG_(helper_fstsw_AX);
-extern void VG_(helper_SAHF);
-extern void VG_(helper_LAHF);
-extern void VG_(helper_DAS);
-extern void VG_(helper_DAA);
-extern void VG_(helper_AAS);
-extern void VG_(helper_AAA);
-extern void VG_(helper_AAD);
-extern void VG_(helper_AAM);
+extern const Char VG_(helper_fstsw_AX)[];
+extern const Char VG_(helper_SAHF)[];
+extern const Char VG_(helper_LAHF)[];
+extern const Char VG_(helper_DAS)[];
+extern const Char VG_(helper_DAA)[];
+extern const Char VG_(helper_AAS)[];
+extern const Char VG_(helper_AAA)[];
+extern const Char VG_(helper_AAD)[];
+extern const Char VG_(helper_AAM)[];
-extern void VG_(helper_cmpxchg8b);
+extern const Char VG_(helper_cmpxchg8b)[];
/* ---------------------------------------------------------------------
--- valgrind/memcheck/mc_from_ucode.c #1.15:1.16
@@ -232,12 +232,11 @@ static void synth_TESTV ( Int sz, Int ta
VG_(synth_call) (
- False,
( sz==4
- ? VG_(helper_offset)((Addr) & MC_(helper_value_check4_fail))
+ ? (Addr) & MC_(helper_value_check4_fail)
: ( sz==2
- ? VG_(helper_offset)((Addr) & MC_(helper_value_check2_fail))
+ ? (Addr) & MC_(helper_value_check2_fail)
: ( sz==1
- ? VG_(helper_offset)((Addr) & MC_(helper_value_check1_fail))
- : VG_(helper_offset)((Addr) & MC_(helper_value_check0_fail))))),
+ ? (Addr) & MC_(helper_value_check1_fail)
+ : (Addr) & MC_(helper_value_check0_fail)))),
False, FlagsEmpty, FlagsOSZACP /* helpers don't preserve flags */
);
--- valgrind/memcheck/mc_main.c #1.56:1.57
@@ -1989,20 +1989,4 @@ void SK_(pre_clo_init)(void)
VG_(init_post_reg_write_clientcall_return) ( & mc_post_reg_write_clientcall );
- /* Three compact slots taken up by stack memory helpers */
- VG_(register_compact_helper)((Addr) & MC_(helper_value_check4_fail));
- VG_(register_compact_helper)((Addr) & MC_(helper_value_check0_fail));
- VG_(register_compact_helper)((Addr) & MC_(helper_value_check2_fail));
- VG_(register_compact_helper)((Addr) & MC_(helperc_STOREV4));
- VG_(register_compact_helper)((Addr) & MC_(helperc_LOADV4));
-
- /* These two made non-compact because 2-byte transactions are rare. */
- VG_(register_noncompact_helper)((Addr) & MC_(helperc_STOREV2));
- VG_(register_noncompact_helper)((Addr) & MC_(helperc_STOREV1));
- VG_(register_noncompact_helper)((Addr) & MC_(helperc_LOADV2));
- VG_(register_noncompact_helper)((Addr) & MC_(helperc_LOADV1));
- VG_(register_noncompact_helper)((Addr) & MC_(fpu_write_check));
- VG_(register_noncompact_helper)((Addr) & MC_(fpu_read_check));
- VG_(register_noncompact_helper)((Addr) & MC_(helper_value_check1_fail));
-
VGP_(register_profile_event) ( VgpSetMem, "set-mem-perms" );
VGP_(register_profile_event) ( VgpCheckMem, "check-mem-perms" );
--- valgrind/addrcheck/ac_main.c #1.71:1.72
@@ -1309,13 +1309,4 @@ void SK_(pre_clo_init)(void)
VG_(init_post_mem_write) ( & ac_make_accessible );
- VG_(register_compact_helper)((Addr) & ac_helperc_LOAD4);
- VG_(register_compact_helper)((Addr) & ac_helperc_LOAD2);
- VG_(register_compact_helper)((Addr) & ac_helperc_LOAD1);
- VG_(register_compact_helper)((Addr) & ac_helperc_STORE4);
- VG_(register_compact_helper)((Addr) & ac_helperc_STORE2);
- VG_(register_compact_helper)((Addr) & ac_helperc_STORE1);
- VG_(register_noncompact_helper)((Addr) & ac_fpu_READ_check);
- VG_(register_noncompact_helper)((Addr) & ac_fpu_WRITE_check);
-
VGP_(register_profile_event) ( VgpSetMem, "set-mem-perms" );
VGP_(register_profile_event) ( VgpCheckMem, "check-mem-perms" );
--- valgrind/cachegrind/cg_main.c #1.82:1.83
@@ -1125,9 +1125,4 @@ void SK_(pre_clo_init)(void)
VG_(needs_command_line_options)();
- VG_(register_compact_helper)((Addr) & log_1I_0D_cache_access);
- VG_(register_compact_helper)((Addr) & log_1I_1Dr_cache_access);
- VG_(register_compact_helper)((Addr) & log_1I_1Dw_cache_access);
- VG_(register_compact_helper)((Addr) & log_1I_2D_cache_access);
-
/* Get working directory */
sk_assert( VG_(getcwd_alloc)(&base_dir) );
--- valgrind/helgrind/hg_main.c #1.92:1.93
@@ -3310,17 +3310,4 @@ void SK_(pre_clo_init)(void)
VG_(init_post_mutex_unlock) (& eraser_post_mutex_unlock);
- VG_(register_compact_helper)((Addr) & eraser_mem_help_read_1);
- VG_(register_compact_helper)((Addr) & eraser_mem_help_read_2);
- VG_(register_compact_helper)((Addr) & eraser_mem_help_read_4);
- VG_(register_noncompact_helper)((Addr) & eraser_mem_help_read_N);
-
- VG_(register_compact_helper)((Addr) & eraser_mem_help_write_1);
- VG_(register_compact_helper)((Addr) & eraser_mem_help_write_2);
- VG_(register_compact_helper)((Addr) & eraser_mem_help_write_4);
- VG_(register_noncompact_helper)((Addr) & eraser_mem_help_write_N);
-
- VG_(register_noncompact_helper)((Addr) & bus_lock);
- VG_(register_noncompact_helper)((Addr) & bus_unlock);
-
for(i = 0; i < LOCKSET_HASH_SZ; i++)
lockset_hash[i] = NULL;
--- valgrind/lackey/lk_main.c #1.25:1.26
@@ -82,11 +82,4 @@ void SK_(pre_clo_init)(void)
VG_(details_bug_reports_to) (VG_BUGS_TO);
VG_(details_avg_translation_sizeB) ( 175 );
-
- VG_(register_compact_helper)((Addr) & add_one_dlrr_call);
- VG_(register_compact_helper)((Addr) & add_one_BB);
- VG_(register_compact_helper)((Addr) & add_one_machine_instr);
- VG_(register_compact_helper)((Addr) & add_one_UInstr);
- VG_(register_compact_helper)((Addr) & add_one_Jcc);
- VG_(register_compact_helper)((Addr) & add_one_Jcc_untaken);
}
|
|
From: Jeremy F. <je...@go...> - 2005-02-01 22:52:59
|
CVS commit by fitzhardinge:
Add option to call helper functions with a direct call rather than
indirectly via the baseBlock.
M +10 -3 core.h 1.73
M +86 -53 vg_from_ucode.c 1.86
M +3 -0 vg_main.c 1.240
M +11 -9 vg_translate.c 1.96
M +10 -4 vg_transtab.c 1.38
--- valgrind/coregrind/core.h #1.72:1.73
@@ -301,4 +301,6 @@ extern Bool VG_(clo_run_libc_freeres);
/* Use the basic-block chaining optimisation? Default: YES */
extern Bool VG_(clo_chain_bb);
+/* Use direct jumps to helper functions? Default: YES */
+extern Bool VG_(clo_direct_helpers);
/* Generate branch-prediction hints? */
extern Bool VG_(clo_branchpred);
@@ -999,5 +1001,5 @@ extern void VG_(demangle) ( Char* orig,
------------------------------------------------------------------ */
-extern UChar* VG_(emit_code) ( UCodeBlock* cb, Int* nbytes, UShort jumps[VG_MAX_JUMPS] );
+extern UChar* VG_(emit_code) ( UCodeBlock* cb, Int* nbytes );
extern void VG_(print_ccall_stats) ( void );
@@ -1005,4 +1007,5 @@ extern void VG_(print_UInstr_histogram
extern void VG_(unchain_jumpsite) ( Addr jumpsite );
+extern void VG_(reloc_abs_jump) ( UChar *jmp );
extern Addr VG_(get_jmp_dest) ( Addr jumpsite );
@@ -1026,4 +1029,8 @@ struct _UCodeBlock {
UInstr* instrs;
Int nextTemp;
+
+ UShort *relocs;
+ Int nrelocs;
+ UShort jumps[VG_MAX_JUMPS];
};
@@ -1645,5 +1652,5 @@ extern void VG_(init_tt_tc) ( void
extern void VG_(add_to_trans_tab) ( Addr orig_addr, Int orig_size,
Addr trans_addr, Int trans_size,
- UShort jumps[VG_MAX_JUMPS]);
+ UCodeBlock *cb );
extern Addr VG_(search_transtab) ( Addr original_addr );
@@ -1676,5 +1683,5 @@ extern UInt VG_(run_innerloop) ( void );
/* The patching routing called when a BB wants to chain itself to
another. */
-extern UInt VG_(patch_me);
+extern UChar VG_(patch_me)[];
/* ---------------------------------------------------------------------
--- valgrind/coregrind/vg_from_ucode.c #1.85:1.86
@@ -44,15 +44,5 @@
/*------------------------------------------------------------*/
-/* [2001-07-08 This comment is now somewhat out of date.]
-
- This is straightforward but for one thing: to facilitate generating
- code in a single pass, we generate position-independent code. To
- do this, calls and jmps to fixed addresses must specify the address
- by first loading it into a register, and jump to/call that
- register. Fortunately, the only jump to a literal is the jump back
- to vg_dispatch, and only %eax is live then, conveniently. UCode
- call insns may only have a register as target anyway, so there's no
- need to do anything fancy for them.
-
+/*
The emit_* routines constitute the lowest level of instruction
emission. They simply emit the sequence of bytes corresponding to
@@ -64,5 +54,6 @@
routines. These detect impossible operand combinations and turn
them into sequences of legal instructions. Finally, emitUInstr is
- phrased in terms of the synth_* abstraction layer. */
+ phrased in terms of the synth_* abstraction layer.
+*/
/* Static state for the current basic block */
@@ -71,8 +62,13 @@ static Int emitted_code_used;
static Int emitted_code_size;
-/* offset (in bytes into the basic block) */
+/* offset of jump sites (in bytes into the basic block) */
static UShort jumps[VG_MAX_JUMPS];
static Int jumpidx;
+/* offset of addresses which need relocation (absolute->relative) */
+static UShort *relocs; /* array of relocation offsets */
+static Int nrelocs; /* number of relocations */
+static Int relocsz; /* size of reloc array */
+
static enum _eflags_state {
UPD_Simd, /* baseblock copy is up to date */
@@ -112,6 +108,26 @@ static void reset_state(void)
jumpidx = 0;
eflags_state = UPD_Simd;
+
+ relocs = NULL;
+ nrelocs = relocsz = 0;
}
+static void add_reloc(UShort off)
+{
+ if (nrelocs == relocsz) {
+ if (relocsz == 0) {
+ vg_assert(relocs == NULL);
+ relocsz = 2;
+ relocs = VG_(arena_malloc)(VG_AR_JITTER, sizeof(*relocs) * relocsz);
+ } else {
+ vg_assert(relocs != NULL);
+ relocsz *= 2;
+ relocs = VG_(arena_realloc)(VG_AR_JITTER, relocs, VG_MIN_MALLOC_SZB,
+ sizeof(*relocs) * relocsz);
+ }
+ }
+ vg_assert(nrelocs < relocsz);
+ relocs[nrelocs++] = off;
+}
/* Statistics about C functions called from generated code. */
@@ -1964,4 +1980,19 @@ void VG_(emit_call_reg) ( Int reg )
static
+void emit_call_abs(Bool simd_flags, Addr target,
+ FlagSet use_flag, FlagSet set_flag)
+{
+ /* Used for helpers which expect to see Simd flags in Real flags */
+ VG_(new_emit)(simd_flags, use_flag, set_flag);
+
+ add_reloc(emitted_code_used);
+ VG_(emitB)(0xE8);
+ VG_(emitL)(target);
+
+ if (dis)
+ VG_(printf)( "\n\t\tcall %p\n", target );
+}
+
+static
void emit_call_star_EBP_off ( Bool simd_flags, Int byte_off,
FlagSet use_flag, FlagSet set_flag )
@@ -2181,21 +2212,10 @@ static Bool is_chained_jumpsite(Addr a)
}
-static
-Bool is_fresh_jumpsite(UChar *cp)
-{
- return
- cp[0] == 0x0F && /* UD2 */
- cp[1] == 0x0B &&
- cp[2] == 0x0F && /* UD2 */
- cp[3] == 0x0B &&
- cp[4] == 0x90; /* NOP */
-}
-
-/* Predicate used in sanity checks elsewhere - returns true if all
- jump-sites are calls to VG_(patch_me) */
+/* Predicate used in sanity checks elsewhere - returns true if the
+ jump-site is a call to VG_(patch_me) */
static Bool is_unchained_jumpsite(Addr a)
{
UChar *cp = (UChar *)a;
- Int delta = ((Addr)&VG_(patch_me)) - (a + VG_PATCHME_CALLSZ);
+ Int delta = ((Addr)VG_(patch_me)) - (a + VG_PATCHME_CALLSZ);
Int idelta;
@@ -2231,5 +2251,5 @@ Addr VG_(get_jmp_dest)(Addr a)
void VG_(unchain_jumpsite)(Addr a)
{
- Int delta = ((Addr)&VG_(patch_me)) - (a + VG_PATCHME_CALLSZ);
+ Int delta = ((Addr)VG_(patch_me)) - (a + VG_PATCHME_CALLSZ);
UChar *cp = (UChar *)a;
@@ -2237,5 +2257,4 @@ void VG_(unchain_jumpsite)(Addr a)
return; /* don't write unnecessarily */
- if (!is_fresh_jumpsite(cp))
VG_(bb_dechain_count)++; /* update stats */
@@ -2247,11 +2266,22 @@ void VG_(unchain_jumpsite)(Addr a)
}
-/* This doesn't actually generate a call to VG_(patch_me), but
- reserves enough space in the instruction stream for it to happen
- and records the offset into the jump table. This is because call
- is a relative jump, and so will be affected when this code gets
- moved about. The translation table will "unchain" this basic block
- on insertion (with VG_(unchain_BB)()), and thereby generate a
- proper call instruction. */
+/* Relocate an direct call or jmp; the address is initially an
+ absolute address; this replaces it with a relative offset. */
+void VG_(reloc_abs_jump)(UChar *instr)
+{
+ Addr *absaddr = (Addr *)(instr+1);
+ Int delta = *absaddr - (Addr)(absaddr + 1);
+
+ vg_assert(*instr == 0xE8 || /* call */
+ *instr == 0xEB); /* jmp */
+
+ *absaddr = delta;
+}
+
+/* Generate a call to VG_(patch_me); this will be properly relocated
+ when this generated code is inserted into the translation cache.
+ If we hit the limit of chained jumps per basic block, then just
+ generate the normal unchained sequence (return to the dispatch
+ loop). */
static void emit_call_patchme( void )
{
@@ -2279,12 +2309,5 @@ static void emit_call_patchme( void )
jumps[jumpidx++] = emitted_code_used;
- VG_(emitB) ( 0x0F ); /* UD2 - undefined instruction */
- VG_(emitB) ( 0x0B );
- VG_(emitB) ( 0x0F ); /* UD2 - undefined instruction */
- VG_(emitB) ( 0x0B );
- VG_(emitB) ( 0x90 ); /* NOP */
-
- if (dis)
- VG_(printf)("\n\t\tud2; ud2; nop /* call VG_(patch_me) */\n");
+ emit_call_abs(False, (Addr)VG_(patch_me), FlagsEmpty, FlagsEmpty);
}
}
@@ -2349,6 +2372,5 @@ static Condcode invertCondition ( Condco
-/* Synthesise a call to *baseBlock[offset], ie,
- call * (4 x offset)(%ebp).
+/* Synthesise a call to a helper.
*/
void VG_(synth_call) ( Bool ensure_shortform, Int word_offset,
@@ -2360,5 +2382,13 @@ void VG_(synth_call) ( Bool ensure_short
vg_assert(word_offset < 32);
}
+ if (VG_(clo_direct_helpers)) {
+ /* Call the helper directly */
+ Addr target = VG_(baseBlock)[word_offset];
+ emit_call_abs ( simd_flags, target, use_flags, set_flags );
+ } else {
+ /* Call the helper via the baseBlock: *baseBlock[offset], ie,
+ call * (4 x offset)(%ebp). */
emit_call_star_EBP_off ( simd_flags, 4 * word_offset, use_flags, set_flags );
+ }
}
@@ -4453,6 +4483,5 @@ static void emitUInstr ( UCodeBlock* cb,
generated code and setting *nbytes to its size. */
UChar* VG_(emit_code) ( UCodeBlock* cb,
- Int* nbytes,
- UShort j[VG_MAX_JUMPS] )
+ Int* nbytes )
{
Int i;
@@ -4503,8 +4532,12 @@ UChar* VG_(emit_code) ( UCodeBlock* cb,
vg_assert(eflags_state != UPD_Real); /* flags can't just be in CPU */
- vg_assert(NULL != j);
vg_assert(jumpidx <= VG_MAX_JUMPS);
for(i = 0; i < jumpidx; i++)
- j[i] = jumps[i];
+ cb->jumps[i] = jumps[i];
+
+ cb->relocs = relocs;
+ cb->nrelocs = nrelocs;
+ relocs = NULL;
+ nrelocs = relocsz = 0;
/* Returns a pointer to the emitted code. This will have to be
--- valgrind/coregrind/vg_translate.c #1.95:1.96
@@ -72,4 +72,6 @@ static UCodeBlock* alloc_UCodeBlock ( Ad
{
UCodeBlock* cb = VG_(arena_malloc)(VG_AR_CORE, sizeof(UCodeBlock));
+ Int i;
+
cb->orig_eip = orig_eip;
cb->used = 0;
@@ -77,4 +79,8 @@ static UCodeBlock* alloc_UCodeBlock ( Ad
cb->instrs = NULL;
cb->nextTemp = 0;
+ cb->relocs = NULL;
+ cb->nrelocs = 0;
+ for(i = 0; i < VG_MAX_JUMPS; i++)
+ cb->jumps[i] = -1;
return cb;
}
@@ -91,4 +97,5 @@ void VG_(free_UCodeBlock) ( UCodeBlock*
{
if (cb->instrs) VG_(arena_free)(VG_AR_CORE, cb->instrs);
+ if (cb->relocs) VG_(arena_free)(VG_AR_JITTER, cb->relocs);
VG_(arena_free)(VG_AR_CORE, cb);
}
@@ -2433,6 +2440,5 @@ Bool VG_(translate) ( ThreadId tid, Addr
{
Addr trans_addr, redir, orig_addr0 = orig_addr;
- UShort jumps[VG_MAX_JUMPS];
- Int i, orig_size, trans_size;
+ Int orig_size, trans_size;
UCodeBlock* cb;
Bool notrace_until_done;
@@ -2445,7 +2451,4 @@ Bool VG_(translate) ( ThreadId tid, Addr
beforeLiveness = True;
- for (i = 0; i < VG_MAX_JUMPS; i++)
- jumps[i] = (UShort)-1;
-
/* Look in the code redirect table to see if we should
translate an alternative address for orig_addr. */
@@ -2557,7 +2560,6 @@ Bool VG_(translate) ( ThreadId tid, Addr
VG_(print_codegen) = DECIDE_IF_PRINTING_CODEGEN_FOR_PHASE(5);
VGP_PUSHCC(VgpFromUcode);
- trans_addr = (Addr)VG_(emit_code)(cb, &trans_size, jumps );
+ trans_addr = (Addr)VG_(emit_code)(cb, &trans_size );
VGP_POPCC(VgpFromUcode);
- VG_(free_UCodeBlock)(cb);
#undef DECIDE_IF_PRINTING_CODEGEN_FOR_PHASE
@@ -2573,10 +2575,10 @@ Bool VG_(translate) ( ThreadId tid, Addr
// Note that we use orig_addr0, not orig_addr, which might have been
// changed by the redirection
- VG_(add_to_trans_tab)( orig_addr0, orig_size, trans_addr, trans_size,
- jumps );
+ VG_(add_to_trans_tab)( orig_addr0, orig_size, trans_addr, trans_size, cb );
}
/* Free the intermediary -- was allocated by VG_(emit_code). */
VG_(arena_free)( VG_AR_JITTER, (void*)trans_addr );
+ VG_(free_UCodeBlock)(cb);
VGP_POPCC(VgpTranslate);
--- valgrind/coregrind/vg_transtab.c #1.37:1.38
@@ -559,5 +559,5 @@ Int VG_(get_bbs_translated) ( void )
void VG_(add_to_trans_tab) ( Addr orig_addr, Int orig_size,
Addr trans_addr, Int trans_size,
- UShort jumps[VG_MAX_JUMPS])
+ UCodeBlock *cb )
{
Int i, nBytes, trans_size_aligned;
@@ -569,4 +569,8 @@ 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);
@@ -587,5 +591,5 @@ void VG_(add_to_trans_tab) ( Addr orig_a
tce->trans_size = (UShort)trans_size_aligned;
for (i = 0; i < VG_MAX_JUMPS; i++) {
- tce->jump_sites[i] = jumps[i];
+ tce->jump_sites[i] = cb->jumps[i];
}
for (i = 0; i < trans_size; i++) {
@@ -593,5 +597,7 @@ void VG_(add_to_trans_tab) ( Addr orig_a
}
- unchain_tce(tce);
+ /* relocate absolute jumps */
+ for(i = 0; i < cb->nrelocs; i++)
+ VG_(reloc_abs_jump)(&tce->payload[cb->relocs[i]]);
add_tt_entry(tce);
--- valgrind/coregrind/vg_main.c #1.239:1.240
@@ -1500,4 +1500,5 @@ Bool VG_(clo_run_libc_freeres) = True;
Bool VG_(clo_track_fds) = False;
Bool VG_(clo_chain_bb) = True;
+Bool VG_(clo_direct_helpers) = True;
Bool VG_(clo_show_below_main) = False;
Bool VG_(clo_pointercheck) = True;
@@ -1558,4 +1559,5 @@ void usage ( Bool debug_help )
" --profile=no|yes profile? (tool must be built for it) [no]\n"
" --chain-bb=no|yes do basic-block chaining? [yes]\n"
+" --direct-helpers=yes|no call helpers directly? [yes]\n"
" --branchpred=yes|no generate branch prediction hints [no]\n"
" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
@@ -1715,4 +1717,5 @@ static void process_cmd_line_options( UI
else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
else VG_BOOL_CLO("--chain-bb", VG_(clo_chain_bb))
+ else VG_BOOL_CLO("--direct-helpers", VG_(clo_direct_helpers))
else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
|
|
From: Jeremy F. <je...@go...> - 2005-02-01 08:00:24
|
On Tue, 2005-02-01 at 07:16 +0000, Tom Hughes wrote:
> In message <1107227702.4290.295.camel@localhost>
> Jeremy Fitzhardinge <je...@go...> wrote:
>
> > On Mon, 2005-01-31 at 16:13 +0100, Tom Hughes wrote:
> > > CVS commit by thughes:
> > >
> > > Make sure we can actually run a program that uses TLS variables before
> > > deciding that it is supported as we might have a system where the
> > > compiler support it but the dynamic loader doesn't.
> >
> > This breaks cross-compilation...
>
> Well do you have any better ideas? I have some machine where the
> compiler has TLS support but the programs won't actually run.
Hm. I guess do the compile-time test (which I wish was something better
than checking compiler versions), a runtime test (look for /lib/tls) and
if that fails, have a set of *.exp2 files for the "runtime doesn't
support TLS" case?
J
|
|
From: Tom H. <th...@cy...> - 2005-02-01 07:16:22
|
In message <1107227702.4290.295.camel@localhost>
Jeremy Fitzhardinge <je...@go...> wrote:
> On Mon, 2005-01-31 at 16:13 +0100, Tom Hughes wrote:
> > CVS commit by thughes:
> >
> > Make sure we can actually run a program that uses TLS variables before
> > deciding that it is supported as we might have a system where the
> > compiler support it but the dynamic loader doesn't.
>
> This breaks cross-compilation...
Well do you have any better ideas? I have some machine where the
compiler has TLS support but the programs won't actually run.
Tom
--
Tom Hughes (th...@cy...)
Software Engineer, Cyberscience Corporation
http://www.cyberscience.com/
|
|
From: <js...@ac...> - 2005-02-01 03:56:32
|
Nightly build on phoenix ( SuSE 9.1 ) started at 2005-02-01 03:50:00 GMT Checking out source tree ... done Configuring ... done Building ... done Running regression tests ... done Last 20 lines of log.verbose follow -- Finished tests in none/tests ---------------------------------------- == 194 tests, 15 stderr failures, 0 stdout failures ================= corecheck/tests/as_mmap (stderr) corecheck/tests/fdleak_fcntl (stderr) helgrind/tests/allok (stderr) helgrind/tests/deadlock (stderr) helgrind/tests/inherit (stderr) helgrind/tests/race (stderr) helgrind/tests/race2 (stderr) helgrind/tests/readshared (stderr) massif/tests/toobig-allocs (stderr) massif/tests/true_html (stderr) massif/tests/true_text (stderr) memcheck/tests/pth_once (stderr) memcheck/tests/scalar (stderr) memcheck/tests/threadederrno (stderr) memcheck/tests/writev (stderr) make: *** [regtest] Error 1 |
|
From: Tom H. <to...@co...> - 2005-02-01 03:24:02
|
Nightly build on dunsmere ( Fedora Core 3 ) started at 2005-02-01 03:20:09 GMT Checking out source tree ... done Configuring ... done Building ... done Running regression tests ... done Last 20 lines of log.verbose follow seg_override: valgrind --num-callers=4 ./seg_override -- Finished tests in none/tests/x86 ------------------------------------ yield: valgrind --num-callers=4 ./yield -- Finished tests in none/tests ---------------------------------------- == 201 tests, 12 stderr failures, 0 stdout failures ================= helgrind/tests/allok (stderr) helgrind/tests/deadlock (stderr) helgrind/tests/inherit (stderr) helgrind/tests/race (stderr) helgrind/tests/race2 (stderr) helgrind/tests/readshared (stderr) massif/tests/toobig-allocs (stderr) massif/tests/true_html (stderr) massif/tests/true_text (stderr) memcheck/tests/scalar (stderr) memcheck/tests/scalar_supp (stderr) memcheck/tests/vgtest_ume (stderr) make: *** [regtest] Error 1 |
|
From: Tom H. <th...@cy...> - 2005-02-01 03:21:25
|
Nightly build on audi ( Red Hat 9 ) started at 2005-02-01 03:15:04 GMT Checking out source tree ... done Configuring ... done Building ... done Running regression tests ... done Last 20 lines of log.verbose follow corecheck/tests/fdleak_socketpair (stderr) helgrind/tests/allok (stderr) helgrind/tests/deadlock (stderr) helgrind/tests/inherit (stderr) helgrind/tests/race (stderr) helgrind/tests/race2 (stderr) helgrind/tests/readshared (stderr) massif/tests/toobig-allocs (stderr) massif/tests/true_html (stderr) massif/tests/true_text (stderr) memcheck/tests/badpoll (stderr) memcheck/tests/buflen_check (stderr) memcheck/tests/execve (stderr) memcheck/tests/execve2 (stderr) memcheck/tests/scalar (stderr) memcheck/tests/scalar_exit_group (stderr) memcheck/tests/scalar_supp (stderr) memcheck/tests/writev (stderr) make: *** [regtest] Error 1 |
|
From: Jeremy F. <je...@go...> - 2005-02-01 03:18:20
|
On Mon, 2005-01-31 at 16:13 +0100, Tom Hughes wrote: > CVS commit by thughes: > > Make sure we can actually run a program that uses TLS variables before > deciding that it is supported as we might have a system where the > compiler support it but the dynamic loader doesn't. This breaks cross-compilation... J |
|
From: Tom H. <th...@cy...> - 2005-02-01 03:14:45
|
Nightly build on ginetta ( Red Hat 8.0 ) started at 2005-02-01 03:10:02 GMT Checking out source tree ... done Configuring ... done Building ... done Running regression tests ... done Last 20 lines of log.verbose follow seg_override: valgrind --num-callers=4 ./seg_override -- Finished tests in none/tests/x86 ------------------------------------ yield: valgrind --num-callers=4 ./yield -- Finished tests in none/tests ---------------------------------------- == 199 tests, 12 stderr failures, 0 stdout failures ================= helgrind/tests/allok (stderr) helgrind/tests/deadlock (stderr) helgrind/tests/inherit (stderr) helgrind/tests/race (stderr) helgrind/tests/race2 (stderr) helgrind/tests/readshared (stderr) massif/tests/toobig-allocs (stderr) massif/tests/true_html (stderr) massif/tests/true_text (stderr) memcheck/tests/pth_once (stderr) memcheck/tests/scalar (stderr) memcheck/tests/threadederrno (stderr) make: *** [regtest] Error 1 |
|
From: Tom H. <th...@cy...> - 2005-02-01 03:09:51
|
Nightly build on alvis ( Red Hat 7.3 ) started at 2005-02-01 03:05:02 GMT Checking out source tree ... done Configuring ... done Building ... done Running regression tests ... done Last 20 lines of log.verbose follow yield: valgrind --num-callers=4 ./yield -- Finished tests in none/tests ---------------------------------------- == 199 tests, 14 stderr failures, 0 stdout failures ================= helgrind/tests/allok (stderr) helgrind/tests/deadlock (stderr) helgrind/tests/inherit (stderr) helgrind/tests/race (stderr) helgrind/tests/race2 (stderr) helgrind/tests/readshared (stderr) massif/tests/toobig-allocs (stderr) massif/tests/true_html (stderr) massif/tests/true_text (stderr) memcheck/tests/post-syscall (stderr) memcheck/tests/pth_once (stderr) memcheck/tests/scalar (stderr) memcheck/tests/threadederrno (stderr) memcheck/tests/vgtest_ume (stderr) make: *** [regtest] Error 1 |
|
From: Tom H. <th...@cy...> - 2005-02-01 03:04:54
|
Nightly build on standard ( Red Hat 7.2 ) started at 2005-02-01 03:00:03 GMT Checking out source tree ... done Configuring ... done Building ... done Running regression tests ... done Last 20 lines of log.verbose follow -- Finished tests in none/tests/x86 ------------------------------------ yield: valgrind --num-callers=4 ./yield -- Finished tests in none/tests ---------------------------------------- == 199 tests, 13 stderr failures, 0 stdout failures ================= helgrind/tests/allok (stderr) helgrind/tests/deadlock (stderr) helgrind/tests/inherit (stderr) helgrind/tests/race (stderr) helgrind/tests/race2 (stderr) helgrind/tests/readshared (stderr) massif/tests/toobig-allocs (stderr) massif/tests/true_html (stderr) massif/tests/true_text (stderr) memcheck/tests/pth_once (stderr) memcheck/tests/scalar (stderr) memcheck/tests/threadederrno (stderr) memcheck/tests/vgtest_ume (stderr) make: *** [regtest] Error 1 |