Merge pull request #21907 from alexrp/valgrind-stuff

Add client request support for all architectures supported by Valgrind
This commit is contained in:
Alex Rønne Petersen 2024-11-05 10:03:44 +01:00 committed by GitHub
commit bd7dda0c55
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 204 additions and 80 deletions

View File

@ -7,50 +7,96 @@ pub fn doClientRequest(default: usize, request: usize, a1: usize, a2: usize, a3:
return default;
}
switch (builtin.target.cpu.arch) {
.x86 => {
return asm volatile (
\\ roll $3, %%edi ; roll $13, %%edi
\\ roll $29, %%edi ; roll $19, %%edi
\\ xchgl %%ebx,%%ebx
: [_] "={edx}" (-> usize),
: [_] "{eax}" (&[_]usize{ request, a1, a2, a3, a4, a5 }),
[_] "0" (default),
: "cc", "memory"
);
},
.x86_64 => {
return asm volatile (
\\ rolq $3, %%rdi ; rolq $13, %%rdi
\\ rolq $61, %%rdi ; rolq $51, %%rdi
\\ xchgq %%rbx,%%rbx
: [_] "={rdx}" (-> usize),
: [_] "{rax}" (&[_]usize{ request, a1, a2, a3, a4, a5 }),
[_] "0" (default),
: "cc", "memory"
);
},
.aarch64 => {
return asm volatile (
\\ ror x12, x12, #3 ; ror x12, x12, #13
\\ ror x12, x12, #51 ; ror x12, x12, #61
\\ orr x10, x10, x10
: [_] "={x3}" (-> usize),
: [_] "{x4}" (&[_]usize{ request, a1, a2, a3, a4, a5 }),
[_] "0" (default),
: "cc", "memory"
);
},
// ppc32
// ppc64
// arm
// s390x
// mips32
// mips64
else => {
return default;
},
}
const args = &[_]usize{ request, a1, a2, a3, a4, a5 };
return switch (builtin.cpu.arch) {
.arm, .armeb, .thumb, .thumbeb => asm volatile (
\\ mov r12, r12, ror #3 ; mov r12, r12, ror #13
\\ mov r12, r12, ror #29 ; mov r12, r12, ror #19
\\ orr r10, r10, r10
: [_] "={r3}" (-> usize),
: [_] "{r4}" (args),
[_] "{r3}" (default),
: "cc", "memory"
),
.aarch64, .aarch64_be => asm volatile (
\\ ror x12, x12, #3 ; ror x12, x12, #13
\\ ror x12, x12, #51 ; ror x12, x12, #61
\\ orr x10, x10, x10
: [_] "={x3}" (-> usize),
: [_] "{x4}" (args),
[_] "{x3}" (default),
: "cc", "memory"
),
.mips, .mipsel => asm volatile (
\\ srl $0, $0, 13
\\ srl $0, $0, 29
\\ srl $0, $0, 3
\\ srl $0, $0, 19
\\ or $13, $13, $13
: [_] "={$11}" (-> usize),
: [_] "{$12}" (args),
[_] "{$11}" (default),
: "memory"
),
.mips64, .mips64el => asm volatile (
\\ dsll $0, $0, 3 ; dsll $0, $0, 13
\\ dsll $0, $0, 29 ; dsll $0, $0, 19
\\ or $13, $13, $13
: [_] "={$11}" (-> usize),
: [_] "{$12}" (args),
[_] "{$11}" (default),
: "memory"
),
.powerpc, .powerpcle => asm volatile (
\\ rlwinm 0, 0, 3, 0, 31 ; rlwinm 0, 0, 13, 0, 31
\\ rlwinm 0, 0, 29, 0, 31 ; rlwinm 0, 0, 19, 0, 31
\\ or 1, 1, 1
: [_] "={r3}" (-> usize),
: [_] "{r4}" (args),
[_] "{r3}" (default),
: "cc", "memory"
),
.powerpc64, .powerpc64le => asm volatile (
\\ rotldi 0, 0, 3 ; rotldi 0, 0, 13
\\ rotldi 0, 0, 61 ; rotldi 0, 0, 51
\\ or 1, 1, 1
: [_] "={r3}" (-> usize),
: [_] "{r4}" (args),
[_] "{r3}" (default),
: "cc", "memory"
),
.s390x => asm volatile (
\\ lr %%r15, %%r15
\\ lr %%r1, %%r1
\\ lr %%r2, %%r2
\\ lr %%r3, %%r3
\\ lr %%r2, %%r2
: [_] "={r3}" (-> usize),
: [_] "{r2}" (args),
[_] "{r3}" (default),
: "cc", "memory"
),
.x86 => asm volatile (
\\ roll $3, %%edi ; roll $13, %%edi
\\ roll $29, %%edi ; roll $19, %%edi
\\ xchgl %%ebx, %%ebx
: [_] "={edx}" (-> usize),
: [_] "{eax}" (args),
[_] "{edx}" (default),
: "cc", "memory"
),
.x86_64 => asm volatile (
\\ rolq $3, %%rdi ; rolq $13, %%rdi
\\ rolq $61, %%rdi ; rolq $51, %%rdi
\\ xchgq %%rbx, %%rbx
: [_] "={rdx}" (-> usize),
: [_] "{rax}" (args),
[_] "{rdx}" (default),
: "cc", "memory"
),
else => default,
};
}
pub const ClientRequest = enum(u32) {
@ -121,7 +167,7 @@ pub fn discardTranslations(qzz: []const u8) void {
}
pub fn innerThreads(qzz: [*]u8) void {
doClientRequestStmt(.InnerThreads, qzz, 0, 0, 0, 0);
doClientRequestStmt(.InnerThreads, @intFromPtr(qzz), 0, 0, 0, 0);
}
pub fn nonSimdCall0(func: fn (usize) usize) usize {
@ -273,7 +319,7 @@ pub fn enableErrorReporting() void {
/// If no connection is opened, output will go to the log output.
/// Returns 1 if command not recognised, 0 otherwise.
pub fn monitorCommand(command: [*]u8) bool {
return doClientRequestExpr(0, .GdbMonitorCommand, @intFromPtr(command.ptr), 0, 0, 0, 0) != 0;
return doClientRequestExpr(0, .GdbMonitorCommand, @intFromPtr(command), 0, 0, 0, 0) != 0;
}
pub const memcheck = @import("valgrind/memcheck.zig");

View File

@ -90,26 +90,26 @@ pub fn checkMemIsDefined(qzz: []const u8) usize {
/// Do a full memory leak check (like --leak-check=full) mid-execution.
pub fn doLeakCheck() void {
doClientRequestStmt(.DO_LEAK_CHECK, 0, 0, 0, 0, 0);
doClientRequestStmt(.DoLeakCheck, 0, 0, 0, 0, 0);
}
/// Same as doLeakCheck() but only showing the entries for
/// which there was an increase in leaked bytes or leaked nr of blocks
/// since the previous leak search.
pub fn doAddedLeakCheck() void {
doClientRequestStmt(.DO_LEAK_CHECK, 0, 1, 0, 0, 0);
doClientRequestStmt(.DoLeakCheck, 0, 1, 0, 0, 0);
}
/// Same as doAddedLeakCheck() but showing entries with
/// increased or decreased leaked bytes/blocks since previous leak
/// search.
pub fn doChangedLeakCheck() void {
doClientRequestStmt(.DO_LEAK_CHECK, 0, 2, 0, 0, 0);
doClientRequestStmt(.DoLeakCheck, 0, 2, 0, 0, 0);
}
/// Do a summary memory leak check (like --leak-check=summary) mid-execution.
pub fn doQuickLeakCheck() void {
doClientRequestStmt(.DO_LEAK_CHECK, 1, 0, 0, 0, 0);
doClientRequestStmt(.DoLeakCheck, 1, 0, 0, 0, 0);
}
/// Return number of leaked, dubious, reachable and suppressed bytes found by
@ -191,7 +191,7 @@ test countLeakBlocks {
/// impossible to segfault your system by using this call.
pub fn getVbits(zza: []u8, zzvbits: []u8) u2 {
std.debug.assert(zzvbits.len >= zza.len / 8);
return @as(u2, @intCast(doClientRequestExpr(0, .GetVbits, @intFromPtr(zza.ptr), @intFromPtr(zzvbits), zza.len, 0, 0)));
return @as(u2, @intCast(doClientRequestExpr(0, .GetVbits, @intFromPtr(zza.ptr), @intFromPtr(zzvbits.ptr), zza.len, 0, 0)));
}
/// Set the validity data for addresses zza, copying it
@ -204,7 +204,7 @@ pub fn getVbits(zza: []u8, zzvbits: []u8) u2 {
/// impossible to segfault your system by using this call.
pub fn setVbits(zzvbits: []u8, zza: []u8) u2 {
std.debug.assert(zzvbits.len >= zza.len / 8);
return @as(u2, @intCast(doClientRequestExpr(0, .SetVbits, @intFromPtr(zza.ptr), @intFromPtr(zzvbits), zza.len, 0, 0)));
return @as(u2, @intCast(doClientRequestExpr(0, .SetVbits, @intFromPtr(zza.ptr), @intFromPtr(zzvbits.ptr), zza.len, 0, 0)));
}
/// Disable and re-enable reporting of addressing errors in the

View File

@ -11592,29 +11592,81 @@ pub const FuncGen = struct {
template: [:0]const u8,
constraints: [:0]const u8,
} = switch (target.cpu.arch) {
.x86 => .{
.arm, .armeb, .thumb, .thumbeb => .{
.template =
\\roll $$3, %edi ; roll $$13, %edi
\\roll $$61, %edi ; roll $$51, %edi
\\xchgl %ebx,%ebx
\\ mov r12, r12, ror #3 ; mov r12, r12, ror #13
\\ mov r12, r12, ror #29 ; mov r12, r12, ror #19
\\ orr r10, r10, r10
,
.constraints = "={edx},{eax},0,~{cc},~{memory}",
},
.x86_64 => .{
.template =
\\rolq $$3, %rdi ; rolq $$13, %rdi
\\rolq $$61, %rdi ; rolq $$51, %rdi
\\xchgq %rbx,%rbx
,
.constraints = "={rdx},{rax},0,~{cc},~{memory}",
.constraints = "={r3},{r4},{r3},~{cc},~{memory}",
},
.aarch64, .aarch64_be => .{
.template =
\\ror x12, x12, #3 ; ror x12, x12, #13
\\ror x12, x12, #51 ; ror x12, x12, #61
\\orr x10, x10, x10
\\ ror x12, x12, #3 ; ror x12, x12, #13
\\ ror x12, x12, #51 ; ror x12, x12, #61
\\ orr x10, x10, x10
,
.constraints = "={x3},{x4},0,~{cc},~{memory}",
.constraints = "={x3},{x4},{x3},~{cc},~{memory}",
},
.mips, .mipsel => .{
.template =
\\ srl $$0, $$0, 13
\\ srl $$0, $$0, 29
\\ srl $$0, $$0, 3
\\ srl $$0, $$0, 19
\\ or $$13, $$13, $$13
,
.constraints = "={$11},{$12},{$11},~{memory}",
},
.mips64, .mips64el => .{
.template =
\\ dsll $$0, $$0, 3 ; dsll $$0, $$0, 13
\\ dsll $$0, $$0, 29 ; dsll $$0, $$0, 19
\\ or $$13, $$13, $$13
,
.constraints = "={$11},{$12},{$11},~{memory}",
},
.powerpc, .powerpcle => .{
.template =
\\ rlwinm 0, 0, 3, 0, 31 ; rlwinm 0, 0, 13, 0, 31
\\ rlwinm 0, 0, 29, 0, 31 ; rlwinm 0, 0, 19, 0, 31
\\ or 1, 1, 1
,
.constraints = "={r3},{r4},{r3},~{cc},~{memory}",
},
.powerpc64, .powerpc64le => .{
.template =
\\ rotldi 0, 0, 3 ; rotldi 0, 0, 13
\\ rotldi 0, 0, 61 ; rotldi 0, 0, 51
\\ or 1, 1, 1
,
.constraints = "={r3},{r4},{r3},~{cc},~{memory}",
},
.s390x => .{
.template =
\\ lr %r15, %r15
\\ lr %r1, %r1
\\ lr %r2, %r2
\\ lr %r3, %r3
\\ lr %r2, %r2
,
.constraints = "={r3},{r2},{r3},~{cc},~{memory}",
},
.x86 => .{
.template =
\\ roll $$3, %edi ; roll $$13, %edi
\\ roll $$61, %edi ; roll $$51, %edi
\\ xchgl %ebx, %ebx
,
.constraints = "={edx},{eax},{edx},~{cc},~{memory}",
},
.x86_64 => .{
.template =
\\ rolq $$3, %rdi ; rolq $$13, %rdi
\\ rolq $$61, %rdi ; rolq $$51, %rdi
\\ xchgq %rbx, %rbx
,
.constraints = "={rdx},{rax},{edx},~{cc},~{memory}",
},
else => unreachable,
};

View File

@ -79,19 +79,45 @@ pub fn defaultSingleThreaded(target: std.Target) bool {
return false;
}
/// Valgrind supports more, but Zig does not support them yet.
pub fn hasValgrindSupport(target: std.Target) bool {
switch (target.cpu.arch) {
.x86,
.x86_64,
.aarch64,
.aarch64_be,
=> {
return target.os.tag == .linux or target.os.tag == .solaris or target.os.tag == .illumos or
(target.os.tag == .windows and target.abi.isGnu());
// We can't currently output the necessary Valgrind client request assembly when using the C
// backend and compiling with an MSVC-like compiler.
const ofmt_c_msvc = (target.abi == .msvc or target.abi == .itanium) and target.ofmt == .c;
return switch (target.cpu.arch) {
.arm, .armeb, .thumb, .thumbeb => switch (target.os.tag) {
.linux => true,
else => false,
},
else => return false,
}
.aarch64, .aarch64_be => switch (target.os.tag) {
.linux, .freebsd => true,
else => false,
},
.mips, .mipsel, .mips64, .mips64el => switch (target.os.tag) {
.linux => true,
else => false,
},
.powerpc, .powerpcle, .powerpc64, .powerpc64le => switch (target.os.tag) {
.linux => true,
else => false,
},
.s390x => switch (target.os.tag) {
.linux => true,
else => false,
},
.x86 => switch (target.os.tag) {
.linux, .freebsd, .solaris, .illumos => true,
.windows => !ofmt_c_msvc,
else => false,
},
.x86_64 => switch (target.os.tag) {
.linux => target.abi != .gnux32 and target.abi != .muslx32,
.freebsd, .solaris, .illumos => true,
.windows => !ofmt_c_msvc,
else => false,
},
else => false,
};
}
/// The set of targets that LLVM has non-experimental support for.