Fixed a minor bug -- the condition for determining whether
VG_(handle_esp_assignment)() was needed by a skin (and thus whether to register
it in the baseBlock) was different to that used when determining whether to
call it in code generation... so it could be (attempted to be) called having
not been registered.
Fixed this by consistifying the conditions, using a function
VG_(need_to_handle_esp_assignment)() that is used in both places. The bug
hadn't been found previously because no existing skin exercised the mismatched
conditions in conflicting ways.
Also took VG_(track).post_mem_write out of consideration because it's no longer
important (due to a change in how stack switching is detected).
----
Improved the error message for when a helper can't be found in the baseBlock --
now looks up the debug info to tell you the name of the not-found function.
----
Increased the number of noncompact helpers allowed from 8 to 24
----
Removed a magic number that was hardcoded all over the place, introducing
VG_MAX_REGS_USED for the size of the arrays needed by VG_(get_reg_usage)()
----
Also added these functions
VG_(get_archreg)()
VG_(get_thread_archreg)()
VG_(get_thread_shadow_archreg)()
VG_(set_thread_shadow_archreg)()
which can be useful for skins.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1419 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/vg_from_ucode.c b/coregrind/vg_from_ucode.c
index c9c7f9f..a70f157 100644
--- a/coregrind/vg_from_ucode.c
+++ b/coregrind/vg_from_ucode.c
@@ -1767,6 +1767,7 @@
Int VG_(helper_offset)(Addr a)
{
Int i;
+ Char buf[100];
for (i = 0; i < VG_(n_compact_helpers); i++)
if (VG_(compact_helper_addrs)[i] == a)
@@ -1776,9 +1777,11 @@
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).\n"
- "A helper function probably used hasn't been registered?\n\n", a);
+ "\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++)
@@ -2704,6 +2707,41 @@
}
}
+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_thread_archreg");
+ }
+}
+
+UInt VG_(get_thread_archreg) ( ThreadId tid, UInt arch )
+{
+ ThreadState* tst;
+
+ vg_assert(VG_(is_valid_tid)(tid));
+ tst = & VG_(threads)[tid];
+
+ switch (arch) {
+ case R_EAX: return tst->m_eax;
+ case R_ECX: return tst->m_ecx;
+ case R_EDX: return tst->m_edx;
+ case R_EBX: return tst->m_ebx;
+ case R_ESP: return tst->m_esp;
+ case R_EBP: return tst->m_ebp;
+ case R_ESI: return tst->m_esi;
+ case R_EDI: return tst->m_edi;
+ default: VG_(core_panic)( "get_thread_archreg");
+ }
+}
+
/* Return the baseBlock index for the specified shadow register */
Int shadow_reg_index ( Int arch )
{
@@ -2743,12 +2781,51 @@
VG_(baseBlock)[ shadow_reg_index(archreg) ] = val;
}
+UInt VG_(get_thread_shadow_archreg) ( ThreadId tid, UInt archreg )
+{
+ ThreadState* tst;
+
+ vg_assert(VG_(is_valid_tid)(tid));
+ tst = & VG_(threads)[tid];
+
+ switch (archreg) {
+ case R_EAX: return tst->sh_eax;
+ case R_ECX: return tst->sh_ecx;
+ case R_EDX: return tst->sh_edx;
+ case R_EBX: return tst->sh_ebx;
+ case R_ESP: return tst->sh_esp;
+ case R_EBP: return tst->sh_ebp;
+ case R_ESI: return tst->sh_esi;
+ case R_EDI: return tst->sh_edi;
+ default: VG_(core_panic)( "get_thread_shadow_archreg");
+ }
+}
+
+void VG_(set_thread_shadow_archreg) ( ThreadId tid, UInt archreg, UInt val )
+{
+ ThreadState* tst;
+
+ vg_assert(VG_(is_valid_tid)(tid));
+ tst = & VG_(threads)[tid];
+
+ switch (archreg) {
+ case R_EAX: tst->sh_eax = val; break;
+ case R_ECX: tst->sh_ecx = val; break;
+ case R_EDX: tst->sh_edx = val; break;
+ case R_EBX: tst->sh_ebx = val; break;
+ case R_ESP: tst->sh_esp = val; break;
+ case R_EBP: tst->sh_ebp = val; break;
+ case R_ESI: tst->sh_esi = val; break;
+ case R_EDI: tst->sh_edi = val; break;
+ default: VG_(core_panic)( "set_thread_shadow_archreg");
+ }
+}
+
Addr VG_(shadow_archreg_address) ( UInt archreg )
{
return (Addr) & VG_(baseBlock)[ shadow_reg_index(archreg) ];
}
-
static void synth_WIDEN_signed ( Int sz_src, Int sz_dst, Int reg )
{
if (sz_src == 1 && sz_dst == 4) {
@@ -2910,11 +2987,7 @@
if (u->tag2 == ArchReg
&& u->val2 == R_ESP
&& u->size == 4
- && (VG_(track_events).new_mem_stack ||
- VG_(track_events).new_mem_stack_aligned ||
- VG_(track_events).die_mem_stack ||
- VG_(track_events).die_mem_stack_aligned ||
- VG_(track_events).post_mem_write))
+ && VG_(need_to_handle_esp_assignment)())
{
synth_handle_esp_assignment ( i, u->val1, regs_live_before,
u->regs_live_after );
diff --git a/coregrind/vg_include.h b/coregrind/vg_include.h
index a17661c..86e024f 100644
--- a/coregrind/vg_include.h
+++ b/coregrind/vg_include.h
@@ -1322,6 +1322,9 @@
extern void VG_(copy_baseBlock_to_m_state_static) ( void );
extern void VG_(copy_m_state_static_to_baseBlock) ( void );
+/* Determine if VG_(handle_esp_assignment)() will be used */
+extern Bool VG_(need_to_handle_esp_assignment) ( void );
+
/* Called when some unhandleable client behaviour is detected.
Prints a msg and aborts. */
extern void VG_(unimplemented) ( Char* msg )
diff --git a/coregrind/vg_main.c b/coregrind/vg_main.c
index feb9fd7..a7d9ad9 100644
--- a/coregrind/vg_main.c
+++ b/coregrind/vg_main.c
@@ -105,7 +105,7 @@
/* 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 8
+#define MAX_NONCOMPACT_HELPERS 24
UInt VG_(n_compact_helpers) = 0;
UInt VG_(n_noncompact_helpers) = 0;
@@ -177,13 +177,21 @@
for (i = 0; i < n; i++) offsets[i] = alloc_BaB_1_set( addrs[i] );
}
+/* Will we need to call VG_(handle_esp_assignment)() ? */
+Bool VG_(need_to_handle_esp_assignment)(void)
+{
+ return (VG_(track_events).new_mem_stack ||
+ VG_(track_events).new_mem_stack_aligned ||
+ VG_(track_events).die_mem_stack ||
+ VG_(track_events).die_mem_stack_aligned);
+}
+
/* Here we assign actual offsets. It's important to get the most
popular referents within 128 bytes of the start, so we can take
advantage of short addressing modes relative to %ebp. Popularity
of offsets was measured on 22 Feb 02 running a KDE application, and
the slots rearranged accordingly, with a 1.5% reduction in total
size of translations. */
-
static void vg_init_baseBlock ( void )
{
/* Those with offsets under 128 are carefully chosen. */
@@ -216,8 +224,7 @@
/* (9 or 18) + n_compact_helpers */
/* Register VG_(handle_esp_assignment) if needed. */
- if (VG_(track_events).new_mem_stack_aligned ||
- VG_(track_events).die_mem_stack_aligned)
+ if (VG_(need_to_handle_esp_assignment)())
VG_(register_compact_helper)( (Addr) & VG_(handle_esp_assignment) );
/* Allocate slots for compact helpers */
diff --git a/coregrind/vg_translate.c b/coregrind/vg_translate.c
index 1b30f15..e1c4984 100644
--- a/coregrind/vg_translate.c
+++ b/coregrind/vg_translate.c
@@ -1273,8 +1273,8 @@
Bool uInstrMentionsTempReg ( UInstr* u, Int tempreg )
{
Int i, k;
- Int tempUse[3];
- Bool notUsed[3];
+ Int tempUse[VG_MAX_REGS_USED];
+ Bool notUsed[VG_MAX_REGS_USED];
k = VG_(get_reg_usage) ( u, TempReg, &tempUse[0], ¬Used[0] );
for (i = 0; i < k; i++)
@@ -1300,8 +1300,8 @@
Int i, j, k, m, n, ar, tr, told, actual_areg;
Int areg_map[8];
Bool annul_put[8];
- Int tempUse[3];
- Bool isWrites[3];
+ Int tempUse[VG_MAX_REGS_USED];
+ Bool isWrites[VG_MAX_REGS_USED];
UInstr* u;
Bool wr;
Int* last_live_before;
@@ -1641,9 +1641,9 @@
Int ss_busy_until_before[VG_MAX_SPILLSLOTS];
Int i, j, k, m, r, tno, max_ss_no;
Bool wr, defer, isRead, spill_reqd;
- UInt realUse[3];
- Int tempUse[3];
- Bool isWrites[3];
+ UInt realUse[VG_MAX_REGS_USED];
+ Int tempUse[VG_MAX_REGS_USED];
+ Bool isWrites[VG_MAX_REGS_USED];
UCodeBlock* c2;
/* Used to denote ... well, "no value" in this fn. */
@@ -1670,7 +1670,7 @@
for (i = 0; i < c1->used; i++) {
k = VG_(get_reg_usage)(&c1->instrs[i], TempReg, &tempUse[0],
&isWrites[0]);
- vg_assert(k >= 0 && k <= 3);
+ vg_assert(k >= 0 && k <= VG_MAX_REGS_USED);
/* For each temp usage ... fwds in program order */
for (j = 0; j < k; j++) {
@@ -1811,7 +1811,7 @@
k = VG_(get_reg_usage)(&c1->instrs[i], TempReg, &tempUse[0],
&isWrites[0]);
- vg_assert(k >= 0 && k <= 3);
+ vg_assert(k >= 0 && k <= VG_MAX_REGS_USED);
/* For each ***different*** temp mentioned in the insn .... */
for (j = 0; j < k; j++) {
@@ -1980,8 +1980,8 @@
{
Int i, j, k;
RRegSet rregs_live;
- Int regUse[3];
- Bool isWrites[3];
+ Int regUse[VG_MAX_REGS_USED];
+ Bool isWrites[VG_MAX_REGS_USED];
UInstr* u;
/* All regs are dead at the end of the block */