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
(17) |
2
(15) |
3
(36) |
4
(24) |
5
(36) |
|
6
(18) |
7
(16) |
8
(18) |
9
(19) |
10
(18) |
11
(37) |
12
(18) |
|
13
(13) |
14
(21) |
15
(27) |
16
(10) |
17
(16) |
18
(25) |
19
(21) |
|
20
(11) |
21
(14) |
22
(6) |
23
(15) |
24
(27) |
25
(3) |
26
(9) |
|
27
(16) |
28
(24) |
29
(21) |
30
(43) |
31
(42) |
|
|
|
From: Tom H. <to...@co...> - 2005-03-29 02:28:40
|
Nightly build on dunsmere ( Fedora Core 3 ) started at 2005-03-29 03:20:03 BST Checking out source tree ... done Configuring ... done Building ... done Running regression tests ... done Last 20 lines of log.verbose follow insn_cmov: valgrind ./insn_cmov insn_fpu: valgrind ./insn_fpu insn_mmx: valgrind ./insn_mmx insn_mmxext: valgrind ./insn_mmxext insn_sse: valgrind ./insn_sse insn_sse2: (skipping, prereq failed: ../../../tests/cputest x86-sse2) int: valgrind ./int sh: line 1: 531 Segmentation fault VALGRINDLIB=/tmp/valgrind.7900/valgrind/.in_place /tmp/valgrind.7900/valgrind/./coregrind/valgrind --command-line-only=yes --memcheck:leak-check=no --addrcheck:leak-check=no --tool=none ./int >int.stdout.out 2>int.stderr.out pushpopseg: valgrind ./pushpopseg rcl_assert: valgrind ./rcl_assert seg_override: valgrind ./seg_override -- Finished tests in none/tests/x86 ------------------------------------ yield: valgrind ./yield -- Finished tests in none/tests ---------------------------------------- == 207 tests, 2 stderr failures, 0 stdout failures ================= memcheck/tests/scalar (stderr) memcheck/tests/scalar_supp (stderr) make: *** [regtest] Error 1 |
|
From: Tom H. <th...@cy...> - 2005-03-29 02:22:24
|
Nightly build on audi ( Red Hat 9 ) started at 2005-03-29 03:15:02 BST Checking out source tree ... done Configuring ... done Building ... done Running regression tests ... done Last 20 lines of log.verbose follow fpu_lazy_eflags: valgrind ./fpu_lazy_eflags insn_basic: valgrind ./insn_basic insn_cmov: valgrind ./insn_cmov insn_fpu: valgrind ./insn_fpu insn_mmx: valgrind ./insn_mmx insn_mmxext: valgrind ./insn_mmxext insn_sse: valgrind ./insn_sse insn_sse2: (skipping, prereq failed: ../../../tests/cputest x86-sse2) int: valgrind ./int pushpopseg: valgrind ./pushpopseg rcl_assert: valgrind ./rcl_assert seg_override: valgrind ./seg_override -- Finished tests in none/tests/x86 ------------------------------------ yield: valgrind ./yield -- Finished tests in none/tests ---------------------------------------- == 206 tests, 1 stderr failure, 0 stdout failures ================= memcheck/tests/scalar (stderr) make: *** [regtest] Error 1 |
|
From: Tom H. <th...@cy...> - 2005-03-29 02:16:30
|
Nightly build on ginetta ( Red Hat 8.0 ) started at 2005-03-29 03:10:01 BST Checking out source tree ... done Configuring ... done Building ... done Running regression tests ... done Last 20 lines of log.verbose follow insn_cmov: valgrind ./insn_cmov insn_fpu: valgrind ./insn_fpu insn_mmx: valgrind ./insn_mmx insn_mmxext: valgrind ./insn_mmxext insn_sse: valgrind ./insn_sse insn_sse2: (skipping, prereq failed: ../../../tests/cputest x86-sse2) int: valgrind ./int pushpopseg: valgrind ./pushpopseg rcl_assert: valgrind ./rcl_assert seg_override: valgrind ./seg_override -- Finished tests in none/tests/x86 ------------------------------------ yield: valgrind ./yield -- Finished tests in none/tests ---------------------------------------- == 205 tests, 3 stderr failures, 0 stdout failures ================= memcheck/tests/pth_once (stderr) memcheck/tests/scalar (stderr) memcheck/tests/threadederrno (stderr) make: *** [regtest] Error 1 |
|
From: Tom H. <th...@cy...> - 2005-03-29 02:15:28
|
Nightly build on standard ( Red Hat 7.2 ) started at 2005-03-29 03:00:01 BST Checking out source tree ... done Configuring ... done Building ... done Running regression tests ... done Last 20 lines of log.verbose follow insn_mmxext: valgrind ./insn_mmxext insn_sse: valgrind ./insn_sse insn_sse2: (skipping, prereq failed: ../../../tests/cputest x86-sse2) int: valgrind ./int pushpopseg: valgrind ./pushpopseg rcl_assert: valgrind ./rcl_assert seg_override: valgrind ./seg_override -- Finished tests in none/tests/x86 ------------------------------------ yield: valgrind ./yield -- Finished tests in none/tests ---------------------------------------- == 205 tests, 6 stderr failures, 0 stdout failures ================= memcheck/tests/leak-tree (stderr) memcheck/tests/pth_once (stderr) memcheck/tests/scalar (stderr) memcheck/tests/threadederrno (stderr) memcheck/tests/vgtest_ume (stderr) addrcheck/tests/leak-tree (stderr) make: *** [regtest] Error 1 |
|
From: Tom H. <th...@cy...> - 2005-03-29 02:11:53
|
Nightly build on alvis ( Red Hat 7.3 ) started at 2005-03-29 03:05:01 BST Checking out source tree ... done Configuring ... done Building ... done Running regression tests ... done Last 20 lines of log.verbose follow == 205 tests, 17 stderr failures, 0 stdout failures ================= memcheck/tests/addressable (stderr) memcheck/tests/describe-block (stderr) memcheck/tests/distinguished-writes (stderr) memcheck/tests/leak-0 (stderr) memcheck/tests/leak-cycle (stderr) memcheck/tests/leak-regroot (stderr) memcheck/tests/leak-tree (stderr) memcheck/tests/match-overrun (stderr) memcheck/tests/pointer-trace (stderr) memcheck/tests/pth_once (stderr) memcheck/tests/scalar (stderr) memcheck/tests/threadederrno (stderr) memcheck/tests/vgtest_ume (stderr) addrcheck/tests/leak-0 (stderr) addrcheck/tests/leak-cycle (stderr) addrcheck/tests/leak-regroot (stderr) addrcheck/tests/leak-tree (stderr) make: *** [regtest] Error 1 |
|
From: Robert W. <rj...@du...> - 2005-03-28 20:36:45
|
On Mon, 2005-03-28 at 21:21 +0100, Tom Hughes wrote: > You need to configure with --disable-pie as PIE builds don't > work at the moment. Ah. Yup - that worked. Thanks! |
|
From: Tom H. <to...@co...> - 2005-03-28 20:21:48
|
In message <111...@he...>
Robert Walsh <rj...@du...> wrote:
> Anyone else seeing this error when attempting to link stage2 on an FC3
> AMD64 box?
>
> gcc -Wmissing-prototypes -Winline -Wall -Wshadow -O -g -fomit-frame-
> pointer -DELFSZ=64 -fno-omit-frame-pointer -Wno-long-long -o stage2 -
> Wl,--export-dynamic -g -Wl,-version-script ./valgrind.vs -pie stage2-
> execontext.o stage2-stacktrace.o stage2-ume.o stage2-vg_scheduler.o
> stage2-vg_default.o stage2-vg_demangle.o stage2-vg_errcontext.o stage2-
> vg_hashtable.o stage2-vg_instrument.o stage2-vg_main.o stage2-
> vg_malloc2.o stage2-vg_memory.o stage2-vg_messages.o stage2-vg_mylibc.o
> stage2-vg_needs.o stage2-vg_procselfmaps.o stage2-vg_dummy_profile.o
> stage2-vg_signals.o stage2-vg_symtab2.o stage2-vg_threadmodel.o stage2-
> vg_pthreadmodel.o stage2-vg_redir.o stage2-vg_dwarf.o stage2-vg_stabs.o
> stage2-vg_skiplist.o stage2-vg_symtypes.o stage2-vg_syscalls.o stage2-
> vg_toolint.o stage2-vg_translate.o stage2-vg_transtab.o
> demangle/libdemangle.a amd64-linux/libplatform.a amd64/libarch.a
> linux/libos.a /home/rjwalsh/svn/vex/libvex.a -ldl
> /usr/bin/ld: amd64-linux/libplatform.a(syscalls.o): relocation
> R_X86_64_32 against `a local symbol' can not be used when making a
> shared object; recompile with -fPIC
>
> I tried compiling with -fPIC but it bugged out with a similar error in
> libarch.a. Any thoughts?
You need to configure with --disable-pie as PIE builds don't
work at the moment.
tom
--
Tom Hughes (to...@co...)
http://www.compton.nu/
|
|
From: Robert W. <rj...@du...> - 2005-03-28 20:18:10
|
Anyone else seeing this error when attempting to link stage2 on an FC3 AMD64 box? gcc -Wmissing-prototypes -Winline -Wall -Wshadow -O -g -fomit-frame- pointer -DELFSZ=64 -fno-omit-frame-pointer -Wno-long-long -o stage2 - Wl,--export-dynamic -g -Wl,-version-script ./valgrind.vs -pie stage2- execontext.o stage2-stacktrace.o stage2-ume.o stage2-vg_scheduler.o stage2-vg_default.o stage2-vg_demangle.o stage2-vg_errcontext.o stage2- vg_hashtable.o stage2-vg_instrument.o stage2-vg_main.o stage2- vg_malloc2.o stage2-vg_memory.o stage2-vg_messages.o stage2-vg_mylibc.o stage2-vg_needs.o stage2-vg_procselfmaps.o stage2-vg_dummy_profile.o stage2-vg_signals.o stage2-vg_symtab2.o stage2-vg_threadmodel.o stage2- vg_pthreadmodel.o stage2-vg_redir.o stage2-vg_dwarf.o stage2-vg_stabs.o stage2-vg_skiplist.o stage2-vg_symtypes.o stage2-vg_syscalls.o stage2- vg_toolint.o stage2-vg_translate.o stage2-vg_transtab.o demangle/libdemangle.a amd64-linux/libplatform.a amd64/libarch.a linux/libos.a /home/rjwalsh/svn/vex/libvex.a -ldl /usr/bin/ld: amd64-linux/libplatform.a(syscalls.o): relocation R_X86_64_32 against `a local symbol' can not be used when making a shared object; recompile with -fPIC I tried compiling with -fPIC but it bugged out with a similar error in libarch.a. Any thoughts? Regards, Robert. |
|
From: Julian S. <js...@ac...> - 2005-03-28 18:41:05
|
Replying to several messages at once, up to and including discussion
of the proposed patch.
Simplifying the tool interface is definitely a Good Thing To Do. However
I'm not convinced by the objections raised thus far to the struct passing
approach, and I like its simplicity. Reasons below.
> > The "register" approach means (if I understand correctly) that
> > the tool's init function is called, resulting in a bunch of calls
> > back to the core to register functions; eventually the tool init
> > fn returns. That sounds more complex (mutable state; more complex
> > control flow) and I'm not sure what the benefit is.
>
> One problem with the dictionary approach is that you are exposing the
> internals of the struct to tools. I avoided this approach with the
> 'needs' and 'details' structs for just this reason.
Confused. Each tool would assemble a struct and pass a pointer
to it to the core as the return value of the tool's initialisation
function. So inevitably the internals of the struct are visible
to the tool anyway since it created the struct.
> Yes, I think that's better because it removes the fragility of having a
> structure as part of the interface.
How does having a struct as part of the interface make it fragile?
I am thinking of a very simple struct which contains only function
pointers; no other data.
If you are really worried about version mismatches in the struct,
make the first field (viz, offset 0) be an int which carries a
version identifier. Then we can safely say
"if (struct->version != ...) barf()"
This at least allows detection of ABI-level mismatches at startup
time, providing the version number is bumped each time the API changes.
> And this isn't any more robust than passing a structure against adding
> new interface functions (it's worse, because adding a new function would
> require every caller to VG_(needs_tool_errors)() be changed, even if
> they don't care about the new function; a static struct will
> automatically initialize otherwise uninitialized members to NULL).
I agree. Especially if the struct has a version field at the start.
------
The registration-based scheme feels cluttered to me, because there are
more names and storage locations (global state) to keep track of. For
example, the tool makes a registration call:
+ VG_(basic_tool_funcs) (TL_(post_clo_init),
+ TL_(instrument),
+ TL_(fini));
Now in the core, if I want to call one of these, first I have to find the
global variables that those pointers got stored in -- probably using
grep. Then I have to be convinced that they've been initialised, and
only then can I make the call. Also I have to figure out precisely
which groups of functions make up the interface, and whether I've
forgotten to consider any.
By comparison, if I have a struct "tdict" from the tool, then there are
no banks of global variables to be found, no questions about initialisation,
and if I want assurance I'm seeing the complete interface, I only have to
read the struct definition -- nothing else. Then I can do:
assert(tdict->instrument); // we're hosed if this fails
bbi = tdict->instrument(bb);
or
if (tdict->some_optional_function)
some_optional_function(args);
------
Re-reading that, my real point is that the struct scheme is easier for
human readers of the code to read and reason about. And as Jeremy says,
it's not really any less robust against API changes relative to the
registration-scheme.
J
|
|
From: Oswald B. <os...@kd...> - 2005-03-28 18:34:17
|
On Mon, Mar 28, 2005 at 09:30:23AM -0800, Jeremy Fitzhardinge wrote: > If you were to have a registration function per tool entrypoint, it > means you can add new entrypoints without breaking the binaries of any > existing tool. That way you can reserve interface version numbers to > mean semantic changes to the interface. > one can also use a real dictionary (name -> address) ... which is sort of exactly what the current dlsym solution does, only a bit more explicit. -- Hi! I'm a .signature virus! Copy me into your ~/.signature, please! -- Chaos, panic, and disorder - my work here is done. |
|
From: Jeremy F. <je...@go...> - 2005-03-28 17:42:42
|
Nicholas Nethercote wrote:
> The reason I did it this way is that with the ones I grouped together,
> the tool has to provide none of them or all of them. All tools have
> to provide pre_clo_init(), instrument() and fini(), so they're grouped
> together. If the tool wants to report errors (ie. needs_tool_errors),
> it has to provide all eight of those functions: eq_Error(),
> pp_Error(), etc.
> If it doesn't provide all of them the core will bomb out at some point
> with a "missing tool function" error.
>
> Does that make a difference to how you feel about it?
Well, a function with 15 (or even 8) arguments is always going to be
hard to read, and hard to write or modify (it's impossible to remember
what order they should go in, and very easy to stuff it up by adding or
deleting an argument - in either case you need to carefully check the
call against the function prototype).
Are you saying that the needs functions are, by definition, all-or-none,
so that if you want to add a new function with is related but not
essential (say, get_extra_address_info) would actually be a different
need? Or that a tool would be always required to implement a function
because of the all-or-none policy, even if its a nul implementation?
I'm all for grouping the interface callback registrations into
functionally related pieces, but it seems like a stretch to further
assert that functional grouping == all-or-none.
J
|
|
From: Jeremy F. <je...@go...> - 2005-03-28 17:30:28
|
Julian Seward wrote:
>How does having a struct as part of the interface make it fragile?
>I am thinking of a very simple struct which contains only function
>pointers; no other data.
>
>If you are really worried about version mismatches in the struct,
>make the first field (viz, offset 0) be an int which carries a
>version identifier. Then we can safely say
>
> "if (struct->version != ...) barf()"
>
>This at least allows detection of ABI-level mismatches at startup
>time, providing the version number is bumped each time the API changes.
>
>
The trouble with this is that you break the ABI with every function you
add to the interface, even if it doesn't affect the semantics of any
other function, and most tools don't care about it. That's what is
fragile - you break the interface very easily. If you were to have a
registration function per tool entrypoint, it means you can add new
entrypoints without breaking the binaries of any existing tool. That
way you can reserve interface version numbers to mean semantic changes
to the interface.
J
|
|
From: Nicholas N. <nj...@cs...> - 2005-03-28 15:33:03
|
On Mon, 28 Mar 2005, Julian Seward wrote: > Ah. I didn't realise that the struct exists on the core side; I thought > it only existed on the core side. Do you mean "only existed on the tool side?" > That would be a nice clarification. I'd prefer to directly call > > (*VG_(tool_interface).tool_fini)(exitcode) > > rather than > > TL_(fini)(Int exitcode) > > even though it's more verbose -- less layers of abstraction is good. Yes. > Part of the reason I didn't even realise there was a tool_interface > struct on the core side was as a result of this hiding. I think that was the point :) Jeremy implemented it in a way that made it look just like the 2.0.0 system, so the core could still call TL_(fini)(), even though the underlying details were quite different. N |
|
From: Nicholas N. <nj...@cs...> - 2005-03-28 15:27:54
|
On Mon, 28 Mar 2005, Jeremy Fitzhardinge wrote: >> Where would the USERREQ_FREE requrest be embedded in the client? Would >> every client have to have such a request in it? > > No client directly calls USERREQ_FREE. Any client which calls pthread_create > ends up calling it via code in vg_inject.so (compiled from vg_intercept.c). Ah, that's the key idea I was missing. Thanks. N |
|
From: Julian S. <js...@ac...> - 2005-03-28 15:24:31
|
> > The registration-based scheme feels cluttered to me, because there are
> > more names and storage locations (global state) to keep track of. For
> > example, the tool makes a registration call:
> >
> > + VG_(basic_tool_funcs) (TL_(post_clo_init),
> > + TL_(instrument),
> > + TL_(fini));
> >
> > Now in the core, if I want to call one of these, first I have to find the
> > global variables that those pointers got stored in -- probably using
> > grep.
>
> Global variables? There are no global variables, the function pointers
> will all get stored in the single VgToolInterface struct.
Ah. I didn't realise that the struct exists on the core side; I thought
it only existed on the core side. (== I didn't understand that). That
zaps some of my objections.
> I think the patch is a lot closer to what you described and want than you
> realise. Perhaps it's unclear because it's only a first step and there's
> more cruft to remove (eg. the double-meaning of TL_). But it has a single
> struct, which I think is the main thing you want.
Yes, you could be right.
> Another confusing aspect currently is that vg_toolint.c defines lots of
> TL_ functions like this:
>
> void TL_(fini)(Int exitcode)
> {
> return (*VG_(tool_interface).tool_fini)(exitcode);
> }
>
> where TL_ here means "vgToolInternal_" and so is different to the TL_
> within the tools. So this is just a short-cut for your "tdict->fini(x)"
> example which the core can call. We could get rid of these, and just
> always use "tdict->fini(x)" to make it explicit. And then there are the
> VG_(defined_*) and VG_(missing_*) functions which further clutter things,
> and could possibly be removed.
That would be a nice clarification. I'd prefer to directly call
(*VG_(tool_interface).tool_fini)(exitcode)
rather than
TL_(fini)(Int exitcode)
even though it's more verbose -- less layers of abstraction is good.
Part of the reason I didn't even realise there was a tool_interface
struct on the core side was as a result of this hiding.
J
|
|
From: Nicholas N. <nj...@cs...> - 2005-03-28 14:35:38
|
On Mon, 28 Mar 2005, Julian Seward wrote:
>> One problem with the dictionary approach is that you are exposing the
>> internals of the struct to tools. I avoided this approach with the
>> 'needs' and 'details' structs for just this reason.
>
> Confused. Each tool would assemble a struct and pass a pointer
> to it to the core as the return value of the tool's initialisation
> function. So inevitably the internals of the struct are visible
> to the tool anyway since it created the struct.
In the current approach the struct is defined and allocated within the
core. It's called VG_(tool_interface), it has type "VgToolInterface.
The tool doesn't know what this struct looks like.
> How does having a struct as part of the interface make it fragile?
> I am thinking of a very simple struct which contains only function
> pointers; no other data.
I think the concern is if (when) fields get added or removed. Doing it
via functions can help, eg. if a field is removed you can make the
function that sets that field just do nothing. Just a general
abstract-types-are-nice thing. Although in this case it doesn't help that
much, as I agree below.
> If you are really worried about version mismatches in the struct,
> make the first field (viz, offset 0) be an int which carries a
> version identifier. Then we can safely say
>
> "if (struct->version != ...) barf()"
>
> This at least allows detection of ABI-level mismatches at startup
> time, providing the version number is bumped each time the API changes.
I don't like version numbers much, they're easy to forget to change.
Although I guess if you tied it into the existing MAJOR_VERSION_NUMBER (or
whatever it's called) that would help.
> ------
>
> The registration-based scheme feels cluttered to me, because there are
> more names and storage locations (global state) to keep track of. For
> example, the tool makes a registration call:
>
> + VG_(basic_tool_funcs) (TL_(post_clo_init),
> + TL_(instrument),
> + TL_(fini));
>
> Now in the core, if I want to call one of these, first I have to find the
> global variables that those pointers got stored in -- probably using
> grep.
Global variables? There are no global variables, the function pointers
will all get stored in the single VgToolInterface struct.
> Then I have to be convinced that they've been initialised, and only then
> can I make the call.
I don't see how this would be different if the tool does the struct
initialisation? (More below.)
> Also I have to figure out precisely which groups of functions make up
> the interface, and whether I've forgotten to consider any.
>
> By comparison, if I have a struct "tdict" from the tool, then there are
> no banks of global variables to be found,
As I've done it, we still have the single struct, it's just on the core
side. There are no banks of global variables. Perhaps it's confusing
because the names above TL_(post_clo_init)(), TL_(instrument)(), etc,
still have the TL_ prefix (which here means "vgTool_"). They don't need
to, I just haven't changed that in the patch. They could be eg.
mc_post_clo_init(), mc_instrument(), etc.
> no questions about initialisation,
> and if I want assurance I'm seeing the complete interface, I only have to
> read the struct definition -- nothing else.
That's true of how I've done it -- just look at VgToolInterface.
(Actually, it was already like that, I don't mean to take credit for it.)
> Then I can do:
>
> assert(tdict->instrument); // we're hosed if this fails
> bbi = tdict->instrument(bb);
>
> or
>
> if (tdict->some_optional_function)
> some_optional_function(args);
That's how it is with my patch. VG_(tool_interface) is the name of the
"tdict" struct. A shorter name might be better.
Another confusing aspect currently is that vg_toolint.c defines lots of
TL_ functions like this:
void TL_(fini)(Int exitcode)
{
return (*VG_(tool_interface).tool_fini)(exitcode);
}
where TL_ here means "vgToolInternal_" and so is different to the TL_
within the tools. So this is just a short-cut for your "tdict->fini(x)"
example which the core can call. We could get rid of these, and just
always use "tdict->fini(x)" to make it explicit. And then there are the
VG_(defined_*) and VG_(missing_*) functions which further clutter things,
and could possibly be removed.
> ------
>
> Re-reading that, my real point is that the struct scheme is easier for
> human readers of the code to read and reason about. And as Jeremy says,
> it's not really any less robust against API changes relative to the
> registration-scheme.
I think the patch is a lot closer to what you described and want than you
realise. Perhaps it's unclear because it's only a first step and there's
more cruft to remove (eg. the double-meaning of TL_). But it has a single
struct, which I think is the main thing you want.
As for the robustness against API changes, I agree that the way I've done
it isn't any more robust against API changes. But the advantage it does
have over a naked struct is robustness against one possible tool screwup:
the cases where the tool has to provide multiple functions together, as I
explained in my other response to Jeremy's comments.
--
Thanks for the feedback, really! I'm defending my patch, because there
are constraints involved that aren't obvious. But I won't refuse to
change it if the consensus is still against it after those constraints
have been made clearer. I'll be away until Thursday night, and I'm not
sure how much email contact I'll have, so if I don't reply it's not
because I'm sulking :)
N
|
|
From: Nicholas N. <nj...@cs...> - 2005-03-28 14:09:01
|
On Mon, 28 Mar 2005, Jeremy Fitzhardinge wrote:
> At present, there's a somewhat artificial dependency between loading the
> tool.so and initializing the allocator. If the allocator could stand to have
> the redzone size set after the rest of the allocator is initialized (but
> before the first client arena allocation), we could initialize and use the
> allocator much earlier. I don't know if this change would help or not, but
> it looks like it might.
Yes, I realised after sending the patch that there's a better way.
vg_malloc2.c could export a tool-visible function
VG_(set_malloc_redzone_szB)(). There would be a restriction that tools
can only call it before calling VG_(malloc)() for the first time. It
would have a little check in it to enforce this. That avoids the global
variable VG_(malloc_redzone_szB)() and keeps it all neatly within
vg_malloc2.c.
>> + VG_(basic_tool_funcs) (TL_(post_clo_init),
>> + TL_(instrument),
>> + TL_(fini));
>
> I would either go with a registry function per function, or pass a struct.
> Having registry functions which takes lots of args doesn't seem like much of
> an improvement. Though a bit more verbose, something like:
>
> VG_(register_clo_init)(my_clo_init);
> VG_(register_instrument)(my_instrument);
> VG_(register_fini)(my_fini);
>
> seems more maintainable and robust in the face of interface change to me.
>
>> +
>> VG_(needs_core_errors) ();
>> - VG_(needs_tool_errors) ();
>> + VG_(needs_tool_errors) (TL_(eq_Error),
>> + TL_(pp_Error),
>> + TL_(update_extra),
>> + TL_(recognised_suppression),
>> + TL_(read_extra_suppression_info),
>> + TL_(error_matches_suppression),
>> + TL_(get_error_name),
>> + TL_(print_extra_suppression_info));
>
>
> Particularly compared to this kind of thing. What if you don't want all
> these callbacks? You end up with a call like this (totally made up example):
>
> VG_(needs_tool_errors)(NULL, NULL, NULL, NULL,
> TL_(read_extra_suppression_info), NULL,
> TL_(get_error_name), NULL);
>
> which doesn't seem very readable or maintainable.
The reason I did it this way is that with the ones I grouped together, the
tool has to provide none of them or all of them. All tools have to
provide pre_clo_init(), instrument() and fini(), so they're grouped
together. If the tool wants to report errors (ie. needs_tool_errors), it
has to provide all eight of those functions: eq_Error(), pp_Error(), etc.
If it doesn't provide all of them the core will bomb out at some point
with a "missing tool function" error.
Does that make a difference to how you feel about it?
> At least with a struct you can name the elements you're initializing:
>
> static const struct tool_error_funcs my_tool_errors = {
> .read_extra_suppression = my_read_extra_suppression,
> .get_error_name = my_get_error_name,
> };
> VG_(needs_tool_errors)(&my_tool_errors);
Having the name on the LHS is nice.
> And this isn't any more robust than passing a structure against adding new
> interface functions (it's worse, because adding a new function would require
> every caller to VG_(needs_tool_errors)() be changed, even if they don't care
> about the new function; a static struct will automatically initialize
> otherwise uninitialized members to NULL).
If new functions are added to any of the groups, all tools that use those
groups would have to be changed anyway, due to the all-or-nothing
property.
N
|
|
From: Jeremy F. <je...@go...> - 2005-03-28 12:03:57
|
Jeremy Fitzhardinge wrote:
> VG_(needs_tool_errors)(NULL, NULL, NULL, NULL,
> TL_(read_extra_suppression_info), NULL,
> TL_(get_error_name), NULL);
>
> which doesn't seem very readable or maintainable.
(Particularly when one's mail program mangles the formatting. But you
get the point.)
J
|
|
From: Jeremy F. <je...@go...> - 2005-03-28 08:59:43
|
Nicholas Nethercote wrote:
> 2. Tools that replace malloc now specify the size of the heap block
> redzones
> through the VG_DETERMINE_INTERFACE_VERSION macro, rather than with a
> variable VG_(vg_malloc_redzone_szB).
At present, there's a somewhat artificial dependency between loading the
tool.so and initializing the allocator. If the allocator could stand to
have the redzone size set after the rest of the allocator is initialized
(but before the first client arena allocation), we could initialize and
use the allocator much earlier. I don't know if this change would help
or not, but it looks like it might.
> + VG_(basic_tool_funcs) (TL_(post_clo_init),
> + TL_(instrument),
> + TL_(fini));
I would either go with a registry function per function, or pass a
struct. Having registry functions which takes lots of args doesn't seem
like much of an improvement. Though a bit more verbose, something like:
VG_(register_clo_init)(my_clo_init);
VG_(register_instrument)(my_instrument);
VG_(register_fini)(my_fini);
seems more maintainable and robust in the face of interface change to me.
> +
> VG_(needs_core_errors) ();
> - VG_(needs_tool_errors) ();
> + VG_(needs_tool_errors) (TL_(eq_Error),
> + TL_(pp_Error),
> + TL_(update_extra),
> + TL_(recognised_suppression),
> + TL_(read_extra_suppression_info),
> + TL_(error_matches_suppression),
> + TL_(get_error_name),
> + TL_(print_extra_suppression_info));
Particularly compared to this kind of thing. What if you don't want all
these callbacks? You end up with a call like this (totally made up
example):
VG_(needs_tool_errors)(NULL, NULL, NULL, NULL,
TL_(read_extra_suppression_info),
NULL, TL_(get_error_name), NULL);
which doesn't seem very readable or maintainable. At least with a
struct you can name the elements you're initializing:
static const struct tool_error_funcs my_tool_errors = {
.read_extra_suppression = my_read_extra_suppression,
.get_error_name = my_get_error_name,
};
VG_(needs_tool_errors)(&my_tool_errors);
And this isn't any more robust than passing a structure against adding
new interface functions (it's worse, because adding a new function would
require every caller to VG_(needs_tool_errors)() be changed, even if
they don't care about the new function; a static struct will
automatically initialize otherwise uninitialized members to NULL).
J
|
|
From: <js...@ac...> - 2005-03-28 08:57:49
|
Nightly build on phoenix ( SuSE 9.1 ) started at 2005-03-28 03:50:00 BST Checking out source tree ... done Configuring ... done Building ... done Running regression tests ... done Last 20 lines of log.verbose follow insn_mmx: valgrind ./insn_mmx insn_mmxext: (skipping, prereq failed: ../../../tests/cputest x86-mmxext) insn_sse: valgrind ./insn_sse insn_sse2: (skipping, prereq failed: ../../../tests/cputest x86-sse2) int: valgrind ./int pushpopseg: valgrind ./pushpopseg rcl_assert: valgrind ./rcl_assert seg_override: valgrind ./seg_override -- Finished tests in none/tests/x86 ------------------------------------ yield: valgrind ./yield -- Finished tests in none/tests ---------------------------------------- == 201 tests, 5 stderr failures, 0 stdout failures ================= memcheck/tests/pth_once (stderr) memcheck/tests/scalar (stderr) memcheck/tests/threadederrno (stderr) memcheck/tests/writev (stderr) corecheck/tests/fdleak_fcntl (stderr) make: *** [regtest] Error 1 |
|
From: Jeremy F. <je...@go...> - 2005-03-28 08:41:19
|
Nicholas Nethercote wrote:
> Hmm, I didn't really follow that... I'm not clear on what
> functions/bits of memory are from the client, what are from the
> pthreads implementation, and what are in Valgrind/pthreadmodel.
before_pthread_create() allocates an instance of
vg_pthread_newthread_data; this function is run as part of the core. The
pointer to this instance ends up being passed to the real
pthread_create, and is used then freed in
vg_intercept.c:VG_WRAPPER(pthread_startfunc_wrapper)(), which is run as
part of the client code.
> Where would the USERREQ_FREE requrest be embedded in the client?
> Would every client have to have such a request in it?
No client directly calls USERREQ_FREE. Any client which calls
pthread_create ends up calling it via code in vg_inject.so (compiled
from vg_intercept.c).
J
|
|
From: Nicholas N. <nj...@cs...> - 2005-03-28 03:26:03
|
On Sun, 27 Mar 2005, Jeremy Fitzhardinge wrote:
>> VG_(init_post_clo_init) ( & ac_post_clo_init );
>> VG_(init_instrument) ( & ac_instrument );
>> VG_(init_handle_client_request)( & ac_handle_client_request );
>>
>> (That's slightly different your suggestion of passing a struct of function
>> pointers, but very similar.)
>
> Yes, I think that's better because it removes the fragility of having a
> structure as part of the interface.
The below patch against the current SVN HEAD (with changelog) is a first
step towards this. Comments are welcome -- Julian, how do you think it
looks doing it with functions rather than naked structs?
N
-----------------------------------------------------------------------------
This change reduces the number of calls to dlsym() when loading tools from a
lot to one. This required two basic changes:
1. Tools are responsible for telling the tool about any functions they
provide that the tool may call. This includes basic functions like
TL_(instrument)(), functions that assist core services such as
TL_(pp_Error)(), and malloc-replacement-related functions like
TL_(malloc)().
2. Tools that replace malloc now specify the size of the heap block redzones
through the VG_DETERMINE_INTERFACE_VERSION macro, rather than with a
variable VG_(vg_malloc_redzone_szB).
One consequence of these changes is that VG_(tool_init_dlsym)() no longer
needs to be generated by gen_toolint.pl.
There are a number of further improvements that could follow on from this one.
- Avoid the confusingly different definitions of the TL_() macro in the
core vs. for tools. Indeed, the functions provided by the tools now don't
need to use the TL_() macro at all, as they can have arbitrary names.
- Remove a lot of the auto-generated stuff in vg_toolint.c and vg_toolint.h
(indeed, it might be possible to not auto-generate these at all, which
would be nice).
- The handling of VgToolInterface is currently split across vg_needs.c and
vg_toolint.c, which isn't nice.
-----------------------------------------------------------------------------
Index: corecheck/cc_main.c
===================================================================
--- corecheck/cc_main.c (revision 3466)
+++ corecheck/cc_main.c (working copy)
@@ -40,13 +40,15 @@
"Copyright (C) 2002-2005, and GNU GPL'd, by Nicholas Nethercote.");
VG_(details_bug_reports_to) (VG_BUGS_TO);
+ VG_(basic_tool_funcs) (TL_(post_clo_init),
+ TL_(instrument),
+ TL_(fini));
+
VG_(needs_core_errors)();
/* No core events to track */
}
-VG_DETERMINE_INTERFACE_VERSION(TL_(pre_clo_init), 0)
-
void TL_(post_clo_init)(void)
{
}
@@ -61,6 +63,8 @@
{
}
+VG_DETERMINE_INTERFACE_VERSION(TL_(pre_clo_init), 0, 0)
+
/*--------------------------------------------------------------------*/
/*--- end cc_main.c ---*/
/*--------------------------------------------------------------------*/
Index: memcheck/mc_main.c
===================================================================
--- memcheck/mc_main.c (revision 3466)
+++ memcheck/mc_main.c (working copy)
@@ -1873,14 +1873,38 @@
VG_(details_bug_reports_to) (VG_BUGS_TO);
VG_(details_avg_translation_sizeB) ( 370 );
+ VG_(basic_tool_funcs) (TL_(post_clo_init),
+ TL_(instrument),
+ TL_(fini));
+
VG_(needs_core_errors) ();
- VG_(needs_tool_errors) ();
+ VG_(needs_tool_errors) (TL_(eq_Error),
+ TL_(pp_Error),
+ TL_(update_extra),
+ TL_(recognised_suppression),
+ TL_(read_extra_suppression_info),
+ TL_(error_matches_suppression),
+ TL_(get_error_name),
+ TL_(print_extra_suppression_info));
VG_(needs_libc_freeres) ();
- VG_(needs_command_line_options)();
- VG_(needs_client_requests) ();
- VG_(needs_sanity_checks) ();
+ VG_(needs_command_line_options)(TL_(process_cmd_line_option),
+ TL_(print_usage),
+ TL_(print_debug_usage));
+ VG_(needs_client_requests) (TL_(handle_client_request));
+ VG_(needs_sanity_checks) (TL_(cheap_sanity_check),
+ TL_(expensive_sanity_check));
VG_(needs_shadow_memory) ();
+ VG_(malloc_funcs) (TL_(malloc),
+ TL_(__builtin_new),
+ TL_(__builtin_vec_new),
+ TL_(memalign),
+ TL_(calloc),
+ TL_(free),
+ TL_(__builtin_delete),
+ TL_(__builtin_vec_delete),
+ TL_(realloc) );
+
MAC_( new_mem_heap) = & mc_new_mem_heap;
MAC_( ban_mem_heap) = & mc_make_noaccess;
MAC_(copy_mem_heap) = & mc_copy_address_range_state;
@@ -1951,7 +1975,7 @@
}
}
-VG_DETERMINE_INTERFACE_VERSION(TL_(pre_clo_init), 9./8)
+VG_DETERMINE_INTERFACE_VERSION(TL_(pre_clo_init), 9./8, MALLOC_REDZONE_SZB)
/*--------------------------------------------------------------------*/
/*--- end mc_main.c ---*/
Index: memcheck/mac_malloc_wrappers.c
===================================================================
--- memcheck/mac_malloc_wrappers.c (revision 3466)
+++ memcheck/mac_malloc_wrappers.c (working copy)
@@ -41,9 +41,6 @@
static SizeT cmalloc_n_frees = 0;
static SizeT cmalloc_bs_mallocd = 0;
-/* We want a 16B redzone on heap blocks for Addrcheck and Memcheck */
-SizeT VG_(vg_malloc_redzone_szB) = 16;
-
/* Function pointers for the two tools to track interesting events. */
void (*MAC_(new_mem_heap)) ( Addr a, SizeT len, Bool is_inited ) = NULL;
void (*MAC_(ban_mem_heap)) ( Addr a, SizeT len ) = NULL;
@@ -221,7 +218,7 @@
return NULL;
} else {
return MAC_(new_block) ( tid, 0, n, VG_(clo_alignment),
- VG_(vg_malloc_redzone_szB), /*is_zeroed*/False, MAC_AllocMalloc,
+ MALLOC_REDZONE_SZB, /*is_zeroed*/False, MAC_AllocMalloc,
MAC_(malloc_list));
}
}
@@ -232,7 +229,7 @@
return NULL;
} else {
return MAC_(new_block) ( tid, 0, n, VG_(clo_alignment),
- VG_(vg_malloc_redzone_szB), /*is_zeroed*/False, MAC_AllocNew,
+ MALLOC_REDZONE_SZB, /*is_zeroed*/False, MAC_AllocNew,
MAC_(malloc_list));
}
}
@@ -243,7 +240,7 @@
return NULL;
} else {
return MAC_(new_block) ( tid, 0, n, VG_(clo_alignment),
- VG_(vg_malloc_redzone_szB), /*is_zeroed*/False, MAC_AllocNewVec,
+ MALLOC_REDZONE_SZB, /*is_zeroed*/False, MAC_AllocNewVec,
MAC_(malloc_list));
}
}
@@ -254,7 +251,7 @@
return NULL;
} else {
return MAC_(new_block) ( tid, 0, n, align,
- VG_(vg_malloc_redzone_szB), /*is_zeroed*/False, MAC_AllocMalloc,
+ MALLOC_REDZONE_SZB, /*is_zeroed*/False, MAC_AllocMalloc,
MAC_(malloc_list));
}
}
@@ -265,7 +262,7 @@
return NULL;
} else {
return MAC_(new_block) ( tid, 0, nmemb*size1, VG_(clo_alignment),
- VG_(vg_malloc_redzone_szB), /*is_zeroed*/True, MAC_AllocMalloc,
+ MALLOC_REDZONE_SZB, /*is_zeroed*/True, MAC_AllocMalloc,
MAC_(malloc_list));
}
}
@@ -326,19 +323,19 @@
void TL_(free) ( ThreadId tid, void* p )
{
MAC_(handle_free)(
- tid, (Addr)p, VG_(vg_malloc_redzone_szB), MAC_AllocMalloc );
+ tid, (Addr)p, MALLOC_REDZONE_SZB, MAC_AllocMalloc );
}
void TL_(__builtin_delete) ( ThreadId tid, void* p )
{
MAC_(handle_free)(
- tid, (Addr)p, VG_(vg_malloc_redzone_szB), MAC_AllocNew);
+ tid, (Addr)p, MALLOC_REDZONE_SZB, MAC_AllocNew);
}
void TL_(__builtin_vec_delete) ( ThreadId tid, void* p )
{
MAC_(handle_free)(
- tid, (Addr)p, VG_(vg_malloc_redzone_szB), MAC_AllocNewVec);
+ tid, (Addr)p, MALLOC_REDZONE_SZB, MAC_AllocNewVec);
}
void* TL_(realloc) ( ThreadId tid, void* p, SizeT new_size )
@@ -397,19 +394,17 @@
/* First half kept and copied, second half new,
red zones as normal */
- MAC_(ban_mem_heap) ( p_new-VG_(vg_malloc_redzone_szB),
- VG_(vg_malloc_redzone_szB) );
+ MAC_(ban_mem_heap) ( p_new-MALLOC_REDZONE_SZB, MALLOC_REDZONE_SZB );
MAC_(copy_mem_heap)( (Addr)p, p_new, mc->size );
MAC_(new_mem_heap) ( p_new+mc->size, new_size-mc->size, /*inited*/False );
- MAC_(ban_mem_heap) ( p_new+new_size, VG_(vg_malloc_redzone_szB) );
+ MAC_(ban_mem_heap) ( p_new+new_size, MALLOC_REDZONE_SZB );
/* Copy from old to new */
for (i = 0; i < mc->size; i++)
((UChar*)p_new)[i] = ((UChar*)p)[i];
/* Free old memory */
- die_and_free_mem ( tid, mc, prev_chunks_next_ptr,
- VG_(vg_malloc_redzone_szB) );
+ die_and_free_mem ( tid, mc, prev_chunks_next_ptr, MALLOC_REDZONE_SZB );
/* this has to be after die_and_free_mem, otherwise the
former succeeds in shorting out the new block, not the
Index: memcheck/mac_shared.h
===================================================================
--- memcheck/mac_shared.h (revision 3466)
+++ memcheck/mac_shared.h (working copy)
@@ -290,6 +290,8 @@
extern void MAC_(print_common_usage) ( void );
extern void MAC_(print_common_debug_usage) ( void );
+/* We want a 16B redzone on heap blocks for Addrcheck and Memcheck */
+#define MALLOC_REDZONE_SZB 16
/*------------------------------------------------------------*/
/*--- Variables ---*/
Index: massif/ms_main.c
===================================================================
--- massif/ms_main.c (revision 3466)
+++ massif/ms_main.c (working copy)
@@ -1159,8 +1159,6 @@
// Current directory at startup.
static Char* base_dir;
-SizeT VG_(vg_malloc_redzone_szB) = 0;
-
void TL_(pre_clo_init)()
{
VG_(details_name) ("Massif");
@@ -1169,11 +1167,29 @@
VG_(details_copyright_author)("Copyright (C) 2003, Nicholas Nethercote");
VG_(details_bug_reports_to) (VG_BUGS_TO);
+ // Basic functions
+ VG_(basic_tool_funcs) (TL_(post_clo_init),
+ TL_(instrument),
+ TL_(fini));
+
// Needs
VG_(needs_libc_freeres)();
- VG_(needs_command_line_options)();
- VG_(needs_client_requests) ();
+ VG_(needs_command_line_options)(TL_(process_cmd_line_option),
+ TL_(print_usage),
+ TL_(print_debug_usage));
+ VG_(needs_client_requests) (TL_(handle_client_request));
+ // Malloc replacement
+ VG_(malloc_funcs) (TL_(malloc),
+ TL_(__builtin_new),
+ TL_(__builtin_vec_new),
+ TL_(memalign),
+ TL_(calloc),
+ TL_(free),
+ TL_(__builtin_delete),
+ TL_(__builtin_vec_delete),
+ TL_(realloc) );
+
// Events to track
VG_(init_new_mem_stack_signal) ( new_mem_stack_signal );
VG_(init_die_mem_stack_signal) ( die_mem_stack_signal );
@@ -1812,7 +1828,7 @@
print_summary ( total_ST, heap_ST, heap_admin_ST, stack_ST );
}
-VG_DETERMINE_INTERFACE_VERSION(TL_(pre_clo_init), 0)
+VG_DETERMINE_INTERFACE_VERSION(TL_(pre_clo_init), 0, 0)
/*--------------------------------------------------------------------*/
/*--- end ms_main.c ---*/
Index: include/tool.h.base
===================================================================
--- include/tool.h.base (revision 3466)
+++ include/tool.h.base (working copy)
@@ -107,16 +107,21 @@
/* Specifies how big the shadow segment should be as a ratio to the
client address space. 0 for no shadow segment. */
float shadow_ratio;
+
+ /* Specifies how big the redzone surrounding each heap block should be.
+ Only relevant for tools that replace malloc() et al. */
+ UInt malloc_redzone_szB;
} ToolInfo;
/* Every tool must include this macro somewhere, exactly once. */
-#define VG_DETERMINE_INTERFACE_VERSION(pre_clo_init, shadow) \
+#define VG_DETERMINE_INTERFACE_VERSION(pre_clo_init, ratio, rz_szB) \
const ToolInfo TL_(tool_info) = { \
.sizeof_ToolInfo = sizeof(ToolInfo), \
.interface_major_version = VG_CORE_INTERFACE_MAJOR_VERSION, \
.interface_minor_version = VG_CORE_INTERFACE_MINOR_VERSION, \
.tl_pre_clo_init = pre_clo_init, \
- .shadow_ratio = shadow, \
+ .shadow_ratio = ratio, \
+ .malloc_redzone_szB = rz_szB, \
};
/*====================================================================*/
@@ -908,15 +913,6 @@
follow the following instructions. You can do it from scratch,
though, if you enjoy that sort of thing. */
-/* Arena size for valgrind's own malloc(); default value is 0, but can
- be overridden by tool -- but must be done so *statically*, eg:
-
- SizeT VG_(vg_malloc_redzone_szB) = 4;
-
- It can't be done from a function like TL_(pre_clo_init)(). So it can't,
- for example, be controlled with a command line option, unfortunately. */
-extern SizeT VG_(vg_malloc_redzone_szB);
-
/* Can be called from TL_(malloc) et al to do the actual alloc/freeing. */
extern void* VG_(cli_malloc) ( SizeT align, SizeT nbytes );
extern void VG_(cli_free) ( void* p );
@@ -947,6 +943,16 @@
/*====================================================================*/
/* ------------------------------------------------------------------ */
+/* Basic tool functions */
+
+extern void VG_(basic_tool_funcs)(
+ void(*post_clo_init)(void),
+ IRBB*(*instrument)(IRBB* bb_in, VexGuestLayout* layout,
+ IRType gWordTy, IRType hWordTy ),
+ void(*fini)(Int)
+);
+
+/* ------------------------------------------------------------------ */
/* Details */
/* Default value for avg_translations_sizeB (in bytes), indicating typical
@@ -995,27 +1001,110 @@
lot like being a member of a type class. */
/* Want to report errors from tool? This implies use of suppressions, too. */
-extern void VG_(needs_tool_errors) ( void );
+extern void VG_(needs_tool_errors) (
+ // Identify if two errors are equal, or equal enough. `res' indicates how
+ // close is "close enough". `res' should be passed on as necessary, eg. if
+ // the Error's `extra' part contains an ExeContext, `res' should be
+ // passed to VG_(eq_ExeContext)() if the ExeContexts are considered. Other
+ // than that, probably don't worry about it unless you have lots of very
+ // similar errors occurring.
+ Bool (*eq_Error)(VgRes res, Error* e1, Error* e2),
+ // Print error context.
+ void (*pp_Error)(Error* err),
+
+ // Should fill in any details that could be postponed until after the
+ // decision whether to ignore the error (ie. details not affecting the
+ // result of TL_(eq_Error)()). This saves time when errors are ignored.
+ // Yuk.
+ // Return value: must be the size of the `extra' part in bytes -- used by
+ // the core to make a copy.
+ UInt (*update_extra)(Error* err),
+
+ // Return value indicates recognition. If recognised, must set skind using
+ // VG_(set_supp_kind)().
+ Bool (*recognised_suppression)(Char* name, Supp* su),
+
+ // Read any extra info for this suppression kind. Most likely for filling
+ // in the `extra' and `string' parts (with VG_(set_supp_{extra, string})())
+ // of a suppression if necessary. Should return False if a syntax error
+ // occurred, True otherwise.
+ Bool (*read_extra_suppression_info)(Int fd, Char* buf, Int nBuf, Supp* su),
+
+ // This should just check the kinds match and maybe some stuff in the
+ // `string' and `extra' field if appropriate (using VG_(get_supp_*)() to
+ // get the relevant suppression parts).
+ Bool (*error_matches_suppression)(Error* err, Supp* su),
+
+ // This should return the suppression name, for --gen-suppressions, or NULL
+ // if that error type cannot be suppressed. This is the inverse of
+ // TL_(recognised_suppression)().
+ Char* (*get_error_name)(Error* err),
+
+ // This should print any extra info for the error, for --gen-suppressions,
+ // including the newline. This is the inverse of
+ // TL_(read_extra_suppression_info)().
+ void (*print_extra_suppression_info)(Error* err)
+);
+
+
/* Is information kept about specific individual basic blocks? (Eg. for
cachegrind there are cost-centres for every instruction, stored at a
basic block level.) If so, it sometimes has to be discarded, because
.so mmap/munmap-ping or self-modifying code (informed by the
DISCARD_TRANSLATIONS user request) can cause one instruction address
to be used for more than one instruction in one program run... */
-extern void VG_(needs_basic_block_discards) ( void );
+extern void VG_(needs_basic_block_discards) (
+ // Should discard any information that pertains to specific basic blocks
+ // or instructions within the address range given.
+ void (*discard_basic_block_info)(Addr a, SizeT size)
+);
/* Tool defines its own command line options? */
-extern void VG_(needs_command_line_options) ( void );
+extern void VG_(needs_command_line_options) (
+ // Return True if option was recognised. Presumably sets some state to
+ // record the option as well.
+ Bool (*process_cmd_line_option)(Char* argv),
+ // Print out command line usage for options for normal tool operation.
+ void (*print_usage)(void),
+
+ // Print out command line usage for options for debugging the tool.
+ void (*print_debug_usage)(void)
+);
+
/* Tool defines its own client requests? */
-extern void VG_(needs_client_requests) ( void );
+extern void VG_(needs_client_requests) (
+ // If using client requests, the number of the first request should be equal
+ // to VG_USERREQ_TOOL_BASE('X', 'Y'), where 'X' and 'Y' form a suitable two
+ // character identification for the string. The second and subsequent
+ // requests should follow.
+ //
+ // This function should use the VG_IS_TOOL_USERREQ macro (in
+ // include/valgrind.h) to first check if it's a request for this tool. Then
+ // should handle it if it's recognised (and return True), or return False if
+ // not recognised. arg_block[0] holds the request number, any further args
+ // from the request are in arg_block[1..]. 'ret' is for the return value...
+ // it should probably be filled, if only with 0.
+ Bool (*handle_client_request)(ThreadId tid, UWord* arg_block, UWord* ret)
+);
/* Tool does stuff before and/or after system calls? */
-extern void VG_(needs_syscall_wrapper) ( void );
+// Nb: If either of the pre_ functions malloc() something to return, the
+// corresponding post_ function had better free() it!
+extern void VG_(needs_syscall_wrapper) (
+ void (* pre_syscall)(ThreadId tid, UInt syscallno),
+ void (*post_syscall)(ThreadId tid, UInt syscallno, Int res)
+);
/* Are tool-state sanity checks performed? */
-extern void VG_(needs_sanity_checks) ( void );
+// Can be useful for ensuring a tool's correctness. TL_(cheap_sanity_check)
+// is called very frequently; TL_(expensive_sanity_check) is called less
+// frequently and can be more involved.
+extern void VG_(needs_sanity_checks) (
+ Bool(*cheap_sanity_check)(void),
+ Bool(*expensive_sanity_check)(void)
+);
/* Do we need to see data symbols? */
extern void VG_(needs_data_syms) ( void );
@@ -1028,6 +1117,22 @@
extern float TL_(shadow_ratio);
/* ------------------------------------------------------------------ */
+/* Malloc replacement */
+
+// The 'v' prefix avoids GCC complaints about overshadowing global names.
+extern void VG_(malloc_funcs)(
+ void* (*vmalloc) ( ThreadId tid, SizeT n ),
+ void* (*v__builtin_new) ( ThreadId tid, SizeT n ),
+ void* (*v__builtin_vec_new) ( ThreadId tid, SizeT n ),
+ void* (*vmemalign) ( ThreadId tid, SizeT align, SizeT n ),
+ void* (*vcalloc) ( ThreadId tid, SizeT nmemb, SizeT size1 ),
+ void (*vfree) ( ThreadId tid, void* p ),
+ void (*v__builtin_delete) ( ThreadId tid, void* p ),
+ void (*v__builtin_vec_delete) ( ThreadId tid, void* p ),
+ void* (*vrealloc) ( ThreadId tid, void* p, SizeT new_size )
+);
+
+/* ------------------------------------------------------------------ */
/* Core events to track */
/* Part of the core from which this call was made. Useful for determining
Index: cachegrind/cg_main.c
===================================================================
--- cachegrind/cg_main.c (revision 3466)
+++ cachegrind/cg_main.c (working copy)
@@ -1132,9 +1132,15 @@
VG_(details_bug_reports_to) (VG_BUGS_TO);
VG_(details_avg_translation_sizeB) ( 155 );
- VG_(needs_basic_block_discards)();
- VG_(needs_command_line_options)();
+ VG_(basic_tool_funcs) (TL_(post_clo_init),
+ TL_(instrument),
+ TL_(fini));
+ VG_(needs_basic_block_discards)(TL_(discard_basic_block_info));
+ VG_(needs_command_line_options)(TL_(process_cmd_line_option),
+ TL_(print_usage),
+ TL_(print_debug_usage));
+
/* Get working directory */
tl_assert( VG_(getcwd_alloc)(&base_dir) );
@@ -1162,7 +1168,7 @@
VG_(register_profile_event)(VgpCacheResults, "cache-results");
}
-VG_DETERMINE_INTERFACE_VERSION(TL_(pre_clo_init), 0)
+VG_DETERMINE_INTERFACE_VERSION(TL_(pre_clo_init), 0, 0)
/*--------------------------------------------------------------------*/
/*--- end cg_main.c ---*/
Index: none/nl_main.c
===================================================================
--- none/nl_main.c (revision 3466)
+++ none/nl_main.c (working copy)
@@ -39,6 +39,10 @@
"Copyright (C) 2002-2005, and GNU GPL'd, by Nicholas Nethercote.");
VG_(details_bug_reports_to) (VG_BUGS_TO);
+ VG_(basic_tool_funcs) (TL_(post_clo_init),
+ TL_(instrument),
+ TL_(fini));
+
/* No needs, no core events to track */
}
@@ -56,7 +60,7 @@
{
}
-VG_DETERMINE_INTERFACE_VERSION(TL_(pre_clo_init), 0)
+VG_DETERMINE_INTERFACE_VERSION(TL_(pre_clo_init), 0, 0)
/*--------------------------------------------------------------------*/
/*--- end ---*/
Index: addrcheck/ac_main.c
===================================================================
--- addrcheck/ac_main.c (revision 3466)
+++ addrcheck/ac_main.c (working copy)
@@ -1318,14 +1318,38 @@
VG_(details_bug_reports_to) (VG_BUGS_TO);
VG_(details_avg_translation_sizeB) ( 135 );
+ VG_(basic_tool_funcs) (TL_(post_clo_init),
+ TL_(instrument),
+ TL_(fini));
+
VG_(needs_core_errors) ();
- VG_(needs_tool_errors) ();
+ VG_(needs_tool_errors) (TL_(eq_Error),
+ TL_(pp_Error),
+ TL_(update_extra),
+ TL_(recognised_suppression),
+ TL_(read_extra_suppression_info),
+ TL_(error_matches_suppression),
+ TL_(get_error_name),
+ TL_(print_extra_suppression_info));
VG_(needs_libc_freeres) ();
- VG_(needs_command_line_options)();
- VG_(needs_client_requests) ();
- VG_(needs_sanity_checks) ();
+ VG_(needs_command_line_options)(TL_(process_cmd_line_option),
+ TL_(print_usage),
+ TL_(print_debug_usage));
+ VG_(needs_client_requests) (TL_(handle_client_request));
+ VG_(needs_sanity_checks) (TL_(cheap_sanity_check),
+ TL_(expensive_sanity_check));
VG_(needs_shadow_memory) ();
+ VG_(malloc_funcs) (TL_(malloc),
+ TL_(__builtin_new),
+ TL_(__builtin_vec_new),
+ TL_(memalign),
+ TL_(calloc),
+ TL_(free),
+ TL_(__builtin_delete),
+ TL_(__builtin_vec_delete),
+ TL_(realloc) );
+
MAC_( new_mem_heap) = & ac_new_mem_heap;
MAC_( ban_mem_heap) = & ac_make_noaccess;
MAC_(copy_mem_heap) = & ac_copy_address_range_state;
@@ -1381,7 +1405,7 @@
MAC_(common_fini)( ac_detect_memory_leaks );
}
-VG_DETERMINE_INTERFACE_VERSION(TL_(pre_clo_init), 1./8)
+VG_DETERMINE_INTERFACE_VERSION(TL_(pre_clo_init), 1./8, MALLOC_REDZONE_SZB)
/*--------------------------------------------------------------------*/
Index: lackey/lk_main.c
===================================================================
--- lackey/lk_main.c (revision 3466)
+++ lackey/lk_main.c (working copy)
@@ -81,6 +81,10 @@
"Copyright (C) 2002-2005, and GNU GPL'd, by Nicholas Nethercote.");
VG_(details_bug_reports_to) (VG_BUGS_TO);
VG_(details_avg_translation_sizeB) ( 175 );
+
+ VG_(basic_tool_funcs) (TL_(post_clo_init),
+ TL_(instrument),
+ TL_(fini));
}
void TL_(post_clo_init)(void)
@@ -278,7 +282,7 @@
VG_(message)(Vg_UserMsg, "Exit code: %d", exitcode);
}
-VG_DETERMINE_INTERFACE_VERSION(TL_(pre_clo_init), 0)
+VG_DETERMINE_INTERFACE_VERSION(TL_(pre_clo_init), 0, 0)
/*--------------------------------------------------------------------*/
Index: coregrind/gen_toolint.pl
===================================================================
--- coregrind/gen_toolint.pl (revision 3466)
+++ coregrind/gen_toolint.pl (working copy)
@@ -166,32 +166,6 @@
print "void VG_(init_$func)($ret (*func)($args));\n";
};
$headerguard=$output;
-} elsif ($output eq "initdlsym") {
- $pre = sub () {
- print <<EOF;
-#include <dlfcn.h>
-void VG_(tool_init_dlsym)(void *dlhandle)
-{
- void *ret;
-
-EOF
- };
- $post = sub () {
- print "}\n";
- };
- $generate = sub ($$$@) {
- my ($pfx, $ret, $func, @args) = @_;
- my $args = join ", ", getargtypes(@args);
-
- print <<EOF;
- ret = dlsym(dlhandle, "vgTool_$func");
- if (ret != NULL)
- VG_(init_$func)(($ret (*)($args))ret);
-
-EOF
- };
-
- $passcomment = 0;
}
die "Unknown output format \"$output\"" unless defined $generate;
Index: coregrind/vg_default.c
===================================================================
--- coregrind/vg_default.c (revision 3466)
+++ coregrind/vg_default.c (working copy)
@@ -66,10 +66,6 @@
/*--- Replacing malloc et al ---*/
/*------------------------------------------------------------*/
-/* Default redzone size for CLIENT arena of Valgrind's malloc() */
-__attribute__ ((weak))
-SizeT VG_(vg_malloc_redzone_szB) = 8;
-
Bool VG_(tl_malloc_called_deliberately) = False;
/* If the tool hasn't replaced malloc(), this one can be called
Index: coregrind/vg_main.c
===================================================================
--- coregrind/vg_main.c (revision 3466)
+++ coregrind/vg_main.c (working copy)
@@ -1175,7 +1175,7 @@
/* Find and load a tool, and check it looks ok. Also looks to see if there's
* a matching vgpreload_*.so file, and returns its name in *preloadpath. */
-static void load_tool( const char *toolname, void** handle_out,
+static void load_tool( const char *toolname,
ToolInfo** toolinfo_out, char **preloadpath_out )
{
Bool ok;
@@ -1184,7 +1184,6 @@
void* handle;
ToolInfo* toolinfo;
char* preloadpath = NULL;
- Int* vg_malloc_redzonep;
// XXX: allowing full paths for --tool option -- does it make sense?
// Doesn't allow for vgpreload_<tool>.so.
@@ -1244,13 +1243,9 @@
}
// Set redzone size for V's allocator
- vg_malloc_redzonep = dlsym(handle, VG_STRINGIFY(VG_(vg_malloc_redzone_szB)));
- if ( NULL != vg_malloc_redzonep ) {
- VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
- }
+ VG_(vg_malloc_redzone_szB) = toolinfo->malloc_redzone_szB;
- vg_assert(NULL != handle && NULL != toolinfo);
- *handle_out = handle;
+ vg_assert(NULL != toolinfo);
*toolinfo_out = toolinfo;
*preloadpath_out = preloadpath;
return;
@@ -2422,7 +2417,6 @@
Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
struct exeinfo info;
ToolInfo *toolinfo = NULL;
- void *tool_dlhandle;
Addr client_eip;
Addr sp_at_startup; /* client's SP at the point we gained control. */
UInt * client_auxv;
@@ -2495,7 +2489,7 @@
// p: set-libdir [for VG_(libdir)]
// p: pre_process_cmd_line_options() [for 'tool']
//--------------------------------------------------------------
- load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
+ load_tool(tool, &toolinfo, &preload);
//==============================================================
// Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
@@ -2572,13 +2566,12 @@
//--------------------------------------------------------------
// Init tool: pre_clo_init, process cmd line, post_clo_init
// p: setup_client_stack() [for 'VG_(client_arg[cv]']
- // p: load_tool() [for 'tool']
+ // p: load_tool() [for 'toolinfo']
// p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
// p: parse_procselfmaps [so VG segments are setup so tool can
// call VG_(malloc)]
//--------------------------------------------------------------
(*toolinfo->tl_pre_clo_init)();
- VG_(tool_init_dlsym)(tool_dlhandle);
VG_(sanity_check_needs)();
// If --tool and --help/--help-debug was given, now give the core+tool
Index: coregrind/vg_malloc2.c
===================================================================
--- coregrind/vg_malloc2.c (revision 3466)
+++ coregrind/vg_malloc2.c (working copy)
@@ -329,6 +329,9 @@
// The arena structures themselves.
static Arena vg_arena[VG_N_ARENAS];
+// Redzone size for CLIENT arena of Valgrind's malloc(). Set in vg_main.c.
+SizeT VG_(vg_malloc_redzone_szB);
+
// Functions external to this module identify arenas using ArenaIds,
// not Arena*s. This fn converts the former to the latter.
static Arena* arenaId_to_ArenaP ( ArenaId arena )
Index: coregrind/vg_needs.c
===================================================================
--- coregrind/vg_needs.c (revision 3466)
+++ coregrind/vg_needs.c (working copy)
@@ -36,6 +36,23 @@
Tool data structure initialisation
------------------------------------------------------------------ */
+/*--------------------------------------------------------------------*/
+/* Setting basic functions */
+
+void VG_(basic_tool_funcs)(
+ void(*post_clo_init)(void),
+ IRBB*(*instrument)(IRBB*, VexGuestLayout*, IRType, IRType ),
+ void(*fini)(Int)
+)
+{
+ VG_(tool_interface).tool_post_clo_init = post_clo_init;
+ VG_(tool_interface).tool_instrument = instrument;
+ VG_(tool_interface).tool_fini = fini;
+}
+
+/*--------------------------------------------------------------------*/
+/* Setting details */
+
/* Init with default values. */
VgDetails VG_(details) = {
.name = NULL,
@@ -46,6 +63,23 @@
.avg_translation_sizeB = VG_DEFAULT_TRANS_SIZEB,
};
+/* Use macro because they're so repetitive */
+#define DETAILS(type, detail) \
+ extern void VG_(details_##detail)(type detail) \
+ { \
+ VG_(details).detail = detail; \
+ }
+
+DETAILS(Char*, name)
+DETAILS(Char*, version)
+DETAILS(Char*, description)
+DETAILS(Char*, copyright_author)
+DETAILS(Char*, bug_reports_to)
+DETAILS(UInt, avg_translation_sizeB)
+
+/*--------------------------------------------------------------------*/
+/* Setting needs */
+
VgNeeds VG_(needs) = {
.core_errors = False,
.tool_errors = False,
@@ -115,44 +149,115 @@
#undef CHECK_NOT
}
-/*--------------------------------------------------------------------*/
-/* Setting details */
-
/* Use macro because they're so repetitive */
-#define DETAILS(type, detail) \
- extern void VG_(details_##detail)(type detail) \
- { \
- VG_(details).detail = detail; \
- }
-
-DETAILS(Char*, name)
-DETAILS(Char*, version)
-DETAILS(Char*, description)
-DETAILS(Char*, copyright_author)
-DETAILS(Char*, bug_reports_to)
-DETAILS(UInt, avg_translation_sizeB)
-
-/*--------------------------------------------------------------------*/
-/* Setting needs */
-
-/* Use macro because they're so repetitive */
#define NEEDS(need) \
extern void VG_(needs_##need)(void) \
{ \
VG_(needs).need = True; \
}
+// These ones don't require any tool-supplied functions
NEEDS(libc_freeres)
NEEDS(core_errors)
-NEEDS(tool_errors)
-NEEDS(basic_block_discards)
-NEEDS(command_line_options)
-NEEDS(client_requests)
-NEEDS(syscall_wrapper)
-NEEDS(sanity_checks)
NEEDS(data_syms)
NEEDS(shadow_memory)
+void VG_(needs_basic_block_discards)(
+ void (*discard)(Addr, SizeT)
+)
+{
+ VG_(needs).basic_block_discards = True;
+ VG_(tool_interface).tool_discard_basic_block_info = discard;
+}
+
+void VG_(needs_tool_errors)(
+ Bool (*eq) (VgRes, Error*, Error*),
+ void (*pp) (Error*),
+ UInt (*update) (Error*),
+ Bool (*recog) (Char*, Supp*),
+ Bool (*read_extra) (Int, Char*, Int, Supp*),
+ Bool (*matches) (Error*, Supp*),
+ Char* (*name) (Error*),
+ void (*print_extra)(Error*)
+)
+{
+ VG_(needs).tool_errors = True;
+ VG_(tool_interface).tool_eq_Error = eq;
+ VG_(tool_interface).tool_pp_Error = pp;
+ VG_(tool_interface).tool_update_extra = update;
+ VG_(tool_interface).tool_recognised_suppression = recog;
+ VG_(tool_interface).tool_read_extra_suppression_info = read_extra;
+ VG_(tool_interface).tool_error_matches_suppression = matches;
+ VG_(tool_interface).tool_get_error_name = name;
+ VG_(tool_interface).tool_print_extra_suppression_info = print_extra;
+}
+
+void VG_(needs_command_line_options)(
+ Bool (*process)(Char*),
+ void (*usage)(void),
+ void (*debug_usage)(void)
+)
+{
+ VG_(needs).command_line_options = True;
+ VG_(tool_interface).tool_process_cmd_line_option = process;
+ VG_(tool_interface).tool_print_usage = usage;
+ VG_(tool_interface).tool_print_debug_usage = debug_usage;
+}
+
+void VG_(needs_client_requests)(
+ Bool (*handle)(ThreadId, UWord*, UWord*)
+)
+{
+ VG_(needs).client_requests = True;
+ VG_(tool_interface).tool_handle_client_request = handle;
+}
+
+void VG_(needs_syscall_wrapper)(
+ void(*pre) (ThreadId, UInt),
+ void(*post)(ThreadId, UInt, Int res)
+)
+{
+ VG_(needs).syscall_wrapper = True;
+ VG_(tool_interface).tool_pre_syscall = pre;
+ VG_(tool_interface).tool_post_syscall = post;
+}
+
+void VG_(needs_sanity_checks)(
+ Bool(*cheap)(void),
+ Bool(*expen)(void)
+)
+{
+ VG_(needs).sanity_checks = True;
+ VG_(tool_interface).tool_cheap_sanity_check = cheap;
+ VG_(tool_interface).tool_expensive_sanity_check = expen;
+}
+
+
+/* Replacing malloc() */
+
+extern void VG_(malloc_funcs)(
+ void* (*malloc) ( ThreadId, SizeT ),
+ void* (*__builtin_new) ( ThreadId, SizeT ),
+ void* (*__builtin_vec_new) ( ThreadId, SizeT ),
+ void* (*memalign) ( ThreadId, SizeT, SizeT ),
+ void* (*calloc) ( ThreadId, SizeT, SizeT ),
+ void (*free) ( ThreadId, void* ),
+ void (*__builtin_delete) ( ThreadId, void* ),
+ void (*__builtin_vec_delete) ( ThreadId, void* ),
+ void* (*realloc) ( ThreadId, void*, SizeT )
+)
+{
+ VG_(tool_interface).malloc_malloc = malloc;
+ VG_(tool_interface).malloc___builtin_new = __builtin_new;
+ VG_(tool_interface).malloc___builtin_vec_new = __builtin_vec_new;
+ VG_(tool_interface).malloc_memalign = memalign;
+ VG_(tool_interface).malloc_calloc = calloc;
+ VG_(tool_interface).malloc_free = free;
+ VG_(tool_interface).malloc___builtin_delete = __builtin_delete;
+ VG_(tool_interface).malloc___builtin_vec_delete = __builtin_vec_delete;
+ VG_(tool_interface).malloc_realloc = realloc;
+}
+
/*--------------------------------------------------------------------*/
/*--- end vg_needs.c ---*/
/*--------------------------------------------------------------------*/
Index: coregrind/core.h
===================================================================
--- coregrind/core.h (revision 3466)
+++ coregrind/core.h (working copy)
@@ -337,8 +337,6 @@
extern VgNeeds VG_(needs);
-extern void VG_(tool_init_dlsym)(void *dlhandle);
-
#include "vg_toolint.h"
@@ -386,6 +384,12 @@
// Round-up size for --sloppy-malloc=yes.
#define VG_SLOPPY_MALLOC_SZB 4
+// Arena size for valgrind's own malloc(). Gets set by the 3rd parameter
+// to the VG_DETERMINE_INTERFACE_VERSION macro, because it has to be set before
+// any of the tool's functions get called. So it can't, for example, be
+// controlled with a command line option, unfortunately. */
+extern SizeT VG_(vg_malloc_redzone_szB);
+
extern void* VG_(arena_malloc) ( ArenaId arena, SizeT nbytes );
extern void VG_(arena_free) ( ArenaId arena, void* ptr );
extern void* VG_(arena_calloc) ( ArenaId arena,
Index: coregrind/Makefile.am
===================================================================
--- coregrind/Makefile.am (revision 3466)
+++ coregrind/Makefile.am (working copy)
@@ -124,7 +124,6 @@
$(PERL) $(srcdir)/gen_toolint.pl callwrap < $(srcdir)/toolfuncs.def > $@ || rm -f $@
$(PERL) $(srcdir)/gen_toolint.pl missingfuncs < $(srcdir)/toolfuncs.def >> $@ || rm -f $@
$(PERL) $(srcdir)/gen_toolint.pl initfunc < $(srcdir)/toolfuncs.def >> $@ || rm -f $@
- $(PERL) $(srcdir)/gen_toolint.pl initdlsym < $(srcdir)/toolfuncs.def >> $@ || rm -f $@
$(PERL) $(srcdir)/gen_toolint.pl structdef < $(srcdir)/toolfuncs.def >> $@ || rm -f $@
vg_toolint.h: $(srcdir)/gen_toolint.pl $(srcdir)/toolfuncs.def ./Makefile
|
|
From: Tom H. <to...@co...> - 2005-03-28 02:28:38
|
Nightly build on dunsmere ( Fedora Core 3 ) started at 2005-03-28 03:20:03 BST Checking out source tree ... done Configuring ... done Building ... done Running regression tests ... done Last 20 lines of log.verbose follow insn_cmov: valgrind ./insn_cmov insn_fpu: valgrind ./insn_fpu insn_mmx: valgrind ./insn_mmx insn_mmxext: valgrind ./insn_mmxext insn_sse: valgrind ./insn_sse insn_sse2: (skipping, prereq failed: ../../../tests/cputest x86-sse2) int: valgrind ./int sh: line 1: 24367 Segmentation fault VALGRINDLIB=/tmp/valgrind.31669/valgrind/.in_place /tmp/valgrind.31669/valgrind/./coregrind/valgrind --command-line-only=yes --memcheck:leak-check=no --addrcheck:leak-check=no --tool=none ./int >int.stdout.out 2>int.stderr.out pushpopseg: valgrind ./pushpopseg rcl_assert: valgrind ./rcl_assert seg_override: valgrind ./seg_override -- Finished tests in none/tests/x86 ------------------------------------ yield: valgrind ./yield -- Finished tests in none/tests ---------------------------------------- == 207 tests, 2 stderr failures, 0 stdout failures ================= memcheck/tests/scalar (stderr) memcheck/tests/scalar_supp (stderr) make: *** [regtest] Error 1 |
|
From: Tom H. <th...@cy...> - 2005-03-28 02:22:46
|
Nightly build on audi ( Red Hat 9 ) started at 2005-03-28 03:15:02 BST Checking out source tree ... done Configuring ... done Building ... done Running regression tests ... done Last 20 lines of log.verbose follow fpu_lazy_eflags: valgrind ./fpu_lazy_eflags insn_basic: valgrind ./insn_basic insn_cmov: valgrind ./insn_cmov insn_fpu: valgrind ./insn_fpu insn_mmx: valgrind ./insn_mmx insn_mmxext: valgrind ./insn_mmxext insn_sse: valgrind ./insn_sse insn_sse2: (skipping, prereq failed: ../../../tests/cputest x86-sse2) int: valgrind ./int pushpopseg: valgrind ./pushpopseg rcl_assert: valgrind ./rcl_assert seg_override: valgrind ./seg_override -- Finished tests in none/tests/x86 ------------------------------------ yield: valgrind ./yield -- Finished tests in none/tests ---------------------------------------- == 206 tests, 1 stderr failure, 0 stdout failures ================= memcheck/tests/scalar (stderr) make: *** [regtest] Error 1 |
|
From: Tom H. <th...@cy...> - 2005-03-28 02:16:26
|
Nightly build on ginetta ( Red Hat 8.0 ) started at 2005-03-28 03:10:02 BST Checking out source tree ... done Configuring ... done Building ... done Running regression tests ... done Last 20 lines of log.verbose follow insn_cmov: valgrind ./insn_cmov insn_fpu: valgrind ./insn_fpu insn_mmx: valgrind ./insn_mmx insn_mmxext: valgrind ./insn_mmxext insn_sse: valgrind ./insn_sse insn_sse2: (skipping, prereq failed: ../../../tests/cputest x86-sse2) int: valgrind ./int pushpopseg: valgrind ./pushpopseg rcl_assert: valgrind ./rcl_assert seg_override: valgrind ./seg_override -- Finished tests in none/tests/x86 ------------------------------------ yield: valgrind ./yield -- Finished tests in none/tests ---------------------------------------- == 205 tests, 3 stderr failures, 0 stdout failures ================= memcheck/tests/pth_once (stderr) memcheck/tests/scalar (stderr) memcheck/tests/threadederrno (stderr) make: *** [regtest] Error 1 |