|
From: <sv...@va...> - 2005-07-07 10:05:31
|
Author: sewardj
Date: 2005-07-07 11:05:05 +0100 (Thu, 07 Jul 2005)
New Revision: 4122
Log:
Support for self modifying code on unfriendly platforms (x86, amd64)
via the use of self-checking translations. (Friendly platforms which
have icache-invalidation instructions we can observe, such as ppc32,
are already handled correctly.) This should finally fix the
longstanding problem of V incorrectly handling calls of statically
nested functions (a gcc extension), and more generally make it a lot
easier to use V to debug dynamic code generation systems.
Since self-checking is a large performance overhead, there is some
control via a command line flag:
--smc-support=3Dnone=20
Don't make any translations self-checking.
--smc-support=3Dstack
Add checking code for translations taken from segments which
have the SF_GROWDOWN flag set -- stacks, basically.
This is the default. It should make gcc nested functions and
GNU Ada work correctly with no intervention from the user.
--smc-support=3Dall
Make all translations self-checking. This is expensive and=20
you want to do this if you're debugging a JIT compiler or
some such.
Modified:
trunk/coregrind/m_main.c
trunk/coregrind/m_options.c
trunk/coregrind/m_translate.c
trunk/coregrind/m_transtab.c
trunk/coregrind/pub_core_options.h
trunk/coregrind/pub_core_transtab.h
Modified: trunk/coregrind/m_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/coregrind/m_main.c 2005-07-07 08:22:51 UTC (rev 4121)
+++ trunk/coregrind/m_main.c 2005-07-07 10:05:05 UTC (rev 4122)
@@ -1268,6 +1268,8 @@
" --pointercheck=3Dno|yes enforce client address space limits [ye=
s]\n"
" --support-elan3=3Dno|yes hacks for Quadrics Elan3 support [no]\n=
"
" --show-emwarns=3Dno|yes show warnings about emulation limits? [=
no]\n"
+" --smc-support=3Dnone|stack|all support for self-modifying code:\n=
"
+" none, for code found in stacks, or all [s=
tack]\n"
"\n"
" user options for Valgrind tools that report errors:\n"
" --log-fd=3D<number> log messages to file descriptor [2=3Dst=
derr]\n"
@@ -1501,6 +1503,13 @@
else VG_BNUM_CLO(arg, "--num-callers", VG_(clo_backtrace_size=
), 1,
VG_DEEPEST_BACKTRACE)
=20
+ else if (VG_CLO_STREQ(arg, "--smc-support=3Dnone"))
+ VG_(clo_smc_support) =3D Vg_SmcNone;
+ else if (VG_CLO_STREQ(arg, "--smc-support=3Dstack"))
+ VG_(clo_smc_support) =3D Vg_SmcStack;
+ else if (VG_CLO_STREQ(arg, "--smc-support=3Dall"))
+ VG_(clo_smc_support) =3D Vg_SmcAll;
+
else VG_BNUM_CLO(arg, "--vex-iropt-verbosity",
VG_(clo_vex_control).iropt_verbosity, 0, 10)
else VG_BNUM_CLO(arg, "--vex-iropt-level",
Modified: trunk/coregrind/m_options.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/coregrind/m_options.c 2005-07-07 08:22:51 UTC (rev 4121)
+++ trunk/coregrind/m_options.c 2005-07-07 10:05:05 UTC (rev 4122)
@@ -76,8 +76,9 @@
Bool VG_(clo_show_emwarns) =3D False;
Int VG_(clo_max_stackframe) =3D 2000000;
Bool VG_(clo_wait_for_gdb) =3D False;
+VgSmc VG_(clo_smc_support) =3D Vg_SmcStack;
=20
+
/*--------------------------------------------------------------------*/
/*--- end m_options.c ---*/
/*--------------------------------------------------------------------*/
-
Modified: trunk/coregrind/m_translate.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/coregrind/m_translate.c 2005-07-07 08:22:51 UTC (rev 4121)
+++ trunk/coregrind/m_translate.c 2005-07-07 10:05:05 UTC (rev 4122)
@@ -400,7 +400,7 @@
{
Addr64 redir, orig_addr0 =3D orig_addr;
Int tmpbuf_used, verbosity;
- Bool notrace_until_done;
+ Bool notrace_until_done, do_self_check;
UInt notrace_until_limit =3D 0;
Segment* seg;
VexGuestExtents vge;
@@ -503,6 +503,17 @@
} else
seg->flags |=3D SF_CODE; /* contains cached code */
=20
+ /* Do we want a self-checking translation? */
+ do_self_check =3D False;
+ switch (VG_(clo_smc_support)) {
+ case Vg_SmcNone: do_self_check =3D False; break;
+ case Vg_SmcAll: do_self_check =3D True; break;
+ case Vg_SmcStack:=20
+ do_self_check =3D seg ? toBool(seg->flags & SF_GROWDOWN) : Fals=
e;
+ break;
+ default: vg_assert2(0, "unknown VG_(clo_smc_support) value");
+ }
+
/* True if a debug trans., or if bit N set in VG_(clo_trace_codegen).=
*/
verbosity =3D 0;
if (debugging_translation) {
@@ -532,6 +543,7 @@
? vg_SP_update_pass
: NULL,
True, /* cleanup after instrumentation */
+ do_self_check,
NULL,
verbosity
);
@@ -555,7 +567,8 @@
VG_(add_to_transtab)( &vge,
orig_addr0,
(Addr)(&tmpbuf[0]),=20
- tmpbuf_used );
+ tmpbuf_used,
+ do_self_check );
}
=20
VGP_POPCC(VgpTranslate);
Modified: trunk/coregrind/m_transtab.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/coregrind/m_transtab.c 2005-07-07 08:22:51 UTC (rev 4121)
+++ trunk/coregrind/m_transtab.c 2005-07-07 10:05:05 UTC (rev 4122)
@@ -225,10 +225,12 @@
ULong n_full_lookups =3D 0;
ULong n_lookup_probes =3D 0;
=20
-/* Number/osize/tsize of translations entered. */
-ULong n_in_count =3D 0;
-ULong n_in_osize =3D 0;
-ULong n_in_tsize =3D 0;
+/* Number/osize/tsize of translations entered; also the number of
+ those for which self-checking was requested. */
+ULong n_in_count =3D 0;
+ULong n_in_osize =3D 0;
+ULong n_in_tsize =3D 0;
+ULong n_in_sc_count =3D 0;
=20
/* Number/osize of translations discarded due to lack of space. */
ULong n_dump_count =3D 0;
@@ -365,7 +367,8 @@
void VG_(add_to_transtab)( VexGuestExtents* vge,
Addr64 entry,
AddrH code,
- UInt code_len )
+ UInt code_len,
+ Bool is_self_checking )
{
Int tcAvailQ, reqdQ, y, i;
ULong *tce, *tce2;
@@ -383,6 +386,8 @@
n_in_count++;
n_in_tsize +=3D code_len;
n_in_osize +=3D vge_osize(vge);
+ if (is_self_checking)
+ n_in_sc_count++;
=20
y =3D youngest_sector;
vg_assert(isValidSector(y));
@@ -663,9 +668,11 @@
n_fast_updates, n_fast_flushes );
=20
VG_(message)(Vg_DebugMsg,
- "translate: new %lld (%lld -> %lld; ratio %lld:10=
)",
+ "translate: new %lld "
+ "(%lld -> %lld; ratio %lld:10) [%lld scs]",
n_in_count, n_in_osize, n_in_tsize,
- safe_idiv(10*n_in_tsize, n_in_osize));
+ safe_idiv(10*n_in_tsize, n_in_osize),
+ n_in_sc_count);
VG_(message)(Vg_DebugMsg,
"translate: dumped %lld (%lld -> ?" "?)",
n_dump_count, n_dump_osize );
Modified: trunk/coregrind/pub_core_options.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/coregrind/pub_core_options.h 2005-07-07 08:22:51 UTC (rev 4121)
+++ trunk/coregrind/pub_core_options.h 2005-07-07 10:05:05 UTC (rev 4122)
@@ -151,6 +151,22 @@
/* Delay startup to allow GDB to be attached? Default: NO */
extern Bool VG_(clo_wait_for_gdb);
=20
+/* To what extent should self-checking translations be made? These
+ are needed to deal with self-modifying code on uncooperative
+ platforms. */
+typedef=20
+ enum {=20
+ Vg_SmcNone, // never generate self-checking translations
+ Vg_SmcStack, // generate s-c-t's for code found in stacks
+ // (segments with SF_GROWDOWN, to be precise)
+ // (this is the default)
+ Vg_SmcAll // make all translations self-checking.
+ }=20
+ VgSmc;
+
+extern VgSmc VG_(clo_smc_support);
+
+
#endif // __PUB_CORE_OPTIONS_H
=20
/*--------------------------------------------------------------------*/
Modified: trunk/coregrind/pub_core_transtab.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/coregrind/pub_core_transtab.h 2005-07-07 08:22:51 UTC (rev 4121=
)
+++ trunk/coregrind/pub_core_transtab.h 2005-07-07 10:05:05 UTC (rev 4122=
)
@@ -49,7 +49,8 @@
void VG_(add_to_transtab)( VexGuestExtents* vge,
Addr64 entry,
AddrH code,
- UInt code_len );
+ UInt code_len,
+ Bool is_self_checking );
=20
extern Bool VG_(search_transtab) ( /*OUT*/AddrH* result,
Addr64 guest_addr,=20
|
|
From: Duncan S. <dun...@ma...> - 2005-07-07 11:06:53
|
> Support for self modifying code on unfriendly platforms (x86, amd64) > via the use of self-checking translations. (Friendly platforms which > have icache-invalidation instructions we can observe, such as ppc32, > are already handled correctly.) This should finally fix the > longstanding problem of V incorrectly handling calls of statically > nested functions (a gcc extension), and more generally make it a lot > easier to use V to debug dynamic code generation systems. I am comparing results with --smc-support=stack vs --smc-support=none. So far, it works wonderfully! Initial tests on programs that explode and die with --smc-support=none run to completion without problems with --smc-support=stack (the default). I will now start running systematic tests on a wide range of code. I owe you a beer. In fact I owe you many beers! Many thanks! Duncan. |
|
From: Julian S. <js...@ac...> - 2005-07-07 11:28:38
|
> --smc-support=stack (the default). I will now start running systematic > tests on a wide range of code. Good. Please keep us informed of the results. If you have an amd64 platform to test on, that also would be helpful. > I owe you a beer. In fact I owe you many beers! These are difficult to send by email :-) What would be appreciated is a regression test in C, one that fails with --smc-support=none but succeeds with --smc-support=stack. Any chance? J |
|
From: Nicholas N. <nj...@cs...> - 2005-07-07 13:34:22
|
On Thu, 7 Jul 2005, Julian Seward wrote: >> I owe you a beer. In fact I owe you many beers! Nice work, Julian. I've closed bug #69511, which was our oldest open bug, from December 2003. > These are difficult to send by email :-) What would be appreciated > is a regression test in C, one that fails with --smc-support=none > but succeeds with --smc-support=stack. Any chance? And one that fails with --smc-support=stack but succeeds with --smc-support=all would be useful too... N |
|
From: Julian S. <js...@ac...> - 2005-07-07 13:41:52
|
> I've closed bug #69511, which was our oldest open bug, > from December 2003. Cool -- #69511 contains a test case. I'll add it to the test suite. > > These are difficult to send by email :-) What would be appreciated > > is a regression test in C, one that fails with --smc-support=none > > but succeeds with --smc-support=stack. Any chance? > > And one that fails with --smc-support=stack but succeeds with > --smc-support=all would be useful too... I was thinking that --smc-support is an ugly name; perhaps --smc-check=none|stack|all is nicer? Any better suggestions? J |
|
From: Nicholas N. <nj...@cs...> - 2005-07-07 14:04:06
|
On Thu, 7 Jul 2005, Julian Seward wrote: > I was thinking that --smc-support is an ugly name; perhaps > --smc-check=none|stack|all is nicer? Any better suggestions? --smc-check sounds fine to me. N |
|
From: Greg P. <gp...@us...> - 2005-07-07 18:46:30
|
sv...@va... writes: > --smc-support-stack > > Add checking code for translations taken from segments which > have the SF_GROWDOWN flag set -- stacks, basically. > This is the default. It should make gcc nested functions and > GNU Ada work correctly with no intervention from the user. Valgrind should mark stacks explicitly. Mac OS X's stacks are always fixed-size, so none of them would be marked SF_GROWDOWN. -- Greg Parker gp...@us... |
|
From: Robert W. <rj...@du...> - 2005-07-07 18:52:49
|
On Thu, 2005-07-07 at 14:46 -0400, Greg Parker wrote: > sv...@va... writes: > > --smc-support-stack > >=20 > > Add checking code for translations taken from segments which > > have the SF_GROWDOWN flag set -- stacks, basically. > > This is the default. It should make gcc nested functions and > > GNU Ada work correctly with no intervention from the user. >=20 > Valgrind should mark stacks explicitly. Mac OS X's stacks are always=20 > fixed-size, so none of them would be marked SF_GROWDOWN. There's currently a mechanism in place to mark stacks as such, for the user-level thread problem. Probably that could be co-opted for this purpose. --=20 Robert Walsh Amalgamated Durables, Inc. - "We don't make the things you buy." Email: rj...@du... |
|
From: Nicholas N. <nj...@cs...> - 2005-07-07 19:14:17
|
On Thu, 7 Jul 2005, Greg Parker wrote: > Valgrind should mark stacks explicitly. Mac OS X's stacks are always > fixed-size, so none of them would be marked SF_GROWDOWN. I see your point but this is a non-issue for PPC, right? Because it explicitly invalidates the I-cache. N |
|
From: Greg P. <gp...@us...> - 2005-07-07 20:51:34
|
Nicholas Nethercote writes: > On Thu, 7 Jul 2005, Greg Parker wrote: > > Valgrind should mark stacks explicitly. Mac OS X's stacks are always > > fixed-size, so none of them would be marked SF_GROWDOWN. > > I see your point but this is a non-issue for PPC, right? Because it > explicitly invalidates the I-cache. Yes, but Mac OS X on Intel is coming soon. -- Greg Parker gp...@us... |
|
From: Nicholas N. <nj...@cs...> - 2005-07-07 21:13:04
|
On Thu, 7 Jul 2005, Greg Parker wrote: >> I see your point but this is a non-issue for PPC, right? Because it >> explicitly invalidates the I-cache. > > Yes, but Mac OS X on Intel is coming soon. Oh yeah... duh. I should've thought of that. N |
|
From: Duncan S. <bal...@fr...> - 2005-07-18 10:00:29
|
Hi Julian,
> What would be useful is if you could wait a couple of days
> until all the residual tree-shaking has died down, and rerun
> your ada tests to check nothing broke in the interim. Perhaps
> some time early next week. I _think_ I now have it working
> correctly on both x86 and amd64.
I ran the ACATS tests under valgrind. This is about 2400 tests
comprising 150,000 lines of Ada code (they come with the gcc
distribution; see gcc/testsuite/ada/acats). When not run under
valgrind, all tests pass. When run under valgrind (memcheck with
default options) most tests pass, but about 20 or so fail. For
some tests this is clearly a valgrind problem ("the impossible
happened"); for several multitasking tests it could well be that
they failed because the different timing when run under valgrind
exposed a race condition; there was a whole bunch of floating
point failures that I suspect are due to a valgrind problem, but
need to be further analysed; and a number of tests simply hung
apparently forever when run under valgrind. Since the results
are so varied, I plan to group the failures, and send you one
email per group.
If you want to compile tests yourself, you'll need to get an
Ada compiler. I recommend gcc-4. Several linux distributions
ship an Ada enabled gcc, but usually you have to install an
optional package, typically called "gnat". I can also send you
binaries, not to mention easy-to-build source code.
All the best,
Duncan.
|
|
From: Nicholas N. <nj...@cs...> - 2005-07-18 16:03:29
|
On Mon, 18 Jul 2005, Duncan Sands wrote: > I ran the ACATS tests under valgrind. This is about 2400 tests > comprising 150,000 lines of Ada code How useful is Valgrind with Ada programs? Are the bugs detected by Memcheck (use of undefined values, accessing unaddressable memory, bad frees, memory leaks) possible in Ada? N |
|
From: Duncan S. <bal...@fr...> - 2005-07-18 16:56:07
|
> > I ran the ACATS tests under valgrind. This is about 2400 tests > > comprising 150,000 lines of Ada code > > How useful is Valgrind with Ada programs? Are the bugs detected by > Memcheck (use of undefined values, accessing unaddressable memory, bad > frees, memory leaks) possible in Ada? Very useful, in my experience. Use of uninitialised values is certainly possible, and while they often get caught by the automatic range checking, they don't always get caught. This is the main thing valgrind catches in Ada programs in my experience [1]. Pointer arithmetic isn't used (or needed) much in Ada (for example it has a first class array structures, with automatic bounds checking, meaning that the array/pointer confusion in C and the associated problems simply aren't present), so the usual reason for ending up with a dud address is pointers pointing to freed memory, which certainly can and does happen (valgrind's saved my bacon a few times with this one). Finally, valgrind helps catch memory leaks. In my experience, heap allocation is needed a lot less in Ada than in, say, C or C++, but any decent sized program will have some heap allocation for use in linked lists etc, which means that memory problems and leaks are possible. By the way, the problems that valgrind finds in the ACATs tests are not (so far) problems with the tests themselves, but problems with the compiler. The tests push the front and back ends hard - and sometimes the compiler produces bad code which valgrind spots. All the best, Duncan. [1] The compiler can be told to automatically initialise all variables to extreme values that should be promptly spotted; nonetheless I've found valgrind to be more effective in finding uninitialised values. |