authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-11-17 22:29:17+00:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2019-11-17 22:29:17+00:00
log8e3370367bbbcae43670380cb4ca841a9e5ada33
tree5ba2f971ef4c209c97d23742e667eb6afe28156f
parent924dd674e2e584bbef5e7650f481e49829c8fe28
parentd870a68e680242d130dcecef1f1ccc0969f326c0
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #3705 from daurnimator/fix-std.valgrind

std: fix outdated valgrind module

3 files changed, 111 insertions(+), 62 deletions(-)

lib/std/valgrind.zig+44-34
...@@ -1,5 +1,6 @@...@@ -1,5 +1,6 @@
1const builtin = @import("builtin");1const builtin = @import("builtin");
2const math = @import("index.zig").math;2const std = @import("std.zig");
3const math = std.math;
34
4pub fn doClientRequest(default: usize, request: usize, a1: usize, a2: usize, a3: usize, a4: usize, a5: usize) usize {5pub fn doClientRequest(default: usize, request: usize, a1: usize, a2: usize, a3: usize, a4: usize, a5: usize) usize {
5 if (!builtin.valgrind_support) {6 if (!builtin.valgrind_support) {
...@@ -13,7 +14,7 @@ pub fn doClientRequest(default: usize, request: usize, a1: usize, a2: usize, a3:...@@ -13,7 +14,7 @@ pub fn doClientRequest(default: usize, request: usize, a1: usize, a2: usize, a3:
13 \\ roll $29, %%edi ; roll $19, %%edi14 \\ roll $29, %%edi ; roll $19, %%edi
14 \\ xchgl %%ebx,%%ebx15 \\ xchgl %%ebx,%%ebx
15 : [_] "={edx}" (-> usize)16 : [_] "={edx}" (-> usize)
16 : [_] "{eax}" (&[]usize{ request, a1, a2, a3, a4, a5 }),17 : [_] "{eax}" (&[_]usize{ request, a1, a2, a3, a4, a5 }),
17 [_] "0" (default)18 [_] "0" (default)
18 : "cc", "memory"19 : "cc", "memory"
19 );20 );
...@@ -24,7 +25,7 @@ pub fn doClientRequest(default: usize, request: usize, a1: usize, a2: usize, a3:...@@ -24,7 +25,7 @@ pub fn doClientRequest(default: usize, request: usize, a1: usize, a2: usize, a3:
24 \\ rolq $61, %%rdi ; rolq $51, %%rdi25 \\ rolq $61, %%rdi ; rolq $51, %%rdi
25 \\ xchgq %%rbx,%%rbx26 \\ xchgq %%rbx,%%rbx
26 : [_] "={rdx}" (-> usize)27 : [_] "={rdx}" (-> usize)
27 : [_] "{rax}" (&[]usize{ request, a1, a2, a3, a4, a5 }),28 : [_] "{rax}" (&[_]usize{ request, a1, a2, a3, a4, a5 }),
28 [_] "0" (default)29 [_] "0" (default)
29 : "cc", "memory"30 : "cc", "memory"
30 );31 );
...@@ -95,48 +96,52 @@ fn doClientRequestStmt(request: ClientRequest, a1: usize, a2: usize, a3: usize,...@@ -95,48 +96,52 @@ fn doClientRequestStmt(request: ClientRequest, a1: usize, a2: usize, a3: usize,
95/// running under Valgrind which is running under another Valgrind,96/// running under Valgrind which is running under another Valgrind,
96/// etc.97/// etc.
97pub fn runningOnValgrind() usize {98pub fn runningOnValgrind() usize {
98 return doClientRequestExpr(0, ClientRequest.RunningOnValgrind, 0, 0, 0, 0, 0);99 return doClientRequestExpr(0, .RunningOnValgrind, 0, 0, 0, 0, 0);
100}
101
102test "works whether running on valgrind or not" {
103 _ = runningOnValgrind();
99}104}
100105
101/// Discard translation of code in the slice qzz. Useful if you are debugging106/// Discard translation of code in the slice qzz. Useful if you are debugging
102/// a JITter or some such, since it provides a way to make sure valgrind will107/// a JITter or some such, since it provides a way to make sure valgrind will
103/// retranslate the invalidated area. Returns no value.108/// retranslate the invalidated area. Returns no value.
104pub fn discardTranslations(qzz: []const u8) void {109pub fn discardTranslations(qzz: []const u8) void {
105 doClientRequestStmt(ClientRequest.DiscardTranslations, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0);110 doClientRequestStmt(.DiscardTranslations, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0);
106}111}
107112
108pub fn innerThreads(qzz: [*]u8) void {113pub fn innerThreads(qzz: [*]u8) void {
109 doClientRequestStmt(ClientRequest.InnerThreads, qzz, 0, 0, 0, 0);114 doClientRequestStmt(.InnerThreads, qzz, 0, 0, 0, 0);
110}115}
111116
112//pub fn printf(format: [*]const u8, args: ...) usize {117//pub fn printf(format: [*]const u8, args: ...) usize {
113// return doClientRequestExpr(0,118// return doClientRequestExpr(0,
114// ClientRequest.PrintfValistByRef,119// .PrintfValistByRef,
115// @ptrToInt(format), @ptrToInt(args),120// @ptrToInt(format), @ptrToInt(args),
116// 0, 0, 0);121// 0, 0, 0);
117//}122//}
118123
119//pub fn printfBacktrace(format: [*]const u8, args: ...) usize {124//pub fn printfBacktrace(format: [*]const u8, args: ...) usize {
120// return doClientRequestExpr(0,125// return doClientRequestExpr(0,
121// ClientRequest.PrintfBacktraceValistByRef,126// .PrintfBacktraceValistByRef,
122// @ptrToInt(format), @ptrToInt(args),127// @ptrToInt(format), @ptrToInt(args),
123// 0, 0, 0);128// 0, 0, 0);
124//}129//}
125130
126pub fn nonSIMDCall0(func: fn (usize) usize) usize {131pub fn nonSIMDCall0(func: fn (usize) usize) usize {
127 return doClientRequestExpr(0, ClientRequest.ClientCall0, @ptrToInt(func), 0, 0, 0, 0);132 return doClientRequestExpr(0, .ClientCall0, @ptrToInt(func), 0, 0, 0, 0);
128}133}
129134
130pub fn nonSIMDCall1(func: fn (usize, usize) usize, a1: usize) usize {135pub fn nonSIMDCall1(func: fn (usize, usize) usize, a1: usize) usize {
131 return doClientRequestExpr(0, ClientRequest.ClientCall1, @ptrToInt(func), a1, 0, 0, 0);136 return doClientRequestExpr(0, .ClientCall1, @ptrToInt(func), a1, 0, 0, 0);
132}137}
133138
134pub fn nonSIMDCall2(func: fn (usize, usize, usize) usize, a1: usize, a2: usize) usize {139pub fn nonSIMDCall2(func: fn (usize, usize, usize) usize, a1: usize, a2: usize) usize {
135 return doClientRequestExpr(0, ClientRequest.ClientCall2, @ptrToInt(func), a1, a2, 0, 0);140 return doClientRequestExpr(0, .ClientCall2, @ptrToInt(func), a1, a2, 0, 0);
136}141}
137142
138pub fn nonSIMDCall3(func: fn (usize, usize, usize, usize) usize, a1: usize, a2: usize, a3: usize) usize {143pub fn nonSIMDCall3(func: fn (usize, usize, usize, usize) usize, a1: usize, a2: usize, a3: usize) usize {
139 return doClientRequestExpr(0, ClientRequest.ClientCall3, @ptrToInt(func), a1, a2, a3, 0);144 return doClientRequestExpr(0, .ClientCall3, @ptrToInt(func), a1, a2, a3, 0);
140}145}
141146
142/// Counts the number of errors that have been recorded by a tool. Nb:147/// Counts the number of errors that have been recorded by a tool. Nb:
...@@ -144,19 +149,19 @@ pub fn nonSIMDCall3(func: fn (usize, usize, usize, usize) usize, a1: usize, a2:...@@ -144,19 +149,19 @@ pub fn nonSIMDCall3(func: fn (usize, usize, usize, usize) usize, a1: usize, a2:
144/// VG_(unique_error)() for them to be counted.149/// VG_(unique_error)() for them to be counted.
145pub fn countErrors() usize {150pub fn countErrors() usize {
146 return doClientRequestExpr(0, // default return151 return doClientRequestExpr(0, // default return
147 ClientRequest.CountErrors, 0, 0, 0, 0, 0);152 .CountErrors, 0, 0, 0, 0, 0);
148}153}
149154
150pub fn mallocLikeBlock(mem: []u8, rzB: usize, is_zeroed: bool) void {155pub fn mallocLikeBlock(mem: []u8, rzB: usize, is_zeroed: bool) void {
151 doClientRequestStmt(ClientRequest.MalloclikeBlock, @ptrToInt(mem.ptr), mem.len, rzB, @boolToInt(is_zeroed), 0);156 doClientRequestStmt(.MalloclikeBlock, @ptrToInt(mem.ptr), mem.len, rzB, @boolToInt(is_zeroed), 0);
152}157}
153158
154pub fn resizeInPlaceBlock(oldmem: []u8, newsize: usize, rzB: usize) void {159pub fn resizeInPlaceBlock(oldmem: []u8, newsize: usize, rzB: usize) void {
155 doClientRequestStmt(ClientRequest.ResizeinplaceBlock, @ptrToInt(oldmem.ptr), oldmem.len, newsize, rzB, 0);160 doClientRequestStmt(.ResizeinplaceBlock, @ptrToInt(oldmem.ptr), oldmem.len, newsize, rzB, 0);
156}161}
157162
158pub fn freeLikeBlock(addr: [*]u8, rzB: usize) void {163pub fn freeLikeBlock(addr: [*]u8, rzB: usize) void {
159 doClientRequestStmt(ClientRequest.FreelikeBlock, @ptrToInt(addr), rzB, 0, 0, 0);164 doClientRequestStmt(.FreelikeBlock, @ptrToInt(addr), rzB, 0, 0, 0);
160}165}
161166
162/// Create a memory pool.167/// Create a memory pool.
...@@ -165,66 +170,66 @@ pub const MempoolFlags = extern enum {...@@ -165,66 +170,66 @@ pub const MempoolFlags = extern enum {
165 MetaPool = 2,170 MetaPool = 2,
166};171};
167pub fn createMempool(pool: [*]u8, rzB: usize, is_zeroed: bool, flags: usize) void {172pub fn createMempool(pool: [*]u8, rzB: usize, is_zeroed: bool, flags: usize) void {
168 doClientRequestStmt(ClientRequest.CreateMempool, @ptrToInt(pool), rzB, @boolToInt(is_zeroed), flags, 0);173 doClientRequestStmt(.CreateMempool, @ptrToInt(pool), rzB, @boolToInt(is_zeroed), flags, 0);
169}174}
170175
171/// Destroy a memory pool.176/// Destroy a memory pool.
172pub fn destroyMempool(pool: [*]u8) void {177pub fn destroyMempool(pool: [*]u8) void {
173 doClientRequestStmt(ClientRequest.DestroyMempool, pool, 0, 0, 0, 0);178 doClientRequestStmt(.DestroyMempool, pool, 0, 0, 0, 0);
174}179}
175180
176/// Associate a piece of memory with a memory pool.181/// Associate a piece of memory with a memory pool.
177pub fn mempoolAlloc(pool: [*]u8, mem: []u8) void {182pub fn mempoolAlloc(pool: [*]u8, mem: []u8) void {
178 doClientRequestStmt(ClientRequest.MempoolAlloc, @ptrToInt(pool), @ptrToInt(mem.ptr), mem.len, 0, 0);183 doClientRequestStmt(.MempoolAlloc, @ptrToInt(pool), @ptrToInt(mem.ptr), mem.len, 0, 0);
179}184}
180185
181/// Disassociate a piece of memory from a memory pool.186/// Disassociate a piece of memory from a memory pool.
182pub fn mempoolFree(pool: [*]u8, addr: [*]u8) void {187pub fn mempoolFree(pool: [*]u8, addr: [*]u8) void {
183 doClientRequestStmt(ClientRequest.MempoolFree, @ptrToInt(pool), @ptrToInt(addr), 0, 0, 0);188 doClientRequestStmt(.MempoolFree, @ptrToInt(pool), @ptrToInt(addr), 0, 0, 0);
184}189}
185190
186/// Disassociate any pieces outside a particular range.191/// Disassociate any pieces outside a particular range.
187pub fn mempoolTrim(pool: [*]u8, mem: []u8) void {192pub fn mempoolTrim(pool: [*]u8, mem: []u8) void {
188 doClientRequestStmt(ClientRequest.MempoolTrim, @ptrToInt(pool), @ptrToInt(mem.ptr), mem.len, 0, 0);193 doClientRequestStmt(.MempoolTrim, @ptrToInt(pool), @ptrToInt(mem.ptr), mem.len, 0, 0);
189}194}
190195
191/// Resize and/or move a piece associated with a memory pool.196/// Resize and/or move a piece associated with a memory pool.
192pub fn moveMempool(poolA: [*]u8, poolB: [*]u8) void {197pub fn moveMempool(poolA: [*]u8, poolB: [*]u8) void {
193 doClientRequestStmt(ClientRequest.MoveMempool, @ptrToInt(poolA), @ptrToInt(poolB), 0, 0, 0);198 doClientRequestStmt(.MoveMempool, @ptrToInt(poolA), @ptrToInt(poolB), 0, 0, 0);
194}199}
195200
196/// Resize and/or move a piece associated with a memory pool.201/// Resize and/or move a piece associated with a memory pool.
197pub fn mempoolChange(pool: [*]u8, addrA: [*]u8, mem: []u8) void {202pub fn mempoolChange(pool: [*]u8, addrA: [*]u8, mem: []u8) void {
198 doClientRequestStmt(ClientRequest.MempoolChange, @ptrToInt(pool), @ptrToInt(addrA), @ptrToInt(mem.ptr), mem.len, 0);203 doClientRequestStmt(.MempoolChange, @ptrToInt(pool), @ptrToInt(addrA), @ptrToInt(mem.ptr), mem.len, 0);
199}204}
200205
201/// Return if a mempool exists.206/// Return if a mempool exists.
202pub fn mempoolExists(pool: [*]u8) bool {207pub fn mempoolExists(pool: [*]u8) bool {
203 return doClientRequestExpr(0, ClientRequest.MempoolExists, @ptrToInt(pool), 0, 0, 0, 0) != 0;208 return doClientRequestExpr(0, .MempoolExists, @ptrToInt(pool), 0, 0, 0, 0) != 0;
204}209}
205210
206/// Mark a piece of memory as being a stack. Returns a stack id.211/// Mark a piece of memory as being a stack. Returns a stack id.
207/// start is the lowest addressable stack byte, end is the highest212/// start is the lowest addressable stack byte, end is the highest
208/// addressable stack byte.213/// addressable stack byte.
209pub fn stackRegister(stack: []u8) usize {214pub fn stackRegister(stack: []u8) usize {
210 return doClientRequestExpr(0, ClientRequest.StackRegister, @ptrToInt(stack.ptr), @ptrToInt(stack.ptr) + stack.len, 0, 0, 0);215 return doClientRequestExpr(0, .StackRegister, @ptrToInt(stack.ptr), @ptrToInt(stack.ptr) + stack.len, 0, 0, 0);
211}216}
212217
213/// Unmark the piece of memory associated with a stack id as being a stack.218/// Unmark the piece of memory associated with a stack id as being a stack.
214pub fn stackDeregister(id: usize) void {219pub fn stackDeregister(id: usize) void {
215 doClientRequestStmt(ClientRequest.StackDeregister, id, 0, 0, 0, 0);220 doClientRequestStmt(.StackDeregister, id, 0, 0, 0, 0);
216}221}
217222
218/// Change the start and end address of the stack id.223/// Change the start and end address of the stack id.
219/// start is the new lowest addressable stack byte, end is the new highest224/// start is the new lowest addressable stack byte, end is the new highest
220/// addressable stack byte.225/// addressable stack byte.
221pub fn stackChange(id: usize, newstack: []u8) void {226pub fn stackChange(id: usize, newstack: []u8) void {
222 doClientRequestStmt(ClientRequest.StackChange, id, @ptrToInt(newstack.ptr), @ptrToInt(newstack.ptr) + newstack.len, 0, 0);227 doClientRequestStmt(.StackChange, id, @ptrToInt(newstack.ptr), @ptrToInt(newstack.ptr) + newstack.len, 0, 0);
223}228}
224229
225// Load PDB debug info for Wine PE image_map.230// Load PDB debug info for Wine PE image_map.
226// pub fn loadPdbDebuginfo(fd, ptr, total_size, delta) void {231// pub fn loadPdbDebuginfo(fd, ptr, total_size, delta) void {
227// doClientRequestStmt(ClientRequest.LoadPdbDebuginfo,232// doClientRequestStmt(.LoadPdbDebuginfo,
228// fd, ptr, total_size, delta,233// fd, ptr, total_size, delta,
229// 0);234// 0);
230// }235// }
...@@ -234,7 +239,7 @@ pub fn stackChange(id: usize, newstack: []u8) void {...@@ -234,7 +239,7 @@ pub fn stackChange(id: usize, newstack: []u8) void {
234/// result will be dumped in there and is guaranteed to be zero239/// result will be dumped in there and is guaranteed to be zero
235/// terminated. If no info is found, the first byte is set to zero.240/// terminated. If no info is found, the first byte is set to zero.
236pub fn mapIpToSrcloc(addr: *const u8, buf64: [64]u8) usize {241pub fn mapIpToSrcloc(addr: *const u8, buf64: [64]u8) usize {
237 return doClientRequestExpr(0, ClientRequest.MapIpToSrcloc, @ptrToInt(addr), @ptrToInt(&buf64[0]), 0, 0, 0);242 return doClientRequestExpr(0, .MapIpToSrcloc, @ptrToInt(addr), @ptrToInt(&buf64[0]), 0, 0, 0);
238}243}
239244
240/// Disable error reporting for this thread. Behaves in a stack like245/// Disable error reporting for this thread. Behaves in a stack like
...@@ -246,12 +251,12 @@ pub fn mapIpToSrcloc(addr: *const u8, buf64: [64]u8) usize {...@@ -246,12 +251,12 @@ pub fn mapIpToSrcloc(addr: *const u8, buf64: [64]u8) usize {
246/// reporting. Child threads do not inherit this setting from their251/// reporting. Child threads do not inherit this setting from their
247/// parents -- they are always created with reporting enabled.252/// parents -- they are always created with reporting enabled.
248pub fn disableErrorReporting() void {253pub fn disableErrorReporting() void {
249 doClientRequestStmt(ClientRequest.ChangeErrDisablement, 1, 0, 0, 0, 0);254 doClientRequestStmt(.ChangeErrDisablement, 1, 0, 0, 0, 0);
250}255}
251256
252/// Re-enable error reporting, (see disableErrorReporting())257/// Re-enable error reporting, (see disableErrorReporting())
253pub fn enableErrorReporting() void {258pub fn enableErrorReporting() void {
254 doClientRequestStmt(ClientRequest.ChangeErrDisablement, math.maxInt(usize), 0, 0, 0, 0);259 doClientRequestStmt(.ChangeErrDisablement, math.maxInt(usize), 0, 0, 0, 0);
255}260}
256261
257/// Execute a monitor command from the client program.262/// Execute a monitor command from the client program.
...@@ -260,8 +265,13 @@ pub fn enableErrorReporting() void {...@@ -260,8 +265,13 @@ pub fn enableErrorReporting() void {
260/// If no connection is opened, output will go to the log output.265/// If no connection is opened, output will go to the log output.
261/// Returns 1 if command not recognised, 0 otherwise.266/// Returns 1 if command not recognised, 0 otherwise.
262pub fn monitorCommand(command: [*]u8) bool {267pub fn monitorCommand(command: [*]u8) bool {
263 return doClientRequestExpr(0, ClientRequest.GdbMonitorCommand, @ptrToInt(command.ptr), 0, 0, 0, 0) != 0;268 return doClientRequestExpr(0, .GdbMonitorCommand, @ptrToInt(command.ptr), 0, 0, 0, 0) != 0;
264}269}
265270
266pub const memcheck = @import("memcheck.zig");271pub const memcheck = @import("valgrind/memcheck.zig");
267pub const callgrind = @import("callgrind.zig");272pub const callgrind = @import("valgrind/callgrind.zig");
273
274test "" {
275 _ = @import("valgrind/memcheck.zig");
276 _ = @import("valgrind/callgrind.zig");
277}
lib/std/valgrind/callgrind.zig+7-7
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1const std = @import("../index.zig");1const std = @import("../std.zig");
2const valgrind = std.valgrind;2const valgrind = std.valgrind;
33
4pub const CallgrindClientRequest = extern enum {4pub const CallgrindClientRequest = extern enum {
...@@ -20,7 +20,7 @@ fn doCallgrindClientRequestStmt(request: CallgrindClientRequest, a1: usize, a2:...@@ -20,7 +20,7 @@ fn doCallgrindClientRequestStmt(request: CallgrindClientRequest, a1: usize, a2:
2020
21/// Dump current state of cost centers, and zero them afterwards21/// Dump current state of cost centers, and zero them afterwards
22pub fn dumpStats() void {22pub fn dumpStats() void {
23 doCallgrindClientRequestStmt(CallgrindClientRequest.DumpStats, 0, 0, 0, 0, 0);23 doCallgrindClientRequestStmt(.DumpStats, 0, 0, 0, 0, 0);
24}24}
2525
26/// Dump current state of cost centers, and zero them afterwards.26/// Dump current state of cost centers, and zero them afterwards.
...@@ -28,12 +28,12 @@ pub fn dumpStats() void {...@@ -28,12 +28,12 @@ pub fn dumpStats() void {
28/// the dump. This string is written as a description field into the28/// the dump. This string is written as a description field into the
29/// profile data dump.29/// profile data dump.
30pub fn dumpStatsAt(pos_str: [*]u8) void {30pub fn dumpStatsAt(pos_str: [*]u8) void {
31 doCallgrindClientRequestStmt(CallgrindClientRequest.DumpStatsAt, @ptrToInt(pos_str), 0, 0, 0, 0);31 doCallgrindClientRequestStmt(.DumpStatsAt, @ptrToInt(pos_str), 0, 0, 0, 0);
32}32}
3333
34/// Zero cost centers34/// Zero cost centers
35pub fn zeroStats() void {35pub fn zeroStats() void {
36 doCallgrindClientRequestStmt(CallgrindClientRequest.ZeroStats, 0, 0, 0, 0, 0);36 doCallgrindClientRequestStmt(.ZeroStats, 0, 0, 0, 0, 0);
37}37}
3838
39/// Toggles collection state.39/// Toggles collection state.
...@@ -41,7 +41,7 @@ pub fn zeroStats() void {...@@ -41,7 +41,7 @@ pub fn zeroStats() void {
41/// should be noted or if they are to be ignored. Events are noted41/// should be noted or if they are to be ignored. Events are noted
42/// by increment of counters in a cost center42/// by increment of counters in a cost center
43pub fn toggleCollect() void {43pub fn toggleCollect() void {
44 doCallgrindClientRequestStmt(CallgrindClientRequest.ToggleCollect, 0, 0, 0, 0, 0);44 doCallgrindClientRequestStmt(.ToggleCollect, 0, 0, 0, 0, 0);
45}45}
4646
47/// Start full callgrind instrumentation if not already switched on.47/// Start full callgrind instrumentation if not already switched on.
...@@ -49,7 +49,7 @@ pub fn toggleCollect() void {...@@ -49,7 +49,7 @@ pub fn toggleCollect() void {
49/// this will lead to an artificial cache warmup phase afterwards with49/// this will lead to an artificial cache warmup phase afterwards with
50/// cache misses which would not have happened in reality.50/// cache misses which would not have happened in reality.
51pub fn startInstrumentation() void {51pub fn startInstrumentation() void {
52 doCallgrindClientRequestStmt(CallgrindClientRequest.StartInstrumentation, 0, 0, 0, 0, 0);52 doCallgrindClientRequestStmt(.StartInstrumentation, 0, 0, 0, 0, 0);
53}53}
5454
55/// Stop full callgrind instrumentation if not already switched off.55/// Stop full callgrind instrumentation if not already switched off.
...@@ -60,5 +60,5 @@ pub fn startInstrumentation() void {...@@ -60,5 +60,5 @@ pub fn startInstrumentation() void {
60/// To start Callgrind in this mode to ignore the setup phase, use60/// To start Callgrind in this mode to ignore the setup phase, use
61/// the option "--instr-atstart=no".61/// the option "--instr-atstart=no".
62pub fn stopInstrumentation() void {62pub fn stopInstrumentation() void {
63 doCallgrindClientRequestStmt(CallgrindClientRequest.StopInstrumentation, 0, 0, 0, 0, 0);63 doCallgrindClientRequestStmt(.StopInstrumentation, 0, 0, 0, 0, 0);
64}64}
lib/std/valgrind/memcheck.zig+60-21
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1const std = @import("../index.zig");1const std = @import("../std.zig");
2const testing = std.testing;
2const valgrind = std.valgrind;3const valgrind = std.valgrind;
34
4pub const MemCheckClientRequest = extern enum {5pub const MemCheckClientRequest = extern enum {
...@@ -31,7 +32,7 @@ fn doMemCheckClientRequestStmt(request: MemCheckClientRequest, a1: usize, a2: us...@@ -31,7 +32,7 @@ fn doMemCheckClientRequestStmt(request: MemCheckClientRequest, a1: usize, a2: us
31/// This returns -1 when run on Valgrind and 0 otherwise.32/// This returns -1 when run on Valgrind and 0 otherwise.
32pub fn makeMemNoAccess(qzz: []u8) i1 {33pub fn makeMemNoAccess(qzz: []u8) i1 {
33 return @intCast(i1, doMemCheckClientRequestExpr(0, // default return34 return @intCast(i1, doMemCheckClientRequestExpr(0, // default return
34 MemCheckClientRequest.MakeMemNoAccess, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0));35 .MakeMemNoAccess, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0));
35}36}
3637
37/// Similarly, mark memory at qzz.ptr as addressable but undefined38/// Similarly, mark memory at qzz.ptr as addressable but undefined
...@@ -39,7 +40,7 @@ pub fn makeMemNoAccess(qzz: []u8) i1 {...@@ -39,7 +40,7 @@ pub fn makeMemNoAccess(qzz: []u8) i1 {
39/// This returns -1 when run on Valgrind and 0 otherwise.40/// This returns -1 when run on Valgrind and 0 otherwise.
40pub fn makeMemUndefined(qzz: []u8) i1 {41pub fn makeMemUndefined(qzz: []u8) i1 {
41 return @intCast(i1, doMemCheckClientRequestExpr(0, // default return42 return @intCast(i1, doMemCheckClientRequestExpr(0, // default return
42 MemCheckClientRequest.MakeMemUndefined, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0));43 .MakeMemUndefined, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0));
43}44}
4445
45/// Similarly, mark memory at qzz.ptr as addressable and defined46/// Similarly, mark memory at qzz.ptr as addressable and defined
...@@ -47,7 +48,7 @@ pub fn makeMemUndefined(qzz: []u8) i1 {...@@ -47,7 +48,7 @@ pub fn makeMemUndefined(qzz: []u8) i1 {
47pub fn makeMemDefined(qzz: []u8) i1 {48pub fn makeMemDefined(qzz: []u8) i1 {
48 // This returns -1 when run on Valgrind and 0 otherwise.49 // This returns -1 when run on Valgrind and 0 otherwise.
49 return @intCast(i1, doMemCheckClientRequestExpr(0, // default return50 return @intCast(i1, doMemCheckClientRequestExpr(0, // default return
50 MemCheckClientRequest.MakeMemDefined, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0));51 .MakeMemDefined, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0));
51}52}
5253
53/// Similar to makeMemDefined except that addressability is54/// Similar to makeMemDefined except that addressability is
...@@ -56,7 +57,7 @@ pub fn makeMemDefined(qzz: []u8) i1 {...@@ -56,7 +57,7 @@ pub fn makeMemDefined(qzz: []u8) i1 {
56/// This returns -1 when run on Valgrind and 0 otherwise.57/// This returns -1 when run on Valgrind and 0 otherwise.
57pub fn makeMemDefinedIfAddressable(qzz: []u8) i1 {58pub fn makeMemDefinedIfAddressable(qzz: []u8) i1 {
58 return @intCast(i1, doMemCheckClientRequestExpr(0, // default return59 return @intCast(i1, doMemCheckClientRequestExpr(0, // default return
59 MemCheckClientRequest.MakeMemDefinedIfAddressable, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0));60 .MakeMemDefinedIfAddressable, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0));
60}61}
6162
62/// Create a block-description handle. The description is an ascii63/// Create a block-description handle. The description is an ascii
...@@ -65,14 +66,14 @@ pub fn makeMemDefinedIfAddressable(qzz: []u8) i1 {...@@ -65,14 +66,14 @@ pub fn makeMemDefinedIfAddressable(qzz: []u8) i1 {
65/// properties of the memory range.66/// properties of the memory range.
66pub fn createBlock(qzz: []u8, desc: [*]u8) usize {67pub fn createBlock(qzz: []u8, desc: [*]u8) usize {
67 return doMemCheckClientRequestExpr(0, // default return68 return doMemCheckClientRequestExpr(0, // default return
68 MemCheckClientRequest.CreateBlock, @ptrToInt(qzz.ptr), qzz.len, @ptrToInt(desc), 0, 0);69 .CreateBlock, @ptrToInt(qzz.ptr), qzz.len, @ptrToInt(desc), 0, 0);
69}70}
7071
71/// Discard a block-description-handle. Returns 1 for an72/// Discard a block-description-handle. Returns 1 for an
72/// invalid handle, 0 for a valid handle.73/// invalid handle, 0 for a valid handle.
73pub fn discard(blkindex) bool {74pub fn discard(blkindex) bool {
74 return doMemCheckClientRequestExpr(0, // default return75 return doMemCheckClientRequestExpr(0, // default return
75 MemCheckClientRequest.Discard, 0, blkindex, 0, 0, 0) != 0;76 .Discard, 0, blkindex, 0, 0, 0) != 0;
76}77}
7778
78/// Check that memory at qzz.ptr is addressable for qzz.len bytes.79/// Check that memory at qzz.ptr is addressable for qzz.len bytes.
...@@ -80,7 +81,7 @@ pub fn discard(blkindex) bool {...@@ -80,7 +81,7 @@ pub fn discard(blkindex) bool {
80/// error message and returns the address of the first offending byte.81/// error message and returns the address of the first offending byte.
81/// Otherwise it returns zero.82/// Otherwise it returns zero.
82pub fn checkMemIsAddressable(qzz: []u8) usize {83pub fn checkMemIsAddressable(qzz: []u8) usize {
83 return doMemCheckClientRequestExpr(0, MemCheckClientRequest.CheckMemIsAddressable, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0);84 return doMemCheckClientRequestExpr(0, .CheckMemIsAddressable, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0);
84}85}
8586
86/// Check that memory at qzz.ptr is addressable and defined for87/// Check that memory at qzz.ptr is addressable and defined for
...@@ -88,31 +89,31 @@ pub fn checkMemIsAddressable(qzz: []u8) usize {...@@ -88,31 +89,31 @@ pub fn checkMemIsAddressable(qzz: []u8) usize {
88/// established, Valgrind prints an error message and returns the89/// established, Valgrind prints an error message and returns the
89/// address of the first offending byte. Otherwise it returns zero.90/// address of the first offending byte. Otherwise it returns zero.
90pub fn checkMemIsDefined(qzz: []u8) usize {91pub fn checkMemIsDefined(qzz: []u8) usize {
91 return doMemCheckClientRequestExpr(0, MemCheckClientRequest.CheckMemIsDefined, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0);92 return doMemCheckClientRequestExpr(0, .CheckMemIsDefined, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0);
92}93}
9394
94/// Do a full memory leak check (like --leak-check=full) mid-execution.95/// Do a full memory leak check (like --leak-check=full) mid-execution.
95pub fn doLeakCheck() void {96pub fn doLeakCheck() void {
96 doMemCheckClientRequestStmt(MemCheckClientRequest.DO_LEAK_CHECK, 0, 0, 0, 0, 0);97 doMemCheckClientRequestStmt(.DO_LEAK_CHECK, 0, 0, 0, 0, 0);
97}98}
9899
99/// Same as doLeakCheck() but only showing the entries for100/// Same as doLeakCheck() but only showing the entries for
100/// which there was an increase in leaked bytes or leaked nr of blocks101/// which there was an increase in leaked bytes or leaked nr of blocks
101/// since the previous leak search.102/// since the previous leak search.
102pub fn doAddedLeakCheck() void {103pub fn doAddedLeakCheck() void {
103 doMemCheckClientRequestStmt(MemCheckClientRequest.DO_LEAK_CHECK, 0, 1, 0, 0, 0);104 doMemCheckClientRequestStmt(.DO_LEAK_CHECK, 0, 1, 0, 0, 0);
104}105}
105106
106/// Same as doAddedLeakCheck() but showing entries with107/// Same as doAddedLeakCheck() but showing entries with
107/// increased or decreased leaked bytes/blocks since previous leak108/// increased or decreased leaked bytes/blocks since previous leak
108/// search.109/// search.
109pub fn doChangedLeakCheck() void {110pub fn doChangedLeakCheck() void {
110 doMemCheckClientRequestStmt(MemCheckClientRequest.DO_LEAK_CHECK, 0, 2, 0, 0, 0);111 doMemCheckClientRequestStmt(.DO_LEAK_CHECK, 0, 2, 0, 0, 0);
111}112}
112113
113/// Do a summary memory leak check (like --leak-check=summary) mid-execution.114/// Do a summary memory leak check (like --leak-check=summary) mid-execution.
114pub fn doQuickLeakCheck() void {115pub fn doQuickLeakCheck() void {
115 doMemCheckClientRequestStmt(MemCheckClientRequest.DO_LEAK_CHECK, 1, 0, 0, 0, 0);116 doMemCheckClientRequestStmt(.DO_LEAK_CHECK, 1, 0, 0, 0, 0);
116}117}
117118
118/// Return number of leaked, dubious, reachable and suppressed bytes found by119/// Return number of leaked, dubious, reachable and suppressed bytes found by
...@@ -125,27 +126,65 @@ const CountResult = struct {...@@ -125,27 +126,65 @@ const CountResult = struct {
125};126};
126127
127pub fn countLeaks() CountResult {128pub fn countLeaks() CountResult {
128 var res = CountResult{129 var res: CountResult = .{
129 .leaked = 0,130 .leaked = 0,
130 .dubious = 0,131 .dubious = 0,
131 .reachable = 0,132 .reachable = 0,
132 .suppressed = 0,133 .suppressed = 0,
133 };134 };
134 doMemCheckClientRequestStmt(MemCheckClientRequest.CountLeaks, &res.leaked, &res.dubious, &res.reachable, &res.suppressed, 0);135 doMemCheckClientRequestStmt(
136 .CountLeaks,
137 @ptrToInt(&res.leaked),
138 @ptrToInt(&res.dubious),
139 @ptrToInt(&res.reachable),
140 @ptrToInt(&res.suppressed),
141 0,
142 );
135 return res;143 return res;
136}144}
137145
146test "countLeaks" {
147 testing.expectEqual(
148 @as(CountResult, .{
149 .leaked = 0,
150 .dubious = 0,
151 .reachable = 0,
152 .suppressed = 0,
153 }),
154 countLeaks(),
155 );
156}
157
138pub fn countLeakBlocks() CountResult {158pub fn countLeakBlocks() CountResult {
139 var res = CountResult{159 var res: CountResult = .{
140 .leaked = 0,160 .leaked = 0,
141 .dubious = 0,161 .dubious = 0,
142 .reachable = 0,162 .reachable = 0,
143 .suppressed = 0,163 .suppressed = 0,
144 };164 };
145 doMemCheckClientRequestStmt(MemCheckClientRequest.CountLeakBlocks, &res.leaked, &res.dubious, &res.reachable, &res.suppressed, 0);165 doMemCheckClientRequestStmt(
166 .CountLeakBlocks,
167 @ptrToInt(&res.leaked),
168 @ptrToInt(&res.dubious),
169 @ptrToInt(&res.reachable),
170 @ptrToInt(&res.suppressed),
171 0,
172 );
146 return res;173 return res;
147}174}
148175
176test "countLeakBlocks" {
177 testing.expectEqual(
178 @as(CountResult, .{
179 .leaked = 0,
180 .dubious = 0,
181 .reachable = 0,
182 .suppressed = 0,
183 }),
184 countLeakBlocks(),
185 );
186}
187
149/// Get the validity data for addresses zza and copy it188/// Get the validity data for addresses zza and copy it
150/// into the provided zzvbits array. Return values:189/// into the provided zzvbits array. Return values:
151/// 0 if not running on valgrind190/// 0 if not running on valgrind
...@@ -156,7 +195,7 @@ pub fn countLeakBlocks() CountResult {...@@ -156,7 +195,7 @@ pub fn countLeakBlocks() CountResult {
156/// impossible to segfault your system by using this call.195/// impossible to segfault your system by using this call.
157pub fn getVbits(zza: []u8, zzvbits: []u8) u2 {196pub fn getVbits(zza: []u8, zzvbits: []u8) u2 {
158 std.debug.assert(zzvbits.len >= zza.len / 8);197 std.debug.assert(zzvbits.len >= zza.len / 8);
159 return @intCast(u2, doMemCheckClientRequestExpr(0, MemCheckClientRequest.GetVbits, @ptrToInt(zza.ptr), @ptrToInt(zzvbits), zza.len, 0, 0));198 return @intCast(u2, doMemCheckClientRequestExpr(0, .GetVbits, @ptrToInt(zza.ptr), @ptrToInt(zzvbits), zza.len, 0, 0));
160}199}
161200
162/// Set the validity data for addresses zza, copying it201/// Set the validity data for addresses zza, copying it
...@@ -169,17 +208,17 @@ pub fn getVbits(zza: []u8, zzvbits: []u8) u2 {...@@ -169,17 +208,17 @@ pub fn getVbits(zza: []u8, zzvbits: []u8) u2 {
169/// impossible to segfault your system by using this call.208/// impossible to segfault your system by using this call.
170pub fn setVbits(zzvbits: []u8, zza: []u8) u2 {209pub fn setVbits(zzvbits: []u8, zza: []u8) u2 {
171 std.debug.assert(zzvbits.len >= zza.len / 8);210 std.debug.assert(zzvbits.len >= zza.len / 8);
172 return @intCast(u2, doMemCheckClientRequestExpr(0, MemCheckClientRequest.SetVbits, @ptrToInt(zza.ptr), @ptrToInt(zzvbits), zza.len, 0, 0));211 return @intCast(u2, doMemCheckClientRequestExpr(0, .SetVbits, @ptrToInt(zza.ptr), @ptrToInt(zzvbits), zza.len, 0, 0));
173}212}
174213
175/// Disable and re-enable reporting of addressing errors in the214/// Disable and re-enable reporting of addressing errors in the
176/// specified address range.215/// specified address range.
177pub fn disableAddrErrorReportingInRange(qzz: []u8) usize {216pub fn disableAddrErrorReportingInRange(qzz: []u8) usize {
178 return doMemCheckClientRequestExpr(0, // default return217 return doMemCheckClientRequestExpr(0, // default return
179 MemCheckClientRequest.DisableAddrErrorReportingInRange, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0);218 .DisableAddrErrorReportingInRange, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0);
180}219}
181220
182pub fn enableAddrErrorReportingInRange(qzz: []u8) usize {221pub fn enableAddrErrorReportingInRange(qzz: []u8) usize {
183 return doMemCheckClientRequestExpr(0, // default return222 return doMemCheckClientRequestExpr(0, // default return
184 MemCheckClientRequest.EnableAddrErrorReportingInRange, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0);223 .EnableAddrErrorReportingInRange, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0);
185}224}