|
From: <sv...@va...> - 2005-04-20 14:44:16
|
Author: sewardj
Date: 2005-04-20 15:44:11 +0100 (Wed, 20 Apr 2005)
New Revision: 3535
Modified:
trunk/memcheck/mac_leakcheck.c
trunk/memcheck/mac_shared.h
trunk/memcheck/mc_main.c
Log:
Initial rehash of Memcheck's shadow-space management to support both
32- and 64-bit targets, little- and big-endian. It does more or less
work on x86 as-is, although is unusably slow since I have knocked out
all the fast-path cases and am concentrating on getting the baseline
functionality correct. The fast cases will go back in in due course.
The fundamental idea is to retain the old 2-level indexing for speed,
even on a 64-bit target. Since that's clearly unviable on a 64-bit
target, the primary map handles only first N gigabytes of address
space (probably to be set to 16, 32 or 64G). Addresses above that are
handled slowly using an auxiliary primary map which explicitly lists
(base, &-of-secondary-map) pairs. The goal is to have the
address-space-manager try and put everything below the 16/32/64G
boundary, so we hit the fast cases almost all the time.
Performance of the 32-bit case should be unaffected since the fast map
will always cover at least the lowest 4G of address space.
There are many word-size and endianness cleanups.
Jeremy's distinguished-map space-compression scheme is retained, in
modified form, as it is simple and seems effective at reducing
Memcheck's space use.
Note this is all subject to rapid change.
Modified: trunk/memcheck/mac_leakcheck.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/memcheck/mac_leakcheck.c 2005-04-20 14:32:32 UTC (rev 3534)
+++ trunk/memcheck/mac_leakcheck.c 2005-04-20 14:44:11 UTC (rev 3535)
@@ -316,6 +316,7 @@
return ret;
}
=20
+
/* Scan a block of memory between [start, start+len). This range may
be bogus, inaccessable, or otherwise strange; we deal with it.
=20
@@ -323,6 +324,7 @@
cliques, and clique is the index of the current clique leader. */
static void _lc_scan_memory(Addr start, SizeT len, Int clique)
{
+#if 0
Addr ptr =3D ROUNDUP(start, sizeof(Addr));
Addr end =3D ROUNDDN(start+len, sizeof(Addr));
vki_sigset_t sigmask;
@@ -372,8 +374,10 @@
=20
VG_(sigprocmask)(VKI_SIG_SETMASK, &sigmask, NULL);
VG_(set_fault_catcher)(NULL);
+#endif
}
=20
+
static void lc_scan_memory(Addr start, SizeT len)
{
_lc_scan_memory(start, len, -1);
Modified: trunk/memcheck/mac_shared.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/memcheck/mac_shared.h 2005-04-20 14:32:32 UTC (rev 3534)
+++ trunk/memcheck/mac_shared.h 2005-04-20 14:44:11 UTC (rev 3535)
@@ -189,22 +189,23 @@
=20
#endif /* MAC_PROFILE_MEMORY */
=20
-/*------------------------------------------------------------*/
-/*--- V and A bits ---*/
-/*------------------------------------------------------------*/
=20
-/* expand 1 bit -> 8 */
-#define BIT_EXPAND(b) ((~(((UChar)(b) & 1) - 1)) & 0xFF)
-
-#define SECONDARY_SHIFT 16
-#define SECONDARY_SIZE (1 << SECONDARY_SHIFT)
-#define SECONDARY_MASK (SECONDARY_SIZE - 1)
-
-#define PRIMARY_SIZE (1 << (32 - SECONDARY_SHIFT))
-
-#define SM_OFF(addr) ((addr) & SECONDARY_MASK)
-#define PM_IDX(addr) ((addr) >> SECONDARY_SHIFT)
-
+//zz /*------------------------------------------------------------*/
+//zz /*--- V and A bits (Victoria & Albert ?) ---*/
+//zz /*------------------------------------------------------------*/
+//zz=20
+//zz /* expand 1 bit -> 8 */
+//zz #define BIT_EXPAND(b) ((~(((UChar)(b) & 1) - 1)) & 0xFF)
+//zz=20
+//zz #define SECONDARY_SHIFT 16
+//zz #define SECONDARY_SIZE (1 << SECONDARY_SHIFT)
+//zz #define SECONDARY_MASK (SECONDARY_SIZE - 1)
+//zz=20
+//zz #define PRIMARY_SIZE (1 << (32 - SECONDARY_SHIFT))
+//zz=20
+//zz #define SM_OFF(addr) ((addr) & SECONDARY_MASK)
+//zz #define PM_IDX(addr) ((addr) >> SECONDARY_SHIFT)
+/*
#define IS_DISTINGUISHED_SM(smap) \
((smap) >=3D &distinguished_secondary_maps[0] && \
(smap) < &distinguished_secondary_maps[N_SECONDARY_MAPS])
@@ -215,44 +216,63 @@
do { \
if (IS_DISTINGUISHED(addr)) { \
primary_map[PM_IDX(addr)] =3D alloc_secondary_map(caller, primary_map[=
PM_IDX(addr)]); \
- /* VG_(printf)("new 2map because of %p\n", addr); */ \
+ if (0) VG_(printf)("new 2map because of %p\n", addr); \
} \
- } while(0)
+ } while(0)
+*/
=20
#define BITARR_SET(aaa_p,iii_p) \
do { \
- UInt iii =3D (UInt)iii_p; \
- UChar* aaa =3D (UChar*)aaa_p; \
+ UWord iii =3D (UWord)iii_p; \
+ UChar* aaa =3D (UChar*)aaa_p; \
aaa[iii >> 3] |=3D (1 << (iii & 7)); \
} while (0)
=20
#define BITARR_CLEAR(aaa_p,iii_p) \
do { \
- UInt iii =3D (UInt)iii_p; \
- UChar* aaa =3D (UChar*)aaa_p; \
+ UWord iii =3D (UWord)iii_p; \
+ UChar* aaa =3D (UChar*)aaa_p; \
aaa[iii >> 3] &=3D ~(1 << (iii & 7)); \
} while (0)
=20
#define BITARR_TEST(aaa_p,iii_p) \
- (0 !=3D (((UChar*)aaa_p)[ ((UInt)iii_p) >> 3 ] \
- & (1 << (((UInt)iii_p) & 7)))) \
+ (0 !=3D (((UChar*)aaa_p)[ ((UWord)iii_p) >> 3 ] \
+ & (1 << (((UWord)iii_p) & 7)))) \
=20
+static inline=20
+void write_bit_array ( UChar* arr, UWord idx, UWord bit )=20
+{
+ UWord shift =3D idx & 7;
+ idx >>=3D 3;
+ bit &=3D 1;
+ arr[idx] =3D (arr[idx] & ~(1<<shift)) | (bit << shift);
+}
=20
-#define VGM_BIT_VALID 0
-#define VGM_BIT_INVALID 1
+static inline
+UWord read_bit_array ( UChar* arr, UWord idx )
+{
+ UWord shift =3D idx & 7;
+ idx >>=3D 3;
+ return 1 & (arr[idx] >> shift);
+}
=20
-#define VGM_NIBBLE_VALID 0
-#define VGM_NIBBLE_INVALID 0xF
=20
-#define VGM_BYTE_VALID 0
-#define VGM_BYTE_INVALID 0xFF
+#define VGM_BIT_VALID 0
+#define VGM_BIT_INVALID 1
=20
-#define VGM_WORD_VALID 0
-#define VGM_WORD_INVALID 0xFFFFFFFF
+#define VGM_NIBBLE_VALID 0
+#define VGM_NIBBLE_INVALID 0xF
=20
-#define VGM_WORD64_VALID 0x0ULL
-#define VGM_WORD64_INVALID 0xFFFFFFFFFFFFFFFFULL
+#define VGM_BYTE_VALID 0
+#define VGM_BYTE_INVALID 0xFF
=20
+#define VGM_WORD32_VALID 0
+#define VGM_WORD32_INVALID 0xFFFFFFFF
+
+#define VGM_WORD64_VALID 0ULL
+#define VGM_WORD64_INVALID 0xFFFFFFFFFFFFFFFFULL
+
+
/*------------------------------------------------------------*/
/*--- Command line options + defaults ---*/
/*------------------------------------------------------------*/
@@ -408,166 +428,166 @@
=20
Note that this code is executed very frequently and must be highly
optimised, which is why I resort to the preprocessor to achieve the
- factoring, rather than eg. using function pointers.
+ factoring, rather than eg. using function pointers. =20
*/
=20
-#define ESP_UPDATE_HANDLERS(ALIGNED4_NEW, ALIGNED4_DIE, =
\
- ALIGNED8_NEW, ALIGNED8_DIE, =
\
- UNALIGNED_NEW, UNALIGNED_DIE) =
\
- =
\
-void VGA_REGPARM(1) MAC_(new_mem_stack_4)(Addr new_ESP) =
\
-{ =
\
- PROF_EVENT(110); =
\
- if (VG_IS_4_ALIGNED(new_ESP)) { =
\
- ALIGNED4_NEW ( new_ESP ); =
\
- } else { =
\
- UNALIGNED_NEW ( new_ESP, 4 ); =
\
- } =
\
-} =
\
- =
\
-void VGA_REGPARM(1) MAC_(die_mem_stack_4)(Addr new_ESP) =
\
-{ =
\
- PROF_EVENT(120); =
\
- if (VG_IS_4_ALIGNED(new_ESP)) { =
\
- ALIGNED4_DIE ( new_ESP-4 ); =
\
- } else { =
\
- UNALIGNED_DIE ( new_ESP-4, 4 ); =
\
- } =
\
-} =
\
- =
\
-void VGA_REGPARM(1) MAC_(new_mem_stack_8)(Addr new_ESP) =
\
-{ =
\
- PROF_EVENT(111); =
\
- if (VG_IS_8_ALIGNED(new_ESP)) { =
\
- ALIGNED8_NEW ( new_ESP ); =
\
- } else if (VG_IS_4_ALIGNED(new_ESP)) { =
\
- ALIGNED4_NEW ( new_ESP ); =
\
- ALIGNED4_NEW ( new_ESP+4 ); =
\
- } else { =
\
- UNALIGNED_NEW ( new_ESP, 8 ); =
\
- } =
\
-} =
\
- =
\
-void VGA_REGPARM(1) MAC_(die_mem_stack_8)(Addr new_ESP) =
\
-{ =
\
- PROF_EVENT(121); =
\
- if (VG_IS_8_ALIGNED(new_ESP)) { =
\
- ALIGNED8_DIE ( new_ESP-8 ); =
\
- } else if (VG_IS_4_ALIGNED(new_ESP)) { =
\
- ALIGNED4_DIE ( new_ESP-8 ); =
\
- ALIGNED4_DIE ( new_ESP-4 ); =
\
- } else { =
\
- UNALIGNED_DIE ( new_ESP-8, 8 ); =
\
- } =
\
-} =
\
- =
\
-void VGA_REGPARM(1) MAC_(new_mem_stack_12)(Addr new_ESP) =
\
-{ =
\
- PROF_EVENT(112); =
\
- if (VG_IS_8_ALIGNED(new_ESP)) { =
\
- ALIGNED8_NEW ( new_ESP ); =
\
- ALIGNED4_NEW ( new_ESP+8 ); =
\
- } else if (VG_IS_4_ALIGNED(new_ESP)) { =
\
- ALIGNED4_NEW ( new_ESP ); =
\
- ALIGNED8_NEW ( new_ESP+4 ); =
\
- } else { =
\
- UNALIGNED_NEW ( new_ESP, 12 ); =
\
- } =
\
-} =
\
- =
\
-void VGA_REGPARM(1) MAC_(die_mem_stack_12)(Addr new_ESP) =
\
-{ =
\
- PROF_EVENT(122); =
\
- /* Note the -12 in the test */ =
\
- if (VG_IS_8_ALIGNED(new_ESP-12)) { =
\
- ALIGNED8_DIE ( new_ESP-12 ); =
\
- ALIGNED4_DIE ( new_ESP-4 ); =
\
- } else if (VG_IS_4_ALIGNED(new_ESP)) { =
\
- ALIGNED4_DIE ( new_ESP-12 ); =
\
- ALIGNED8_DIE ( new_ESP-8 ); =
\
- } else { =
\
- UNALIGNED_DIE ( new_ESP-12, 12 ); =
\
- } =
\
-} =
\
- =
\
-void VGA_REGPARM(1) MAC_(new_mem_stack_16)(Addr new_ESP) =
\
-{ =
\
- PROF_EVENT(113); =
\
- if (VG_IS_8_ALIGNED(new_ESP)) { =
\
- ALIGNED8_NEW ( new_ESP ); =
\
- ALIGNED8_NEW ( new_ESP+8 ); =
\
- } else if (VG_IS_4_ALIGNED(new_ESP)) { =
\
- ALIGNED4_NEW ( new_ESP ); =
\
- ALIGNED8_NEW ( new_ESP+4 ); =
\
- ALIGNED4_NEW ( new_ESP+12 ); =
\
- } else { =
\
- UNALIGNED_NEW ( new_ESP, 16 ); =
\
- } =
\
-} =
\
- =
\
-void VGA_REGPARM(1) MAC_(die_mem_stack_16)(Addr new_ESP) =
\
-{ =
\
- PROF_EVENT(123); =
\
- if (VG_IS_8_ALIGNED(new_ESP)) { =
\
- ALIGNED8_DIE ( new_ESP-16 ); =
\
- ALIGNED8_DIE ( new_ESP-8 ); =
\
- } else if (VG_IS_4_ALIGNED(new_ESP)) { =
\
- ALIGNED4_DIE ( new_ESP-16 ); =
\
- ALIGNED8_DIE ( new_ESP-12 ); =
\
- ALIGNED4_DIE ( new_ESP-4 ); =
\
- } else { =
\
- UNALIGNED_DIE ( new_ESP-16, 16 ); =
\
- } =
\
-} =
\
- =
\
-void VGA_REGPARM(1) MAC_(new_mem_stack_32)(Addr new_ESP) =
\
-{ =
\
- PROF_EVENT(114); =
\
- if (VG_IS_8_ALIGNED(new_ESP)) { =
\
- ALIGNED8_NEW ( new_ESP ); =
\
- ALIGNED8_NEW ( new_ESP+8 ); =
\
- ALIGNED8_NEW ( new_ESP+16 ); =
\
- ALIGNED8_NEW ( new_ESP+24 ); =
\
- } else if (VG_IS_4_ALIGNED(new_ESP)) { =
\
- ALIGNED4_NEW ( new_ESP ); =
\
- ALIGNED8_NEW ( new_ESP+4 ); =
\
- ALIGNED8_NEW ( new_ESP+12 ); =
\
- ALIGNED8_NEW ( new_ESP+20 ); =
\
- ALIGNED4_NEW ( new_ESP+28 ); =
\
- } else { =
\
- UNALIGNED_NEW ( new_ESP, 32 ); =
\
- } =
\
-} =
\
- =
\
-void VGA_REGPARM(1) MAC_(die_mem_stack_32)(Addr new_ESP) =
\
-{ =
\
- PROF_EVENT(124); =
\
- if (VG_IS_8_ALIGNED(new_ESP)) { =
\
- ALIGNED8_DIE ( new_ESP-32 ); =
\
- ALIGNED8_DIE ( new_ESP-24 ); =
\
- ALIGNED8_DIE ( new_ESP-16 ); =
\
- ALIGNED8_DIE ( new_ESP- 8 ); =
\
- } else if (VG_IS_4_ALIGNED(new_ESP)) { =
\
- ALIGNED4_DIE ( new_ESP-32 ); =
\
- ALIGNED8_DIE ( new_ESP-28 ); =
\
- ALIGNED8_DIE ( new_ESP-20 ); =
\
- ALIGNED8_DIE ( new_ESP-12 ); =
\
- ALIGNED4_DIE ( new_ESP-4 ); =
\
- } else { =
\
- UNALIGNED_DIE ( new_ESP-32, 32 ); =
\
- } =
\
-} =
\
- =
\
-void MAC_(new_mem_stack) ( Addr a, SizeT len ) =
\
-{ =
\
- PROF_EVENT(115); =
\
- UNALIGNED_NEW ( a, len ); =
\
-} =
\
- =
\
-void MAC_(die_mem_stack) ( Addr a, SizeT len ) =
\
-{ =
\
- PROF_EVENT(125); =
\
- UNALIGNED_DIE ( a, len ); =
\
+#define SP_UPDATE_HANDLERS(ALIGNED4_NEW, ALIGNED4_DIE, \
+ ALIGNED8_NEW, ALIGNED8_DIE, \
+ UNALIGNED_NEW, UNALIGNED_DIE) \
+ \
+void VGA_REGPARM(1) MAC_(new_mem_stack_4)(Addr new_SP) \
+{ \
+ PROF_EVENT(110); \
+ if (VG_IS_4_ALIGNED(new_SP)) { \
+ ALIGNED4_NEW ( new_SP ); \
+ } else { \
+ UNALIGNED_NEW ( new_SP, 4 ); \
+ } \
+} \
+ \
+void VGA_REGPARM(1) MAC_(die_mem_stack_4)(Addr new_SP) \
+{ \
+ PROF_EVENT(120); \
+ if (VG_IS_4_ALIGNED(new_SP)) { \
+ ALIGNED4_DIE ( new_SP-4 ); \
+ } else { \
+ UNALIGNED_DIE ( new_SP-4, 4 ); \
+ } \
+} \
+ \
+void VGA_REGPARM(1) MAC_(new_mem_stack_8)(Addr new_SP) \
+{ \
+ PROF_EVENT(111); \
+ if (VG_IS_8_ALIGNED(new_SP)) { \
+ ALIGNED8_NEW ( new_SP ); \
+ } else if (VG_IS_4_ALIGNED(new_SP)) { \
+ ALIGNED4_NEW ( new_SP ); \
+ ALIGNED4_NEW ( new_SP+4 ); \
+ } else { \
+ UNALIGNED_NEW ( new_SP, 8 ); \
+ } \
+} \
+ \
+void VGA_REGPARM(1) MAC_(die_mem_stack_8)(Addr new_SP) \
+{ \
+ PROF_EVENT(121); \
+ if (VG_IS_8_ALIGNED(new_SP)) { \
+ ALIGNED8_DIE ( new_SP-8 ); \
+ } else if (VG_IS_4_ALIGNED(new_SP)) { \
+ ALIGNED4_DIE ( new_SP-8 ); \
+ ALIGNED4_DIE ( new_SP-4 ); \
+ } else { \
+ UNALIGNED_DIE ( new_SP-8, 8 ); \
+ } \
+} \
+ \
+void VGA_REGPARM(1) MAC_(new_mem_stack_12)(Addr new_SP) \
+{ \
+ PROF_EVENT(112); \
+ if (VG_IS_8_ALIGNED(new_SP)) { \
+ ALIGNED8_NEW ( new_SP ); \
+ ALIGNED4_NEW ( new_SP+8 ); \
+ } else if (VG_IS_4_ALIGNED(new_SP)) { \
+ ALIGNED4_NEW ( new_SP ); \
+ ALIGNED8_NEW ( new_SP+4 ); \
+ } else { \
+ UNALIGNED_NEW ( new_SP, 12 ); \
+ } \
+} \
+ \
+void VGA_REGPARM(1) MAC_(die_mem_stack_12)(Addr new_SP) \
+{ \
+ PROF_EVENT(122); \
+ /* Note the -12 in the test */ \
+ if (VG_IS_8_ALIGNED(new_SP-12)) { \
+ ALIGNED8_DIE ( new_SP-12 ); \
+ ALIGNED4_DIE ( new_SP-4 ); \
+ } else if (VG_IS_4_ALIGNED(new_SP)) { \
+ ALIGNED4_DIE ( new_SP-12 ); \
+ ALIGNED8_DIE ( new_SP-8 ); \
+ } else { \
+ UNALIGNED_DIE ( new_SP-12, 12 ); \
+ } \
+} \
+ \
+void VGA_REGPARM(1) MAC_(new_mem_stack_16)(Addr new_SP) \
+{ \
+ PROF_EVENT(113); \
+ if (VG_IS_8_ALIGNED(new_SP)) { \
+ ALIGNED8_NEW ( new_SP ); \
+ ALIGNED8_NEW ( new_SP+8 ); \
+ } else if (VG_IS_4_ALIGNED(new_SP)) { \
+ ALIGNED4_NEW ( new_SP ); \
+ ALIGNED8_NEW ( new_SP+4 ); \
+ ALIGNED4_NEW ( new_SP+12 ); \
+ } else { \
+ UNALIGNED_NEW ( new_SP, 16 ); \
+ } \
+} \
+ \
+void VGA_REGPARM(1) MAC_(die_mem_stack_16)(Addr new_SP) \
+{ \
+ PROF_EVENT(123); \
+ if (VG_IS_8_ALIGNED(new_SP)) { \
+ ALIGNED8_DIE ( new_SP-16 ); \
+ ALIGNED8_DIE ( new_SP-8 ); \
+ } else if (VG_IS_4_ALIGNED(new_SP)) { \
+ ALIGNED4_DIE ( new_SP-16 ); \
+ ALIGNED8_DIE ( new_SP-12 ); \
+ ALIGNED4_DIE ( new_SP-4 ); \
+ } else { \
+ UNALIGNED_DIE ( new_SP-16, 16 ); \
+ } \
+} \
+ \
+void VGA_REGPARM(1) MAC_(new_mem_stack_32)(Addr new_SP) \
+{ \
+ PROF_EVENT(114); \
+ if (VG_IS_8_ALIGNED(new_SP)) { \
+ ALIGNED8_NEW ( new_SP ); \
+ ALIGNED8_NEW ( new_SP+8 ); \
+ ALIGNED8_NEW ( new_SP+16 ); \
+ ALIGNED8_NEW ( new_SP+24 ); \
+ } else if (VG_IS_4_ALIGNED(new_SP)) { \
+ ALIGNED4_NEW ( new_SP ); \
+ ALIGNED8_NEW ( new_SP+4 ); \
+ ALIGNED8_NEW ( new_SP+12 ); \
+ ALIGNED8_NEW ( new_SP+20 ); \
+ ALIGNED4_NEW ( new_SP+28 ); \
+ } else { \
+ UNALIGNED_NEW ( new_SP, 32 ); \
+ } \
+} \
+ \
+void VGA_REGPARM(1) MAC_(die_mem_stack_32)(Addr new_SP) \
+{ \
+ PROF_EVENT(124); \
+ if (VG_IS_8_ALIGNED(new_SP)) { \
+ ALIGNED8_DIE ( new_SP-32 ); \
+ ALIGNED8_DIE ( new_SP-24 ); \
+ ALIGNED8_DIE ( new_SP-16 ); \
+ ALIGNED8_DIE ( new_SP- 8 ); \
+ } else if (VG_IS_4_ALIGNED(new_SP)) { \
+ ALIGNED4_DIE ( new_SP-32 ); \
+ ALIGNED8_DIE ( new_SP-28 ); \
+ ALIGNED8_DIE ( new_SP-20 ); \
+ ALIGNED8_DIE ( new_SP-12 ); \
+ ALIGNED4_DIE ( new_SP-4 ); \
+ } else { \
+ UNALIGNED_DIE ( new_SP-32, 32 ); \
+ } \
+} \
+ \
+void MAC_(new_mem_stack) ( Addr a, SizeT len ) \
+{ \
+ PROF_EVENT(115); \
+ UNALIGNED_NEW ( a, len ); \
+} \
+ \
+void MAC_(die_mem_stack) ( Addr a, SizeT len ) \
+{ \
+ PROF_EVENT(125); \
+ UNALIGNED_DIE ( a, len ); \
}
=20
#endif /* __MAC_SHARED_H */
Modified: trunk/memcheck/mc_main.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/memcheck/mc_main.c 2005-04-20 14:32:32 UTC (rev 3534)
+++ trunk/memcheck/mc_main.c 2005-04-20 14:44:11 UTC (rev 3535)
@@ -30,424 +30,800 @@
The GNU General Public License is contained in the file COPYING.
*/
=20
+/* TODO urgently
+
+ sanity check:=20
+ auxmap only covers address space that the primary doesn't
+ auxmap entries non-duplicated (expensive)
+
+ types of helper functions
+
+ set_address_range_perms to notice when a distinguished secondary
+ will work, and use that (viz, re-implement compression scheme)
+
+ profile
+
+ reinstate fast-path cases
+*/
+
+
#include "mc_include.h"
#include "memcheck.h" /* for client requests */
//#include "vg_profile.c"
=20
-/* Define to debug the mem audit system. */
-/* #define VG_DEBUG_MEMORY */
=20
+typedef enum {
+ MC_Ok =3D 5, MC_AddrErr =3D 6, MC_ValueErr =3D 7
+} MC_ReadResult;
+
#define DEBUG(fmt, args...) //VG_(printf)(fmt, ## args)
=20
+
/*------------------------------------------------------------*/
-/*--- Low-level support for memory checking. ---*/
+/*--- Basic A/V bitmap representation. ---*/
/*------------------------------------------------------------*/
=20
-/* All reads and writes are checked against a memory map, which
- records the state of all memory in the process. The memory map is
- organised like this:
+/* --------------- Basic configuration --------------- */
=20
- The top 16 bits of an address are used to index into a top-level
- map table, containing 65536 entries. Each entry is a pointer to a
- second-level map, which records the accesibililty and validity
- permissions for the 65536 bytes indexed by the lower 16 bits of the
- address. Each byte is represented by nine bits, one indicating
- accessibility, the other eight validity. So each second-level map
- contains 73728 bytes. This two-level arrangement conveniently
- divides the 4G address space into 64k lumps, each size 64k bytes.
+/* The number of entries in the primary map can be altered. However
+ we hardwire the assumption that each secondary map covers precisely
+ 64k of address space. */
=20
- All entries in the primary (top-level) map must point to a valid
- secondary (second-level) map. Since most of the 4G of address
- space will not be in use -- ie, not mapped at all -- there is a
- distinguished secondary map, which indicates `not addressible and
- not valid' writeable for all bytes. Entries in the primary map for
- which the entire 64k is not in use at all point at this
- distinguished map.
+#define N_PRIMARY_BITS 16
+#define N_PRIMARY_MAPS ((1 << N_PRIMARY_BITS)-1)
=20
- There are actually 4 distinguished secondaries. These are used to
- represent a memory range which is either not addressable (validity
- doesn't matter), addressable+not valid, addressable+valid.
+#define MAX_PRIMARY_ADDRESS (Addr)(((Addr)65536) * N_PRIMARY_MAPS)
=20
- [...] lots of stuff deleted due to out of date-ness
=20
- As a final optimisation, the alignment and address checks for
- 4-byte loads and stores are combined in a neat way. The primary
- map is extended to have 262144 entries (2^18), rather than 2^16.
- The top 3/4 of these entries are permanently set to the
- distinguished secondary map. For a 4-byte load/store, the
- top-level map is indexed not with (addr >> 16) but instead f(addr),
- where
+/* --------------- Secondary maps --------------- */
=20
- f( XXXX XXXX XXXX XXXX ____ ____ ____ __YZ )
- =3D ____ ____ ____ __YZ XXXX XXXX XXXX XXXX or=20
- =3D ____ ____ ____ __ZY XXXX XXXX XXXX XXXX
+typedef=20
+ struct {
+ UChar abits[8192];
+ UChar vbyte[65536];
+ }
+ SecMap;
=20
- ie the lowest two bits are placed above the 16 high address bits.
- If either of these two bits are nonzero, the address is misaligned;
- this will select a secondary map from the upper 3/4 of the primary
- map. Because this is always the distinguished secondary map, a
- (bogus) address check failure will result. The failure handling
- code can then figure out whether this is a genuine addr check
- failure or whether it is a possibly-legitimate access at a
- misaligned address. =20
+/* 3 distinguished secondary maps, one for no-access, one for
+ accessible but undefined, and one for accessible and defined.
+ Distinguished secondaries may never be modified.
*/
+#define SM_DIST_NOACCESS 0
+#define SM_DIST_ACCESS_UNDEFINED 1
+#define SM_DIST_ACCESS_DEFINED 2
=20
-/*------------------------------------------------------------*/
-/*--- Function declarations. ---*/
-/*------------------------------------------------------------*/
+static SecMap sm_distinguished[3];
=20
-static ULong mc_rd_V8_SLOWLY ( Addr a );
-static UInt mc_rd_V4_SLOWLY ( Addr a );
-static UInt mc_rd_V2_SLOWLY ( Addr a );
-static UInt mc_rd_V1_SLOWLY ( Addr a );
+static inline Bool is_distinguished_sm ( SecMap* sm ) {
+ return sm >=3D &sm_distinguished[0] && sm <=3D &sm_distinguished[2];
+}
=20
-static void mc_wr_V8_SLOWLY ( Addr a, ULong vbytes );
-static void mc_wr_V4_SLOWLY ( Addr a, UInt vbytes );
-static void mc_wr_V2_SLOWLY ( Addr a, UInt vbytes );
-static void mc_wr_V1_SLOWLY ( Addr a, UInt vbytes );
+/* dist_sm points to one of our three distinguished secondaries. Make
+ a copy of it so that we can write to it.
+*/
+static SecMap* copy_for_writing ( SecMap* dist_sm )
+{
+ SecMap* new_sm;
+ tl_assert(dist_sm =3D=3D &sm_distinguished[0]
+ || dist_sm =3D=3D &sm_distinguished[1]
+ || dist_sm =3D=3D &sm_distinguished[2]);
=20
-/*------------------------------------------------------------*/
-/*--- Data defns. ---*/
-/*------------------------------------------------------------*/
+ new_sm =3D VG_(shadow_alloc)(sizeof(SecMap));
+ VG_(memcpy)(new_sm, dist_sm, sizeof(SecMap));
+ return new_sm;
+}
=20
-typedef=20
- struct {
- UChar abits[SECONDARY_SIZE/8];
- UChar vbyte[SECONDARY_SIZE];
- }
- SecMap;
=20
+/* --------------- Primary maps --------------- */
=20
-static SecMap* primary_map[ /*PRIMARY_SIZE*/ PRIMARY_SIZE*4 ];
+/* The main primary map. This covers some initial part of the address
+ space, addresses 0 .. (N_PRIMARY_MAPS << 16)-1. The rest of it is
+ handled using the auxiliary primary map. =20
+*/
+static SecMap* primary_map[N_PRIMARY_MAPS];
=20
-#define DSM_IDX(a, v) ((((a)&1) << 1) + ((v)&1))
=20
-/* 4 secondary maps, but one is redundant (because the !addressable &&
- valid state is meaningless) */
-static const SecMap distinguished_secondary_maps[4] =3D {
-#define INIT(a, v) \
- [ DSM_IDX(a, v) ] =3D { { [0 ... (SECONDARY_SIZE/8)-1] =3D BIT_EXPAND=
(a) }, \
- { [0 ... SECONDARY_SIZE-1] =3D BIT_EXPAND(a|v) } }
- INIT(VGM_BIT_VALID, VGM_BIT_VALID),
- INIT(VGM_BIT_VALID, VGM_BIT_INVALID),
- INIT(VGM_BIT_INVALID, VGM_BIT_VALID),
- INIT(VGM_BIT_INVALID, VGM_BIT_INVALID),
-#undef INIT
-};
-#define N_SECONDARY_MAPS (sizeof(distinguished_secondary_maps)/sizeof(*d=
istinguished_secondary_maps))
+/* An entry in the auxiliary primary map. base must be a 64k-aligned
+ value, and sm points at the relevant secondary map. As with the
+ main primary map, the secondary may be either a real secondary, or
+ one of the three distinguished secondaries.
+*/
+typedef
+ struct {=20
+ Addr base;
+ SecMap* sm;
+ }
+ AuxMapEnt;
=20
-#define DSM(a,v) ((SecMap *)&distinguished_secondary_maps[DSM_IDX(a, v)=
])
+/* An expanding array of AuxMapEnts. */
+#define N_AUXMAPS 500 /* HACK */
+static AuxMapEnt hacky_auxmaps[N_AUXMAPS];
+static Int auxmap_size =3D N_AUXMAPS;
+static Int auxmap_used =3D 0;
+static AuxMapEnt* auxmap =3D &hacky_auxmaps[0];
=20
-#define DSM_NOTADDR DSM(VGM_BIT_INVALID, VGM_BIT_INVALID)
-#define DSM_ADDR_NOTVALID DSM(VGM_BIT_VALID, VGM_BIT_INVALID)
-#define DSM_ADDR_VALID DSM(VGM_BIT_VALID, VGM_BIT_VALID)
+/* Auxmap statistics */
+static ULong n_auxmap_searches =3D 0;
+static ULong n_auxmap_cmps =3D 0;
=20
-static void init_shadow_memory ( void )
+
+/* Find an entry in the auxiliary map. If an entry is found, move it
+ one step closer to the front of the array, then return its address.
+ If an entry is not found, allocate one. Note carefully that
+ because a each call potentially rearranges the entries, each call
+ to this function invalidates ALL AuxMapEnt*s previously obtained by
+ calling this fn. =20
+*/
+static AuxMapEnt* find_or_alloc_in_auxmap ( Addr a )
{
- Int i, a, v;
+ UWord i;
+ tl_assert(a > MAX_PRIMARY_ADDRESS);
=20
- /* check construction of the 4 distinguished secondaries */
- tl_assert(VGM_BIT_INVALID =3D=3D 1);
- tl_assert(VGM_BIT_VALID =3D=3D 0);
+ a &=3D ~(Addr)0xFFFF;
=20
- for (a =3D 0; a <=3D 1; a++) {
- for (v =3D 0; v <=3D 1; v++) {
- if (DSM(a,v)->abits[0] !=3D BIT_EXPAND(a))
- VG_(printf)("DSM(%d,%d)[%d]->abits[0] =3D=3D %x not %x\n",
- a,v,DSM_IDX(a,v),DSM(a,v)->abits[0], BIT_EXPAND(a));
- if (DSM(a,v)->vbyte[0] !=3D BIT_EXPAND(a|v))
- VG_(printf)("DSM(%d,%d)[%d]->vbyte[0] =3D=3D %x not %x\n",
- a,v,DSM_IDX(a,v),DSM(a,v)->vbyte[0], BIT_EXPAND(a|v));
+ /* Search .. */
+ n_auxmap_searches++;
+ for (i =3D 0; i < auxmap_used; i++) {
+ if (auxmap[i].base =3D=3D a)
+ break;
+ }
+ n_auxmap_cmps +=3D (ULong)(i+1);
=20
- tl_assert(DSM(a,v)->abits[0] =3D=3D BIT_EXPAND(a));
- tl_assert(DSM(a,v)->vbyte[0] =3D=3D BIT_EXPAND(v|a));
+ if (i < auxmap_used) {
+ /* Found it. Nudge it a bit closer to the front. */
+ if (i > 0) {
+ AuxMapEnt tmp =3D auxmap[i-1];
+ auxmap[i-1] =3D auxmap[i];
+ auxmap[i] =3D tmp;
+ i--;
}
+ return &auxmap[i];
}
-=20
- /* These entries gradually get overwritten as the used address
- space expands. */
- for (i =3D 0; i < PRIMARY_SIZE; i++)
- primary_map[i] =3D DSM_NOTADDR;
=20
- /* These ones should never change; it's a bug in Valgrind if they do.=
*/
- for (i =3D PRIMARY_SIZE; i < PRIMARY_SIZE*4; i++)
- primary_map[i] =3D DSM_NOTADDR;
+ /* We didn't find it. Hmm. This is a new piece of address space.
+ We'll need to allocate a new AuxMap entry for it. */
+ if (auxmap_used >=3D auxmap_size) {
+ tl_assert(auxmap_used =3D=3D auxmap_size);
+ /* Out of auxmap entries. */
+ tl_assert2(0, "failed to expand the auxmap table");
+ }
+
+ tl_assert(auxmap_used < auxmap_size);
+
+ auxmap[auxmap_used].base =3D a & ~(Addr)0xFFFF;
+ auxmap[auxmap_used].sm =3D &sm_distinguished[SM_DIST_NOACCESS];
+
+ if (0)
+ VG_(printf)("new auxmap, base =3D 0x%llx\n",=20
+ (ULong)auxmap[auxmap_used].base );
+
+ auxmap_used++;
+ return &auxmap[auxmap_used-1];
}
=20
-/*------------------------------------------------------------*/
-/*--- Basic bitmap management, reading and writing. ---*/
-/*------------------------------------------------------------*/
=20
-/* Allocate and initialise a secondary map. */
+/* --------------- SecMap fundamentals --------------- */
=20
-static SecMap* alloc_secondary_map ( __attribute__ ((unused))=20
- Char* caller,
- const SecMap *prototype)
+/* Produce the secmap for 'a', either from the primary map or by
+ ensuring there is an entry for it in the aux primary map. The
+ secmap may be a distinguished one as the caller will only want to
+ be able to read it.=20
+*/
+static SecMap* get_secmap_readable ( Addr a )
{
- SecMap* map;
- PROF_EVENT(10);
+ if (a <=3D MAX_PRIMARY_ADDRESS) {
+ UWord pm_off =3D a >> 16;
+ return primary_map[ pm_off ];
+ } else {
+ AuxMapEnt* am =3D find_or_alloc_in_auxmap(a);
+ return am->sm;
+ }
+}
=20
- map =3D (SecMap *)VG_(shadow_alloc)(sizeof(SecMap));
+/* Produce the secmap for 'a', either from the primary map or by
+ ensuring there is an entry for it in the aux primary map. The
+ secmap may not be a distinguished one, since the caller will want
+ to be able to write it. If it is a distinguished secondary, make a
+ writable copy of it, install it, and return the copy instead. (COW
+ semantics).
+*/
+static SecMap* get_secmap_writable ( Addr a )
+{
+ if (a <=3D MAX_PRIMARY_ADDRESS) {
+ UWord pm_off =3D a >> 16;
+ if (is_distinguished_sm(primary_map[ pm_off ]))
+ primary_map[pm_off] =3D copy_for_writing(primary_map[pm_off]);
+ return primary_map[pm_off];
+ } else {
+ AuxMapEnt* am =3D find_or_alloc_in_auxmap(a);
+ if (is_distinguished_sm(am->sm))
+ am->sm =3D copy_for_writing(am->sm);
+ return am->sm;
+ }
+}
=20
- VG_(memcpy)(map, prototype, sizeof(*map));
=20
- /* VG_(printf)("ALLOC_2MAP(%s)\n", caller ); */
- return map;
+/* --------------- Endianness helpers --------------- */
+
+/* Returns the offset in memory of the byteno-th most significant byte
+ in a wordszB-sized word, given the specified endianness. */
+static inline UWord byte_offset_w ( UWord wordszB, Bool bigendian,=20
+ UWord byteno ) {
+ return bigendian ? (wordszB-1-byteno) : byteno;
}
=20
=20
-/* Basic reading/writing of the bitmaps, for byte-sized accesses. */
+/* --------------- Fundamental functions --------------- */
=20
-static __inline__ UChar get_abit ( Addr a )
+static=20
+void get_abit_and_vbyte ( /*OUT*/UWord* abit,=20
+ /*OUT*/UWord* vbyte,
+ Addr a )
{
- SecMap* sm =3D primary_map[PM_IDX(a)];
- UInt sm_off =3D SM_OFF(a);
- PROF_EVENT(20);
-# if 0
- if (IS_DISTINGUISHED_SM(sm))
- VG_(message)(Vg_DebugMsg,=20
- "accessed distinguished 2ndary (A)map! 0x%x\n", a)=
;
-# endif
- return BITARR_TEST(sm->abits, sm_off)=20
- ? VGM_BIT_INVALID : VGM_BIT_VALID;
-}
+ SecMap* sm =3D get_secmap_readable(a);
+ *vbyte =3D 0xFF & sm->vbyte[a & 0xFFFF];
+ *abit =3D read_bit_array(sm->abits, a & 0xFFFF);
+}=20
=20
-static __inline__ UChar get_vbyte ( Addr a )
+static=20
+UWord get_abit ( Addr a )
{
- SecMap* sm =3D primary_map[PM_IDX(a)];
- UInt sm_off =3D SM_OFF(a);
- PROF_EVENT(21);
-# if 0
- if (IS_DISTINGUISHED_SM(sm))
- VG_(message)(Vg_DebugMsg,=20
- "accessed distinguished 2ndary (V)map! 0x%x\n", a)=
;
-# endif
- return sm->vbyte[sm_off];
+ SecMap* sm =3D get_secmap_readable(a);
+ return read_bit_array(sm->abits, a & 0xFFFF);
}
=20
-static /* __inline__ */ void set_abit ( Addr a, UChar abit )
+static
+void set_abit_and_vbyte ( Addr a, UWord abit, UWord vbyte )
{
- SecMap* sm;
- UInt sm_off;
- PROF_EVENT(22);
- ENSURE_MAPPABLE(a, "set_abit");
- sm =3D primary_map[PM_IDX(a)];
- sm_off =3D SM_OFF(a);
- if (abit)=20
- BITARR_SET(sm->abits, sm_off);
- else
- BITARR_CLEAR(sm->abits, sm_off);
+ SecMap* sm =3D get_secmap_writable(a);
+ sm->vbyte[a & 0xFFFF] =3D 0xFF & vbyte;
+ write_bit_array(sm->abits, a & 0xFFFF, abit); =20
}
=20
-static __inline__ void set_vbyte ( Addr a, UChar vbyte )
+static
+void set_vbyte ( Addr a, UWord vbyte )
{
- SecMap* sm;
- UInt sm_off;
- PROF_EVENT(23);
- ENSURE_MAPPABLE(a, "set_vbyte");
- sm =3D primary_map[PM_IDX(a)];
- sm_off =3D SM_OFF(a);
- sm->vbyte[sm_off] =3D vbyte;
+ SecMap* sm =3D get_secmap_writable(a);
+ sm->vbyte[a & 0xFFFF] =3D 0xFF & vbyte;
}
=20
=20
-/* Reading/writing of the bitmaps, for aligned word-sized accesses. */
+/* --------------- Load/store slow cases. --------------- */
=20
-static __inline__ UChar get_abits4_ALIGNED ( Addr a )
+static
+ULong mc_LOADVn_slow ( Addr a, SizeT szB, Bool bigendian )
{
- SecMap* sm;
- UInt sm_off;
- UChar abits8;
- PROF_EVENT(24);
-# ifdef VG_DEBUG_MEMORY
- tl_assert(VG_IS_4_ALIGNED(a));
-# endif
- sm =3D primary_map[PM_IDX(a)];
- sm_off =3D SM_OFF(a);
- abits8 =3D sm->abits[sm_off >> 3];
- abits8 >>=3D (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
- abits8 &=3D 0x0F;
- return abits8;
+ /* Make up a result V word, which contains the loaded data for
+ valid addresses and Undefined for invalid addresses. Iterate
+ over the bytes in the word, from the most significant down to
+ the least. */
+ ULong vw =3D VGM_WORD64_INVALID;
+ SizeT i =3D szB-1;
+ SizeT n_addrs_bad =3D 0;
+ Addr ai;
+ Bool aok;
+ UWord abit, vbyte;
+
+ PROF_EVENT(70);
+ tl_assert(szB =3D=3D 8 || szB =3D=3D 4 || szB =3D=3D 2 || szB =3D=3D =
1);
+
+ while (True) {
+ ai =3D a+byte_offset_w(szB,bigendian,i);
+ get_abit_and_vbyte(&abit, &vbyte, ai);
+ aok =3D abit =3D=3D VGM_BIT_VALID;
+ if (!aok)
+ n_addrs_bad++;
+ vw <<=3D 8;=20
+ vw |=3D 0xFF & (aok ? vbyte : VGM_BYTE_INVALID);
+ if (i =3D=3D 0) break;
+ i--;
+ }
+
+ if (n_addrs_bad > 0)
+ MAC_(record_address_error)( VG_(get_running_tid)(), a, szB, False =
);
+
+ //if (n_addrs_bad =3D=3D n)
+ // vw =3D VGM_WORD64_VALID;
+ return vw;
}
=20
-static UInt __inline__ get_vbytes4_ALIGNED ( Addr a )
+
+static=20
+void mc_STOREVn_slow ( Addr a, SizeT szB, UWord vbytes, Bool bigendian )
{
- SecMap* sm =3D primary_map[PM_IDX(a)];
- UInt sm_off =3D SM_OFF(a);
- PROF_EVENT(25);
-# ifdef VG_DEBUG_MEMORY
- tl_assert(VG_IS_4_ALIGNED(a));
-# endif
- return ((UInt*)(sm->vbyte))[sm_off >> 2];
-}
+ SizeT i;
+ SizeT n_addrs_bad =3D 0;
+ UWord abit;
+ Bool aok;
+ Addr ai;
=20
+ PROF_EVENT(71);
+ tl_assert(szB =3D=3D 8 || szB =3D=3D 4 || szB =3D=3D 2 || szB =3D=3D =
1);
=20
-static void __inline__ set_vbytes4_ALIGNED ( Addr a, UInt vbytes )
-{
- SecMap* sm;
- UInt sm_off;
- ENSURE_MAPPABLE(a, "set_vbytes4_ALIGNED");
- sm =3D primary_map[PM_IDX(a)];
- sm_off =3D SM_OFF(a);
- PROF_EVENT(23);
-# ifdef VG_DEBUG_MEMORY
- tl_assert(VG_IS_4_ALIGNED(a));
-# endif
- ((UInt*)(sm->vbyte))[sm_off >> 2] =3D vbytes;
+ /* Dump vbytes in memory, iterating from least to most significant
+ byte. At the same time establish addressibility of the
+ location. */
+ for (i =3D 0; i < szB; i++) {
+ ai =3D a+byte_offset_w(szB,bigendian,i);
+ abit =3D get_abit(ai);
+ aok =3D abit =3D=3D VGM_BIT_VALID;
+ if (!aok)
+ n_addrs_bad++;
+ set_vbyte(ai, vbytes & 0xFF );=20
+ vbytes >>=3D 8;
+ }
+
+ /* If an address error has happened, report it. */
+ if (n_addrs_bad > 0)
+ MAC_(record_address_error)( VG_(get_running_tid)(), a, szB, True )=
;
}
=20
=20
-/*------------------------------------------------------------*/
-/*--- Setting permissions over address ranges. ---*/
-/*------------------------------------------------------------*/
+///////////////////////////////////////////////////////////////
=20
-static void set_address_range_perms ( Addr a, SizeT len,=20
- UInt example_a_bit,
- UInt example_v_bit )
-{
- UChar vbyte, abyte8;
- UInt vword4, sm_off;
- SecMap* sm;
=20
- PROF_EVENT(30);
=20
- if (len =3D=3D 0)
- return;
=20
- if (VG_(clo_verbosity) > 0) {
- if (len > 100 * 1000 * 1000) {
- VG_(message)(Vg_UserMsg,=20
- "Warning: set address range perms: "
- "large range %u, a %d, v %d",
- len, example_a_bit, example_v_bit );
- }
- }
+/////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////
=20
- VGP_PUSHCC(VgpSetMem);
+//zz #if 0 /* this is the old implementation */
+//zz=20
+//zz /* Define to debug the mem audit system. */
+//zz /* #define VG_DEBUG_MEMORY */
+//zz=20
+//zz=20
+//zz /*------------------------------------------------------------*/
+//zz /*--- Low-level support for memory checking. ---*/
+//zz /*------------------------------------------------------------*/
+//zz=20
+//zz /* All reads and writes are checked against a memory map, which
+//zz records the state of all memory in the process. The memory map =
is
+//zz organised like this:
+//zz=20
+//zz The top 16 bits of an address are used to index into a top-level
+//zz map table, containing 65536 entries. Each entry is a pointer to=
a
+//zz second-level map, which records the accesibililty and validity
+//zz permissions for the 65536 bytes indexed by the lower 16 bits of =
the
+//zz address. Each byte is represented by nine bits, one indicating
+//zz accessibility, the other eight validity. So each second-level m=
ap
+//zz contains 73728 bytes. This two-level arrangement conveniently
+//zz divides the 4G address space into 64k lumps, each size 64k bytes=
.
+//zz=20
+//zz All entries in the primary (top-level) map must point to a valid
+//zz secondary (second-level) map. Since most of the 4G of address
+//zz space will not be in use -- ie, not mapped at all -- there is a
+//zz distinguished secondary map, which indicates `not addressible an=
d
+//zz not valid' writeable for all bytes. Entries in the primary map =
for
+//zz which the entire 64k is not in use at all point at this
+//zz distinguished map.
+//zz=20
+//zz There are actually 4 distinguished secondaries. These are used =
to
+//zz represent a memory range which is either not addressable (validi=
ty
+//zz doesn't matter), addressable+not valid, addressable+valid.
+//zz=20
+//zz [...] lots of stuff deleted due to out of date-ness
+//zz=20
+//zz As a final optimisation, the alignment and address checks for
+//zz 4-byte loads and stores are combined in a neat way. The primary
+//zz map is extended to have 262144 entries (2^18), rather than 2^16.
+//zz The top 3/4 of these entries are permanently set to the
+//zz distinguished secondary map. For a 4-byte load/store, the
+//zz top-level map is indexed not with (addr >> 16) but instead f(add=
r),
+//zz where
+//zz=20
+//zz f( XXXX XXXX XXXX XXXX ____ ____ ____ __YZ )
+//zz =3D ____ ____ ____ __YZ XXXX XXXX XXXX XXXX or=20
+//zz =3D ____ ____ ____ __ZY XXXX XXXX XXXX XXXX
+//zz=20
+//zz ie the lowest two bits are placed above the 16 high address bits=
.
+//zz If either of these two bits are nonzero, the address is misalign=
ed;
+//zz this will select a secondary map from the upper 3/4 of the prima=
ry
+//zz map. Because this is always the distinguished secondary map, a
+//zz (bogus) address check failure will result. The failure handling
+//zz code can then figure out whether this is a genuine addr check
+//zz failure or whether it is a possibly-legitimate access at a
+//zz misaligned address. =20
+//zz */
+//zz=20
+//zz /*------------------------------------------------------------*/
+//zz /*--- Function declarations. ---*/
+//zz /*------------------------------------------------------------*/
+//zz=20
+//zz static ULong mc_rd_V8_SLOWLY ( Addr a );
+//zz static UInt mc_rd_V4_SLOWLY ( Addr a );
+//zz static UInt mc_rd_V2_SLOWLY ( Addr a );
+//zz static UInt mc_rd_V1_SLOWLY ( Addr a );
+//zz=20
+//zz static void mc_wr_V8_SLOWLY ( Addr a, ULong vbytes );
+//zz static void mc_wr_V4_SLOWLY ( Addr a, UInt vbytes );
+//zz static void mc_wr_V2_SLOWLY ( Addr a, UInt vbytes );
+//zz static void mc_wr_V1_SLOWLY ( Addr a, UInt vbytes );
+//zz=20
+//zz /*------------------------------------------------------------*/
+//zz /*--- Data defns. ---*/
+//zz /*------------------------------------------------------------*/
+//zz=20
+//zz typedef=20
+//zz struct {
+//zz UChar abits[SECONDARY_SIZE/8];
+//zz UChar vbyte[SECONDARY_SIZE];
+//zz }
+//zz SecMap;
+//zz=20
+//zz=20
+//zz static SecMap* primary_map[ /*PRIMARY_SIZE*/ PRIMARY_SIZE*4 ];
+//zz=20
+//zz #define DSM_IDX(a, v) ((((a)&1) << 1) + ((v)&1))
+//zz=20
+//zz /* 4 secondary maps, but one is redundant (because the !addressable=
&&
+//zz valid state is meaningless) */
+//zz static const SecMap distinguished_secondary_maps[4] =3D {
+//zz #define INIT(a, v) \
+//zz [ DSM_IDX(a, v) ] =3D { { [0 ... (SECONDARY_SIZE/8)-1] =3D BIT_E=
XPAND(a) }, \
+//zz { [0 ... SECONDARY_SIZE-1] =3D BIT_EXPAND(a|v) } }
+//zz INIT(VGM_BIT_VALID, VGM_BIT_VALID),
+//zz INIT(VGM_BIT_VALID, VGM_BIT_INVALID),
+//zz INIT(VGM_BIT_INVALID, VGM_BIT_VALID),
+//zz INIT(VGM_BIT_INVALID, VGM_BIT_INVALID),
+//zz #undef INIT
+//zz };
+//zz #define N_SECONDARY_MAPS (sizeof(distinguished_secondary_maps)/size=
of(*distinguished_secondary_maps))
+//zz=20
+//zz #define DSM(a,v) ((SecMap *)&distinguished_secondary_maps[DSM_IDX(=
a, v)])
+//zz=20
+//zz #define DSM_NOTADDR DSM(VGM_BIT_INVALID, VGM_BIT_INVALID)
+//zz #define DSM_ADDR_NOTVALID DSM(VGM_BIT_VALID, VGM_BIT_INVALID)
+//zz #define DSM_ADDR_VALID DSM(VGM_BIT_VALID, VGM_BIT_VALID)
=20
- /* Requests to change permissions of huge address ranges may
- indicate bugs in our machinery. 30,000,000 is arbitrary, but so
- far all legitimate requests have fallen beneath that size. */
- /* 4 Mar 02: this is just stupid; get rid of it. */
- /* tl_assert(len < 30000000); */
+static void init_shadow_memory ( void )
+{
+ Int i;
+ SecMap* sm;
=20
- /* Check the permissions make sense. */
- tl_assert(example_a_bit =3D=3D VGM_BIT_VALID=20
- || example_a_bit =3D=3D VGM_BIT_INVALID);
- tl_assert(example_v_bit =3D=3D VGM_BIT_VALID=20
- || example_v_bit =3D=3D VGM_BIT_INVALID);
- if (example_a_bit =3D=3D VGM_BIT_INVALID)
- tl_assert(example_v_bit =3D=3D VGM_BIT_INVALID);
+ /* Build the 3 distinguished secondaries */
+ tl_assert(VGM_BIT_INVALID =3D=3D 1);
+ tl_assert(VGM_BIT_VALID =3D=3D 0);
+ tl_assert(VGM_BYTE_INVALID =3D=3D 0xFF);
+ tl_assert(VGM_BYTE_VALID =3D=3D 0);
=20
- /* The validity bits to write. */
- vbyte =3D example_v_bit=3D=3DVGM_BIT_VALID=20
- ? VGM_BYTE_VALID : VGM_BYTE_INVALID;
+ /* Set A invalid, V invalid. */
+ sm =3D &sm_distinguished[SM_DIST_NOACCESS];
+ for (i =3D 0; i < 65536; i++)
+ sm->vbyte[i] =3D VGM_BYTE_INVALID;
+ for (i =3D 0; i < 8192; i++)
+ sm->abits[i] =3D VGM_BYTE_INVALID;
=20
- /* In order that we can charge through the address space at 8
- bytes/main-loop iteration, make up some perms. */
- abyte8 =3D BIT_EXPAND(example_a_bit);
- vword4 =3D (vbyte << 24) | (vbyte << 16) | (vbyte << 8) | vbyte;
+ /* Set A valid, V invalid. */
+ sm =3D &sm_distinguished[SM_DIST_ACCESS_UNDEFINED];
+ for (i =3D 0; i < 65536; i++)
+ sm->vbyte[i] =3D VGM_BYTE_INVALID;
+ for (i =3D 0; i < 8192; i++)
+ sm->abits[i] =3D VGM_BYTE_VALID;
=20
-# ifdef VG_DEBUG_MEMORY
- /* Do it ... */
- while (True) {
- PROF_EVENT(31);
- if (len =3D=3D 0) break;
- set_abit ( a, example_a_bit );
- set_vbyte ( a, vbyte );
- a++;
- len--;
- }
+ /* Set A valid, V valid. */
+ sm =3D &sm_distinguished[SM_DIST_ACCESS_DEFINED];
+ for (i =3D 0; i < 65536; i++)
+ sm->vbyte[i] =3D VGM_BYTE_VALID;
+ for (i =3D 0; i < 8192; i++)
+ sm->abits[i] =3D VGM_BYTE_VALID;
=20
-# else
- /* Slowly do parts preceding 8-byte alignment. */
- while (True) {
- PROF_EVENT(31);
- if (len =3D=3D 0) break;
- if ((a % 8) =3D=3D 0) break;
- set_abit ( a, example_a_bit );
- set_vbyte ( a, vbyte );
- a++;
- len--;
- } =20
+ /* Set up the primary map. */
+ /* These entries gradually get overwritten as the used address
+ space expands. */
+ for (i =3D 0; i < N_PRIMARY_MAPS; i++)
+ primary_map[i] =3D &sm_distinguished[SM_DIST_NOACCESS];
=20
- if (len =3D=3D 0) {
- VGP_POPCC(VgpSetMem);
- return;
- }
- tl_assert((a % 8) =3D=3D 0 && len > 0);
+ /* auxmap_size =3D auxmap_used =3D 0;=20
+ no ... these are statically initialised */
=20
- /* Now align to the next primary_map entry */
- for (; (a & SECONDARY_MASK) && len >=3D 8; a +=3D 8, len -=3D 8) {
+ tl_assert( TL_(expensive_sanity_check)() );
+}
=20
- PROF_EVENT(32);
- /* If the primary is already pointing to a distinguished map
- with the same properties as we're trying to set, then leave
- it that way. */
- if (primary_map[PM_IDX(a)] =3D=3D DSM(example_a_bit, example_v_bit=
))
- continue;
=20
- ENSURE_MAPPABLE(a, "set_address_range_perms(fast)");
- sm =3D primary_map[PM_IDX(a)];
- sm_off =3D SM_OFF(a);
- sm->abits[sm_off >> 3] =3D abyte8;
- ((UInt*)(sm->vbyte))[(sm_off >> 2) + 0] =3D vword4;
- ((UInt*)(sm->vbyte))[(sm_off >> 2) + 1] =3D vword4;
- }
+//zz /*------------------------------------------------------------*/
+//zz /*--- Basic bitmap management, reading and writing. ---*/
+//zz /*------------------------------------------------------------*/
+//zz=20
+//zz /* Allocate and initialise a secondary m...
[truncated message content] |